azarubkin
#1
Hi,
How do I create firmware using STM32 Arduino framework that is usable with bootloader? As far as I understand, I need to tell linker to shift the firmware to higher addresses. How can I do that? Should I just pass some flag to linker, or there’s some option that can be added to platformio.ini
? Perhaps any examples?
My MCU is STM32F103CB.
1 Like
azarubkin
#2
I’ve noticed there’s upload_protocol = dfu
option that, according to builder\frameworks\arduino\maple\stm32f1.
sets appropriate linker script to offset the application to 0x8002000 address.
It apparently can be used with any bootloader, including custom. The only requirement is to fit the bootloader code in the freed ROM region. If it doesn’t fit, that file and bootloader script can be edited, though.
1 Like
azarubkin
#3
Does anyone know how to supply custom .ld
file path to the linker to avoid editing the files supplied with PlatformIO?
I can put it into variant’s ld
subfolder inside Arduino STM32 framework, but what about a subfolder inside a project folder?
azarubkin
#4
Got it. -Wl,-T./my.ld
. The path is relative to project root dir.
azarubkin
#5
When I try to pass custom vector table start address by defining VECT_TAB_ADDR, I get the following error:
TypeError: unhashable type: 'list': File "C:\.platformio\penv\lib\site-packages\platformio\builder\main.py", line 162: env.SConscript("$BUILD_SCRIPT") File "C:\.platformio\packages\tool-scons\script\..\engine\SCons\Script\SConscript.py", line 541: return _SConscript(self.fs, *files, **subst_kw) File "C:\.platformio\packages\tool-scons\script\..\engine\SCons\Script\SConscript.py", line 250: exec _file_ in call_stack[-1].globals File "C:\.platformio\platforms\ststm32\builder\main.py", line 127: target_elf = env.BuildProgram() File "C:\.platformio\packages\tool-scons\script\..\engine\SCons\Environment.py", line 224: return self.method(*nargs, **kwargs) File "C:\.platformio\penv\lib\site-packages\platformio\builder\tools\platformio.py", line 67: env.ProcessUnFlags(env.get("BUILD_UNFLAGS")) File "C:\.platformio\packages\tool-scons\script\..\engine\SCons\Environment.py", line 224: return self.method(*nargs, **kwargs) File "C:\.platformio\penv\lib\site-packages\platformio\builder\tools\platformio.py", line 173: all_flags = set(all_flags)
My platformio.ini
file’s relevant portion:
build_flags = -Wl,-T./my.ld -v -DVECT_TAB_ADDR=134238208 build_unflags = -DVECT_TAB_ADDR=134217728
Adding a space between -D
and VECT_TAB_ADDR
doesn’t help.
azarubkin
#6
It was a bug, it’s fixed now for some time already.
No more questions
sdemen
#7
Добрый день…
Я правда на 401 и тоже из Ардуино попытался прыгнуть!
.
Потом в PlatformIO перешёл в Кубе.
Не помогло , похоже вектор прерывания не устанавливается!
Поскольку между B-1 и B-2 нет соединения gpio для активации режима загрузки для B-2, возможно ли, чтобы плата B-2 установила флаг во флэш-памяти за пределами области основного приложения, чтобы проверить его. и использовать его как флаг активации режима загрузки?
Я не уверен, что вы предлагаете, или как ваше предложение решит проблему. В идеале у вас должно быть средство формы B1 для прямого сброса B2 через его линию /RESET, но в противном случае, если он загружен приложением, которое принимает команду сброса или сигнал через RS-485, тогда вы можете затем выдать программный -reset для запуска загрузчика. На устройствах Cortex-M это можно сделать через NVIC.
Если вам нужно передать информацию загрузчику B2 — возможно, чтобы вызвать обновление или обойти его и загрузить приложение, вам не нужно программировать флэш-память для этого, вы можете просто написать команду загрузки или подпись через зарезервированную область SRAM (лучше всего справа вверху), которая не инициализируется при запуске среды выполнения (или содержимое которого вы захватываете до такой инициализации). Содержимое в SRAM сохранится после сброса до тех пор, пока поддерживается питание, поэтому его можно использовать для связи между приложением и загрузчиком — в обоих направлениях.
Это, конечно, проблема с начальной загрузкой — что делать, если не загружено приложение, принимающее команду сброса, или приложение недействительно/завершено (прерывание программирования). Что ж, перемещенная область приложения будет иметь свою таблицу векторов, включая начальный SP и вектор сброса прямо в начале. В вашем загрузчике, когда получены первые 8 байт образа, вы удерживаете их и не программируете эту область, пока остальная часть образа не будет записана. При программировании вектора сброса последним, если программирование будет прервано, это местоположение не будет действительным адресом. Загрузчик может проверить его (или проверить, находится ли он в состоянии стирания), и, если он недействителен/записан, он может бесконечно ждать обновления или просто выполнить сброс, чтобы повторить опрос обновления. Однако имейте в виду, что здесь есть небольшая ошибка STM32 — большинство частей стирают флэш-память до состояния «все единицы» (0xFF), однако некоторые (части STM32Lxx) стирают до состояния «все нули». Конечно, вы можете просто проверить 0x00000000 или 0xffffffff, поскольку ни один из них не будет действительным начальным адресом, или явно проверить диапазон.
Можно ли записывать поток данных напрямую с входа uart в область флэш-памяти каждого приложения? вот так:
Да, но помните, что на STM32 обычно код выполняется из той же флэш-памяти, которую вы пытаетесь запрограммировать, и что шина останавливается во время записи и стирания флэш-памяти, так что если вы выполняете из флэш-памяти, выполнение останавливается. Для стирания страницы это может быть несколько миллисекунд, а для частей с большими страницами даже несколько сотен миллисекунд. Это может означать, что вы не можете прочитать символы на UART, если вы используете опрос или прерывание.
Эту проблему можно решить путем разработки протокола. Например, если вы используете пакетный протокол, в котором последний пакет должен быть подтвержден перед отправкой следующего, вы можете использовать его в качестве управления потоком. После того, как вы сопоставили блок данных для записи, вы просто откладываете подтверждение последнего пакета до
Теперь, с учетом всего сказанного, вы можете увеличить флэш-память, доступную для B1, вообще не буферизируя образ для B2 на B1, и просто внедрить двунаправленную сквозную передачу, чтобы вход на UART B1 передавался непосредственно на Выход B1 RS-485 (конечно, также UART, поэтому название вашего порта неоднозначно), а вход B1 RS-485 передается непосредственно на выход UART. Таким образом, B1 станет «прозрачным», и будет казаться, что средство обновления взаимодействует напрямую с B2. Возможно, это намного проще и быстрее, и если загрузчик является «отказоустойчивым», как описано выше, он все равно будет разрешать повторные попытки после прерывания.
Функция сквозного доступа может быть частью приложения B1 или «режимом» загрузчика. Сквозной режим может быть вызван определенной командой загрузки, или приложение может передать команду «режим загрузки» через механизм SRAM, описанный ранее.
В любом случае в идеале у вас должен быть одинаковый код загрузчика на B1 и B2 для простоты и гибкости. Нет причин, по которым этого не должно быть; они оба получают обновления через UART.
C:\Program Files (x86)\STMicroelectronics\STM32 ST-LINK Utility\ST- LINK Утилита
клон git https://github.com/BuildStormTechnologies/stm32_bootloader_library
Загрузчик и приложение используют UART2 (PA2, PA3) для обновления прошивки и печати журналов устройства.
компакт-диск stm32_bootloader_library/кли-инструмент
stm32UpdateTool-win.exe
прошить все .\binaries\application_v200.bin
флеш-приложение .\binaries\application_v201.bin
Используйте проект f407_led_demo для создания пользовательского приложения. Он использует предварительно скомпилированный библиотечный объект, который будет связан с пользовательским приложением.
Тип | Адрес | размер | Количество секторов | Индекс сектора |
Загрузчик | 0x08000000 | 14КБ | 1 | 0 |
Конфигурация загрузчика | 0x08004000 | 16КБ | 1 | 1 |
Применение | 0x08010000 | 448 КБ | 4 | 4 – 7 |
Временный раздел загрузки | 0x08070000 | 512 КБ | 4 | 8 – 11 |
Приложение находится по адресу 0x08010000, и его необходимо настроить в настройках компоновщика, как показано ниже.
ПАМЯТЬ { CCMRAM (xrw): ORIGIN = 0x10000000, LENGTH = 64K RAM (xrw): ORIGIN = 0x20000000, LENGTH = 128K FLASH (rx): ORIGIN = 0x8010000, LENGTH = 448K }
Включить в проект папку utils, содержащую заголовочные файлы библиотек.
Включить предварительно скомпилированный объектный файл в проект.
Конечный двоичный файл приложения будет зашифрован с помощью исполняемого скрипта (BS_ENCRYPT.exe). Его необходимо добавить в настройки проекта.
Окончательный зашифрованный двоичный файл приложения будет сгенерирован в папке Debug как projectName_release.bin. Этот файл можно использовать для обновлений встроенного ПО Serial/OTA.
Загрузчик и приложение были протестированы на указанных ниже контроллерах с флэш-памятью 1 Мб. Его можно настроить для использования на любом из контроллеров STM32.
Бесплатное использование библиотеки ограничено 20 циклами загрузки. Она предназначена только для тестирования и демонстрации.