Как предотвратить Atmel Studio g cc 6.3.1 от оптимизации 4-байтовой memcmp () до 4-байтового прямого сравнения? - PullRequest
1 голос
/ 28 февраля 2020

Запуск Atmel Studio с предоставленной g cc 6.3.1 для сборки прошивки для чипа Atmel / Microchip SAMV70 (ARM Cortex-M7). У меня есть код, который сравнивает 4-байтовый массив ввода с 4-байтовым локальным массивом, используя memcmp(). Когда скомпилировано с -O0 для отключения оптимизаций, все работает нормально. При компиляции с -Os для оптимизации по размеру или с -O3 для максимальной оптимизации компилятор заменяет вызов memcmp() прямым 4-байтовым сравнением (проверяется путем изучения разборки). К сожалению, оптимизация также иногда перемещает локальный 4-байтовый массив в невыровненный начальный адрес, поэтому, хотя memcmp() будет работать нормально, прямое сравнение вызывает HardFault из-за невыровненного доступа.

По моему мнению, это 100% ошибка оптимизации компилятора (возможно, g cc, возможно, что-то добавлено Atmel), но я застрял с предоставленным компилятором, поэтому обновление не вариант. Итак, вот мой актуальный вопрос: есть ли способ оставить оптимизацию включенной, но отключить эту конкретную оптимизацию? В противном случае я застрял, заставив локальные 4-байтовые массивы выровняться по 4 байта, или нашел какой-то другой обходной путь.

Версия компилятора: gcc version 6.3.1 20170620 (release) [ARM/embedded-6-branch revision 249437] (Atmel build: 508)

Вот пример функции, которая может вызвать ошибка:

bool example(uint8_t *input_data)
{
    uint8_t local_data[4] = { 0x00, 0x01, 0x02, 0x03 };

    return (memcmp(input_data, local_data, 4) == 0);
}

Мой код всегда передается с выравниванием по 4 байта input_data, так что это не проблема, но опять же это плохая форма для оптимизаций компилятора, чтобы принять это как должное.

1 Ответ

2 голосов
/ 03 марта 2020

Отвечая на мой собственный вопрос, поскольку Юджин не опубликовал официальный ответ:

Из опций 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.

А также :

Доступ к строго упорядоченным типам и типам памяти устройства всегда должны быть естественно выровнены

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

  1. g cc с включенной оптимизацией заменял 4-байтовый memcmp() на прямое сравнение, которое равно , разрешено по умолчанию, поскольку по умолчанию разрешен не выровненный доступ. Так что это не ошибка компилятора.
  2. Область памяти fla sh, которая содержала данные для этого memcmp(), была расположена в сегменте MPU, который был объявлен Strongly Ordered, что не поддержка нелицензионного доступа. Таким образом, когда memcmp() был заменен на прямое сравнение, и данные упали на невыровненный адрес, сравнение вызвало HardFault.

Исправление, которое Юджин исправил в своем первоначальном комментарий, это добавить -mno-unaligned-access к опциям компилятора. В моем случае это все же позволило компилятору заменить memcmp() прямым 4-байтовым сравнением, но также вынудило данные быть выровненными по 4 байта, что позволило выполнить сравнение успешно, не вызывая состояние ошибки.

...