Страница 3 из 6
Re: Зачем stm32 требует самостоятельно настраивать startup.s
Добавлено: Пт авг 26, 2022 15:21:55
ddr4
[uquote="MLX90640",url="/forum/viewtopic.php?p=4278619#p4278619"]Про векторы прерываний очень хорошо сказано в Programming Manual на серию Кортексов. Для M3, стоящем в F401 - это будет документ PM0214, стр.40. Табличка с определенной структурой, в которую помещаются значения адресов, по которым располагается тот или иной исполняемый код, вызываемый при наступлении события прерыавния/исключения. Вторая строчка таблички от начала называется reset Vector и она хранит адрес, по которому расположена первая инструкция исполняемого кода, вызываемая сразу после события сброса МК и которая будет выполнена первой инструкцией. Помещаться эта инструкция может в любом месте из диапазона разрешенных адресов для исполнения инструкций.
Скрипи загрузчика .ld размещает секции в бинарном файле по определенным адресам. Табличка векторов тоже может быть помещена не в самом начале флеша, а где-нить в другом месте, о чем нужно дополнительно сообщить микроконтроллеру в коде программы, изменив VTOR (там, где он есть).
Именно скрипт .ld будет ответственнен за то, что куда кладется на этапе компиляции
В зависимости от конкретной IDE и кмопилятора, состав и синтаксис файлов запуска может отличаться.[/uquote]
Спасибо.
Т.е. по адресу 0x08000000 во флеш записывается наша прошивка,
в начале нашей прошивки расположена таблица векторов (адресов), фактически смещений относительно начала прошивки (которую собрал компоновщик). Встроенный загрузчик stm32 при старте копирует таблицу векторов из флеша в ОЗУ на начальный адрес 0x00000000.
После чего встроенный загрузчик пробегает по таблице, активирует прерывания и прочее согласно данных таблицы, после читает адрес во второй строке таблицы, где расположен адрес начальной функции (reset Vector), в моём случае эта функция _start :
Код: Выделить всё
void __attribute__ ((section(".after_vectors"),noreturn,weak))
_start (void) {...}
В компоновщике указана как ENTRY (_start), функция _start производит инициализацию и секций памяти, а также устройств (в том числе внешних).
Я правильно понимаю?
Re: Зачем stm32 требует самостоятельно настраивать startup.s
Добавлено: Пт авг 26, 2022 15:36:42
VladislavS
[uquote="ddr4",url="/forum/viewtopic.php?p=4278667#p4278667"]Встроенный загрузчик stm32 при старте копирует таблицу векторов из флеша в ОЗУ на начальный адрес 0x00000000.[/uquote]Никак нет. При включении питания на адрес 0x00000000 отображается область памяти, заданная на ножках BOOT0 и BOOT1. Это может быть SRAM (0x20000000), FLASH (0x0800000) или SystemFlash (адрес не помню). Соответственно, то что у вас размещено в коде по адресу 0x08000000 и будет таблицей векторов прерываний. В ней в начале записан адрес стека, затем адреса функций обработки прерываний начиная с Reset_Handler. Посмотрите приложенный файл, он на С, там многое станет понятно.
Re: Зачем stm32 требует самостоятельно настраивать startup.s
Добавлено: Пт авг 26, 2022 15:51:43
MLX90640
Таблица даже не смещений, а абсолютных адресов. Вот так она выглядит в самой прошивке микроконтроллера. Второй элемент таблицы - адрес начала работы программного кода

Re: Зачем stm32 требует самостоятельно настраивать startup.s
Добавлено: Пт авг 26, 2022 16:16:02
VladislavS
[uquote="ddr4",url="/forum/viewtopic.php?p=4278667#p4278667"]После чего встроенный загрузчик пробегает по таблице, активирует прерывания и прочее согласно данных таблицы,[/uquote]И опять нет. Таблица векторов прерываний просто лежит в памяти. При возникновении прерывания контроллер прерываний выбирает по номеру прерывания адрес функции обработчика и передаёт ей управление. Прадварительно сохранив в стеке всё что нужно для возврата из прерывания, само собой.
Добавлено after 17 minutes 22 seconds:
[uquote="ddr4",url="/forum/viewtopic.php?p=4278667#p4278667"]В компоновщике указана как ENTRY (_start),[/uquote]Для кортексов, коими являются чипы STM32, эта опция не имеет особого смысла. Выполнение кода начинается с адреса, указанного в таблице векторов прерывания на месте Reset_Handler.
[uquote="ddr4",url="/forum/viewtopic.php?p=4278667#p4278667"]функция _start производит инициализацию и секций памяти, а также устройств (в том числе внешних).[/uquote]Минимально это инициализация сегментов данных. Нулевых занулением, инициализируемых - копированием из флэш. Строго необходима настройка только тех устройств, без которых невозможна инициализация данных и дальнейшая работа кода. Всё остальное можно делать в main. Я, например, предпочитаю всё железо инициализировать до main, в котором оставляю только логику работы программы. Но это всё уже вкусовщина.
Re: Зачем stm32 требует самостоятельно настраивать startup.s
Добавлено: Пт авг 26, 2022 16:59:01
MLX90640
Есть такая функция, зовется SystemInit() и вызывается до входа в main() как раз из файла "startup_stm32... .s ". По логике названия, оная должна выполнять инициализацию системы. Неплохая задумка, довольно удобная. Ну а по факту написанного в ней, она выполняет только настройку системных частот и латентности флеша. А в случае кубогенерирования, нужность этой функции вообще сведена близко к нулю, поскольку настройка тактирования передана в другую функцию, вызываемую из main().
То есть, изначально по названию задумывалось чуть ли не как основа основ при запуске, а в последствии она стала заброшкой, мусором, который просто забыли удалить.
Да и сам файл "system_stm32..... " так же изначально задумывался как главный файл конфига системы, а сейчас превратился почти в такой же мусор.
Re: Зачем stm32 требует самостоятельно настраивать startup.s
Добавлено: Пт авг 26, 2022 17:18:51
VladislavS
Есть такая штука, как
CMSIS, которая призвана сделать единообразным код для кортексов разных производителей, разных тулчейнов, кодогенераторов и т.д. Следовать ему достаточно хорошая практика. Библиотеки для STM32 и кодогенератор куба достаточно неплохо соответствуют этому шаблону.

Re: Зачем stm32 требует самостоятельно настраивать startup.s
Добавлено: Пт авг 26, 2022 17:22:59
MLX90640
Она то призвана. Да вот с логикой не очень хорошо, недоработали до конца. И реализация в кубогенераторе, повторюсь, совсем не способствует логике как CMSIS, так и вообще логике вещей. Кубогенератор исповедует свою логику тут.
Re: Зачем stm32 требует самостоятельно настраивать startup.s
Добавлено: Пт авг 26, 2022 17:27:27
VladislavS
Кто недоработал?
В зоопарке тигру мясо не докладывают! (c)

Re: Зачем stm32 требует самостоятельно настраивать startup.s
Добавлено: Пт авг 26, 2022 17:29:29
AVI-crak
MLX90640 писал(а):То есть, изначально по названию задумывалось чуть ли не как основа основ при запуске, а в последствии она стала заброшкой, мусором, который просто забыли удалить.
Задумывалось что функция SystemInit() оставит после себя рам память свободной. Для этого в GCC есть нативная галочка - использовать память повторно. Условие всегда срабатывает для SystemInit(), и почти никогда для всего остального.
По этой причине крайне желательно вычистить весь мусор от кодогенераторов, и в ручную настроить периферию по максимуму.
Залезать в startup.s понадобится когда проект перерастёт стадию моргания светиком, но это уже другая тема.
Re: Зачем stm32 требует самостоятельно настраивать startup.s
Добавлено: Пт авг 26, 2022 17:36:06
VladislavS
[uquote="AVI-crak",url="/forum/viewtopic.php?p=4278734#p4278734"]Задумывалось что функция SystemInit() оставит после себя рам память свободной.[/uquote]Я бы сказал больше. Она задумывалась выполняться, когда ещё никакого глобального окружения нет (память не инициализирована) и предназначена для подготовки системы к этой самой инициализации. Собственно и использовать в ней никаких глобальных данных нельзя.
[uquote="AVI-crak",url="/forum/viewtopic.php?p=4278734#p4278734"]По этой причине крайне желательно вычистить весь мусор от кодогенераторов, и в ручную настроить периферию по максимуму.[/uquote]Или не использовать их вовсе.
Re: Зачем stm32 требует самостоятельно настраивать startup.s
Добавлено: Пт авг 26, 2022 17:36:42
MLX90640
*** Блин, дочегоже неудобно тут цитировать цитаты... Вручную копировать/удалять.... елы палы, я уже пальцы сломал добавлять цитаты
Кто не доработал? Да вот даже вы. посмотрите:
Я, например, предпочитаю всё железо инициализировать до main, в котором оставляю только логику работы программы.
то есть, фактически складываете юзер-код в область системы. Впрочем, дело ваше, я тоже так делаю.
функция SystemInit() оставит после себя рам память свободной.
Дак после возврата из любой вызываемой функции стек возвращается в предыдущую позицию и ранее занятая память остается свободной.
алезать в startup.s понадобится когда проект перерастёт стадию моргания светиком,
Практически никогда. Только после того, как вы создадите дополнительные секции, требующие дополнительного обнуления/копирования, или немного изменить поведение кода до входа в main. Например, исключить вызов SystemInit или наоборот, добавить вызов доп.ф-ций инита.
Из описания файла:э
This module performs:
* - Set the initial SP
* - Set the initial PC == Reset_Handler,
* - Set the vector table entries with the exceptions ISR address
* - Configure the clock system --(это записано в файле system_stm32xxx .с)
* - Branches to main in the C library (which eventually
* calls main()).
Она задумывалась выполняться,
В её описании однозначно написано, для чего она задумывалась:
- SystemInit(): Setups the system clock (System clock source, PLL Multiplier
* factors, AHB/APBx prescalers and Flash settings).
* This function is called at startup just after reset and
* before branch to main program. This call is made inside
* the "startup_stm32f1xx_xx.s" file.
(память не инициализирована)
Да ну. Секции data и bss подготавливаются еще до SystemInit (которая в том числе выполняет запуск внешней S(D)RAM, если надо). После неё вызываются статические конструкторы, а затем уже main
Re: Зачем stm32 требует самостоятельно настраивать startup.s
Добавлено: Пт авг 26, 2022 18:19:50
VladislavS
[uquote="MLX90640",url="/forum/viewtopic.php?p=4278741#p4278741"]Да ну. Секции data и bss подготавливаются еще до SystemInit (которая в том числе выполняет запуск внешней S(D)RAM, если надо). После неё вызываются статические конструкторы, а затем уже main[/uquote]Открываем репозиторий CMSIS, находим там
первый попавшийся стартап и наблюдаем, что SystemInit это первое что выполняется в Reset_Handler.
[uquote="MLX90640",url="/forum/viewtopic.php?p=4278741#p4278741"]SystemInit (которая в том числе выполняет запуск внешней S(D)RAM, если надо). После неё вызываются статические конструкторы, а затем уже main[/uquote]Интересно, а если сегменты данных в этой самой SDRAM и находятся? Или в чипах STM32H7 бывают блоки SRAM выключенные при подаче питания. Как тогда в них до SystemInit что-то инициализировать?
Re: Зачем stm32 требует самостоятельно настраивать startup.s
Добавлено: Пт авг 26, 2022 18:35:50
MLX90640
У вас гранаты не той системы

Я вам могу показать кучу источников файлов с иной структурой.
Потому и говорю, что задумка вначале была неплохой, но со временем состав файлов менялся, каждый пишет так, как ему заблагорассудится. И самое главное, что ни одна из версий не является ошибочной с точки зрения микроконтроллера.
Касательно SDRAM - в нее вообще нерекомендовано помещать отдельные переменные или выполнять доступ непакетным образом, из-за сильного снижения скорости.
То же самое, но по иной причине, с выключенными блоками SRAM. Их основное назначение - хранение буферов, завязанных на какой-либо модуль периферии. И не не для того придумывалось выключение, чтобы сразу же их безусловно включать. Обычно они включаеются/выключаются вместе с той периферией, с которой в паре используются, и обычно имеют команду аппаратного обнуления. Выключение придумано для энергосбережения. Иначе никто бы не усложнял.
Re: Зачем stm32 требует самостоятельно настраивать startup.s
Добавлено: Пт авг 26, 2022 18:51:58
VladislavS
[uquote="MLX90640",url="/forum/viewtopic.php?p=4278758#p4278758"]У вас гранаты не той системы

Я вам могу показать кучу источников файлов с иной структурой.[/uquote]
Делай раз
Спойлер

- 1.png
- (24.94 КБ) 629 скачиваний
Делай два
Спойлер

- 2.png
- (38.8 КБ) 619 скачиваний
И почему-то ARM я верю больше, чем каким-то сомнительным источникам.
[uquote="MLX90640",url="/forum/viewtopic.php?p=4278758#p4278758"]И самое главное, что ни одна из версий не является ошибочной с точки зрения микроконтроллера.[/uquote]В сети гуляет блинк на 48 байт. Он тоже не ошибочен с точки зрения микроконтроллера. Только CMSIS там и не пахнет.
[uquote="MLX90640",url="/forum/viewtopic.php?p=4278758#p4278758"]Касательно SDRAM - в нее вообще нерекомендовано помещать отдельные переменные или выполнять доступ непакетным образом, из-за сильного снижения скорости.[/uquote]Причём тут отдельные переменные? Гигантские буферы тоже надо инициализировать.
[uquote="MLX90640",url="/forum/viewtopic.php?p=4278758#p4278758"]То же самое, но по иной причине, с выключенными блоками SRAM.[/uquote]Это всё ваши фантазии. Никто не запрещает мне хранить что угодно где угодно, если это аппаратно возможно.
Re: Зачем stm32 требует самостоятельно настраивать startup.s
Добавлено: Пт авг 26, 2022 19:06:57
ddr4
[uquote="Мурик",url="/forum/viewtopic.php?p=4278638#p4278638"]Посмотрите стартап из архива и сравните с тем что у вас.[/uquote]
Посмотрел, да теперь понятно. Что таблица векторов явно присутствует в коде прошивки, а не создаётся компоновщиком.
И поискав (по папкам блинка) я нашёл её в файле: cmsis/vectors_stm32f401xc.c
Код: Выделить всё
__attribute__ ((section(".isr_vector"),used))
pHandler __isr_vectors[] =
{
// Cortex-M Core Handlers
(pHandler) &_estack, // The initial stack pointer
Reset_Handler, // The reset handler
................
[uquote="VladislavS",url="/forum/viewtopic.php?p=4278660#p4278660"]Вы путаете конфигурационный файл (скрипт) линкера и стартап. Первое это правила размещения кода и данных в памяти.[/uquote]Под памятью, Вы имеете ввиду бинарный файл, который по ld-скрипту соберёт компоновщик из объектов которые создал компилятор?
[uquote="VladislavS",url="/forum/viewtopic.php?p=4278675#p4278675"]При включении питания на адрес 0x00000000 отображается область памяти, заданная на ножках BOOT0 и BOOT1. Это может быть SRAM (0x20000000), FLASH (0x08000000) или SystemFlash (адрес не помню).[/uquote]То есть без режима прошивки (заданного на ножках BOOT) МК при запуске отображает в ОЗУ память flash, куда мы разместили прошивку с таблицей векторов по адресу 0x08000000 (адрес во флеш или озу памяти?).
[uquote="VladislavS",url="/forum/viewtopic.php?p=4278675#p4278675"]то что у вас размещено в коде по адресу 0x080000000 и будет таблицей векторов прерываний. В ней в начале записан адрес стека, затем адреса функций обработки прерываний начиная с Reset_Handler. Посмотрите приложенный файл, он на С, там многое станет понятно.[/uquote]
Разве в коде мы устанавливаем адреса? По моему, код может только обращаться по адресу. Компилятор создаёт бинарный файл, который при прошивке МК мы передаём загрузчику, который размещает его во flash-памяти МК по некоторому адресу. И когда МК стартует он отображает эти данные из flash в озу.
И если так, то почему адрес 0x080000000, - ведь он соответствует размеру flash-памяти 519 МБ ? У МК только 256 кБ, не говоря уже о 64 кБ SRAM.
[uquote="VladislavS",url="/forum/viewtopic.php?p=4278675#p4278675"]
startup_gcc_stm32f401.zip
[/uquote]
Спасибо, я нашёл подобное в Eclipse в cmsis/vectors_stm32f401xc.c
[uquote="VladislavS",url="/forum/viewtopic.php?p=4278675#p4278675"]Для кортексов, коими являются чипы STM32, эта опция не имеет особого смысла. Выполнение кода начинается с адреса, указанного в таблице векторов прерывания на месте Reset_Handler.[/uquote] Да, после того как я нашёл таблицу векторов в коде cmsis/vectors_stm32f401xc.c, соответственно нашёл и Reset_Handler(), который там вызывает _start() который вызывает main().
[uquote="MLX90640",url="/forum/viewtopic.php?p=4278685#p4278685"]Таблица даже не смещений, а абсолютных адресов. Вот так она выглядит в самой прошивке микроконтроллера. Второй элемент таблицы - адрес начала работы программного кода

[/uquote]
Как я понимаю это отладчик памяти МК. Интересно как в таблице появляются эти абсолютные адреса, да тем более по такому адресу?
Re: Зачем stm32 требует самостоятельно настраивать startup.s
Добавлено: Пт авг 26, 2022 19:09:54
MLX90640
Это (на скрине) не отадчик, это просто просмотр hex-файла прошивки в ST-Link Utility - проге для чтения и заливки прошивки в микроконтроллер. А в таблице эти адреса появляются стараниями линкера в процессе компиляции. Он раскладывает программный код по адресам и адреса функций, реализующих обработку прерываний, помещает в таблицу.
Гигантские буферы тоже надо инициализировать.
Попробуйте проинициализировать побайтно пару мегабайт в SDRAM - расскажете о впечатлениях о скорости непактного доступа

Почитайте про SDRAM, расширьте свой кругозор.
Вы видимо не так давно с ARM занимаетесь, потому не вкурсах про историю изменений файлов самими ARM. Я то значительно раньше вас начал их изучать.
Re: Зачем stm32 требует самостоятельно настраивать startup.s
Добавлено: Пт авг 26, 2022 19:44:21
VladislavS
[uquote="ddr4",url="/forum/viewtopic.php?p=4278782#p4278782"]Под памятью, Вы имеете ввиду бинарный файл, который по ld-скрипту соберёт компоновщик из объектов которые создал компилятор?[/uquote]Нет, под памятью я подразумеваю всё адресное пространство. Бинарный файл это как бы "слепок" программы. Стартовый код разворачивает из него данные в разные области памяти. В какие-то занулением, в какие-то копированием.
[uquote="ddr4",url="/forum/viewtopic.php?p=4278782#p4278782"]То есть без режима прошивки (заданного на ножках BOOT) МК при запуске отображает в ОЗУ память flash, куда мы разместили прошивку с таблицей векторов по адресу 0x08000000 (адрес во флеш или озу памяти?).[/uquote]Не в ОЗУ, а в адресное пространство. Если на 0x00000000 отражена SRAM, то запись туда возможна, а если флэш, то соответственно нет.
Добавлено after 20 minutes 28 seconds:
[uquote="ddr4",url="/forum/viewtopic.php?p=4278782#p4278782"]Разве в коде мы устанавливаем адреса? По моему, код может только обращаться по адресу.[/uquote]Ну ещё он может размещаться по адреcу. Размещает по адресу, обычно, линкер в соответствие с правилами заданными в его конфигурационном скрипте.
[uquote="ddr4",url="/forum/viewtopic.php?p=4278782#p4278782"]Компилятор создаёт бинарный файл, который при прошивке МК мы передаём загрузчику, который размещает его во flash-памяти МК по некоторому адресу.[/uquote]Этот некоторый адрес в вашем контроллере 0x08000000.
[uquote="ddr4",url="/forum/viewtopic.php?p=4278782#p4278782"]И если так, то почему адрес 0x08000000, - ведь он соответствует размеру flash-памяти 519 МБ ? У МК только 256 кБ, не говоря уже о 64 кБ SRAM.[/uquote]Адресное пространство 32-разрядное и может адресовать 4 Гб. В любом месте этого адресного пространства могут быть кусочки по несколько килобайт или мегабайт. Это и разного типа памяти, и регистры периферийных устройств, и всякого рода FIFO для USB или Ethernet и т.д. Цифры о которых мы говорим - начальные адреса этих "кусочков". А между ними "дыры".
Re: Зачем stm32 требует самостоятельно настраивать startup.s
Добавлено: Пт авг 26, 2022 20:33:44
ddr4
[uquote="MLX90640",url="/forum/viewtopic.php?p=4278785#p4278785"]это просто просмотр hex-файла прошивки в ST-Link Utility - проге для чтения и заливки прошивки в микроконтроллер. А в таблице эти адреса появляются стараниями линкера в процессе компиляции. Он раскладывает программный код по адресам и адреса функций, реализующих обработку прерываний, помещает в таблицу.[/uquote] Возможно это какой-то умный просмотрщик. Наверняка он эмулирует отображения памяти в МК, либо берёт адрес из файла. Возможно адрес размещения 0x08000000 где-то явно указан. Либо в коде, либо в компиляторе.
Но просто поиск адреса 0x08000000, по коду блинка результата не дал.
[uquote="VladislavS",url="/forum/viewtopic.php?p=4278800#p4278800"]Добавлено after 20 minutes 28 seconds:
[uquote="ddr4",url="/forum/viewtopic.php?p=4278782#p4278782"]Разве в коде мы устанавливаем адреса? По моему, код может только обращаться по адресу.[/uquote]Ну ещё он может размещаться по адреcу. Размещает по адресу, обычно, линкер в соответствие с правилами заданными в его конфигурационном скрипте.[/uquote]Линкер скорее задаёт (записывает в бинарный файл) адрес по которому уже МК будет пытаться разместить код в адресном пространстве. Вот только непонятно откуда Линкер или компилятор берёт адрес 0x08000000, в коде блинка я его не нашёл.
[uquote="VladislavS",url="/forum/viewtopic.php?p=4278800#p4278800"][uquote="ddr4",url="/forum/viewtopic.php?p=4278782#p4278782"]И если так, то почему адрес 0x08000000, - ведь он соответствует размеру flash-памяти 519 МБ ? У МК только 256 кБ, не говоря уже о 64 кБ SRAM.[/uquote]Адресное пространство 32-разрядное и может адресовать 4 Гб. В любом месте этого адресного пространства могут быть кусочки по несколько килобайт или мегабайт. Это и разного типа памяти, и регистры периферийных устройств, и всякого рода FIFO для USB или Eythernet и т.д. Цифры о которых мы говорим - начальные адреса этих "кусочков". А между ними "дыры".[/uquote]Понятно, то есть адресное пространство больше памяти ОЗУ.
Re: Зачем stm32 требует самостоятельно настраивать startup.s
Добавлено: Пт авг 26, 2022 20:41:24
VladislavS
[uquote="ddr4",url="/forum/viewtopic.php?p=4278866#p4278866"]Возможно это какой-то умный просмотрщик. Наверняка он эмулирует отображения памяти в МК, либо берёт адрес из файла. Возможно адрес размещения 0x08000000 где-то явно указан. Либо в коде, либо в компиляторе.[/uquote]HEX-файл содержит адреса.
[uquote="ddr4",url="/forum/viewtopic.php?p=4278866#p4278866"]Вот только непонятно откуда Линкер или компилятор берёт адрес 0x08000000, в коде блинка я его не нашёл.[/uquote]Линкер берёт его из своего скрипта. Загляните в *.ld-файл. Наверняка, что-то похожее найдёте
Код: Выделить всё
MEMORY
{
FLASH (RX) : ORIGIN = 0x08000000, LENGTH = 128K
SRAM (RWX) : ORIGIN = 0x20000000, LENGTH = 20K
}
Re: Зачем stm32 требует самостоятельно настраивать startup.s
Добавлено: Пт авг 26, 2022 20:46:28
MLX90640
Самый обычный просмотрщик стандартного hex-файла. Открываем в блокноте этот файл и читаем первую строчку:
:020000040800F2
выделенное - и есть адрес (его старшие байты) начала размещения данных. Последующие строчки содержат заголовок строки и далее сами данные, в конце контрольная сумма строки.
:1000000000500020DD0300084503000851030008EC