uint8_t index = __builtin_ctz(exti_set_mask);
auto &gpio_irq_info = irq_callback_table[index];
Проблема здесь в том, что irq_callback_table — это std::array размера 16. exti_set_mask — это uint16_t, который вероятно, повышается до uint32_t (32-битная архитектура ЦП), поэтому компилятор не может быть уверен, что результат __builtin_ctz() вернет что-то меньшее чем 16. Из-за возможности доступа за пределами границ размер программного кода увеличивается из-за всего кода, добавленного для поддержки генерации исключения.
Маскировка результата перед использованием он как индекс избавляется от всего этого кода исключений:
uint8_t index = __builtin_ctz(exti_set_mask) & 0xf;
auto &gpio_irq_info = irq_callback_table[index];
В результате размер программного кода снова уменьшается примерно до 4 КБ по сравнению с обычным кодом. 90 КБ!
Эти флаги установлены через meson:
# Specify global compiler flags.
add_project_arguments(
# Free standing environment (no OS, or stdlib)
'-ffreestanding', '-nostdlib', '-specs=nosys.specs',
# Enable linker garbage collection
'-ffunction-sections', '-fdata-sections',
# No dynamic memory allocation
'-fno-builtin-malloc', '-fno-builtin-calloc',
'-fno-builtin-realloc', '-fno-builtin-free',
# Debug optimization
'-Og',
language: ['cpp', 'c']
)
add_project_arguments(
'-std=c++20',
'-fno-exceptions',
'-fno-rtti',
language: ['cpp']
)
Но флага -fno-Exceptions, похоже, недостаточно для предотвращения генерации кода исключения. В идеале я бы хотел, чтобы любая потенциальная эмиссия исключений (или malloc и т. д.) вместо этого отображалась как предупреждение или ошибка. Есть идеи, как это сделать?
РЕДАКТИРОВАТЬ:
Для тех, кто хочет сравнить файл .elf. objdump, вот полностью связанный .elf с замаскированным индексом: https://pastebin.com/hSJgF3PW
И .elf с незамаскированным индексом:
- https://pastebin.com/p9yDxdjx pt1
- https://pastebin.com/NU5nV0tr pt2
- https:/ /pastebin.com/9CX1EtH0 pt3
- https://pastebin.com/evvnmCCa pt4
Немаскированный индекс:
08000d1c :
void CommonISRHandler([[maybe_unused]] uint16_t exti_set_mask) {
8000d1c: b570 push {r4, r5, r6, lr}
8000d1e: 0005 movs r5, r0
while (exti_set_mask) {
8000d20: e011 b.n 8000d46
// Element access.
[[__nodiscard__]]
_GLIBCXX17_CONSTEXPR reference
operator[](size_type __n) noexcept
{
__glibcxx_requires_subscript(__n);
8000d22: 4b18 ldr r3, [pc, #96] @ (8000d84 )
8000d24: 4a18 ldr r2, [pc, #96] @ (8000d88 )
8000d26: 4819 ldr r0, [pc, #100] @ (8000d8c )
8000d28: 21ca movs r1, #202 @ 0xca
8000d2a: f000 f97d bl 8001028
EXTI->RPR1 &= (1 FPR1 &= (1
Подробнее здесь: https://stackoverflow.com/questions/793 ... exceptions
Мобильная версия