[i] Хост-интерфейс. Ошибка чтения периферийных регистров
В процессоре К1967ВН044 (К1967ВН04BG) в хост-интерфейсе присутствует ошибка чтения данных из области "Периферийных устройств SOC-шины", Errata 0009. В качестве путей обхода можно использовать программную пересылку данных из области "Периферийных устройств SOC-шины" во внутреннюю память, где уже возможно чтение по хост-интерфейсу. Пересылку данных процессором можно реализовать в обработчике прерывания от хост-интерфейса.
Возможны два варианта обмена по хост-интерфейсу:
- Обмен с областью "Периферийных устройств SOC-шины" осуществляется до запуска основной программы на процессоре. В этом случае обработчик прерывания загружается в память процессора хостом, настройка контроллера прерываний также осуществляется хостом.
- Обмен с областью "Периферийных устройств SOC-шины" осуществляется после запуска основной программы на процессоре. В этом случае обработчик прерывания описан в самой программе, настройка контроллера прерываний осуществляется в ходе выполнения программы.
Алгоритм чтения данных хостом из области "Периферийных устройств SOC-шины" в обоих случаях одинаковый, при этом само чтение разбивается на два этапа: запись адреса источника данных и чтение данных.
- Хост выполняет запись адреса периферийного регистра во внутреннюю память процессора по определённому адресу, например, 0x4FFFF (можно выбрать любой адрес). После выполнения записи хост-интерфейс генерирует запрос прерывания (в поле DDP бит INT = 1), после чего процессор в обработчике прерывания считывает данные по адресу периферийного регистра и кладёт результат по адресу 0x4FFFF во внутреннюю память.
- Хост считывает значение по адресу 0x4FFFF, которое соответствует значению, хранящемуся по ранее записанному адресу периферийного регистра. Если считанное значение равно записанному адресу, то процессор ещё не успел выполнить чтение данных в обработчике прерывания, поэтому следует повторить чтение.
1. Чтение данных из области "Периферийных устройств SOC-шины" до запуска основной программы
Обмен с областью "Периферийных устройств SOC-шины" осуществляется до запуска основной программы на процессоре, при этом предполагается, что:
- Процессор К1967ВН044 (К1967ВН04BG) находится в состоянии ожидания прерываний, режим BOOT[2:0] = 000 или 001;
- HSEND это процедура отсылки старт бита, слова данных и стоп бита - HSEND(START бит, DATA, STOP бит);
- Все операции осуществляются в коротком формате обмена.
Алгоритм работы:
1) Устанавливаем вектор прерывания для хост-интерфейса:
- HSEND(1'b0, 32'h59280326, 1'b1); // Управляющее слово для записи в регистр IVHOST (0x8000_0326)
- HSEND(1'b0, 32'h300, 1'b1); // Передача данных - адрес обработчика прерывания выбираем равным 0x300
2) Разрешаем прерывания от хост-интерфейса:
- HSEND(1'b0, 32'h59280349, 1'b1); // Управляющее слово для записи в регистр IMASKH (0x8000_0349)
- HSEND(1'b0, 32'h300, 1'b1); // Передача данных - устанавливаем 6 бит - INT_HOST
3) Записываем обработчик прерывания хост-интерфейса по адресу 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, поэтому этот адрес используется для записи адреса источника данных и чтение данных. Для того, чтобы после записи был вызван обработчик прерывания хост-интерфейса, необходимо в управляющем слове в поле управления обменом DDP установить бит INT - генерация запроса прерывания после окончания работы канала. Чтобы уменьшить время выполнения операции также можно установить бит 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) программа настраивает контроллер прерываний для обработки запросов прерываний от хост-интерфейса:
- в регистр IVHOST записывается адрес обработчика прерывания;
- в регистре IMASKH устанавливается разрешение прерываний от хост-интерфейса;
- в регистре SQCTLST разрешаются глобальные прерывания.
В обработчике прерывания от хост-интерфейса описана программа:
unsigned int *host_buf_ptr = (unsigned int *) 0x4FFFF;
void IRQ_Handler_HOST(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. Для того, чтобы после записи был вызван обработчик прерывания хост-интерфейса, необходимо в управляющем слове в поле DDP установить бит INT - генерация запроса прерывания после окончания работы канала. Чтобы уменьшить время выполнения операции записи также можно установить бит 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Сохранить статью в PDF