ВходНаше всё Теги codebook PARTS Поиск Опросы Закон Понедельник
8 марта
/1045927
Топик полностью
evgeniy1294 (21.10.2020 21:56, просмотров: 213) в ответ на stm32 чтот непонятки, создал массив в раме volatile uint8_t __attribute__ ((at (ADR))) tmp_buf[22528] = { 0 }; Смотрю отладчиком а но вообще и не обнулен, мусор... принудительное обнуление через memset на ПО не влияет, т.е. почему то не инитится, вопрос почему ? - автор: Aleksey_75
Как и обещал, сделаю развернутое пояснение. Для начала стоит обратить внимание на выхлоп компилятора, для чего скормим файл прошивки программе readelf (в качестве примера я взял пример blink из своей либины): 
$readelf blink.elf -a
<...>

Заголовки разделов:
[Нм] Имя Тип Адрес Смещ Разм ES Флг Сс Инф Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .isr_flash PROGBITS 08000000 010000 000188 00 A 0 0 4
[ 2] .text PROGBITS 08000188 010188 0004cc 00 AX 0 0 4
[ 3] .rodata PROGBITS 08000654 010654 000004 00 A 0 0 4
[ 4] .data PROGBITS 20000000 020000 0000d8 00 WA 0 0 4
[ 5] .ccmram PROGBITS 10000000 0200d8 000000 00 W 0 0 1
[ 6] .ARM ARM_EXIDX 08000658 010658 000008 00 AL 2 0 4
[ 7] .init_array INIT_ARRAY 08000660 010660 000004 04 WA 0 0 4
[ 8] .fini_array FINI_ARRAY 08000664 010664 000004 04 WA 0 0 4
[ 9] .bss NOBITS 200000d8 0200d8 0000dc 00 WA 0 0 4
[10] ._user_heap_stack NOBITS 200001b4 0200d8 000604 00 WA 0 0 1

Сразу увидим список секций/разделов, в данном случае список сокращен. В секции text покоится наша логика, rodata - константы, data - область с инициализируемыми данными, bss - область для инициализации 0, [init_array - fini_array] - отсюда копируются данные в секцию data. Заглянем в стартап, именно он занимается инициализацией наших переменных, а также вызывает конструкторы классов (в том числе и в голом С):

[noreturn]] void ResetHandler() {
__set_MSP(reinterpret_cast<std::uint32_t>(&__initial_sp__));

// Relocate the .data section
std::uint32_t* dl = & __data_load__;
std::uint32_t* ds = & __data_start__;
std::uint32_t* de = & __data_end__;
if (dl != ds) {
while(ds < de) {
*ds = *dl;
dl++;
ds++;
}
}


// Initiailize .bss to zero
std::uint32_t* bs = & __bss_start__;
std::uint32_t* be = & __bss_end__;
while (bs < be) {
*bs = 0;
bs++;
}

board::Init();

// Call static constructors
__libc_init_array();

main();

while(1) __NOP();
}

Я считаю коментарии в коде исчерпывающими. Теперь посмотрим, что будет, если мы добавим в код ваш массив, а будет плохо:

 warning: 'at' attribute directive ignored [-Wattributes]

GCC не умеет размещать переменные по конкретному адресу, это вообще непонятный, грязный и максимально убогий хак. Зачем это существует в "профессиональных" для меня загадка, необходимо явно задать секцию, в которую будет помещен массив:

__attribute__ ((section(".isr_flash"), used))   void (* const InterruptTable[])(void)

Именно таким образом размещаются таблицы векторов прерываний. Но разместив что-то в одной секции, условно "my_section", это что-то никогда не попадет в секцию "bss", даже если оно инициализируется 0. Если мы внимательно посмотрим в код ResetHandler - переменные, размещенные таким образом в RAM вообще не будут инициализмрованы! Переменные во FLASH в данном случае являются исключением - они будут прошиты по тому адресу, с которого читаются.

Вам необходимо явно сделать обнуление данных вашей секции в функции ResetHandler по аналогии с обнулением bss.

Ответить
Ответы