Прошу прощения, только потом заметил, что не новый пост добавил а редактировал предыдущий, ответ Мурику и arkhnchul будут здесь. Видать движок так работает, чтоб несколько постов одного автора не набивать.
[uquote="VladislavS",url="/forum/viewtopic.php?p=3719535#p3719535"]При включении питания в RAM находятся случайные данные. Стартовый код программы принудительно обнуляет глобальные неинициализированные переменные и записывает начальные значения в инициализированные. После чего вызывает конструкторы глобальных объектов, если код на С++, и передаёт управление в main.[/uquote]
если правильно понимаю в стартапе это void Default_Reset_Handler(void), в ней есть секция ASM:
Код: Выделить всё
/* Zero fill the bss segment. This is done with inline assembly since this
will clear the value of pulDest if it is not kept in a register. */
__asm(" ldr r0, =_sbss\n"
" ldr r1, =_ebss\n"
" mov r2, #0\n"
" .thumb_func\n"
"zero_loop:\n"
" cmp r0, r1\n"
" it lt\n"
" strlt r2, [r0], #4\n"
" blt zero_loop");
Поставив точку останова до этой секции залез в память и там почему-то уже стояли условно обнуленными (за исключением единичных ячеек, с которыми я разбираться не стал) первая часть RAM (в том числе и относящаяся к bss). Правда за чистоту эксперимента стал сейчас сомневаться, тк питания сбрасывал исключительно до погасания светодиодов, может в памяти "энергии" дольше держатся. За информацию спасибо, а где можно почитать про это явление (про память именно на STMках)? Может поисковый запрос какой-то хитрый по ключевым словам подскажите про это явление, до этого искал, не встречал конкретики именно про STM32.
Добавлено after 10 minutes 17 seconds:
[uquote="Мурик",url="/forum/viewtopic.php?p=3719538#p3719538"]
auric писал(а):Короче, sp указывал на адрес в районе 0x20001000, причем ему было все равно, где я указывал положение вершины стека в скрипте линкера
Смотрите стартап файл, в котором расположена таблица прерываний и адрес начала стека.[/uquote]
Спасибо за внимание к вопросу! Что касается стартапа, я брал стандартный CooCox, там все что касается стека:
Код: Выделить всё
/*---------- Configuration-----------------------------------------------*/
#define STACK_SIZE 0x00000100 /*!< The Stack size suggest using even number */
__attribute__ ((section(".co_stack")))
unsigned long pulStack[STACK_SIZE];
Остальное в скрипте и там вот что:
Код: Выделить всё
/* .stack_dummy section doesn't contains any symbols. It is only
* used for linker to calculate size of stack sections, and assign
* values to stack symbols later */
.co_stack (NOLOAD):
{
. = ALIGN(8);
*(.co_stack .co_stack.*)
} > ram
/* Set stack top to end of ram , and stack limit move down by
* size of stack_dummy section */
__StackTop = ORIGIN(ram ) + LENGTH(ram ) - 0x2000;
__StackLimit = __StackTop - SIZEOF(.co_stack);
PROVIDE(__stack = __StackTop);
/* Check if data + heap + stack exceeds ram limit */
ASSERT(__StackLimit >= __HeapLimit, "region ram overflowed with stack")
Здесь есть еще один ньюанс, вот выдержка из мапа:
Код: Выделить всё
.co_stack 0x20000c18 0x400 load address 0x08003698
0x20000c18 . = ALIGN (0x8)
*(.co_stack .co_stack.*)
.co_stack 0x20000c18 0x400 ..\obj\startup_stm32f10x_md.o
0x20000c18 pulStack
0x20003000 __StackTop = ((ORIGIN (ram) + LENGTH (ram)) - 0x2000)
0x20002c00 __StackLimit = (__StackTop - SIZEOF (.co_stack))
[!provide] PROVIDE (__stack, __StackTop)
0x00000001 ASSERT ((__StackLimit >= __HeapLimit), region ram overflowed with stack)
Откуда взялось .co_stack 0x20000c18
0x400 ..\obj\startup_stm32f10x_md.o ? у меня вроде как #define STACK_SIZE
0x00000100 /*!< The Stack size suggest using even number */
Ну про остальные сдвиги уже писал (чешу тыковку)...
[uquote="Мурик",url="/forum/viewtopic.php?p=3719538#p3719538"]
auric писал(а):Вторая половина вопроса номер два про мусор, ведь насколько я понимаю оперативная память после сброса питания должна быть обнулена?
Она обнуляется программно в стартап файле. Аппаратно это не производится.[/uquote]
Понял, спасибо.
Добавлено after 12 minutes 41 second:
[uquote="arkhnchul",url="/forum/viewtopic.php?p=3719552#p3719552"]1. Можно, как раз скриптами линкера. Но это бывает редко нужно - к примеру, если прицепляете внешнюю SRAM в дополнение к внутренней или что-то уж очень хитрое делаете с бутлоадером. Даже RTOS-ы со всякими отдельными стеками под каждую задачу и собственными аллокаторами памяти в куче обычно туда не лезут.[/uquote]
Ну вот я встречал, когда память на старших моделях СТМ имеет реально разные группы адресов, так как раз две группы памяти, по кейлу помню, там если без скрипта собственными настройками тоже была возвожность делить, а как это правильно делать, я так и не понял, потому как работало, но криво. Про бинарник уже писал. Хотя сама программа при этом грузилась и работала без ошибок. Теперь чисто для самообразования хотел закрыть этот вопрос, тк как раз со своим самописным хитрым бутлоадером потом хотел что-то замутить в этом проекте.
[uquote="arkhnchul",url="/forum/viewtopic.php?p=3719552#p3719552"]2а. SP инициализируется значением, с которого начинается таблица векторов прерываний. Задается в startup файле.[/uquote]
Да это в самом самом начале запуска кода, я же говорю про другие этапы, следующие, когда он уже реально указывает на текущую позицию в стеке, она почему-то сильно далеко от своего ориентира - вершины стека, ну не может же по сути простая программа наполнить стек настолько, что он почти к концу подошел, ну мне по крайней мере не верится. К тому же меняя адрес вершины стека я ни на байт не сместил эти значения, проверял с разными настройками, стек стоит как "вкопанный", значит его что-то туда сориентировало.
[uquote="arkhnchul",url="/forum/viewtopic.php?p=3719552#p3719552"]2б. Без принудительно инициализации в RAM мусор, да. Нулями забивается программно в том же startup файле, дефолтно только BSS.[/uquote]
ок
[uquote="arkhnchul",url="/forum/viewtopic.php?p=3719552#p3719552"]стек можно разместить и иногда размещают по-разному, но, опять же, непонятно, зачем. По крайней мере от меня смысл ускользает - стандартное расположение и направление вполне логично и разумно. "Развернуть" стек принципиально можно, но это развлечение скорее для ассемблерщиков - ибо в С попросить линкер подвинуть адреса еще можно, но способа сказать компилятору использовать другие команды для доступа к данным в стеке я не знаю.[/uquote]
Тут тоже вопрос чисто для полноты картины понимания, сдвинуть как я понял не проблема (хотя сдвинуть точно на какую-то величину все-таки для меня пока проблема), а встречал где-то упоминания без конкретных примеров, что вроде как можно размещать стек и в начало и даже разворачивать ход его наполнения, вот это бы для себя хотелось так сказать либо опровергнуть либо подтвердить.