Программирование ARM-контроллеров STM32 на ядре Cortex-M3. Часть 5. Как залить прошивку в контроллер
Ну, вот мы и дошли до одного из самых интересных этапов, — как же залить в контроллер готовую прошивку и оживить наконец нашу железяку (а также как считать прошивку обратно или защитить её от чтения / перезаписи).
Вообще-то прошивать контроллеры STM32 можно по-разному, но мы рассмотрим самый простой вариант прошивки — через последовательный интерфейс с помощью фирменной утилиты Flash Loader Demonstrator. Эта утилита совершенно бесплатна и её можно скачать как с официального, так и с нашего сайта.
Как мы ранее уже говорили, — в системной области памяти контроллера зашит bootloader. Именно он и позволяет записать прошивку во flash-память через последовательный интерфейс.
Детально bootloader описан в документе AN2606 (CD00167594.pdf), а используемый им протокол — в документе AN3155 (CD00264342.pdf). Это для тех, кто хочет исчерпывающей информации, а мы рассмотрим процесс прошивки через bootloader вкратце.
Для начала вам нужно скачать и установить себе на компьютер утилиту Flash Loader Demonstrator.
Далее, нужно соединить контроллер с компьютером через UART1. Мой подопытный STM32F103C8T6 имеет 48-выводный корпус, в котором UART1 выведен на ноги 30 (Tx) и 31 (Rx).
Обратите внимание, что в контроллере используется именно UART (причём с уровнями 0/+3,3В), а не RS-232, то есть соединять напрямую выводы контроллера и com-порт компьютера нельзя. Я нашёл выход из этой ситуации в использовании USB-to-COM преобразователя RH-0002 на микросхеме cp2102. Помимо того, что этот преобразователь может использоваться как USB-to-UART с уровнями 0/+3,3 В (его можно разделить на две отдельных части: USB-to-UART и UART-to-RS232), он также позволяет запитать контроллер напряжением 3,3 Вольта (то есть отпадает необходимость во внешнем источнике питания). Вот здесь описано, как собрать преобразователь самостоятельно
Итак, ногу Tx контроллера нужно соединить с ногой Rx преобразователя, а ногу Rx контроллера — с ногой Tx преобразователя. Кроме этого, контроллер нужно запитать и обеспечить нужные уровни на ногах BOOT0 (pin 44), BOOT1 (pin 20). Для запуска bootloadera, который расположен в system memory, ногу BOOT1 нужно подтянуть к «земле», а BOOT0 — к «питанию» (табличка справа).
Подтяжку для BOOT0, BOOT1 лучше делать не жёсткую, а джамперами, чтобы можно было легко выбирать режимы загрузки (например, переключившись после заливки проги в режим загрузки из flash, можно будет эту прогу сразу и потестить).
Схема подключения показана ниже.
Дальше всё просто. Запускаем Flash Loader Demonstrator. Откроется страничка, на которой нужно выбрать com-порт и скорость обмена.
Чётность и количество бит данных уже настроены как надо, скорость можно менять — контроллер в процессе инициализации обмена настраивается на выбранную скорость автоматически, com-порт нужно выбрать тот, который создался при подключении USB-to-COM преобразователя к компьютеру (наш преобразователь создаёт при подключении виртуальный com-порт, полностью имитирующий настоящий аппаратный). После того, как всё настроили — жмём «Next».
О том, что всё нормально и соединиться с контроллером удалось, нам сообщит зелёный сигнал светофора на следующей страничке. Если связь не установится — на эту страничку нас вообще не пустят, сообщив, что контроллер не отвечает.
При установлении связи программа автоматически определит сколько у контроллера flash-памяти и защищена ли эта память от чтения. Нажав кнопку «Remove protection» защиту можно снять, но при этом содержимое флеша будет стёрто (предыдущая записанная туда прошивка уничтожится). Жмём «Next».
В следующем окне нам предлагают выбрать тип программируемого камня (хотя непонятно зачем, — он и так автоматически определяется), а также показывают для нашего камня PID, карту flash-памяти, и версию bootloader-а. Просто жмём «Next».
В следующем окне нужно выбрать, что мы собственно хотим с нашим контроллером делать. Тут возможны следующие варианты: Erase (стереть), Download to device (загрузить в контроллер прошивку), Upload from device (считать прошивку с контроллера), Enable/Disable Flash protection (включить/выключить защиту flash-памяти), Edit option bytes (изменить байты опций).
- Если мы хотим залить прошивку — выбираем Download to device, потом жмём на квадрат с тремя точками и выбираем в проводнике файл с прошивкой, которую надо залить, после чего опять жмём «Next».
- Если мы выберем считывание прошивки, то нажав на квадрат с тремя точками напротив пункта Upload from device нужно указать путь к файлу, в который вы хотите сохранить считанную прошивку (если файл не существует, — вас спросят хотите ли вы его создать).
- Если же нам нужно защитить прошивку от чтения или перезаписи или, наоборот, отменить такую защиту, то ставим галочку напротив Enable/Disable Flash protection и ниже, в выпадающих меню, выбираем, что же именно нужно сделать.
- Если нам нужна более «тонкая настройка» контроллера — выбираем пункт Edit option bytes.
Как я уже говорил, если вы отмените установленную ранее защиту от чтения, то это всё равно не даст вам возможности считать защищённую программу, так как программа после отмены защиты будет попросту стёрта.
Ну да ладно, мы немного отвлеклись. Итак, допустим мы выбрали заливку прошивки в контроллер и нажали «Next».
На следующей странице внизу появится прогресс-бар, в котором будет показан ход выполнения процедуры загрузки. После того, как вся прошивка будет загружена в контроллер, этот прогресс-бар станет зелёным и в нём белыми буквами будет написано: «Download operation finished successfully» (операция загрузки успешно завершена). После этого, можно нажать кнопку «Close» и закрыть Flash Loader Demonstrator
Всё, теперь чтобы залитая программа начала выполняться нам останется только настроить контроллер на загрузку из flash (BOOT0 = 0, BOOT1 — любой уровень) и перезагрузить его.
ru_radio_electr
Вынужденно слезаем с ST32F103VGT6 на его китайский аналог GD32F103VGT6. Код проекта с стм32 байт в байт залился в китайский камень как был. Даже линк файлы не меняли. Все работает вроде бы отлично, отлаживается даже, как так и надо. НО. некоторый код выполняется в полтора раза быстрей, словно работает на 108мгц, а не на 75.
Причем, судя по наблюдениям за периферией (таймеры и прочее), все остальное работает штатно. Частоты шин и периферии совпадают с стм32 (работает на том же коде).
SysTick тикает одинаково.
DWT тикает одинаково.
Timer2 тикает одинаково.
UART и прочее работает штатно, на нужных бодрейтах.
Да, ГД может работать на 108, но я покурил даташит его и, судя по нему, все биты прескаллеров один к одному как в стм32, т.е. если код запускает стм32 на 72мгц, то этот же код должен запустить ГД32 на 72мгц. А код исполняется быстрей. Хм.
- 22 comments
- —
Когда-то давно, во времена DOS, с выпуском новых процессоров (кажется, фирмы Cyrix) некоторые программы стали при запуске выдавать ошибку деления на ноль, хотя в самой программе никакого деления не было (или до него просто не доходило). Сначала это объясняли тем, что эти процессоры — не «настоящие, от Intel»; но по мере роста частоты, эта ошибка появилась и на Intel.
Оказалось, что какие-то компиляторы вставляли в начало программы «измерение скорости процессора», которое делалось замером времени выполнения какого-то цикла, а потом делением константы на это время. И на быстрых процессорах время оказывалось нулевым.
Короче говоря, нет ничего удивительного в том, что подражатели делают процессор, который на отдельных командах оказывается намного быстрее оригинала.
Не «какие-то», а Borland Turbo Pascal версии 7.0 и около, причём проблема возникала только в программах использовавших модуль CRT — это в нём был замер скорости холостым циклом чтобы потом делать Delay.
Случилось это примерно во времена перехода с 486 на пентиум, который был хоть и слабенький, но суперскаляр, и обгонял 486 значительно, хотя и не настолько чтобы время было нулевым — просто результат деления не помещался в 16 бит результата, что тоже приводило к исключению.
А то что это случилось именно на Cyrix’ах (сами по себе они были достаточно хуёвенькие) объясняется очень просто: они были значительно дешевле и потому распространены сильнее ориджинал пентиумов. Так что никаким мифическим «последователи и подражатели делают лучше чем оригинал» здесь и не пахнет, а объясняется всё факторами чисто экономическими.
Да нет же, любой код. Вот, например, такой:
void stupid(uint32_t delay)
<
volatile uint32_t i;
i = delay;
while(i)
<
i—;
>
>
Этот цикл на китайце прокручивается в полтора раза быстрей. При той же частоте.
то есть ты ему вводишь показатель задержки исполнения , а как по твоему это должно повлиять на другие операции ? Например на скорость выборки из памяти ?
То что у тебя раньше этот код давал задержку выборки не значит что это хоть как то соответствует требованию RTOS.
У тебя таймер в устройстве есть ? Или ты просто выставляешь задержку исполнения и ждёшь что у тебя будет одинаковый интервал на разных устройствах.
Пойми в девайсе ты имеешь дело с частотой ЦПУ но организация кеша или внутренней памяти, эффективность суперскаляра ( если таковой имеется) , у всех разная. Естественно если устройство выполнено не методом фотокопирования а разработано то скорее всего у него просто более эффективная организация памяти как я сразу и говорил.
То что ты побочным образом выставляя задержку по выборке из памяти старого устройства получал нужный тебе интервал вовсе не означает что он будет и тут такой же.
typedef struct _PROCESSOR_POWER_INFORMATION <
ULONG Number;
ULONG MaxMhz;
ULONG CurrentMhz;
ULONG MhzLimit;
ULONG MaxIdleState;
ULONG CurrentIdleState;
> PROCESSOR_POWER_INFORMATION, * PPROCESSOR_POWER_INFORMATION;
int main(int argc, char* argv[])
<
SYSTEM_INFO si = < 0 >;
GetSystemInfo(&si);
std::vector a(si.dwNumberOfProcessors);
DWORD dwSize = sizeof(PROCESSOR_POWER_INFORMATION) * si.dwNumberOfProcessors;
CallNtPowerInformation(ProcessorInformat ion, NULL, 0, &a[0], dwSize);
std::cout << a[0].CurrentMhz << » Mhz»;
Вот так правильно
Т должен снять параметры частоты устройства а задержку или делитель выставлять исходя из него.
Тогда переносимость программы будет 100%
А так у тебя даже на оригиналах отклонения в периодах задержки были разные — просто они были в рамках твоей допустимой погрешности
Плата микроконтроллера YD-CH32V307VCT6 RISC-V поставляется с Ethernet и большим количеством входов/выходов.
В начале года мы писали о микроконтроллере WCH CH32V307 RISC-V и макетной плате с 8х портами UART, управляемыми по Ethernet. Теперь нам сообщили о похожем устройстве, но гораздо более компактном VCC-GND Studio под названием «YD-CH32V307VCT6».
Помимо микроконтроллера RISC-V с частотой 144 МГц, плата оснащена портом Ethernet 10 Мбит/с, двумя портами USB Type-C, флэш-памятью SPI, EEPROM, разъемом для карты microSD и четырьмя рядами по 24 контакта в каждом, всего 96 контактов, открывающих все контакты из корпуса LQFP100.
Технические характеристики платы YD-CH32V307VCT6:
- MCU — WCH CH32V307VCT6 32-битный микроконтроллер RISC-V с частотой 144 МГц с 256K Flash, 64K SRAM
- Хранилище — 32 Мбит SPI NOR flash (W25Q32), 64 Кбит EEPROM (24C64), слот для карты MicroSD
- Сеть — Ethernet 10 Мбит/с
- USB — 1х порт USB 2.0 Type-C (высокая скорость: 480 Мбит/с), 1х порт USB 2.0 Type-C (полная скорость: 12 Мбит/с)
- Расширение — 2x 48-контактных разъема с
- 2 х 12-битных ЦАП
- 2-элементный 16-канальный 12-разрядный АЦП
- 16-канальный TouchKey.
- 2x USART, 5x UART.
- 2x интерфейса CAN (2.0B активен).
- SDIO-интерфейс
- 2x I2C, 3x интерфейса SPI
- 2 интерфейса I2S.
- До 80 портов GPIO, до 16 внешних прерываний
- Так далее…
- 5В через USB-порт
- 1А LDO
- Устройство PPTC (полимерный положительный температурный коэффициент), также известное как самовосстанавливающийся предохранитель.
Любой порт USB можно использовать для сохранения прошивки с помощью WCHISPTool (только для Windows), а программирование можно выполнять в среде MounRiver Studio IDE , которая, как говорят, похожа на Arm Keil MDK и доступна как для Windows, так и для Linuх и включает также инструмент для загрузки (так что WCHISPTool может не понадобиться?). Вы также найдете техническое описание и справочное руководство CH32V307VCT6, а также примеры кода на Github. Этот репозиторий предназначен для платы WCH, но он также должен работать на плате VCC-GND Studio с минимальными модификациями (или вообще без них).
Вы также можете подключить отладчик YD-Link, показанный выше, к плате YD-CH32V307VCT6 для упрощения отладки. VCC-GND Studio также хранит некоторую документацию по плате и отладчику, но только/в основном на китайском языке.
Плату YD-CH32V307VCT6 можно приобрести на Aliexpress за 9,50 долларов плюс доставка, но есть также вариант «Board Dugger» за 12 долларов, который, как мы полагаем, включает в себя плату ввода-вывода Ethernet RISC-V и отладчик YD-Link.
С конца прошлого года вокруг WCH царила «позитивная атмосфера». Это началось с того, что компания открыла учетную запись openwch Github, содержащую ресурсы для их микроконтроллеров и других чипов. К тому же, Патрик Янг, технический директор WCH принимает активное участие и отвечал на все вопросы в Twitter, и мы прочитали несколько положительных отзывов, в том числе от Olimex:
Просто хочу поделиться тем, что @WCH_TECH @Patrick_RISCV оказывают невероятную поддержку своим клиентам! Мы сообщили об ошибке в драйвере CH9344L Linux, и она была исправлена всего за несколько дней. Вы, ребята, потрясающие! В будущем будет много плат Olimex с вашими микросхемами.
Если бы только у них был форум поддержки или список рассылки, это помогло бы большему количеству людей, поскольку Twitter — не лучшее решение для хранения истории распространенных проблем или сообщений об ошибках.