рис.1


Недавно мне в руки противоестественными путями попал интересный представитель RISC-V контроллеров производства НИИЭТ. Упакован он в пластиковый lqfp100 корпус, в котором скрывается ядро на 50 МГц, мегабайт флеш-памяти и 256 кБ оперативки. Разумеется, в наличии и стандартная периферия вроде UART-ов, SPI и USB. А вот из необычного — сигма-дельта АЦП на 16 бит. Ну и всякая неинтересная периферия вроде аппаратных модулей шифрования. Сразу оговорюсь, что тыкаю палочкой я его меньше двух недель, поэтому здесь описаны именно первые впечатления.


1. Корпус и плата


Рис.2 Распиновка


Корпус у контроллера большой, стоногий. Что любопытно, НИИЭТ расположили выводы портов GPIO по порядку, а не хаотично как какие-нибудь stm. Разве что между PB7 и PB8 не удержались и воткнули-таки одно из питаний. Это приятно. А вот что неприятно, так это куча абсолютно бесполезных AT_IN и WAKEUP, которым зачем-то отвели индивидуальные ноги вместо того, чтобы совместить с чем-то полезным. Да и USB могли бы убрать в альтернативную функцию, все равно, если верить еррате, он едва работает. А вот вынесение аналоговых входов понять можно: вероятно побоялись наводок на них от цифровых цепей. В конце концов, если уж ставить 16-битный АЦП, глупо портить сигнал посторонними шумами. На это же указывает наличие отдельной ножки AREF, выводов под соответствующие конденсаторы и вообще группировка всей аналоговой части в одном углу.


Еще в глаза бросается, что выводы SPI назвали нетрадиционно: вместо обычных MISO, MOSI обозвали их RX, TX. Впрочем, переключение режима ведущий — ведомый прямо на лету требуется не так уж часто, наверное это не доставит слишком больших проблем.


2. Карта памяти и стартап


В отличие от тех же stm32 (и контроллеров, которые создавались под впечатлением от них — gd32, ch32), флеш-память начинается не с 0x0800'0000, а с 0x8000'0000, ОЗУ с 0x4000'0000 (второе ОЗУ — с 0x1000'0000), а периферия с 0x2000'0000. А вот бутлоадера не завезли, поэтому его придется изобретать вручную.


Стартует камень на встроенном RC-генераторе на 1 МГц, но программно можно переключиться на внешний кварц или ФАПЧ до 50 или 60 МГц (в документации встречаются и то, и другое). И тут, внимание, грабли: частота встроенного RC-генератора довольно сильно отличается от заявленной. В моем экземпляре она оказалась примерно 947 кГц — более чем на 5% ниже обещанного. Это настолько большая погрешность, что не позволяет обеспечить работу UART без ручной подстройки.


Стартап, расположенный в официальном репозитории, был, похоже, взят от существенно более сложного ядра. Там неоднократно упоминаются Hart-ы, вызывается прямая проверка поддерживается ли FPU, предприняты специальные ухищрения для получения позиционно-независимых адресов. В относительно несложном микроконтроллере все это ни к чему, поэтому я его переписал. Из интереса — на Си. Получилось чуть компактнее, но менее универсально. И, честно говоря, учитывая количество ассемблерных вставок, смысла от Си в стартапе для RISC-V немного. Отдельно отмечу вот этот участок стартапа от НИИЭТ (чуть сократил):


.macro load_addrword_abs reg, sym
  .option push
  .option norelax
  lui \reg, %hi(\sym)
  addi \reg, \reg, %lo(\sym)
  .option pop
.endm
...
load_addrword_abs gp, __global_pointer$

Здесь в регистр gp записывается абсолютное значение переменной __global_pointer$, объявленной в ld-скрипте. Обычное присвоение выглядело бы как la gp, __global_pointer$, развернулось бы в auipc + addi и записало бы в регистр значение, вычисленное относительно pc. Отличие в том, что "фирменный" стартап может быть прошит не только в 0x8000'0000, но и в любое другое место без перекомпиляции. Вот только пользу из этого извлечь можно только когда и весь остальной код написан в том же стиле. Под контроллеры же обычно позиционно-независимый код не пишут, и все наши обращения к переменным из Си будут развернуты в тот же la, что сводит смысл от страдания со стартапом на нет. Поэтому в своей версии я оставил la.


Ах да, еще "фирменный" стартап требует наличия функций memset и memcpy. Они, конечно, есть в libgcc, но его подключение в мейкфайле тоже может оказаться далеко не таким тривиальным, как хотелось бы. Разумеется, я говорю про обычный risc-v gcc из репозитория.


3. Прошивка


Как уже было сказано, бутлоадер в данный контроллер не записали. И, зная любовь различных производителей делать бутлоадеры ни с чем несовместимыми, возможно, оно и к лучшему… Но вот что не сделали отдельной области памяти и отдельной ножки, конечно, недочет. Поэтому прошивка по умолчанию возможна только через JTAG при помощи пропатченного openocd. Ну хоть не стали изобретать свои проприетарные протоколы, как, скажем, WCH, камни которого шьются только их же wch-link-ом. В данном же случае можно обойтись обычным программатором на микросхеме ft2232. У меня, правда, нашелся только ft4232, но по сути это тоже самое. На всякий случай выложу приблизительное заклинание прошивки (хотя особой нужды в этом и нет. Спасибо НИИЭТам, свои примеры они не скрывают: niiet_riscv_sdk/tools/openocd/openocd-snippets/README.md ):


../xpack-openocd-k1921vk-0.12.0-k1921vk/bin/openocd -f ft4232.cfg -f k1921vg015.cfg -c 'init' -c 'reset halt' -c 'program firmware.bin 0x80000000 verify' -c 'reset run' -c 'exit'

Внимание, грабли: прошивка по JTAG не может полноценно поресетить контроллер. В регистрах сохраняются старые значения, и это здорово мешает. Лично я пока что использую костыль с ручным ресетом кнопкой. Возможно, есть какая-то команда и для openocd чтобы он все-таки ресетил контроллер по-нормальному.


Также, я думаю, здесь самое место рассказать об одной интересной ножке, SERVEN. Если ее подтянуть к питанию во время старта, контроллер перейдет в сервисный режим, в котором его можно только стереть. Сначала я подумал, что это просто еще она "лишняя" ножка, которой разработчики не нашли применения (как те же AT_IN). Но нет. Иногда, записывая некоторые значения в регистры, контроллер можно превратить в кирпич. Причем настолько качественно, что JTAG к нему подключиться не может. В этом случае ножку SERVEN можно замкнуть на питание (после чего JTAG все-таки подключается, но полноценно все равно не взаимодействует) и подать команду сервисного стирания. Это важно: не обычного, а именно сервисного. В общем, себе я на всякий случай написал отдельную команду для makefile:


unbrick:
    echo "Connect SERVEN to VCC, reset controller and press Enter"
    read
    ssh $(virt) "cd /home/user/prog/vg015/rem ; "\
    "../xpack-openocd-k1921vk-0.12.0-k1921vk/bin/openocd -f ft4232.cfg -f k1921vg015.cfg -c 'init' -c 'reset halt' -c 'mww 0x3000F104 0x00000100' -c 'mdw 0x3000F104' -c 'reset run' -c 'exit'"

4. GPIO


Портов у нас три. Как я уже сказал, они удобно сгруппированы по трем сторонам корпуса, и ноги в них идут подряд. У каждой ноги есть хотя бы две альтернативные функции — I2C, Timer,… ну, все как обычно. А вот работа с ними уже необычна. Вместо одного — двух регистров, отвечающего за режим работы, вход — выход, наличие подтяжки и т.д., в которые можно писать нули и единицы, здесь многие регистры организованы по принципу set — clear. Например, в регистр OUTENSET можно записать единицу, это переведет соответствующую ножку в режим выхода. Но вот запись нуля не повлияет ни на что. Чтобы вернуть ее в режим входа, надо записать единицу в другой регистр, OUTENCLR. Такой подход проявляется повсюду. Вероятно, разработчики хотели сделать работу с периферией максимально атомарной, но при первом знакомстве это изрядно ломает мозг.


А вот с регистром выхода DATAOUT они, наоборот, недожали. Да, у него есть DATAOUTSET, DATAOUTCLR и даже DATAOUTTGL, но вот атомарной установки по маске (аналог GPIO->BSRR в stm32, где можно было в reset-половину записать маску, а в set — значение) как раз нет. Ну, по крайней мере, я не нашел.


Альтернативные функции порта задаются в "обычном" (не set-clear) регистре ALTFUNCNUM (а вот само их включение — как раз в set-clear паре ALTFUNCSET, ALTFUNCCLR). Причем сами номера альтернативных функций не прописаны нигде. Есть предположение, что они соответствуют положению вот в этой таблице


рис.3. Таблица альтернативных функций


То есть для PA4 альтернативной функцией 1 будет UART2_RX, функцией 2 будет TMR1_CCIA, а функцией 3 — QSPI_CLK. Как минимум, для UART это предположение подтверждается, но как на самом деле, пока не знаю.


Также из таблицы видно, что альтернативные функции назначаются не для периферии, а для самих портов. То есть можно настроить, например, UART0_RX на PA0, а на UART0_TX не PA1, а PB7. Более того, можно настроить и PA1, и PB7 на UART0_TX, выход UART пойдет на обе ножки. Что будет, если настроить две ножки на RX, я проверять не рискнул.


Что еще интересно в регистрах 1921вг015, так это то, что в заголовочном файле разработчики прописали не только битовые маски, но и битовые поля:


/*--  DATAOUTSET: Data output set bits register ---------------------------------------------------------------*/
typedef struct {
  uint32_t PIN0                   :1;                                /*!< Data output set bit 0 */
  uint32_t PIN1                   :1;                                /*!< Data output set bit 1 */
  uint32_t PIN2                   :1;                                /*!< Data output set bit 2 */
  uint32_t PIN3                   :1;                                /*!< Data output set bit 3 */
  uint32_t PIN4                   :1;                                /*!< Data output set bit 4 */
  uint32_t PIN5                   :1;                                /*!< Data output set bit 5 */
  uint32_t PIN6                   :1;                                /*!< Data output set bit 6 */
  uint32_t PIN7                   :1;                                /*!< Data output set bit 7 */
  uint32_t PIN8                   :1;                                /*!< Data output set bit 8 */
  uint32_t PIN9                   :1;                                /*!< Data output set bit 9 */
  uint32_t PIN10                  :1;                                /*!< Data output set bit 10 */
  uint32_t PIN11                  :1;                                /*!< Data output set bit 11 */
  uint32_t PIN12                  :1;                                /*!< Data output set bit 12 */
  uint32_t PIN13                  :1;                                /*!< Data output set bit 13 */
  uint32_t PIN14                  :1;                                /*!< Data output set bit 14 */
  uint32_t PIN15                  :1;                                /*!< Data output set bit 15 */
} _GPIO_DATAOUTSET_bits;

Благодаря этому выставить PA3 в лог.1 можно не только наложением маски GPIOA->DATAOUTSET = (1<<3);, но и обращением к соответствующему битовому полю GPIOA->DATAOUTSET_bit.PIN3 = 1;. Не то чтобы это сильно на что-то влияло, но подход интересный. Опять же, когда битовые поля состоят из нескольких битов, запись может получиться чуть более компактной.


5. Прерывания


А вот тут разработчики решили обойтись необходимым минимумом. В стандарте RISC-V описана единственная точка входа в обработчик, вот и нам хватит. Никаких таблиц векторов прерываний, никаких таблиц адресов. Даже разделения на прерывания и исключения — и то нет. При любом событии ядро прыгает по адресу mtvec, а дальше уже пусть программисты разбираются. Вот только программисты немного схалтурили:


void PLIC_MachHandler(void) {
    uint32_t isr_num = PLIC_ClaimIrq(Plic_Mach_Target);
    if(mach_plic_handler[isr_num] != NULL_IRQ) {
        mach_plic_handler[isr_num]();
        PLIC_ClaimComplete(Plic_Mach_Target, isr_num);
    }
}
...
void trap_handler (void)
{
    uint32_t mcause_val = read_csr(mcause);

    if((mcause_val & MCAUSE_INTERRUPT_FLAG) == 0) {
        // handle exception
        switch (mcause_val & MCAUSE_EXCEPT_MASK)
        {
            case MCAUSE_EXCEPT_INSTRADDRMISALGN:
                break;
            case MCAUSE_EXCEPT_INSTRACCSFAULT:
                break;
            case MCAUSE_EXCEPT_INSTRILLEGAL:
                break;
            case MCAUSE_EXCEPT_BREAKPNT:
                break;
            case MCAUSE_EXCEPT_LOADADDRMISALGN :
                break;
            case MCAUSE_EXCEPT_LOADACCSFAULT:
                break;
            case MCAUSE_EXCEPT_STAMOADDRMISALGN:
                break;
            case MCAUSE_EXCEPT_STAMOACCSFAULT:
                break;
            case MCAUSE_EXCEPT_ECALLFRM_M_MODE:
                break;

            default: // MCAUSE_EXCEPT UNKNOWN

                break;
        }

        while(1) {}; //TRAP
    } else {
        // handle interrupt
        PLIC_MachHandler();
    }
}

Если присмотреться, сначала идет проверка mcause чтобы выяснить прерывание произошло или исключение. И если второе — программа просто-напросто зависает. Даже без возможности добавить юзерский обработчик. Ну а для прерываний они просто разместили в оперативной памяти таблицу mach_plic_handler указателей на функции обработчиков. И тут даже копированием из более сложного проекта, как в случае стартапа, оправдать нельзя. Ну разве ж это дело, молча зависать при любом исключении! В общем, со временем придется эту функцию переписывать.


А еще я не нашел способа сбросить флаг прерывания программно, без вызова обработчика. Но тут, возможно, просто плохо искал.


6. АЦП


(мнение Бориса, @Debian_ks)


Вчера разбирался с дельта-сигма АЦП. По факту каналы ch0 — ch6 заработали, канал ch7 молчит, даже флаг DATAUPD не выставляется. Помимо этого каналы ch0 — ch6 смещены вниз каждый от -920 до -1020 отсчетов. Кроме этого в SVD файле и K1921VG015.h есть некий регистр DIFF который не описан в руководстве пользователя.

7. Бонус, или "извините, не смог удержаться"


Ну и как же без реализации чего-нибудь красивого и бесполезного. Как-то так сложилось, что у меня одной из первых прошивок под новые контроллеры оказывается реализация трехмерной графики. Так было с stm32, так было с gd32. Так же получилось и с 1921вг015. Разумеется, код ни в коем случае не может служить примером для подражания, но демка это демка, много от нее не требуется. Частота ядра и частота SPI 60 МГц, частота обновления 11 — 12 кадров в секунду, причем ограничена она в основном SPI, а не расчетами.


рис.4. Трехмерная графика


Заключение


Вот такой вот камень мне довелось пощупать.


Начнем с недостатков. Крайне неточный HSI. Отсутствие таблицы прерываний. Отсутствие бутлоадера. Поддерживается прошивка обычными JTAG-программаторами (это-то достоинство), но все же нужен пропатченный openocd. Целых семь ног отвели под какую-то ерунду — AT_IN, WKUP, плюс еще две под USB. Сами-то функции, может, и могут где пригодиться, но их стоило совместить с GPIO. Слабый USB (даже без учета ерраты, всего 4 конечные точки). Суровая необходимость в ножке SERVEN (иначе говоря, возможность окирпичить контроллер просто записью неверного значения в регистр).


Достоинства. Необычность: что распределение памяти, что подход к регистрам не похож на то, что я видел в stm32; довольно интересно его изучать. Большой объем памяти: 1 МБ флеша и 256+64 кБ ОЗУ. Выводы портов расположены по порядку, а не абы как. Поддерживается прошивка обычными JTAG-программаторами. Мощные аналоговые модули (АЦП, компараторы — теоретически; в реальности я их не проверял).


Возможно, достоинства, но лично мне применить их некуда. Аппаратные блоки подсчета CRC-сумм, хеширования, криптографии (AES-128, AES-256, "Кузнечик", "Магма"), CAN.


В целом, камень весьма интересный. Косяков, конечно, много, но будем надеяться, что НИИЭТ в будущих разработках их исправит. Да и те, что есть, обойти почти всегда возможно. Полагаю, что применение ему в каких-то устройствах найдется.

Комментарии (111)


  1. kompilainenn2
    17.02.2025 11:50

    Первые впечатления, что судя по маркировке, он Ленина живым видел


    1. COKPOWEHEU Автор
      17.02.2025 11:50

      Если во времена Ленина выпускались РИСК-5 (ну не на иностранном же языке маркировать!) микросхемы с мегабайтом ЭСППЗУ... А вообще, это скорее последствия отмывки или неудачно выставленного света.


      1. NekitGeek
        17.02.2025 11:50

        Может он про логотип и стандартное обозначение? Видел похожий логотип на советских микросхемах от спектрума.


        1. kompilainenn2
          17.02.2025 11:50

          Может, я про первые 4 цифры на самом деле, а вовсе не про качество печати или самого чипа. Хабр в юмор не научится никогда


      1. vladkorotnev
        17.02.2025 11:50

        РИСК-5 (ну не на иностранном же языке маркировать!)

        Тогда уж МУНИ-5 (Микропроцессор с Упрощённым Набором Инструкций) :-)


        1. peacemakerv
          17.02.2025 11:50

          Не микропроцессор, а контроллер :)


          1. COKPOWEHEU Автор
            17.02.2025 11:50

            однокристальная микро-ЭВМ!


            1. peacemakerv
              17.02.2025 11:50

              Нифига вы в аббревиатурах не понимаете :)


          1. torgeek
            17.02.2025 11:50

            Если смотреть словарь Ершова, то это микропроцессор. И далее по роли — периферийный или центральный, в зависимости от применения и выполняемым функциям.


          1. vladkorotnev
            17.02.2025 11:50

            Я сначала так и написал, но вышло слишком по Фрейду :-)


            1. torgeek
              17.02.2025 11:50

              Главное не путать редукцию и упрощение — в RISC системах команд нет упрощения, там редукция.


    1. Hlad
      17.02.2025 11:50

      Так то существует ГОСТ, который говорит, как должны называться микросхемы. И как правило, отечественные микросхемы имеют два названия: для сертификационных документов и нормальное. Например,К1986ВК025 и MDR1206FI.


      1. kompilainenn2
        17.02.2025 11:50

        Которого года сей ГОСТ? Ну и емнип, ГОСТы, которые не оказывают влияние на здоровье и жизнь людей не обязательны к применению


        1. Hlad
          17.02.2025 11:50

          Так никто не заставляет эти ГОСТы применять - разрабатывайте микросхемы на свои собственные деньги, и продавайте на свободном рынке, никто слова не скажет. Но если хочется присосаться к золотому пенису госфинансирования - будьте добры называть микросхему в соответствии с действующими стандартами.


          1. checkpoint
            17.02.2025 11:50

            Вы уверены что он золотой ? ИМХО обычный, кожаный. ;)


  1. Mox
    17.02.2025 11:50

    А где его реально делают? И делают ли?


    1. torgeek
      17.02.2025 11:50

      Ядро риск5 — делают в Петербурге.
      СФ-блоки — скорее всего собственные проекты компании в Воронеже.
      Топологию всего чипа делают в Воронеже.
      Кристаллы выпекают, наверное, в поднебесной.
      Корпусировку чипа делают в Воронеже, хотя именно эта партия, может и нет.
      Тестирование делают в Воронеже.
      Отладочные платы делают во Владивостоке.
      Рабочую документацию и системный софт делают в Воронеже и Владивостоке.


      1. Mox
        17.02.2025 11:50

        Я имею ввиду именно изготовление кристаллов.
        А тот просто наши производители CPU никак не могут осилить изготовление в Китае, а внутри РФ только Амур делают - хочется понять - это реально изготавливается или как с Эльбрусами - все выпущенные партии распроданы, ждите.


        1. torgeek
          17.02.2025 11:50

          Почему не могут? Это же "мелкие" чипы. Поставки идут бесперебойно с прошлой зимы, как минимум.


    1. checkpoint
      17.02.2025 11:50

      Тоже интересуюсь этим впросом. Есть у кого-то информация на сей счет ?

      Судя по описанию, там внутри сэндвич из двух кристаллов - сам МК и flash память. Flash понятно что китайская, а где произведен кристалл МК ?


      1. torgeek
        17.02.2025 11:50

        Его заявили как чип второго уровня, так что понятно — не конкурент АМУРу, который первого уровня.


  1. AKudinov
    17.02.2025 11:50

     Ну разве ж это дело, молча зависать при любом исключении!

    Насколько помню, штатный код для STM32 делает так же. А нужно это, чтобы можно было увидеть, что контроллер завис, подключиться отладчиком через JTAG и увидеть, что программа циклит в обработчике исключения, и дальше уже разбираться, как так вышло. Например, прочитать регистры, в которые сохранилось значение PC, при котором было выброшено исключение (STM32 так делает; как здесь реализовано, не знаю).


    1. COKPOWEHEU Автор
      17.02.2025 11:50

      Принцип максимизации ошибки это, конечно, хорошо. Плохо, когда ошибку не дают отследить из юзерского кода. Самое простое - могли сделать дефолтный обработчик исключений и объявить его weak. Соответственно, если юзер напишет свою альтернативу - использоваться будет она. И, насколько я понимаю, в stm32 используется именно такой подход. Те же ecall-ы как иначе отслеживать? Это же не ошибка, это именно системный вызов.


      1. AKudinov
        17.02.2025 11:50

        Согласен с вами. Возможно, предполагается, что пользователь сам перепишет предлагаемый ему код.


  1. Rusrst
    17.02.2025 11:50

    Демка зачёт (камень тоже) ! Может её ещё подробно опишете? Я бы почитал)


    1. COKPOWEHEU Автор
      17.02.2025 11:50

      Про демку там есть ссылка на статью по прототипу, который еще давным-давно под stm32 писался. Что там еще описывать?
      Про камень - надо будет сначала самому разбираться. Если чего-то интересное найдется - опишу.


  1. byman
    17.02.2025 11:50

    А вот тут разработчики решили обойтись необходимым минимумом. В стандарте RISC-V описана единственная точка входа в обработчик, вот и нам хватит. Никаких таблиц векторов прерываний, никаких таблиц адресов

    Сейчас у RISC-V с этим вроде все ОК. Но похоже МК делался долго и процессорное ядро еще не включало последних обновлений.


    1. COKPOWEHEU Автор
      17.02.2025 11:50

      А можно подробнее? Сейчас пролистал спецификацию на risc-v, не увидел ничего более интересного, чем парсинг того же mcause.


      1. lorc
        17.02.2025 11:50

        У больших ARMов почти так же. Хотя, все же есть отдельные точки входа для прерывания и для исключения. А дальше - либо лезем в контроллер прерываний смотреть что там пришло, либо в регистр ESR, разбираться что за исключение.


      1. byman
        17.02.2025 11:50

        1. COKPOWEHEU Автор
          17.02.2025 11:50

          Чем-то напоминает то, что в gd32 реализовали


  1. rojer
    17.02.2025 11:50

    спасибо за обзор! мне вот показалось странным, что уартов аж 5, а I2C всего один.

    во всей своей практике не видел применения для более 3 уартов, а вот разделять слейвы по I2C шинам приходилось (когда нет возможности смены адреса).


    1. jaha33
      17.02.2025 11:50

      Имею обратный опыт, уартов надо 5 и более, а шины i2c одной хватает, на нее 3-4 микросхемы можно вешать. Тут уже каждому свое


      1. rojer
        17.02.2025 11:50

        я же уточнил: когда нет возможности поменять адреса слейвов. плюс, допустим, одна шина может смотреть "внутрь", а другая "в мир", в виде расширения. в любом случае, иметь всего 1 и2ц - это странно.


    1. kgbplus
      17.02.2025 11:50

      У меня ощущение, что этот контроллер делался под конкретную задачу (оттуда и 16 бит АЦП и хитрый бутлоадер)


      1. COKPOWEHEU Автор
        17.02.2025 11:50

        Какой еще хитрый бутлоадер? В вг015 бутлоадера вообще нет.


      1. nixtonixto
        17.02.2025 11:50

        Почти все отечественные СБИС делаются под конкретное применение, в частности, эта - под счётчики. Иначе не выбить денег на разработку.


        1. torgeek
          17.02.2025 11:50

          Тогда уж все СБИС в мире делают под конкретные применения. Зачем делать под случайные не просчитанные задачи? Кстати, у этого ВГ015 неизвестна дола между коммерческими инвесторами, кредитами и госбюджетным заказом. Вполне возможно, что там чип — чисто коммерческая инициатива НИИЭТ. К тому же он напрямую конкурирует по назначению с миландровским риск5 чипом Счётчик, который выпускается серийно несколько лет.


          1. nixtonixto
            17.02.2025 11:50

            Нет. Вот, к примеру, STM32 с такой же мегабайтной флешкой - там и таймеров больше десятка, причём с кучей режимов работы, и все (кроме BOOT0) ноги видны как GPIO, включая ноги резонаторов и программирования, и ремап есть почти на все ноги, и даже у F373 ремап на входы 16-битного АЦП никак не влияет на этот самый АЦП. Тут же таймеров всего 4 шт, чего достаточно какой-то АТмеге, но уже маловато для 32-битника с большой программой... Треть ног прибита гвоздями к какой-то одной функции, из которых конкретно мне сейчас вообще ничего не нужно - может кнопки повешу на WAKEUP-ноги, если не хватит GPIO, но там, возможно, будет не просто фильтровать дребезг и удержание. И вот по этим безальтернативным функциям виден заказчик - какая-то измерительная штука с защитой от вскрытия и шифрацией данных.


            1. COKPOWEHEU Автор
              17.02.2025 11:50

              может кнопки повешу на WAKEUP-ноги, если не хватит GPIO, но там, возможно, будет не просто фильтровать дребезг и удержание.

              Это вы здорово недооцениваете бездну геморроя с использованием WKUP как входов. Нормального чтения там нет вообще никак. Единственный способ, которым мне удалось воспользоваться - через прерывание RTC. И этот способ невероятно кривой. Хотя есть шанс, что это я чего-то недоглядел.


            1. torgeek
              17.02.2025 11:50

              Про какой из итальянцев речь? SMT32 не чип, а большая линейка совершенно разных чипов под разные задачи.

              У НИИЭТ линейка разнообразная в выпускаемых чипах и в проектируемых. Для примера только чипы на риск5 системе команд:
              К1921ВГ015 в серии
              К1921ВГ1Т разработка
              К1921ВГ3Т разработка
              К1921ВГ5У разработка
              К1921ВГ7У разработка


          1. GidraVydra
            17.02.2025 11:50

            Под какое конкретное применение делали stm32?


        1. ahdenchik
          17.02.2025 11:50

          под счётчики

          Но встроенный модем/трансивер делать не стали...


  1. yaxn
    17.02.2025 11:50

    Спасибо за обзор. Как там дела с сишными библиотеками, они есть вообще? Не хочется самому USB стек делать. И я не вижу реальное применение криптоядра, кроме как делать криптофлешки, ключи и т.п. Жаль, что нет MII, считаю, что добавление Ethernet стека должно быть стандартом 32х битных современных микроконтроллеров.


    1. COKPOWEHEU Автор
      17.02.2025 11:50

      С usb, если верить еррате, там все плохо. Работает только одна конечная точка, и то нестабильно. Впрочем, возможно, это верно только для старых ревизий, а в новых уже все исправлено. Не знаю.
      Сишные библиотеки какие-то есть, но лично по мне они неудобные (но я-то вообще не показатель).
      Для криптомодулей - хз, возможно, для военных или какой-нибудь бюрократии важен сам факт их наличия. Вряд ли ведь контроллер делали с нуля специально для продажи всяким радиолюбителям.
      Ethernet - не знаю, скорее все же нет. Возможность (и желание) протащить к устройству витую пару все же меньше, чем USB или даже CAN. В любом случае, не стоит требовать слишком многого сразу. Именно этот МК заточен больше под аналоговые схемы, чем под сложные вычисления или обмен.


      1. yaxn
        17.02.2025 11:50

        Так Ethernet не только про вычисления и обмен. Делать промавтоматику на езернет - благодать, стек обеспечивает большую надёжность и отказоустойчивость, чем RS485, особенно при разработке нового. См. промавтоматику Овен, построенную на stm32.

        Для меня применение USB более экзотическая сфера. Флешки вставлять странно, делать клавиатуры и мышки избыточно, делать криптотокен хорошо, но нишевая сфера.


        1. COKPOWEHEU Автор
          17.02.2025 11:50

          В целом - смотря какая задача. Изобразить из контроллера флешку, на которой хранится снятые данные - а почему бы и нет? Или некое комбинированное устройство. Или, в порядке извращения, программатор для таких же микросхем.
          В любом случае, вряд ли производительность ядра позволит отличить аппаратный эзернет от spi-ного.


        1. rojer
          17.02.2025 11:50

          езернет легко подключается по SPI. да, надо будет брать MAC+PHY, а не просто PHY, ну так и ладно, зато экономия ног - на RMII нужно 9 штук + резет, на SPI MAC+PHY надо 6 (4 SPI + int + rst). 10 мбит/с вполне потянет.


          1. nixtonixto
            17.02.2025 11:50

            И на каком чипе вы "легко" подключите езернет по SPI? KSZ8851 будет смотреться весьма странно в импортозамещающем девайсе, учитывая, что сайт Микрочипа даже не открывается без VPN, а на чипах WCH это не легко и с кучей ограничений по сравнению с нативным MAC.


            1. rojer
              17.02.2025 11:50

              речь как раз о CH392T - лично подключал, работает нормально. у него там есть претензии на поддержку IP, но их можно смело игнорировать, переводить в raw MAC режим и вперёд, с песнями. у него немного странный протокол и местами глючный SPI, но 2.5 мбита/с он мне выдавал.


            1. checkpoint
              17.02.2025 11:50

              Отчественный Ethernet PHY всё равно не завезли, так что большой разницы нет что и как там будет смотреться. Но в целом, я согласен, что такие МК уже должны иметь встроенный MAC.


        1. rsashka
          17.02.2025 11:50

          стек обеспечивает большую надёжность и отказоустойчивость, чем RS485

          но обвязка на порядок дороже и требовательнее к вычислительным ресурсам.


          1. yaxn
            17.02.2025 11:50

            Мы же должны стремиться в светлое будущее, а опираться на RS-485 в новом - путь в никуда. Дешевеет сетевое оборудование, оптика, придуманы надежные отказоустойчивые решения. На моем опыте, с RS-485 на объектах возникает намного больше проблем, нежели с Ethernet, т.к. нет нормального стека с избыточным кодированием, адресацией, контролем линии, приходится каждый раз своё городить. Здесь в чипе пять эрэсов обалдеть, кто-то же ТЗ для поддержки своего легаси писал. CAN убирать не надо.

            А еще я перед сном мечтаю об ОКРе с российской PHY микросхемой с xMII интерфейсом. Миландр был близок, но что-то не задалось.


            1. nixtonixto
              17.02.2025 11:50

              У Миландра есть контроллер со встроенным PHY. Но у них другая крайность - 128к флеш, чего даже на SSL маловато, не говоря уже о поддержке кучи протоколов.


              1. yaxn
                17.02.2025 11:50

                Хорошее замечание, что для езернета память нужна. Мы используем LWIP и ModbusTCP на ВЕ3Т, вроде умещается, но стек реально половину объема занимает. Впрочем, можно подключить дополнительное ОЗУ.

                Зато во время отладки, стыковки, работы в условиях сильных наводок и помех, проблем было существенно меньше, чем с RS-485. С эрэсом по-классике перепутали RX и TX, землю припаяли не туда, кто-то всю шину повалил, и всё ради баснословной скорости в 921600 бод/с.


            1. madiggo
              17.02.2025 11:50

              На моем опыте, с RS-485 на объектах возникает намного больше проблем, нежели с Ethernet, т.к. нет нормального стека с избыточным кодированием, адресацией, контролем линии, приходится каждый раз своё городить.

              Да, точно. Так и норовит поймать наводку, особенно если не на специальном кабеле да с заземлением хреново.


              1. yaxn
                17.02.2025 11:50

                В местах, где будет применяться сабж и другие контроллеры из треда, не экономят на кабеле с заземлением.

                Ethernet PHY хорошо проработанная область из-за большого рынка. Можно обеспечить шифрованное TCP соединение на кабеле с плохим, окисленных контактом. Кастомный канальный протокол на RS-485 вряд ли будет также продуман, как в Ethernet.

                Более того, если имеется MII интерфейс, то можно подключить оптический SFP, который с лихвой побеждает RS485 по дальности связи, скорости и защите от помех. И при более дешёвом кабеле.


    1. YDR
      17.02.2025 11:50

      отдельный чип флешки и криптозадачи - не очень стыкуются. То ли дело в каком-то чипе для электросчетчиков: флеш на чипе, да еще и заэкранирован проводящими слоями с защитой от иголочки стирания и пр.


  1. almaz1c
    17.02.2025 11:50

    А что по цене?

    Со скрипом взяли в работу К1948ВК018 (Амур), хотя в нем очень не хватает CAN интерфейса.

    1921вг015 по-жирнее, судя по всему?


    1. torgeek
      17.02.2025 11:50

      Отпуская цена в мелких партиях — около 500 ₽ плюс НДС.
      Розница у перепродавцов — около 1 500 ₽.
      В марте компания обещает начать официальные розничные продажи через маркетплейсы.


      1. Mox
        17.02.2025 11:50

        Чет с такой ценой - это не перемаркированный ли китаец?


        1. COKPOWEHEU Автор
          17.02.2025 11:50

          Перемаркированный вряд ли, уж больно странные решения и странные косяки. Изготовление в Китае возможно. Но давайте верить в лучшее :)


        1. torgeek
          17.02.2025 11:50

          Это не единственный русский чип в этой ценовой категории. Есть у Миландра на том же ядре риск5 и давно в серии, причём АЦП у Миландра, говорят, лучше получается. Скоро у других компаний ожидается выход риск5 чипов. Вариантов больше чем один.


          1. COKPOWEHEU Автор
            17.02.2025 11:50

            речь не про Амур, надеюсь?


            1. torgeek
              17.02.2025 11:50

              АМУР в другой ценовой категории и он пока такой один. Вторую ревизию АМУРа или даже совсем новый чип проектируют, но это не раньше следующего года в производстве. Хотя даже текущие возможности фабрики позволяют изготовить чип с гораздо лучшими характеристиками, как показал МИЭТ со своим экспериментальным риск5 чипом Хаки, выпущенным на том же Микроне.


              1. almaz1c
                17.02.2025 11:50

                Вторую ревизию АМУРа или даже совсем новый чип проектируют

                Что новенького ждать? CAN может быть?


        1. byman
          17.02.2025 11:50

          В процессорном ядре есть всякие ID , в отладочном интерфейсе. Можно посмотреть чьё.


    1. torgeek
      17.02.2025 11:50

      Отдельная опция для ростовчан — бесплатно по дружбе))


    1. COKPOWEHEU Автор
      17.02.2025 11:50

      1921вг015 по-жирнее, судя по всему?

      Ну да. Плюс встроенная флешка аж на мегабайт есть. И подешевле вроде как. Впрочем, что там с Амуром не знаю, может, у него есть и свои преимущества. Но лично меня вг015 впечатлил больше.


    1. jaha33
      17.02.2025 11:50

      Разительно жирнее, флеша (встроенного) и ОЗУ много, куча интерфейсов. По сути это весьма современный контроллер по всем ТТХ. Если облагородить SDK, то вообще станет хорошо.

      Но тут неясно сколько там своего. Та же периферия. Вот будет сейчас народ глюки находить, сможет ли производитель выпускать ревизии чипов с фиксами или нет. Если нет, то китайского в этих чипах сильно больше чем заявляют.


      1. GidraVydra
        17.02.2025 11:50

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


        1. jaha33
          17.02.2025 11:50

          С OEM производством ниразу не сталкивался, но все китайские STM заменители, которые пришли к нам, вообще ревизий не выпускают.

          Читаешь reference manual, пробуешь так настроить какие нибудь регистры - что то работает, а что то нет. Потом выясняется что это глюк чипа. Проблем причем много, а китайцы говорят что ревизий делать не будут, пробуйте другие чипы из семейства, может там заработает, если вам это критично. Такое ощущение что они сами только корпусируют, а вся начинка покупная


          1. VT100
            17.02.2025 11:50

            Про покупность СФБ.


          1. GidraVydra
            17.02.2025 11:50

            Вы смотрите на это с позиции энд юзера, ради которого никто ревизий делать не будет. Энд юзер для китайцев вообще не является заказчиком, его запросы для них - как письма в редакцию газеты Крыжопольский садовод. Если же ревизию запросит контрактор с объемами, китайцы становятся очень гибкими. Правда, обычно становится только хуже.


            1. jaha33
              17.02.2025 11:50

              Работаю в компании с весьма приличными объемами потребления микросхем. Всякие ST и TI, если были проблемы, всегда шли на встречу или фиксили проблему (естественно не сразу, вполне могло и больше года пройти) или предлагали временные пути обхода или скидки. С китайцами, увы, такого и близко нет.

              Разговор то был изначально о том смогут ли НИИЭТ править глюки (а они будут) или забьют. Заказчик то у них видимо уже есть и ему деваться некуда. Но как мы такими путями наразвиваем свою микроэлектронику - неясно.


  1. checkpoint
    17.02.2025 11:50

    Спасибо за статью. Но всё же тема Bad Apple не раскрыта. ;)


    1. COKPOWEHEU Автор
      17.02.2025 11:50

      Еще бы про запуск Doom вспомнили :) Хватит с вас и трехмерного шныга.


  1. vlatro
    17.02.2025 11:50

    ВГ3Т тоже интересная машинка.


    1. COKPOWEHEU Автор
      17.02.2025 11:50

      Написано, что еще в разработке. Или его уже можно пощупать?


  1. Vcoderlab
    17.02.2025 11:50

    Протестируйте пожалуйста, как плывёт результат измерений сигма-дельта АЦП при изменении температуры: поморозить корпус freezer-ом и погреть феном. В официальной документации про точность измерений ни слова, а без этого применять этот МК для точных измерений как-то слишком авантюрно.

    Если есть чем, можно при этом ещё померить опорное напряжение на выводе 25 "SDADC_CAP". В документе "РП-К1921ВГ015-v3.pdf" в разделе 22.1 очень интересно написано, что напряжение на этом выводе составляет (1,250 ±0,125) В. Это же 10% разброс! Мне интересно, это допустимый разброс от экземпляра к экземпляру, или оно может в этих пределах во время работы плавать? Если второе, то о какой точности измерений вообще можно говорить?


    1. COKPOWEHEU Автор
      17.02.2025 11:50

      По стабильности ИОНов есть более интересные планы (не только вг015), но там надо здорово с установкой замороситься. Не малейшего представления найдется ли вообще на это время.
      А что до SDADC, там же, наверное, можно внешний ИОН подключить на крайний случай?


      1. Vcoderlab
        17.02.2025 11:50

        А что до SDADC, там же, наверное, можно внешний ИОН подключить на крайний случай?

        Как я понял, нет. Потому что SDADC_CAP - это выход встроенного ИОН для подключения конденсатора 0,1 мкФ. То есть подавать сюда напряжение с внешнего ИОН нельзя - они подерутся. Про возможность использования внешнего ИОН и куда его в таком случае подключать, в руководстве не сказано. Или я не нашёл.


        1. COKPOWEHEU Автор
          17.02.2025 11:50

          Не буду настаивать. Я к местным АЦП пока что и близко не подходил. Важнее было с базовыми цифровыми интерфейсами разобраться. И даже сейчас важнее написать нормальный бутлоадер и собрать стенд для удобной прошивки. В общем, основной специфике вг015 придется подождать


          1. Nick0las
            17.02.2025 11:50

            А чем прошивка через openocd неудобна на стенде?


            1. COKPOWEHEU Автор
              17.02.2025 11:50

              То, что openocd из репозитория не подходит, нужно специальный от производителя. А стенд не у меня стоит, устанавливать туда сторонние программы не хочется.
              В любом случае, под "собрать стенд" я имел в виду скорее железо: эмулятор клавиатуры, экрана, UART, микрофона,...


              1. wigneddoom
                17.02.2025 11:50

                Ну чтобы OpenOCD из репозитория подходил, есть только один путь - пропихнуть патчи в апстрим, что маловероятно. Тут хоть от производителя, а много лет назад я по всея интернету искал патчи для TI.


                1. COKPOWEHEU Автор
                  17.02.2025 11:50

                  Мне разбираться с openocd не под силу. Вот написать бутлоадер - другое дело. Впрочем, там видно будет.


        1. 8street
          17.02.2025 11:50

          Про возможность использования внешнего ИОН и куда его в таком случае подключать, в руководстве не сказано. Или я не нашёл.

          Вроде есть вход AREF.


          1. COKPOWEHEU Автор
            17.02.2025 11:50

            Он может идти только на один АЦП, например, последовательного приближения, а сигма-дельта - от внутреннего (хотя логичнее наоборот). Но это все надо изучать отдельно.


    1. GidraVydra
      17.02.2025 11:50

      Извините, у них погрешность внутренней тактовки 5%, о какой точности измерений в принципе может идти речь?


      1. VT100
        17.02.2025 11:50

        При чём тут это? Или речь о соответствующем временном джиттере дискретизации?


        1. GidraVydra
          17.02.2025 11:50

          Во-первых, речь об отношении разработчика/производителя к точности в целом. Во-вторых, интегрирование в АЦП завязано на тактовку, со всеми вытекающими.

          Джиттер будет если задаваемая частота нестабильна.


          1. COKPOWEHEU Автор
            17.02.2025 11:50

            Сдается мне, вы путаете точность и стабильность. То есть систематическую погрешность и случайную. То, что HSI отличается на 5% от номинала, не значит, что он на 5% плавает во время работы - это всего лишь значит, что НИИЭТ не стали его калибровать. Для АЦП важна именно стабильность частоты, а не точность. И интуитивно мне кажется, что стабильность у любых встроенных RC-генераторов будет примерно одинаковая, что у stm32, что у ch32, что у вг015.


          1. VT100
            17.02.2025 11:50

            Недорогие ширпотребные АЦП, вроде встраиваемых в МК, строятся на принципе поразрядного уравновешивания зарядов (последовательных приближений). Поэтому там нет особых требований к стабильности частоты во время квантования сигнала.

            Интегрирование - более характерно для измерительных приборов. И там оно делается двухстадийным, для снижения требований к тактовому сигналу.


  1. Dr_Faksov
    17.02.2025 11:50

    Увидел фото печатной платы - и начал читать статью. Чтобы убедится, что это сделано сейчас, а не во времена моей далёкой молодости. Убедился, удивился.


    1. COKPOWEHEU Автор
      17.02.2025 11:50

      Что, недостаточно апокалиптично? Вот такая, наверное, покрасивее будет: https://habrastorage.org/r/w1560/webt/tq/q2/2b/tqq22bjmf-yx77utxwt-v0ia8u4.jpeg


      1. sim2q
        17.02.2025 11:50

        Неужели резцом?:)
        Когда то помню старшие товарищи затачивали полотно от ножовки крючком под определённым углом. Самому повторить так не удавалось, что бы резало также хорошо.


      1. AKudinov
        17.02.2025 11:50

        Сурово как. Посадочное место под МК тоже руками вырезали? Респект!


        1. COKPOWEHEU Автор
          17.02.2025 11:50

          А как же. Ради интереса решил попробовать сделать плату максимально подручными средствами, даже без принтера. Даже записал процесс этого мракобесия: https://www.youtube.com/watch?v=tPAHEwi4Fzg&list=PLc7FYD_FgfqcgaWyrxhSr8cy2q23xCY3Q&index=14


          1. isden
            17.02.2025 11:50

            Мне как-то доводилось делать не очень сложную плату с парой 14 ногих микрух с помощью шила и железной линейки =)


          1. sim2q
            17.02.2025 11:50

            для интереса попробовать электромеханической эрозией рисовать


  1. evgeny_72
    17.02.2025 11:50

    Нвидиа вздрогнула:)) я одину плату с мин обвязкой взял, и чувствую что надо более глобальное сделать. Нормальный проект.


    1. COKPOWEHEU Автор
      17.02.2025 11:50

      Видеокарта на 256 ядрах вг015. Суровая российская видеокарта с ручками для переноски.


      1. Vytian
        17.02.2025 11:50

        Зачем ручки, куда ее из бункера вывозить, кто позволит?

        А если серьезно, присоединяюсь к просьбам насчет АЦП. Причем сразу и дифференциально.


  1. ahdenchik
    17.02.2025 11:50

    Отсутствие таблицы прерываний. Отсутствие бутлоадера.

    Меньше аппаратуры - меньше errata. Не забывайте что с этим контроллером россияне будут жить лет 30-50

    (Вообще, мне лично кажется странным когда производители пытаются напихать аппаратную поддержку в те места, которые "без штрафа" реализуемы программно)

    Поддерживается прошивка обычными JTAG-программаторами (это-то достоинство), но все же нужен пропатченный openocd.

    Такой "патч" нужен любым микросхемам, поддерживаемым openocd: это патч к конфигу, которым краёвая конфигурация задаётся. Со временем он попадёт в ~master

    Целых семь ног отвели под какую-то ерунду — AT_IN, WKUP, плюс еще две под USB. Сами-то функции, может, и могут где пригодиться, но их стоило совместить с GPIO.

    Видимо, корпус выбран по каким-то другим соображениям и недостатка в ногах не было


  1. Disasm
    17.02.2025 11:50

    Под контроллеры же обычно позиционно-независимый код не пишут, и все наши обращения к переменным из Си будут развернуты в тот же la, что сводит смысл от страдания со стартапом на нет.

    Есть как минимум два сценария, когда нужен абсолютный адрес, а не относительный:

    • флеш может располагаться по адресу 0x0800_0000, но выполнение кода происходить по адресу 0. Можно конечно с помощью ld-скрипта разместить код тоже по адресу 0, но тогда прошивка чипа может перестать работать

    • в чипе могут быть регионы кэшируемой и не кэшируемой памяти, и выполнение может начинаться с не кэшируемой памяти, а потом переходить в кэшируемую в стартапе. До тех пор, пока адрес выполняемой инструкции не будет 100% известен, пользоваться la опасно.

    Помимо всего этого когда вы запускаете прошивку под дебаггером, он может начать её выполнять с "правильного" адреса, а потом после ресета микроконтроллер начнёт выполнять её с того, который ему кажется правильным. В общем, загрузка абсолютного адреса позволяет минимизировать проблемы, связанные с особенностями конкретного МК, потому что она работает всегда одинаково.


    1. COKPOWEHEU Автор
      17.02.2025 11:50

      Во всех этих случаях заботиться о позиционно-независимом коде приходится самому программисту. А речь-то шла о том, что компилятор gcc по умолчанию будет генерировать обычный, позиционно-зависимый код.
      И, на самом деле, это проблема: я-то надеялся написать бутлоадер, который бы располагался в начале флеша, а юзерский код записывал где-нибудь дальше. И если бы прошивка получалась позиционно-независимой, проблемы бы не было: ну стартует он не с 0x8000'0000, а с 0x8001`0000 - не страшно, переходы-то относительные. Но вот обращение к ОЗУ из-за la поломается. Поэтому придется либо вкручивать флаги компилятору (пока не знаю с какими побочными эффектами), либо править ld-скрипт. А раз так, то и возня с позиционно-независимым загрузчиком не особо полезна.
      А самое обидное, что я так и не нашел способа передать в li адрес метки, компилятор ругается и требует la.


      1. Disasm
        17.02.2025 11:50

        Я пока тут не вижу никакого позиционно-независимого кода, вижу только обычный позиционно-зависимый. Тот факт, что код может выполняться из других адресов -- проблема исключительно стартап-кода, он должен сделать так, чтобы остальной код ничего не заметил.

        Проблема с li, насколько я понимаю, в том, что компилятор не может её сразу скомпилировать если он не знает адрес метки. А адрес метки неизвестен до линковки. В зависимости от значения адреса нужно сгенерировать или одну инструкцию, или две, поэтому на этапе компиляции просто выдаётся ошибка. Если всё же очень хочется, приходится выписывать вручную li как две инструкции (lui+addi), тогда всё будет ок, но addi в итоге может оказаться лишней.


        1. COKPOWEHEU Автор
          17.02.2025 11:50

          Еще раз. Любое обращение к памяти из юзерского кода на Си. Оно разворачивается в auipc, а не в lui. Если не предпринимать дополнительных мер. И с этой проблемой стартап-код никак не поможет, будь он хоть трижды позиционно-независимым.


          1. Disasm
            17.02.2025 11:50

            Вероятно у нас какие-то очень разные компиляторы или параметры компиляции, потому что у меня разворачивается в lui:

            int C = 5;
            
            int foo(int a, int b) {
                return a + b + C;
            }
            
            0000000000010244 <foo>:
               10244:	67c5                	lui	a5,0x11
               10246:	2507a783          	lw	a5,592(a5) # 11250 <C>
               1024a:	9d2d                	addw	a0,a0,a1
               1024c:	9d3d                	addw	a0,a0,a5
               1024e:	8082                	ret
            

            Но даже безотносительно этого, если у вас доступ к памяти через auipc, стартап-код как раз может обеспечить корректность выполняемого кода, передав на него управление по правильному адресу. По тому, который ожидает линкер во время линковки.


            1. COKPOWEHEU Автор
              17.02.2025 11:50

              int C = 5;
              
              int foo(int a, int b) {
                  return a + b + C;
               202:	952e                	add	a0,a0,a1
               204:	20000797          	auipc	a5,0x20000
               208:	dfc7a783          	lw	a5,-516(a5) # 20000000 <C>
              }
               20c:	953e                	add	a0,a0,a5
               20e:	8082                	ret
              

              Похоже, дело во флаге -mcmodel. У меня стоял medany, а у вас, вероятно, medlow. По крайней мере, я сейчас его поменял и ваше lui получилось. Так вот зачем этот флаг нужен. Спасибо что пнули в нужном направлении.
              Что забавно, в документации позиционно-независимым назван как раз medany:

              The code generated by the medium-any code model is position-independent, but is not guaranteed to function correctly when linked into position-independent executables or libraries.

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

              Если в ld-скрипте адрес начала прошивки указан 0x8000'0000, в реальности ее располагают в 0x8001'0000, а для доступа к оперативке используется auipc, стартап никак не может на это повлиять.

              Другое дело, что если mcmodel действительно позволяет отвязать адреса оперативки от адресов флеша и генерировать позиционно-независимый код (надо будет еще проверить ссылки на функции, таблицы переходов и т.п.), то со стартапом заморачиваться уже стоит.