Из любого описания на популярные FPGA известно, что для хранения их конфигураций используются специальные микросхемы – конфигураторы. В комментариях меня поправили, что потихоньку набирают популярность и FPGA, где это не требуется, но пока многие делают разработки именно на классике, где нужен конфигуратор, и с этим надо считаться. Например, для Altera Cyclone используются микросхемы EPCS. Ниже схема от типичной макетной платы с кристаллом семейства Cyclone IV. На ней мы видим конфигуратор EPCS16. Всё бы ничего, но традиционно эти конфигураторы достаточно дороги, поэтому хотелось бы использовать что-нибудь подешевле.
Подробности в длиннющем тексте ниже. Если же очень интересно, но лень читать так много букв, то можно упростить задачу, посмотрев подробное 20-минутное видео.
Итак, вернёмся к нашей проблеме.
![](https://habrastorage.org/r/w1560/webt/2v/mp/_r/2vmp_rrzfryetaeutfl6gkeczfa.png)
Если повертеть в руках ту самую макетную плату с кристаллом семейства Cyclone IV, то мы увидим очень удивительную вещь.
Вот она, ПЛИСина, а вот конфигурационная ПЗУ:
![](https://habrastorage.org/r/w1560/webt/gh/4g/w3/gh4gw3g-lvarghjfy2yltcdcsxw.png)
Как ни странно, это никакой не EPCS, а обычная 25-тая флешка. Такие флешки стоят дёшево и продаются достаточно много у кого.
Но, как говорится, не все йогурты одинаково полезны. В частности, наши заказчики на радостях закупили подобные флешки, припаяли на плату и получили глобальную проблему. Заходим в программатор, грузим файл, подготовленный для прошивки, начинаем его прошивать и получаем ошибку:
![](https://habrastorage.org/r/w1560/webt/ai/r7/xz/air7xzoggo7ae-lmfdmvhxdsqug.png)
Вот сообщение об ошибке:
![](https://habrastorage.org/r/w1560/webt/mg/4y/xs/mg4yxsb4-pjbl4wsaaxbl-y4cvg.png)
Error (209025): Can't recognize silicon ID for device 1. A device's silicon ID is different from its JTAG ID. Verify that all cables are securely connected, select a different device, or check the power on the target system. Make sure the device pins are connected and configured correctly.
Не опознан идентификатор устройства. То есть у флешки неизвестный идентификатор с точки зрения квартуса. Конкретно у наших заказчиков были закуплены кристаллы 25P32, которые вообще не поддерживаются в принципе, но в жизни может быть и более приземлённая ситуация. В частности, на фото выше припаяна флешка от ST, а определяется она как MICRON. Китайские продавцы и не такое могут намаркировать, а когда партия закуплена и не работает – что можно сделать?
Я полез на форумы. Все русскоязычные, какие удалось осмотреть, пестрели обсуждениями, у каких поставщиков и что следует брать, чтобы не напороться на подобную проблему. Но в нашем случае никто покупать новую партию не хотел. В англоязычных источниках удалось найти лишь одну статью с решением, но в современной среде Quartus Prime данное решение «в лоб» не сработает. Поэтому мы взялись задокументировать данную проблему для современной среды, на русском языке и в видео формате.
Итак, как вообще программируется ПЗУшина?
В ПЛИС вливается специальная конфигурация, по которой становится возможно по JTAG достукиваться до флешки. И потом, пользуясь этой конфигурацией, мы заливаем данные. Оказывается, можно сделать подобную конфигурацию, которая даст нам доступ к флешке и даст прошить, невзирая на ID, причём при этом не придётся писать ни строчки собственного кода, да и утилиты все будут использоваться из поставки Quartus Prime (либо Qiartus II, кто пользуется старыми версиями среды разработки).
То есть нам предстоит сделать 3 шага:
Давайте этим и займёмся. Начнём с разработки собственной «прошивки» (она же конфигурация), не написав при этом ни одной строчки своего кода.
Заходим в Quartus:
![](https://habrastorage.org/r/w1560/webt/ha/mv/bg/hamvbg02ebfvu7qpsb9ng7ievpm.png)
Создаём новый проект:
![](https://habrastorage.org/r/w1560/webt/gb/c_/1s/gbc_1sfqsy6hzd2o9lhd4ttgxuo.png)
Назовём его, скажем, flasher:
![](https://habrastorage.org/r/w1560/webt/jf/zu/uh/jfzuuhpvskzogswobbhefq1cmfo.png)
Это имя следует запомнить – оно нам ещё понадобится.
Создаём пустой проект, семейство у меня Cyclone IV E, используемый в проекте кристалл вот такой:
![](https://habrastorage.org/r/w1560/webt/ut/zg/we/utzgweqh88n_njaazeimn2njgzg.png)
Так. Заканчиваем создание проекта, нажимаем Finish. Проект создан. Как уже было сказано, мы не пишем ни одной строчки своего кода. Но заставить среду сделать что-то всё-таки нужно. Для этого идем в Tools – Platform Designer.
Вот он загрузился. Конкретно у меня в этой плате кварц на 60 Гц, поэтому я подправлю установки частоты:
![](https://habrastorage.org/r/w1560/webt/wv/ke/ss/wvkessebx-sl6nnlimdmghpmkaw.png)
То, что я делаю сейчас, мы делаем один раз для платформы. То есть если изготовлена какая-то плата, то вот этот загрузчик будет для нее для любого проекта работать.
Я подготовил кварц – теперь мы ставим процессор. В библиотеке слева находим «Процессоры и Периферия», «Встроенные процессоры» и затем – Nios II Processor:
![](https://habrastorage.org/r/w1560/webt/zr/bo/0m/zrbo0mowty04wddiwiywlnkdn2i.png)
Выбираем его и нажимаем «Добавить».
В открывшемся окне, в свойствах, выбираем Nios II/e, потому что он абсолютно бесплатный и к нему не нужна никакая лицензия.
![](https://habrastorage.org/r/w1560/webt/x_/se/ng/x_sengjmqxpdymm3mdn17lpuo2o.png)
Ошибки сообщают нам, что не настроены вектора. Мы не собираемся ничего программировать для этого процессора. Поэтому вектора мы просто направляем в первое попавшееся место из списка:
![](https://habrastorage.org/r/w1560/webt/mf/5o/al/mf5oaltsdihzbv-txbfjltwzwme.png)
Нам очень важно, чтобы у процессора работал модуль JTAG:
![](https://habrastorage.org/r/w1560/webt/o9/ck/od/o9ckodfmxwztbobu77eutscze8i.png)
После наших манипуляций ошибки ушли.
![](https://habrastorage.org/r/w1560/webt/ka/rz/-t/karz-tchhpiuyndteemhkljraea.png)
С процессором закончено. Нажимаем Finish и двигаемся дальше.
Теперь мы идём в основные функции. Здесь есть конфигураторы:
![](https://habrastorage.org/r/w1560/webt/gi/ha/px/gihapxxslh10ja85vf_nikamdms.png)
Раскрываем список конфигураторов – ближе к концу находим EPCS-ки – наши конфигураторы:
![](https://habrastorage.org/r/w1560/webt/ar/uv/zv/aruvzv-nz_olj7h3z1xo8yrrgxi.png)
Всё оставляем по умолчанию:
![](https://habrastorage.org/r/w1560/webt/vg/ai/20/vgai205_qg68qscsurbvhyhfwxq.png)
Теперь начинаем их связывать. Тактовые сигналы пропускаем на оба модуля, сигнал сброса пропускаем на оба модуля. Сигнал сброса, выходящий из аппаратуры JTAG, – debug_reset_request – мы также пропускаем на оба модуля. Дальше data_master пропускаем на оба модуля. Instruction_master пропускаем только на отладчик. И запрос на прерывания мы также пропускаем:
![](https://habrastorage.org/r/w1560/webt/5o/bu/ak/5obuakh-ax08zigxd4ixc0g-kay.png)
Дальше мы переходим к внешним ножкам – external. Экспортируем их, для чего дважды щелкаем в поле Double-click to export:
![](https://habrastorage.org/r/w1560/webt/ng/gd/26/nggd26ho4r9mpf7qqdm5cmetj8u.png)
Для простоты назову epcs, чтобы меньше длина была:
![](https://habrastorage.org/r/w1560/webt/mh/yo/fd/mhyofdyjdfssyjas2jmyla3lwvq.png)
Теперь привычным движением руки назначаем базовые адреса:
![](https://habrastorage.org/r/w1560/webt/24/fn/_m/24fn_mx3bbca-gmh5fl7yfqukiy.png)
И назначаем прерывания:
![](https://habrastorage.org/r/w1560/webt/pn/95/wa/pn95wa16adrxhw43f0ka6v201kg.png)
Автоматически назначенный адрес для нашего flash-контроллера – 0×800 – нам следует запомнить:
![](https://habrastorage.org/r/w1560/webt/io/rh/zl/iorhzlp4ghtrss3lvbh-52lxq08.png)
Он нам еще пригодится. А всё остальное, в принципе, само сделалось и будет работать.
Сейчас очень важно, так как мы не собираемся писать ни одной строчки своего кода, чтобы имя процессорной системы совпадало с именем проекта. Проект у нас был flasher.
Сохраняем систему, называем flasher:
![](https://habrastorage.org/r/w1560/webt/bu/yy/o-/buyyo-fp8a5qmat3ndafgqdxvrs.png)
Именно тогда у нас топ-модуль будет именно этот процессор, и поэтому нам не придется ничего делать.
Следующий наш шаг:
![](https://habrastorage.org/r/w1560/webt/dt/f6/w8/dtf6w8yqknpwsqpj42j5tqjaovc.png)
Все оставляем по умолчанию, потому что мы просто пользуемся тем, что уже готово:
![](https://habrastorage.org/r/w1560/webt/pa/fg/x6/pafgx67xetykwso_hb-mksg16f8.png)
Завершаем:
![](https://habrastorage.org/r/w1560/webt/p4/tu/hx/p4tuhxrfvz9s454ziovlg7il7pm.png)
Появилось сообщение о том, что нам надо не забыть добавить файл в проект:
![](https://habrastorage.org/r/w1560/webt/nr/zz/xv/nrzzxvax1r2o0di3iqrnguspozw.png)
Давайте добавим. Идём в Project – Add/Remove Files in Project:
![](https://habrastorage.org/r/w1560/webt/qs/lj/uh/qsljuh_hwtmhf6kfk8goyq5lgbc.png)
Находим наш файл на компьютере.
![](https://habrastorage.org/r/w1560/webt/g7/3p/5j/g73p5juvuptyhjmqtehwwud-4uy.png)
Вот он, наш файл flasher с расширением qsys.
![](https://habrastorage.org/r/w1560/webt/5i/a7/zf/5ia7zfoailscfs-dfahto2pvotc.png)
Добавили его:
![](https://habrastorage.org/r/w1560/webt/o0/uj/l1/o0ujl1nw_1uqusr897f5witkfqw.png)
Теперь делаем черновую компиляцию:
![](https://habrastorage.org/r/w1560/webt/5_/pc/xu/5_pcxuwywovccnhbxf0mfezcfdi.png)
Она завершилась успешно.
![](https://habrastorage.org/r/w1560/webt/rh/p5/k7/rhp5k7anat1xu-t_u9rmoz-o8rk.png)
Теперь, когда она прошла, мы можем назначить выводы. Идем в Pin Planner:
![](https://habrastorage.org/r/w1560/webt/or/v7/8r/orv78rt4yao5hbihp_eeh-na6t8.png)
JTAG-овские ножки нам назначать не надо – мы назначаем ножки флешки.
![](https://habrastorage.org/r/w1560/webt/cg/t6/s9/cgt6s9zmrgnvjfwbdb2ognb95u8.png)
Для каждой микросхемы, для каждого корпуса они свои. В принципе, можно смотреть документацию на микросхему или на свою плату. Например, вот у нас двенадцатая ножка DCLK:
![](https://habrastorage.org/r/w1560/webt/om/ws/my/omwsmy50cr1ld3dklygkndmpr6y.png)
У меня список уже подготовлен – просто вобьём по нему.
Так, epcs_data0, LOCATION: PIN13, epcs_dclk – PIN12, epcs_sce – PIN8, epcs_sdo – PIN6. И конкретно на плате наших заказчиков тактовая частота PIN24, reset_n – PIN88.
![](https://habrastorage.org/r/w1560/webt/lg/ea/hq/lgeahqv-jh2qyycna4ewbtfj5as.png)
Ножки назначили. Запускаем компиляцию. Выдаются ошибки:
![](https://habrastorage.org/r/w1560/webt/4_/lp/7f/4_lp7fufsohakbflxfm_orvlaw0.png)
Все потому, что я сделал вид, что забыл произвести очень важную настройку. Мы сейчас подключили флешку к служебным линиям. И, по окончании конфигурирования, часть этих линий вообще не доступна, а часть – используется для служебных целей. Поэтому нам выдали сообщения, что у нас конфликт:
![](https://habrastorage.org/r/w1560/webt/ey/hr/zo/eyhrzog5z-s8j2tqnjtofutkgve.png)
Чтобы это устранить, идем в Assignments – Device:
![](https://habrastorage.org/r/w1560/webt/pd/po/wy/pdpowy05eudqvyurrm8xxzse9pa.png)
Device and Pin Options:
![](https://habrastorage.org/r/w1560/webt/89/8q/uv/898quviagn6ofboxifsweq6ioc0.png)
Здесь выбираем Dual-Purpose Pins. И все эти линии по окончании программирования мы просим сделать обычными линиями ввода-вывода:
![](https://habrastorage.org/r/w1560/webt/f3/vq/vb/f3vqvbwtzjjf8va5ugluvylx83y.png)
Жмём OK, запускаем компилятор. И всё получилось.
![](https://habrastorage.org/r/w1560/webt/hr/s1/n3/hrs1n3e9mufdlnsi0na47ai6rwe.png)
Итак, первый шаг завершен. У нас получилась конфигурация, через которую мы можем достукиваться до флешки.
Теперь наша задача – сделать файл, с помощью которого система нашу флешку будет опознавать.
Идём во все программы, Intel FPGA (для старых версий это будет Altera), Nios II Command Shell.
![](https://habrastorage.org/r/w1560/webt/if/dh/87/ifdh87cify7wzy5dybr_e8sgykk.png)
Здесь мы идём в каталог, где мы только что все собрали. При этом не забываем, что слэши тут должны быть не обратные, а прямые, и что результирующий файл flasher.sof лежит в каталоге output_files:
![](https://habrastorage.org/r/w1560/webt/v2/gg/0i/v2gg0isguijykujgjva9oia_8kq.png)
Теперь начинаем произносить волшебные заклинания. Итак, нам нужно влить только что сформированную конфигурацию. Для этого мы пишем:
nios2-configure-sof flasher.sof
и нажимаем Enter:
![](https://habrastorage.org/r/w1560/webt/4m/fq/ub/4mfquby1v3lz9m9gwurmbc1gbge.png)
Файл залился – теперь у нас есть доступ к флешке. Для того, чтобы определить все, что касается доступа к флешке, нам нужно запустить следующую программу:
nios2-flash-programmer --epcs --base=0x800--debug.
где 0x800 – это тот самый адрес, который автоматически назначился на блок epcs и который надо было не забыть.
![](https://habrastorage.org/r/w1560/webt/qn/8o/jz/qn8ojzeakabrjq_a4uaobn6y5ri.png)
Нажимаем Enter:
![](https://habrastorage.org/r/w1560/webt/0s/kb/z5/0skbz5nix9cmp1rq2tealijuvbs.png)
Что он нам сказал? Он попытался осмотреть ту область, которую мы назвали. И по смещению 0 по адресу 800 не нашёл ничего. По адресу с00 он нашёл то, что нам требуется:
![](https://habrastorage.org/r/w1560/webt/qy/zy/g4/qyzyg404zn6gay5wccrocvuhajg.png)
Теперь мы запоминаем не просто базовый адрес 800, а конкретный адрес с00 – в дальнейшем работа будет вестись с ним.
Он нашел флешку, ее идентификатор 202016, но сказал, что понятия не имеет, что с ней делать, потому что её не знает.
Вот документация на нашу флешку:
![](https://habrastorage.org/r/w1560/webt/qf/dh/oh/qfdhoh9vwfc4c5wrf-ucxmlapaw.png)
![](https://habrastorage.org/r/w1560/webt/1n/3m/fn/1n3mfnsa1lgp_rm9s8l7jpbj9we.png)
Её полный идентификатор 202016 – именно его она возвращает в ответ на команду запроса своего кода.
Так что всё правильно – флешка нашлась правильная.
Он нам говорит, что должен быть файл с секцией EPCS-202016.
Замечательно. Изменить – Пометить. Выделяем её имя и берём в буфер обмена.
![](https://habrastorage.org/r/w1560/webt/vp/9s/bk/vp9sbkumu56mylijquelfbpoko0.png)
![](https://habrastorage.org/r/w1560/webt/r-/c4/o0/r-c4o0hch6gqiomsvzpvffmkfsi.png)
Создаём файл ovr.txt и секцию с именем, которое только что скопировали:
![](https://habrastorage.org/r/w1560/webt/e_/ad/1e/e_ad1ey45zwng8opixfzptqobug.png)
В документации на нашу флешку, в разделе Memory Map, мы можем посмотреть, что она состоит из 64 секторов. Каждый сектор имеет размер 64 Кбайт, потому что от 0000 до FFFF.
![](https://habrastorage.org/r/w1560/webt/ty/h1/67/tyh167quppjepvcwismak8uzdd8.png)
Поэтому файл с конфигурацией, который мы только что создали, должен выглядеть вот так:
![](https://habrastorage.org/r/w1560/webt/1s/jr/1-/1sjr1-tyxfvebxur4np3g89ftcm.png)
64 сектора размером по 64 Кбайта, или 65536 байта, каждый.
Второй шаг готов. У нас имеются файлы flasher.sof и ovr.txt, который содержит конфигурацию флешки.
Переходим к третьему шагу.
Напомню, что рабочий проект был USB16_my. А файл для прошивания назывался Test1.sof. Мы копируем flasher.sof и ovr.txt к нему.
Теперь мы закончили все подготовительные шаги – приступаем к непосредственным боевым действиям. Чтобы подчеркнуть отсутствие связи между подготовкой и работой, я войду в терминал ещё раз, как будто это происходит на следующий день, через неделю, через месяц или через любой срок после завершения подготовки.
![](https://habrastorage.org/r/w1560/webt/aa/zb/63/aazb63_mfjiealxzyobm_nflcz8.png)
Первое, что нам нужно сделать, это сформировать выходной файл. Потому что файл sof не шьется в ПЗУ – шьется немного другой файл. Для того чтобы его сформировать, мы пишем:
![](https://habrastorage.org/r/w1560/webt/dt/r0/xw/dtr0xw_9fdn7klalwe-a8w510ga.png)
Получился файл Test1.flash:
![](https://habrastorage.org/r/w1560/webt/u4/uy/n6/u4uyn6ndmq_lmpxggev8rytgyoq.png)
Теперь, чисто формально, пришёл черёд действий, которые должны делать сборщики плат. В первую очередь, они точно так же должны загрузить наш flasher, то есть:
![](https://habrastorage.org/r/w1560/webt/bm/ew/fg/bmewfgw--kdgzsbm_ojzwk_nfma.png)
После чего они должны прошить ПЗУ:
![](https://habrastorage.org/r/w1560/webt/cy/gy/jj/cygyjj0h44u-genhaerjdrpi-uo.png)
Собственно, на этом всё. Задача решена, флешка прошита – можно ее использовать, даже несмотря на то, что основной путь говорил про несовпадение ID-шников. И совершенно не требуется покупать дорогие конфигураторы или искать, у какого поставщика 25-е флешки имеют совместимые ID. Мы подготовили «прошивальщик» для нашей конкретной платы (и любых других, где стоит такой же кристалл и Reset с генератором подключены к тому же выводу), мы подготовили текстовый файл для конфигуратора, после чего влили «прошивку», пользуясь утилитами, идущими в комплекте поставки штатной среды Quartus Prime (они же шли и со средой Quartus II).
Подробности в длиннющем тексте ниже. Если же очень интересно, но лень читать так много букв, то можно упростить задачу, посмотрев подробное 20-минутное видео.
Итак, вернёмся к нашей проблеме.
![](https://habrastorage.org/webt/2v/mp/_r/2vmp_rrzfryetaeutfl6gkeczfa.png)
Если повертеть в руках ту самую макетную плату с кристаллом семейства Cyclone IV, то мы увидим очень удивительную вещь.
Вот она, ПЛИСина, а вот конфигурационная ПЗУ:
![](https://habrastorage.org/webt/gh/4g/w3/gh4gw3g-lvarghjfy2yltcdcsxw.png)
Как ни странно, это никакой не EPCS, а обычная 25-тая флешка. Такие флешки стоят дёшево и продаются достаточно много у кого.
Но, как говорится, не все йогурты одинаково полезны. В частности, наши заказчики на радостях закупили подобные флешки, припаяли на плату и получили глобальную проблему. Заходим в программатор, грузим файл, подготовленный для прошивки, начинаем его прошивать и получаем ошибку:
![](https://habrastorage.org/webt/ai/r7/xz/air7xzoggo7ae-lmfdmvhxdsqug.png)
Вот сообщение об ошибке:
![](https://habrastorage.org/webt/mg/4y/xs/mg4yxsb4-pjbl4wsaaxbl-y4cvg.png)
Error (209025): Can't recognize silicon ID for device 1. A device's silicon ID is different from its JTAG ID. Verify that all cables are securely connected, select a different device, or check the power on the target system. Make sure the device pins are connected and configured correctly.
Не опознан идентификатор устройства. То есть у флешки неизвестный идентификатор с точки зрения квартуса. Конкретно у наших заказчиков были закуплены кристаллы 25P32, которые вообще не поддерживаются в принципе, но в жизни может быть и более приземлённая ситуация. В частности, на фото выше припаяна флешка от ST, а определяется она как MICRON. Китайские продавцы и не такое могут намаркировать, а когда партия закуплена и не работает – что можно сделать?
Я полез на форумы. Все русскоязычные, какие удалось осмотреть, пестрели обсуждениями, у каких поставщиков и что следует брать, чтобы не напороться на подобную проблему. Но в нашем случае никто покупать новую партию не хотел. В англоязычных источниках удалось найти лишь одну статью с решением, но в современной среде Quartus Prime данное решение «в лоб» не сработает. Поэтому мы взялись задокументировать данную проблему для современной среды, на русском языке и в видео формате.
Итак, как вообще программируется ПЗУшина?
В ПЛИС вливается специальная конфигурация, по которой становится возможно по JTAG достукиваться до флешки. И потом, пользуясь этой конфигурацией, мы заливаем данные. Оказывается, можно сделать подобную конфигурацию, которая даст нам доступ к флешке и даст прошить, невзирая на ID, причём при этом не придётся писать ни строчки собственного кода, да и утилиты все будут использоваться из поставки Quartus Prime (либо Qiartus II, кто пользуется старыми версиями среды разработки).
То есть нам предстоит сделать 3 шага:
- Сделать конфигурацию, которая достукивается до флешки.
- Написать файл, в котором флешка описывается.
- Прошить.
Давайте этим и займёмся. Начнём с разработки собственной «прошивки» (она же конфигурация), не написав при этом ни одной строчки своего кода.
Заходим в Quartus:
![](https://habrastorage.org/webt/ha/mv/bg/hamvbg02ebfvu7qpsb9ng7ievpm.png)
Создаём новый проект:
![](https://habrastorage.org/webt/gb/c_/1s/gbc_1sfqsy6hzd2o9lhd4ttgxuo.png)
Назовём его, скажем, flasher:
![](https://habrastorage.org/webt/jf/zu/uh/jfzuuhpvskzogswobbhefq1cmfo.png)
Это имя следует запомнить – оно нам ещё понадобится.
Создаём пустой проект, семейство у меня Cyclone IV E, используемый в проекте кристалл вот такой:
![](https://habrastorage.org/webt/ut/zg/we/utzgweqh88n_njaazeimn2njgzg.png)
Так. Заканчиваем создание проекта, нажимаем Finish. Проект создан. Как уже было сказано, мы не пишем ни одной строчки своего кода. Но заставить среду сделать что-то всё-таки нужно. Для этого идем в Tools – Platform Designer.
Вот он загрузился. Конкретно у меня в этой плате кварц на 60 Гц, поэтому я подправлю установки частоты:
![](https://habrastorage.org/webt/wv/ke/ss/wvkessebx-sl6nnlimdmghpmkaw.png)
То, что я делаю сейчас, мы делаем один раз для платформы. То есть если изготовлена какая-то плата, то вот этот загрузчик будет для нее для любого проекта работать.
Я подготовил кварц – теперь мы ставим процессор. В библиотеке слева находим «Процессоры и Периферия», «Встроенные процессоры» и затем – Nios II Processor:
![](https://habrastorage.org/webt/zr/bo/0m/zrbo0mowty04wddiwiywlnkdn2i.png)
Выбираем его и нажимаем «Добавить».
В открывшемся окне, в свойствах, выбираем Nios II/e, потому что он абсолютно бесплатный и к нему не нужна никакая лицензия.
![](https://habrastorage.org/webt/x_/se/ng/x_sengjmqxpdymm3mdn17lpuo2o.png)
Ошибки сообщают нам, что не настроены вектора. Мы не собираемся ничего программировать для этого процессора. Поэтому вектора мы просто направляем в первое попавшееся место из списка:
![](https://habrastorage.org/webt/mf/5o/al/mf5oaltsdihzbv-txbfjltwzwme.png)
Нам очень важно, чтобы у процессора работал модуль JTAG:
![](https://habrastorage.org/webt/o9/ck/od/o9ckodfmxwztbobu77eutscze8i.png)
После наших манипуляций ошибки ушли.
![](https://habrastorage.org/webt/ka/rz/-t/karz-tchhpiuyndteemhkljraea.png)
С процессором закончено. Нажимаем Finish и двигаемся дальше.
Теперь мы идём в основные функции. Здесь есть конфигураторы:
![](https://habrastorage.org/webt/gi/ha/px/gihapxxslh10ja85vf_nikamdms.png)
Раскрываем список конфигураторов – ближе к концу находим EPCS-ки – наши конфигураторы:
![](https://habrastorage.org/webt/ar/uv/zv/aruvzv-nz_olj7h3z1xo8yrrgxi.png)
Всё оставляем по умолчанию:
![](https://habrastorage.org/webt/vg/ai/20/vgai205_qg68qscsurbvhyhfwxq.png)
Теперь начинаем их связывать. Тактовые сигналы пропускаем на оба модуля, сигнал сброса пропускаем на оба модуля. Сигнал сброса, выходящий из аппаратуры JTAG, – debug_reset_request – мы также пропускаем на оба модуля. Дальше data_master пропускаем на оба модуля. Instruction_master пропускаем только на отладчик. И запрос на прерывания мы также пропускаем:
![](https://habrastorage.org/webt/5o/bu/ak/5obuakh-ax08zigxd4ixc0g-kay.png)
Дальше мы переходим к внешним ножкам – external. Экспортируем их, для чего дважды щелкаем в поле Double-click to export:
![](https://habrastorage.org/webt/ng/gd/26/nggd26ho4r9mpf7qqdm5cmetj8u.png)
Для простоты назову epcs, чтобы меньше длина была:
![](https://habrastorage.org/webt/mh/yo/fd/mhyofdyjdfssyjas2jmyla3lwvq.png)
Теперь привычным движением руки назначаем базовые адреса:
![](https://habrastorage.org/webt/24/fn/_m/24fn_mx3bbca-gmh5fl7yfqukiy.png)
И назначаем прерывания:
![](https://habrastorage.org/webt/pn/95/wa/pn95wa16adrxhw43f0ka6v201kg.png)
Автоматически назначенный адрес для нашего flash-контроллера – 0×800 – нам следует запомнить:
![](https://habrastorage.org/webt/io/rh/zl/iorhzlp4ghtrss3lvbh-52lxq08.png)
Он нам еще пригодится. А всё остальное, в принципе, само сделалось и будет работать.
Сейчас очень важно, так как мы не собираемся писать ни одной строчки своего кода, чтобы имя процессорной системы совпадало с именем проекта. Проект у нас был flasher.
Сохраняем систему, называем flasher:
![](https://habrastorage.org/webt/bu/yy/o-/buyyo-fp8a5qmat3ndafgqdxvrs.png)
Именно тогда у нас топ-модуль будет именно этот процессор, и поэтому нам не придется ничего делать.
Следующий наш шаг:
![](https://habrastorage.org/webt/dt/f6/w8/dtf6w8yqknpwsqpj42j5tqjaovc.png)
Все оставляем по умолчанию, потому что мы просто пользуемся тем, что уже готово:
![](https://habrastorage.org/webt/pa/fg/x6/pafgx67xetykwso_hb-mksg16f8.png)
Завершаем:
![](https://habrastorage.org/webt/p4/tu/hx/p4tuhxrfvz9s454ziovlg7il7pm.png)
Появилось сообщение о том, что нам надо не забыть добавить файл в проект:
![](https://habrastorage.org/webt/nr/zz/xv/nrzzxvax1r2o0di3iqrnguspozw.png)
Давайте добавим. Идём в Project – Add/Remove Files in Project:
![](https://habrastorage.org/webt/qs/lj/uh/qsljuh_hwtmhf6kfk8goyq5lgbc.png)
Находим наш файл на компьютере.
![](https://habrastorage.org/webt/g7/3p/5j/g73p5juvuptyhjmqtehwwud-4uy.png)
Вот он, наш файл flasher с расширением qsys.
![](https://habrastorage.org/webt/5i/a7/zf/5ia7zfoailscfs-dfahto2pvotc.png)
Добавили его:
![](https://habrastorage.org/webt/o0/uj/l1/o0ujl1nw_1uqusr897f5witkfqw.png)
Теперь делаем черновую компиляцию:
![](https://habrastorage.org/webt/5_/pc/xu/5_pcxuwywovccnhbxf0mfezcfdi.png)
Она завершилась успешно.
![](https://habrastorage.org/webt/rh/p5/k7/rhp5k7anat1xu-t_u9rmoz-o8rk.png)
Теперь, когда она прошла, мы можем назначить выводы. Идем в Pin Planner:
![](https://habrastorage.org/webt/or/v7/8r/orv78rt4yao5hbihp_eeh-na6t8.png)
JTAG-овские ножки нам назначать не надо – мы назначаем ножки флешки.
![](https://habrastorage.org/webt/cg/t6/s9/cgt6s9zmrgnvjfwbdb2ognb95u8.png)
Для каждой микросхемы, для каждого корпуса они свои. В принципе, можно смотреть документацию на микросхему или на свою плату. Например, вот у нас двенадцатая ножка DCLK:
![](https://habrastorage.org/webt/om/ws/my/omwsmy50cr1ld3dklygkndmpr6y.png)
У меня список уже подготовлен – просто вобьём по нему.
Так, epcs_data0, LOCATION: PIN13, epcs_dclk – PIN12, epcs_sce – PIN8, epcs_sdo – PIN6. И конкретно на плате наших заказчиков тактовая частота PIN24, reset_n – PIN88.
![](https://habrastorage.org/webt/lg/ea/hq/lgeahqv-jh2qyycna4ewbtfj5as.png)
Ножки назначили. Запускаем компиляцию. Выдаются ошибки:
![](https://habrastorage.org/webt/4_/lp/7f/4_lp7fufsohakbflxfm_orvlaw0.png)
Все потому, что я сделал вид, что забыл произвести очень важную настройку. Мы сейчас подключили флешку к служебным линиям. И, по окончании конфигурирования, часть этих линий вообще не доступна, а часть – используется для служебных целей. Поэтому нам выдали сообщения, что у нас конфликт:
![](https://habrastorage.org/webt/ey/hr/zo/eyhrzog5z-s8j2tqnjtofutkgve.png)
Чтобы это устранить, идем в Assignments – Device:
![](https://habrastorage.org/webt/pd/po/wy/pdpowy05eudqvyurrm8xxzse9pa.png)
Device and Pin Options:
![](https://habrastorage.org/webt/89/8q/uv/898quviagn6ofboxifsweq6ioc0.png)
Здесь выбираем Dual-Purpose Pins. И все эти линии по окончании программирования мы просим сделать обычными линиями ввода-вывода:
![](https://habrastorage.org/webt/f3/vq/vb/f3vqvbwtzjjf8va5ugluvylx83y.png)
Жмём OK, запускаем компилятор. И всё получилось.
![](https://habrastorage.org/webt/hr/s1/n3/hrs1n3e9mufdlnsi0na47ai6rwe.png)
Итак, первый шаг завершен. У нас получилась конфигурация, через которую мы можем достукиваться до флешки.
Теперь наша задача – сделать файл, с помощью которого система нашу флешку будет опознавать.
Идём во все программы, Intel FPGA (для старых версий это будет Altera), Nios II Command Shell.
![](https://habrastorage.org/webt/if/dh/87/ifdh87cify7wzy5dybr_e8sgykk.png)
Здесь мы идём в каталог, где мы только что все собрали. При этом не забываем, что слэши тут должны быть не обратные, а прямые, и что результирующий файл flasher.sof лежит в каталоге output_files:
![](https://habrastorage.org/webt/v2/gg/0i/v2gg0isguijykujgjva9oia_8kq.png)
Теперь начинаем произносить волшебные заклинания. Итак, нам нужно влить только что сформированную конфигурацию. Для этого мы пишем:
nios2-configure-sof flasher.sof
и нажимаем Enter:
![](https://habrastorage.org/webt/4m/fq/ub/4mfquby1v3lz9m9gwurmbc1gbge.png)
Файл залился – теперь у нас есть доступ к флешке. Для того, чтобы определить все, что касается доступа к флешке, нам нужно запустить следующую программу:
nios2-flash-programmer --epcs --base=0x800--debug.
где 0x800 – это тот самый адрес, который автоматически назначился на блок epcs и который надо было не забыть.
![](https://habrastorage.org/webt/qn/8o/jz/qn8ojzeakabrjq_a4uaobn6y5ri.png)
Нажимаем Enter:
![](https://habrastorage.org/webt/0s/kb/z5/0skbz5nix9cmp1rq2tealijuvbs.png)
Что он нам сказал? Он попытался осмотреть ту область, которую мы назвали. И по смещению 0 по адресу 800 не нашёл ничего. По адресу с00 он нашёл то, что нам требуется:
![](https://habrastorage.org/webt/qy/zy/g4/qyzyg404zn6gay5wccrocvuhajg.png)
Теперь мы запоминаем не просто базовый адрес 800, а конкретный адрес с00 – в дальнейшем работа будет вестись с ним.
Он нашел флешку, ее идентификатор 202016, но сказал, что понятия не имеет, что с ней делать, потому что её не знает.
Вот документация на нашу флешку:
![](https://habrastorage.org/webt/qf/dh/oh/qfdhoh9vwfc4c5wrf-ucxmlapaw.png)
![](https://habrastorage.org/webt/1n/3m/fn/1n3mfnsa1lgp_rm9s8l7jpbj9we.png)
Её полный идентификатор 202016 – именно его она возвращает в ответ на команду запроса своего кода.
Так что всё правильно – флешка нашлась правильная.
Он нам говорит, что должен быть файл с секцией EPCS-202016.
Замечательно. Изменить – Пометить. Выделяем её имя и берём в буфер обмена.
![](https://habrastorage.org/webt/vp/9s/bk/vp9sbkumu56mylijquelfbpoko0.png)
![](https://habrastorage.org/webt/r-/c4/o0/r-c4o0hch6gqiomsvzpvffmkfsi.png)
Создаём файл ovr.txt и секцию с именем, которое только что скопировали:
![](https://habrastorage.org/webt/e_/ad/1e/e_ad1ey45zwng8opixfzptqobug.png)
В документации на нашу флешку, в разделе Memory Map, мы можем посмотреть, что она состоит из 64 секторов. Каждый сектор имеет размер 64 Кбайт, потому что от 0000 до FFFF.
![](https://habrastorage.org/webt/ty/h1/67/tyh167quppjepvcwismak8uzdd8.png)
Поэтому файл с конфигурацией, который мы только что создали, должен выглядеть вот так:
![](https://habrastorage.org/webt/1s/jr/1-/1sjr1-tyxfvebxur4np3g89ftcm.png)
64 сектора размером по 64 Кбайта, или 65536 байта, каждый.
Второй шаг готов. У нас имеются файлы flasher.sof и ovr.txt, который содержит конфигурацию флешки.
Переходим к третьему шагу.
Напомню, что рабочий проект был USB16_my. А файл для прошивания назывался Test1.sof. Мы копируем flasher.sof и ovr.txt к нему.
Теперь мы закончили все подготовительные шаги – приступаем к непосредственным боевым действиям. Чтобы подчеркнуть отсутствие связи между подготовкой и работой, я войду в терминал ещё раз, как будто это происходит на следующий день, через неделю, через месяц или через любой срок после завершения подготовки.
![](https://habrastorage.org/webt/aa/zb/63/aazb63_mfjiealxzyobm_nflcz8.png)
Первое, что нам нужно сделать, это сформировать выходной файл. Потому что файл sof не шьется в ПЗУ – шьется немного другой файл. Для того чтобы его сформировать, мы пишем:
![](https://habrastorage.org/webt/dt/r0/xw/dtr0xw_9fdn7klalwe-a8w510ga.png)
Получился файл Test1.flash:
![](https://habrastorage.org/webt/u4/uy/n6/u4uyn6ndmq_lmpxggev8rytgyoq.png)
Теперь, чисто формально, пришёл черёд действий, которые должны делать сборщики плат. В первую очередь, они точно так же должны загрузить наш flasher, то есть:
![](https://habrastorage.org/webt/bm/ew/fg/bmewfgw--kdgzsbm_ojzwk_nfma.png)
После чего они должны прошить ПЗУ:
![](https://habrastorage.org/webt/cy/gy/jj/cygyjj0h44u-genhaerjdrpi-uo.png)
Собственно, на этом всё. Задача решена, флешка прошита – можно ее использовать, даже несмотря на то, что основной путь говорил про несовпадение ID-шников. И совершенно не требуется покупать дорогие конфигураторы или искать, у какого поставщика 25-е флешки имеют совместимые ID. Мы подготовили «прошивальщик» для нашей конкретной платы (и любых других, где стоит такой же кристалл и Reset с генератором подключены к тому же выводу), мы подготовили текстовый файл для конфигуратора, после чего влили «прошивку», пользуясь утилитами, идущими в комплекте поставки штатной среды Quartus Prime (они же шли и со средой Quartus II).