а) МК вылетает в исключение HardFault, если запустить программу на автоматическое выполнение до брейкпоинта.
б) если выполнять пошагово до него же, то всё работает.
в) после каждой строчки начиная с первой выдаётся предупреждение, что указатель стека вне допустимого диапазона.
Я изучил в дизассемблере пролог функции main(), т.е. в промежуток между её началом и первой командой:
int main()
{
// <- тут пролог... его не видно, потому что его делает компилятор.
func1();
//...
return 0;
}
Обнаружил там странную команду:
SUB.W SP, #7306
То есть, вычесть из указателя стека семь тысяч с гаком. А стека было всего две тысячи. То есть, программа не работала потому, что новый указатель стека выходил за пределы стека, о чём и выдавалось предупреждение. Но это ещё не всё -- указатель оказывался В ОБЛАСТИ КОДА и переписывал его данными на ходу. Это МК, тут нету DEP. Этим и был вызван HardFault.
Но почему же вычитались семь тысяч? Я думал, это безумие какое-то. А потом мне коллега напомнил, что локальные переменные выделяются в стеке. Эта команда как раз выделяла место под них. А у меня там среди прочего массивы на пару тысяч чисел.