Comments 38
GPIOB_CTL0 = (GPIOB_CTL0 &~(0b1111<<(RLED*4))) | 0b0011 << (RLED*4);
будет выглядеть совсем по другому, что то вроде
PortB.Pin5=PinMode_Out+PinMode_OpenDrain;
хотя еще лучше
SetPinMode(PortB, Pin5, PinMode_Out_OpenDrain);
#define RLED B, 5, 1, GPIO_PP50
...
GPIO_config( RLED );
GPO_ON( RLED );
Это сишка курильщика. Здоровые атлеты используют K&R и KNF.
Ищите по полному имени gd32vf103cbt6. Там на Али какие-то проблемы с поиском
Если вы имеете в виду что приведенные в статье исходные коды непонятны без расшифровки, то да, надо будет не забыть сделать приложение с описанием инструкций.
Есть ли возможность как в ARM сохранять на стек или снимать с него сразу пачку регистров?
А вот это в статье описано. Собственно стека в RISCV нет, так что все манипуляции делаются ручками. Хотите чтобы рос вверх — пожалуйста, увеличивайте sp вместо уменьшения. Хотите вместо sp использовать, скажем, a5 — пожалуйста. Просто другие процедуры этого могут не понять. Как и компилятор Си.
Собственно стека в RISCV нет, так что все манипуляции делаются ручками.
Так же, как и нет всем привычной команды mov. В RISC-V пересылка содержимого одного регистра в другой делается через АЛУ, т.е. mov x1, x2 является частным сучаем инструкции сложения: add x1, x0, x2 — что инструктирует процессор сложить содержимое регистра x2 с содержимым регистра x0, которые всегда содержит константу 0, и сохранить результат в регистр x1.
Всем начинающим настоятельно рекомендую прочитать базову спецификацию RISC-V — она очень короткая, всего 218 страниц, с четким и понятным описанием всех основных (unprivileged) инструкций, в отличии от сорока томов ARM-овской или Intel-овской. :-)
А вот тут есть хорошая шпоргалка по RISC-V ISA в формате PDF на два листочка.
ниоткуда не следует, что физически процессор будет эту команду выполнять через ALU. он вполне может декодировать сразу такую команду как mov
и далее выполнить её тупо переименованием регистров, не доводя до конвеера ALU.
Да. В доке на риск-в во многих местах говорится, что вот эти команды можно 'фьюзить' в одну макрооперацию (в данном случае это будет загрузка 32-битной константы в регистр). Ессно в мелочи типа как у вас никто этим не занимается, а вот в жирных суперскалярах такое вполне можно делать. Ну как х86 может mov+op фьюзить в одну 3-адресную внутреннюю операцию.
ниоткуда не следует, что физически процессор будет эту команду выполнять через ALU.
Это хорошо прослеживается из формата инструкции.
Теоритически, никто не запрещает реализовать микроархитектуру так, как вам это угодно, главное обеспечить совместимость по системе команд. Но, основной посыл RISC-V это минимизация количества внутренних цепей и повторное использование существующих блоков. Зачем тратиться на дополнительные цепи при реализации копирования регистров если можно прогнать через существующий AЛУ. По этой причение ядра RISC-V очень компактные и очень быстрые (до 5ГГц в железе).
А вот за шпаргалку по инструкциям спасибо, добавлю ее в статью и доки на гитхабе.
Но там нет скриптов сборки, так что непонятно как их вообще компилировать, какие флаги, какой стартап код, как подключить стандартные библиотеки и т.п. В общем, не разобрался я с тамошними примерами, пришлось ковырять с нуля.
А вот по чему не отказался бы от консультации, так это по подключению стандартных Си-шной библиотек вроде math или string.
Текстовый редактор удобно, когда у вас один файл. Когда в проекте появляется полный обвес периферии, прокладки между драйвером и основным кодом, в этом случае будет уже тяжело. Но тут каждый сам себе злой ТОС-1.
Накидал примерный проект на основе ссылки выше, проверить не смог готовый gcc не нашёл, а компилить было лень. Может кому пригодиться.
(1). JTAG — теоретически, самый правильный способ. Вот только подобрать правильное заклинание для него мне так и не удалось
а мне удалось, как раз на sipeed lognan nano (наверное). достаточно было найти патченный под рискв openocd, собрать под него же gdb и всё. железкой был клон jlink'а. удалось в gdb прошагать работающую программу и полюбоваться на дизасм рискв. очевидно что и остальное получилось бы, но я дальше не стал копать, плату отдал.
la a5, 0x40021018
для загрузки 32-х битного адреса порта управления GPIO. На самом деле это не инструкция процессору, а макрокоманда ассемблеру которая при компиляции расширится в нечто вроде:
lui a5,0x40021
addi a5,a5,24
Вроде бы все логично и прозрачно, скажете вы, а вот и не совсем. Все непосредственные операнды в RISC-V попадающие на вход АЛУ проходят через блоки расширения знака, причем блоки эти разные и зависят от формата инструкции. В данном случае 12-ти битная непосредственная константа 24 будет расширена до 32-х бит, при этом старший бит будет скопирован и использован в качестве заполнителя для отсутствующих бит, и дальнейшее сложение в АЛУ будет проведено с учетом знака. У обеих приведенных здесь констант старшие биты равны нулю, а значит после расширения и сложения мы получим искомую положительную константу. Но что произойдет если у обеих констант старший бит будет равен единице? Фактически мы получим сложение двух отрицательных чисел и результ будет не совсем очевидным для программистов начинающих изучать RISC-V.
Допустим, мы хотим загрузить константу 0xDCBA9876 в регистр a5, мы даем ассемблеру команду li a5, 0xdcba9876 которая генерируется в следующую неочевиную последовательность инструкций:
lui a5,0xdcbaa
addi a5,a5,-1930
В более общем виде, макрорасширение команды li выглядит вот так:
# sign extend low 12 bits
M=(N << 20) >> 20
# Upper 20 bits
K=((N-M) >> 12) <<12
# Load upper 20 bits
LUI x2,K
# Add lower bits
ADDI x2,x2,M
По этому будьте внимательны при дизассемблировании своего же когда. Я наткнулся на эти грабли и протоптался на них дня три, пока понял в чем прикол.
Команда lui загружает 0xDCBAA в старшие 20 бит, то есть x5 = 0xDBCAA000 = 3'687'489'536
Потом addi вычитает прибавляет к нему -1930. Раз уж в команду можно писать отрицательные числа, наверное она умеет с ними работать правильно и расширяет до нужного диапазона
x5 = x5 — 1930 = 3'687'487'606 = 0xDBCA'9876.
Для меня гораздо большим выносом мозга была загрузка относительно pc.
Впрочем, objdump умеет это сам писать в комментариях что же туда будет сохранено и какой метке / константе оно соответствует:
19c: 20000597 auipc a1,0x20000
1a0: e6458593 addi a1,a1,-412 # 20000000 <_data_end>
0x19C + 0x20'00'00'00 — 412 = 0x20'00'00'00
22a: 400117b7 lui a5,0x40011
22e: c0078793 addi a5,a5,-1024 # 40010c00 <GPIOB_BASE>
0x40'01'10'00 -1024 = 0x40'01'0c'00
кстати, возник ещё вопрос. насколько периферия f103 и этого vf103 одинакова? можно ли тут использовать инклуды с адресами регистров и положениями битов от обычного stm32f103? речь ессно не про NVIC, а про обычную периферию типа RCC, GPIO или того же UARTа.
Издеваться мы будем над микросхемой GD32VF103CBT6, являющейся аналогом широко известной STM32F103, с небольшим, но важным отличием: вместо ядра ARM там используется ядро RISC-V.В этом месте ожидал увидеть краткие преимущества ядра RISC-V по сравнению с ARM, чтобы понять имеет ли смысл интересоваться RISC-V.
Для этого традиционно используется мигание светодиодом (привет отладочным платам, на которых его нет!).Неужто такие платы существуют?
Не забывайте, что в современных системах доступ к COM и USB портам считается опасным действием и разрешен только руту.О том, что используемый софт предназначен для Linux следовало упомянуть раньше, в разделе «Настройка программного окружения».
В этом месте ожидал увидеть краткие преимущества ядра RISC-V по сравнению с ARM, чтобы понять имеет ли смысл интересоваться RISC-V.А я их не знаю :) Ну то есть теоретически у risc более приятный ассемблер, но программируют-то все равно чаще на Си, так что какая разница. Теоретически, он быстрее, но именно vf103 в сравнении с f130 выигрывает скорее за счет каких-то аппаратных ухищрений. А аналогов чего-то другого GigaDevice не делает. Так что просто другая архитектура, почему бы ее не рассмотреть.
Неужто такие платы существуют?
Та же bluepill, у которой единственный диод на PC13, та же arduino, у которой диоды на TX, RX и SCK.
О том, что используемый софт предназначен для Linux следовало упомянуть раньше, в разделе «Настройка программного окружения».Насколько я знаю, под Windows есть порты всего этого, да еще там вроде виртуалку линуксовую завезли.
С другой стороны, сколько статей я здесь читал, никто не делает акцента что софт предназначен, скажем, для windows. Вот разработчики на Mac иногда упоминают.
Где то чуть (ну совсем чуть-чуть) лучше, где то чуть (тоже чуть-чуть) хуже ARM, потребление сравнимо, быстродействие сравнимо.
Главное преимущество с точки зрения изготовителя — отсутствие необходимости лицензирования, но к нам это не относится, вряд ли готовые кристаллы станут дешевле.
Основное преимущество risc-v — что она реально открытая, можно брать и делать свой проц, не платя денег за лицензию и роялти. А можно купить проц у того, кто его уже сделал. Есть выбор.
И насчёт рута. Можно всегда добавить права доступа в конкретный усб-девайс (по vendor/device ID) в конфиг-файлы udev'а, будет доступно всем. Ну а чтоб в ком лазить, и вовсе достаточно юзера добавить в какую-то группу, забыл как она называется.
Изучаем RISC-V с нуля, часть 1: Ассемблер и соглашения