[Из песочницы] Еще немного RISC-V
Я занимаюсь программированием микроконтроллеров. И не только пишу для них программы, а по большей части программы для программаторов. И хотел поделиться небольшой радостью заработавшего мк. Вдруг кто-то сейчас мучается с gd32vfxx.
МК программирую самые разные. Это и всем известные stm, lattice, microchip, nuvoton, altera и т.д и экзотика типа azoteq, silicon works или freescale какого-нибудь 2003 года выпуска. Все они (ну, или почти все) разрабатывают свой собственный протокол, уникальный, которого нет больше ни у кого и он самый-самый лучший. Хотя и проходит под лозунгом универсального. И все это множество универсальных протоколов радует своим разнообразием. Если здесь и есть преувеличение, то совсем чуть.
Но сподвигла меня сюда написать вот эта недавняя статья. Ко мне как раз пришли образцы по разным семействам gd32 и, написав программы для программирования всех младших семейств, я пыхтел над семейством RISC-V. И увидел эту статью. Ну я и подумал, если кому-то интересен пересказ даташита, то может будет интересен и даташит по программированию программирования.
Младшие семейства программируются через JTAG и SWD (за мелким исключением, где есть только SWD. gd32f130xx, например). gd32vf, наоборот, имеет только JTAG. Но JTAG или SWD — это только инструмент. Вколачивание этими инструментами происходит совсем по-разному. Если про gd32f можно почитать ARM Debug Interface Architecture Specification и там все довольно ясно описано, то про gd32vf размазано в RISC-V External Debug Support и The RISC-V Instruction Set Manual. И эти два труда с полпинка не осилишь. У последнего еще есть подзаголовок Volume II. Это насторожило. Значит есть еще свинья с номером 1 и, возможно, с номерами 3 и 4.
Согласно RISC-V External Debug Support доступ к регистрам можно осуществить двумя способами:
- Using Abstract Command
- Using Program Buffer
К памяти тремя:
- Using System Bus Access (у GD32VF отсутствует)
- Using Program Buffer
- Using Abstract Memory Access
Так как System Bus Access у GD32VF нет (биты «system bus accesses are supported» в регистре sbcs), а использовать программный буфер и писать туда assembler нет никакой радости, то очень удачно есть прекрасный способ обойтись командами. Сначала мне было совершенно непонятно, откуда эти чертовы умники берут номер регистра (Number of the register to access). В описании значения regno гордо значится: Number of the register to access, as described in Table 3.3.
Но где какой конкретно. Но потом я их обнаружил в соседнем даташите, упомянутом выше (The RISC-V Instruction Set Manual. Том 2) и солнце засияло.
Итак все заработало. Все действительно оказалось удобнее, чем у gd32f. С точки зрения залить в него код. Но это было только начало. Теперь мне нужно было написать для него монитор. Чтобы было еще быстрее, чем быстро. IAR не дал мне скачать с него свой WORKBENCH, хотя хвастался им вовсю. Я так и не нашел место, где нажать кнопку и скачать. Главный Китайский Менеджер, который присылал образцы, сказал, что они пользуют NucleiStudio и я скачал это и поставил. Мне казалось, что самая неудобная вещь, которой я пользовался — это коромысло. Я не понимаю, как бырышни прошлого носили в нем воду и ходили потом сухими. Я был мокрый по самую макушку. Но NucleiStudio перещеголяло коромысло. В общем, после долгих мучений я умудрился распихать данные и функцию в нужные места памяти. Я уверен, что можно сделать это более изящно, но меня уже не хватило.
Выглядит это так.
Нужно найти оригинальный скрипт (я его нашел где-то в недрах этого eсlipse’а, будь он неладен), который содержит кучу непонятных каракулей и добавить туда описание нужных адресов
. = 0x20000000;
.data_sect : { *(.data_sect) }
. = 0x20000400;
.a_sect : { *(.a_sect) }
. = 0x20000500;
.f_sect : { *(.f_sect) }
Все-таки насколько IAR’овский *.icf файл выглядит куда понятнее и проще! Но это дело привычки, наверное. Когда я искал этот злосчастный файл, Гугл меня все время уверял, что нет ничего мощнее и крепче и круче и гибче, чем линк скрипт. Возможно, Но я намучился. Ну да ладно. Распихано.
Тепер мне нужно только переставить PC и все заработает со страшной скоростью. Но монитор все равно не работал. И теперь абзац, ради которого я все это затеял. Который поможет будущим исследователям RISC-V-чуда.
Вот он.
Чтобы переставить PC нужно просто написать его значение в регистр dpc и потом при старте hart’а значение скопируется в PC. До этого места программа уже написала и прочитала кучу других регистров. С большим успехом, надо признать. А монитор не работает. Как оказалось, чтобы написать в dpc нужно туда записать, а потом оттуда прочитать. Почему это так, я не знаю. Я прочел еще раз все документацию и «с волнением следил за судьбой героев». Но так и не нашел почему это так.
После этого все заработало. Единственное неудобство, чтобы прочитать что-то из памяти, нужно останавливать hart, а потом опять запускать. Это не очень удобно, но не страшно. Например, чтобы узнать, как там себя чувствует монитор и закончил ли он работу, нужно остановить hart, прочитать нужную память и, если нужно, запустить снова.
Надеюсь, что параграф про dpc сэкономит кому-нибудь пару часов времени и можно будет ничего не делать все это сэкономленное время.