Пример реализации загрузчика образа программного кода из EPCS.

Есть у альтеры пример расширенного копировщика, но он мне, во 1-ых не понравился, во 2-ых я с ним долго провозился — но так и не запустил. Если точно следовать пиндоской инструкции, то загрузчика для EPCS не получится. А чтоб отклонится от инструкции — нужно знать матчасть. Ну а если изучить матчасть, то ни какие инструкции не нужны. ИМХО. А не понравился он мне из-за того, что нужно указывать куда размещать образ программы в flash памяти и следить за тем чтоб не перекрыть конфигурацию. Причем это все делается ручками. А если вдруг придется подвинуть локацию образа программы, то нужно опять пересобирать загрузчик, пересобирать Quartus, перепиливать скрипты и т. д. Ад и израиль!


Исходные данные: имеется рабочий проект — конфигурация + программа.

Конфигурация в 2-х словах: Cyclon III + NIOS II + EPCS + SDRAM. Вектор сброса на контроллер EPCS. Вектор прерывания на SDRAM.

При включении питания загружается конфигурация и процессор сбрасывается. По сбросу выполняется код загрузчика по умолчанию, размещённого в начале адресного пространства контроллера EPCS. Этот загрузчик находит образ программы в EPCS и загружает исполняемый код из flash в SDRAM. После передает управление на точку входа основной программы. Если требуется во время загрузки что-то ещё сделать, то придется писать свой загрузчик. Например мне пришлось до загрузки основной программы в SDRAM сделать тест ОЗУ, т. е. проверить на залипухи/обрывы шины адреса/данных/управления.



Возможны 2 варианта загрузчика.

1 вариант: При включении запускается расширенный загрузчик из onchip-memory, загрузчик копирует  код программы  из образа flash- EPCS  в SDRAM, переписывает вектор сброса. Теперь в векторе сброса стоит инструкция типа

jmp entry_point_in_SDRAM;

Далее загрузчик передает управление основной программе. После очередного сброса процессора программа начинает выполнятся с точки входа основной программы entry_point_in_SDRAM. Наш расширенный загрузчик больше не выполнится до выкл/вкл питания. Т. е. Исполняемый код основной программы заново не грузится из flash в SDRAM, а основная программа стартует незамедлительно.

2 вариант: При включении запускается расширенный загрузчик из onchip-memory, из образа flash в EPCS копирует код программы в SDRAM, и передает управление основной программе. После очередного сброса процессора программа начинает выполнятся, начиная с загрузчика, точно также, как после включения. Т. е. опять загрузчик из образа flash в EPCS копирует код программы в SDRAM и передает управление основной программе.

Размер копировщика не зависит от варианта и занимает примерно 6...7 Кбайт без выхлопа в JTAG_UART, и примерно 9 Кбайт с выводом в JTAG_UART.

Время работы загрузчика.... на глаз.... с выводом в jtag_uart 3-4 секунды, без вывода меньше секунды.

 

Загрузчик написан на С и состоит из 2-х файлов advanced_boot_copier.h и advanced_boot_copier.с

Вариант I

1. Добавим в SOPC память onchip-memory. RAM(Writable). Размер 12 Кбайт. Отметим галочку Initialize memory content. Остальное по умолчанию. Переименуем в bootRom.

2. Вектор сброса на bootRom, offset 0x0, вектор исключений на bootRom, offset 0x20

 3. Собираем процессор.

4. Компилируем проект в Quartus-e.  

5. Открываем Eclipse. Создаем новый проект: File->New->NIOS II Aplication and BSP from Template 

6. В SOPC Information File name указываем свой процессор, у меня был D:\Work\Quartus\testBoot\cpuNew.sopcinfo 

7. Задаем имя проекту, пусть будет bootLoader. Project template – Hello World. Жмём Finish 

 8. В проводнике идем в папку нашего загрузчика и удаляем файл hello_world.c. Добавляем в эту папку файлы: advanced_boot_copier.c и advanced_boot_copier.h

9. В Eclipse в Project Explorer правой кнопкой мыши по проекту bootLoader, в контекстном меню Refres. 

10. В BSP редакторе указываем Uart для ввода/вывода jtag_uart. Отмечаем галочки как на рисунке.

Оптимизацию -Os. На вкладке Linker Script указать все регионы на bootRom

    Жмём Generate, ждем окончания процесса и закрываем окно. 

    11. Если требуется дебажный вывод в uart то отмечаем в advanced_boot_copier.c

#define USING_JTAG_UART 1

иначе

#define USING_JTAG_UART 0 

12. У меня в устройстве есть линейка светодиодов. На разных процессах загрузки я зажигаю разные диоды, тем самым контролирую процесс без терминала. Если у вас есть индикация, то замените вывод индикации на свой или закоментируйте строки

 IOWR_ALTERA_AVALON_PIO_DATA(IOLED_BASE, 0x2);

13. Собираем проект bootLoader

14. Собираем *.hex. ПКМ по проекту в Project Explorer ->Make Targets->Build... Выбираем mem_init_install, жмём Build. Создастся *.hex с расширенным загрузчиком

15. Запускаем повторную компиляцию в Quartus-e. При этом наш hex с загрузчиком подцепится к *.sof файлу.

16. Программируем ПЛИС полученным *.sof файлом (через квартусовский программатор)

 

Теперь займёмся рихтовкой рабочей программы/проекта

17. В BSP Editore я ни чего не менял. Оставил всё, как было без расширенного загрузчика.

Жмём Generate, ждем окончания процесса и закрываем окно.

18. Собираем рабочий проект — на выходе *.elf

Ну вот собственно и всё. Осталось залить все это в EPCS

19. В Eclipse открываем флеш-программатор NIOS II->Flash Programmer Создаем/откываем сеттинг файл и программируем. Образ из *.elf должен лечь сразу за *.sof, без смещений.

20. Выключаем плис. Включаем.

21. Если вы указали USING_JTAG_UART 1 и после включения плис, как нинзя, успеть в шеле ввести команду nios2-terminal, то можно залицезреть выхлоп

После сброса процессора вывода в терминал не будет, т. к. код загрузчика больше не выполняется.

Вариант II

1. Добавим в SOPC память onchip-memory. RAM(Writable). Размер 4 Кбайт. Остальное по умолчанию. Снимим галочку Initialize memory content. Переименуем в onchip-memory.

2. Добавим в SOPC память onchip-memory. ROM(Read only). Размер 10 Кбайт. Отметим галочку Initialize memory content. Остальное по умолчанию. Переименуем в onchip-memory.

3. Вектор сброса на bootRom, offset 0x0, вектор исключений на onchip-memory, offset 0x0.

4. Собираем процессор.

5. Компилируем проект в Quartus-e.

6. Открываем Eclipse. Создаем новый проект: File->New->NIOS II Aplication and BSP from Template

7. В SOPC Information File name указываем свой про процессор, у меня был D:\Work\Quartus\testBoot\cpuNew.sopcinfo

8. Задаем имя проекту, пусть будет bootLoader. Project template – Hello World. Жмём Finish

9. В проводнике идем в папку нашего загрузчика и удаляем файл hello_world.c. Добавляем в эту папку файлы: advanced_boot_copier.c и advanced_boot_copier.h

10. В Eclipse в Project Explorer правой кнопкой мыши по проекту bootLoader, в контекстном меню Refres.

В BSP редакторе указываем Uart для ввода/вывода jtag_uart. Отмечаем галочки как на рисунке в п.10 варианта I. 

Отметчаем enable_alt_load_copy_rodata

13. На вкладке Linker Script: .text на bootRom, остальные на onchip_memory.

    Жмём Generate, ждем окончания процесса и закрываем окно. 

    13. Если требуется дебажный вывод в uart то отмечаем в advanced_boot_copier.c

#define USING_JTAG_UART 1

иначе

#define USING_JTAG_UART 0 

14. У меня в устройстве есть линейка светодиодов. На разных процессах загрузки я зажигаю разные диоды, тем самым контролирую процесс без терминала. Если у вас есть индикация, то замените вывод индикации на свой или закоментируйте строки

 IOWR_ALTERA_AVALON_PIO_DATA(IOLED_BASE, 0x2);

15. Собираем проект bootLoader

16. Собираем *.hex. ПКМ по проекту в Project Explorer ->Make Targets->Build... Выбираем mem_init_install, жмём Build. Создастся *.hex с расширенным загрузчиком

17. Запускаем повторную компиляцию в Quartus-e. При этом наш hex с загрузчиком подцепится к *.sof файлу.

18. Программируем ПЛИС полученным *.sof файлом (я делал через квартусовский программатор)

 

Теперь займёмся рихтовкой рабочей программы/проекта

19. В BSP Editore я ни чего не менял. Оставил всё, как было без расширенного загрузчика. (см рисунок п. 17 варианта 1)

Жмём Generate, ждем окончания процесса и закрываем окно. 

20. Собираем рабочий проект — на выходе *.elf

Ну вот собственно и всё. Осталось залить все это в EPCS

21. В Eclipse открываем флеш-программатор NIOS II->Flash Programmer Создаем/откываем сеттинг файл и программируем. Образ из *.elf должен лечь сразу за *.sof, без смещений.

22. Выключаем плис. Включаем.

23. Если вы указали USING_JTAG_UART 1, то после включения плис, в терминале видим вывод.

Конструктор сайтов - uCoz