[i] Хост-интерфейс. Ошибка чтения периферийных регистров

ID статьи: 62937
Дата последнего изменения: 23.01.2026 12:14:34
В процессоре К1967ВН044 (К1967ВН04BG) в хост-интерфейсе присутствует ошибка чтения данных из области "Периферийных устройств SOC-шины", Errata 0009. В качестве путей обхода можно использовать программную пересылку данных из области "Периферийных устройств SOC-шины" во внутреннюю память, где уже возможно чтение по хост-интерфейсу. Пересылку данных процессором можно реализовать в обработчике прерывания от 13 канала DMA, который используется для работы хост-интерфейса.
 
Возможны два варианта обмена по хост-интерфейсу:

  1. Обмен с областью "Периферийных устройств SOC-шины" осуществляется до запуска основной программы на процессоре. В этом случае обработчик прерывания загружается в память процессора хостом, настройка контроллера прерываний также осуществляется хостом.
  2. Обмен с областью "Периферийных устройств SOC-шины" осуществляется после запуска основной программы на процессоре. В этом случае обработчик прерывания описан в самой программе, настройка контроллера прерываний осуществляется в ходе выполнения программы.
Алгоритм чтения данных хостом из области "Периферийных устройств SOC-шины" в обоих случаях одинаковый, при этом само чтение разбивается на два этапа: запись адреса источника данных и чтение данных.

  1. Хост выполняет запись адреса периферийного регистра во внутреннюю память процессора по определённому адресу, например, 0x4FFFF (можно выбрать любой адрес). После выполнения записи 13 канал DMA генерирует запрос прерывания (в поле DDP бит INT = 1), после чего процессор в обработчике прерывания считывает данные по адресу периферийного регистра и кладёт результат по адресу 0x4FFFF во внутреннюю память.
  2. Хост считывает значение по адресу 0x4FFFF, которое соответствует значению, хранящемуся по ранее записанному адресу периферийного регистра. Если считанное значение равно записанному адресу, то процессор ещё не успел выполнить чтение данных в обработчике прерывания, поэтому следует повторить чтение.

1. Чтение данных из области "Периферийных устройств SOC-шины" до запуска основной программы

Обмен с областью "Периферийных устройств SOC-шины" осуществляется до запуска основной программы на процессоре, при этом предполагается, что:
- процессор К1967ВН044 (К1967ВН04BG) находится в состоянии ожидания прерываний, режим BOOT[2:0] = 000 или 001;
- HSEND это процедура отсылки старт бита, слова данных и стоп бита - HSEND(START бит, DATA, STOP бит);
- все операции осуществляются в коротком формате обмена.

Алгоритм работы:

1) Устанавливаем вектор прерывания для 13 канала DMA:
- HSEND(1'b0, 32'h59280326, 1'b1); // Управляющее слово для записи в регистр IVDMA13 (0x8000_0326)
- HSEND(1'b0, 32'h300, 1'b1); // Передача данных - адрес обработчика прерывания выбираем равным 0x300

2) Разрешаем прерывания от 13 канала DMA:
- HSEND(1'b0, 32'h59280349, 1'b1); // Управляющее слово для записи в регистр IMASKH (0x8000_03490)
- HSEND(1'b0, 32'h300, 1'b1); // Передача данных - устанавливаем 6 бит - PDMA13

3) Записываем обработчик прерывания DMA13 по адресу 0x300. Код обработчика прерывания, с указанным справа машинным кодом:
j0 = [j31+0x4FFFF];;           - 0x01803FA0, 0xB20004FF
j0 = [j0+0];;                  - 0x81802000
[j31+0x4FFFF] = j0;;           - 0x05803FA0, 0xB20004FF
rds;;                          - 0xB3080040
idle;;                         - 0xB3C40000
nop;; nop;; nop;; nop;;        - 0xB3C00000, 0xB3C00000, 0xB3C00000, 0xB3C00000

Суть обработчика в том, что он берет из памяти по адресу 0x4FFFF значение, которое есть адрес, и читает по этому адресу значение. Прочитанное значение он пишет обратно в этот же адрес. Далее процессор сбрасывает флаг обработки прерывания с помощью команды "rds", после чего переходит в режим ожидания прерывания с помощью команды "idle".

Запись обработчика прерывания:
- HSEND(1'b0, 32'h55200300, 1'b1); // Управляющее слово для записи по адресу 0x300
- HSEND(1'b0, 32'h01803FA0, 1'b1); // Передача машинного кода
...

4) Приступаем к чтению любого регистра периферии. Для связи хоста и обработчика прерывания мы используем ячейку памяти 0x4FFFF, поэтому этот адрес используется для записи адреса источника данных и чтение данных. Для того, чтобы после записи был вызван обработчик прерывания DMA13, необходимо в управляющем слове в поле DDP установить бит INT - генерация запроса прерывания после окончания работы канала. Чтобы уменьшить время выполнения операции записи DMA также можно установить бит PR - приоритет циклов обмена. 

а) Записываем по адресу 0x4FFFF адрес периферийного регистра:
- HSEND(1'b0, 32'h5531FFFF, 1'b1); // Управляющее слово для записи по адресу 0x4FFFF с установленными битами INT и PR
- HSEND(1'b0, 32'h80000140, 1'b1);  // Передача адреса периферийного регистра SPSR0

б) Считываем по адресу 0x4FFFF значение, которое соответствует значению в регистре SPSR0. Если считанное значение равно записанному адресу, то процессор ещё не успел выполнить чтение данных в обработчике прерывания, поэтому следует повторить чтение.
- HSEND(1'b0, 32'h1521FFFF, 1'b1);  // Управляющее слово для чтения по адресу 0x4FFFF с установленным битом PR 
- HSEND(1'b1, 32'hFFFFFFFF, 1'b1); // Передача тактовых импульсом, пока HDO != 0, после чего чтение слова данных 

2. Чтение данных из области "Периферийных устройств SOC-шины" после запуска основной программы

Обмен с областью "Периферийных устройств SOC-шины" осуществляется после запуска основной программы на процессоре. Проект с тестовой программой для CM-LYNX приведен ниже.

Алгоритм работы:

1) Запущенная на процессоре К1967ВН044 (К1967ВН04BG) программа настраивает контроллер прерываний для обработки запросов прерываний от 13 канала DMA:
- в регистр IVDMA13 записывается адрес обработчика прерывания;
- в регистре IMASKH устанавливается разрешение прерываний от 13 канала DMA;
- в регистре SQCTLST разрешаются глобальные прерывания.

В обработчике прерывания от канала 13 DMA описана программа:
unsigned int *host_buf_ptr = (unsigned int *) 0x4FFFF;
void IRQ_Handler_DMA13(void) __attribute__((interrupt))
{
unsigned int *read_addr;
read_addr = (unsigned int *) *host_buf_ptr;
*host_buf_ptr = *read_addr;
}

При выполнении обработчика прерывания значение по адресу 0x4FFFF, которое является адресом из области "Периферийных устройств SOC-шины", присваивается указателю read_addr, после чего выполняется чтение по указателю read_addr, результат которого кладётся обратно по адресу 0x4FFFF.

2) Чтение хостом из области "Периферийных устройств SOC-шины" разбивается на два этапа: запись адреса источника данных и чтение данных.

а) Запись адреса источника данных. Хост выполняет запись адреса периферийного регистра, например SPSR0 (0x80000140), во внутреннюю память по адресу 0x4FFFF. Для того, чтобы после записи был вызван обработчик прерывания DMA13, необходимо в управляющем слове в поле DDP установить бит INT - генерация запроса прерывания после окончания работы канала. Чтобы уменьшить время выполнения операции записи DMA также можно установить бит PR - приоритет циклов обмена. Таким образом управляющее слово в коротком формате для записи адреса SPSR0 будет иметь значение: 0x59380140. 

б) Чтение данных. Хост считывает значение по адресу 0x4FFFF, которое соответствует значению, хранящемуся по ранее записанному адресу. Если считанное значение равно записанному адресу, то процессор ещё не успел выполнить чтение данных в обработчике прерывания, поэтому следует повторить чтение.

Здесь есть важный момент: чтобы компилятор не использовал выбранную ячейку памяти (в данном случае это 0x4FFFF), необходим в ldf-файле выделить данную ячейку памяти в отдельную область, например, вместо:

M2DataA { TYPE(RAM) START(0x00040000) END(0x00040000 +
           (INT_MEM_BANK_SIZE - 1)) WIDTH(32)           } // 0x40000-0x4FFFF

необходимо записать:
M2DataA { TYPE(RAM) START(0x00040000) END(0x00040000 +
           (INT_MEM_BANK_SIZE - 2)) WIDTH(32)           } // 0x40000-0x4FFFE

M2DataA_Host { TYPE(RAM) START(0x00040000 + (INT_MEM_BANK_SIZE - 1))
                 END(0x00040000 + (INT_MEM_BANK_SIZE - 1)) WIDTH(32)   } // 0x4FFFF
 

Контактная информация

Сайт:https://support.milandr.ru
E-mail:support@milandr.ru
Телефон: +7 495 221-13-55