Отвечая на мой собственный вопрос, поскольку Юджин не опубликовал официальный ответ:
Из опций g cc ARM :
По умолчанию не выровнен доступ отключен для всех предшествующих ARMv6, всех ARMv6-M и для базовых архитектур ARMv8-M и включен для всех других архитектур.
Это означает, что доступ без выравнивания разрешен по умолчанию для ARMv7-M. Оказывается, это имеет смысл, поскольку из Справочное руководство по архитектуре ARMv7-M :
Следующие обращения к данным поддерживают адресацию без выравнивания и генерируют ошибки выравнивания, только когда CCR.UNALIGN_TRP бит установлен в 1, см. Регистр конфигурации и управления:
• LDR {S} H {T} и STRH {T} не выровнены по полуслову.
• TBH не выровнены по полуслову.
• LDR {T} и STR {T}, не выровненные по словам.
Это означает, что ARMv7-M поддерживает ограниченный набор невыровненных обращений. Однако , он не поддерживает все невыровненные доступы:
Следующие обращения к данным всегда генерируют ошибку выравнивания:
• Non halfword LDREXH и STREXH с выравниванием по буквам.
• LDREX и STREX с выравниванием по словам.
• LDRD без выравнивания по словам, LDMIA, LDMDB, POP, LD C, VLDR, VLDM и VPOP.
• STRD без выравнивания слов, STMIA, STMDB, PU SH, ST C, VSTR, VSTM и VPU SH.
А также :
Доступ к строго упорядоченным типам и типам памяти устройства всегда должны быть естественно выровнены
Итак, вот условие сбоя, которое побудило меня задать первоначальный вопрос:
- g cc с включенной оптимизацией заменял 4-байтовый
memcmp()
на прямое сравнение, которое равно , разрешено по умолчанию, поскольку по умолчанию разрешен не выровненный доступ. Так что это не ошибка компилятора. - Область памяти fla sh, которая содержала данные для этого
memcmp()
, была расположена в сегменте MPU, который был объявлен Strongly Ordered
, что не поддержка нелицензионного доступа. Таким образом, когда memcmp()
был заменен на прямое сравнение, и данные упали на невыровненный адрес, сравнение вызвало HardFault
.
Исправление, которое Юджин исправил в своем первоначальном комментарий, это добавить -mno-unaligned-access
к опциям компилятора. В моем случае это все же позволило компилятору заменить memcmp()
прямым 4-байтовым сравнением, но также вынудило данные быть выровненными по 4 байта, что позволило выполнить сравнение успешно, не вызывая состояние ошибки.