ARM двоичный размер

Я программирую микроконтроллеры, такие как STM32F4 ** и STM32F0 **, используя компилятор ARM GCC noneabi, c / c ++ и нашел интересный паттерн.

Если я создаю какой-нибудь файл * .bin, его размер всегда делится на 4.

Я думаю, что это может быть потому, что MCU является 32-битным (= 4 байта). Поэтому bin_size% 4 == 0. Я попробовал несколько «хаков»; например, увеличить некоторый байтовый массив на 1, но двоичный размер всегда одинаков. Когда я увеличиваю массив, размер двоичного файла увеличивается, но он снова делится на 4.

Могу ли я считать этот эффект аксиомой?

Или есть какая-то ситуация, когда это не работает? Например, возможно ли как-то переключить 32-битный STM32 MCU в 16-битный режим? Или возможно создать неделимый двоичный файл на 4 с другим компилятором?

2

Решение

Можно создавать двоичные файлы произвольного размера., выравнивание 4 байтов — просто вопрос удобства. Все делают это таким образом, и все ожидают этого.

Выравнивание осуществляется в файле сценария компоновщика. Если вы посмотрите в *.ld файл вашего проекта, вы обнаружите, что есть много

. = ALIGN(4);

заявления. Они инструктируют компоновщик увеличивать текущий выходной адрес до значения, кратного 4.

Итак, я создал пустой проект и удалил большую часть ALIGN строки из скрипта компоновщика:

ENTRY(Reset_Handler)
__stack = 0x20014000;
MEMORY
{
FLASH (rx)      : ORIGIN = 0x08000000, LENGTH = 512K
RAM   (xrw)     : ORIGIN = 0x20000000, LENGTH = 80K
}
SECTIONS
{
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector))
. = ALIGN(4);
} >FLASH
.text :
{
*(.text)
*(.text*)
} >FLASH
.rodata :
{
*(.rodata)
*(.rodata*)
} >FLASH
_sidata = LOADADDR(.data);
.data :
{
_sdata = .;
*(.data)
*(.data*)
_edata = .;
} >RAM AT> FLASH
.bss :
{
_sbss = .;
*(.bss)
*(.bss*)
*(COMMON)
_ebss = .;
} >RAM
}

минимальная программа:

void Reset_Handler(void) {
while(1)
;
}

скомпилировал и связал его с -nostartfiles -nodefaultlibs -nostdlib, чтобы пропустить все стандартные вещи библиотеки. Результат

arm-none-eabi-size --format=berkeley "unaligned.elf"text    data     bss     dec     hex filename
320       0       0     320     140 unaligned.elf

делится на четыре Затем я добавил переменную char и кое-что с ней сделал:

volatile char c = 0x42;
void Reset_Handler(void) {
while(1)
c+=1;
}

что привело к

Invoking: Cross ARM GNU Print Size
arm-none-eabi-size --format=berkeley "unaligned.elf"text    data     bss     dec     hex filename
336       1       0     337     151 unaligned.elf
Finished building: unaligned.siz

Инструкции выровнены до 16 бит.

Микроконтроллеры на базе Cortex-M, такие как серии STM32, используют набор команд Thumb2, представляющий собой комбинацию 16- и 32-битных инструкций. Оказывается, наша первая программа имела длину, кратную четырем. Я добавил один nop инструкция

void Reset_Handler(void) {
asm("nop");
while(1)
;
}

и размер вырос на два байта по сравнению с оригиналом:

Invoking: Cross ARM GNU Print Size
arm-none-eabi-size --format=berkeley "unaligned.elf"text    data     bss     dec     hex filename
322       0       0     322     142 unaligned.elf
Finished building: unaligned.siz
4

Другие решения

«Например, можно ли как-нибудь переключить 32-битный микроконтроллер STM32 в 16-битный режим»

Там является режим 16 бит, но вы не можете точно понять, что это означает. Чтобы гуглить, вы должны искать «ARM Thumb». Это вполне может привести к * bin-файлам, кратным 2 байтам.

Однако «32-битный режим» и «16-битный режим» обычно относятся к размерам указателей или регистров, а не к размерам команд, например, набор инструкций AMD x64 может называться «режимом 64 битов», даже если его инструкции имеют переменную длину. Некоторые инструкции x64 занимают всего один байт.

0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector