Ответ может зависеть от серии (STM32F1, STM32F4, STM32L1 и т. Д.), Поскольку они имеют несколько разные контроллеры флэш-памяти.
Однажды я совершил ту же ошибку на STM32F429 и немного исследовал ее, поэтому я могу сказать, что произойдет на STM32F4.
Возможно ничего.
Флэш-память по умолчанию защищена, чтобы быть несколько устойчивой к такого рода программным ошибкам. Чтобы изменить флэш-память, необходимо записать определенные значения в регистр FLASH->KEYR
. Если записано неправильное значение, флэш-память будет заблокирована до сброса, поэтому ничего страшного не произойдет, если программа не запишет 64 бита правильных значений. Не может быть никаких неожиданных прерываний, потому что этот ключ также защищен битом разрешения прерываний. При попытке установить некоторые биты ошибок в FLASH->SR
, чтобы программа могла проверить это и предупредить пользователя (предпочтительно тестера).
Однако, если там есть какой-то код (например, загрузчик или записывающий что-то во флэш-память), который должен записать что-то во флэш-память, т.е. он разблокирует флэш-память с правильными ключами, то плохие вещи может случиться.
Если флэш-память остается разблокированной после предыдущей операции записи, то запись в ранее запрограммированную область изменит биты с 1
на 0
, но не с 0
на 1
. Это означает, что флэш-память будет содержать побитовое AND
старого и вновь записанного значения.
Если неудачная попытка записи происходит первой, а затем разблокируется, то никакая законная операция записи или стирания не будет успешной, если только сначала не будут правильно очищены биты состояния.
Если предполагаемый и непреднамеренный доступ происходит с чередованием, например, в обработчиках прерываний все ставки отключены.
Даже если значения находятся в неизменяемой флэш-памяти, результат все равно может быть неожиданным. Считайте этот код
int foo(int *array) {
array[0] = 1;
array[1] = 3;
array[2] = 5;
return array[0];
}
Оптимизирующий компилятор может распознать, что возвращаемое значение всегда должно быть 1
, и выдать код с этой целью. Или это может не произойти, и перезагрузите array[0]
из того места, где оно хранится, возможно, значение отличается от флэш-памяти. Он может вести себя по-разному в сборках отладки и выпуска, или когда функция вызывается из разных мест, так как она может быть встроена по-разному.
Если указатель указывает на не отображенную область, ни ОЗУ, ни FLASH, ни какой-либо регистр отображения памяти, произойдет сбой , а так как обработчики ошибок по умолчанию содержат только бесконечный цикл, программа зависнет если на нем не установлен обработчик ошибок, который может справиться с ситуацией. Нет необходимости говорить, что перезапись случайных областей ОЗУ или регистров может привести к едва предсказуемому поведению.
UPDATE
Я пробовал ваш код на реальном оборудовании. Когда я запустил его дословно, компилятор (gcc-arm-none-eabi-7-2018-q2-update -O3 -lto
) оптимизировал все, так как переменные впоследствии не использовались. Пометка a, b, c, d
как volatile
привела к c=2
и d=12
, он все еще рассматривал первый массив const
, и доступ к массивам не был создан. constarray
вообще не отображался в файле карты, компоновщик полностью его исключил.
Итак, я попробовал несколько вещей по одному, чтобы заставить оптимизатор генерировать код, который фактически получал бы доступ к массивам.
- Отключить оптимизацию (
-O0
)
- Создание всех переменных
volatile
- Вставка пары барьеров памяти времени компиляции (
asm volatile("":::"memory");
- Выполнение сложных вычислений в середине
Любой из них оказывал различное влияние на разные MCU, но они всегда были согласованы на одной платформе.
STM32F103
: неисправность. Только полугодовое (16-битное) обращение к записи разрешено для флэш-памяти, 8 или 32 бита всегда приводят к ошибке. Когда я изменил типы данных на short
, код работал, конечно, без какого-либо влияния на флэш-память. STM32F417
: выполнение кода без влияния на содержимое флэш-памяти, но биты 6 и 7, PGPERR
и PGSERR
в FLASH->SR
были установлены через несколько циклов после первой записи попытка constarray
.
STM32L151
: выполнение кода без влияния на состояние контроллера флэш-памяти.