Попробую ответить на самое первое сообщение.
У меня в проекте, загрузчик располагается в начальных адресах и занимает не более 16кБ кода (я ему выделил такую секцию, оставшихся 48кБ от 64кБ общей памяти, для основной прошивки достаточно).
Алгоритм действий (исключая кучу проверок на наличие и корректность прошивки на месте):
1. Отключить ВСЕ задействованные загрузчиком прерывания.
2. Сбросить задействованную загрузчиком периферию.
3. Считать начальные адреса прошивки (AppSect + 0, AppSect + 4)
4. Выполнить:
Код: Выделить всё
jump_app (0x80004000);
void jump_app( uint32_t address ) {
__asm ("LDR SP, [R0]\n"); // Load new stack pointer address
__asm ("LDR PC, [R0, #4]\n"); //Load new program counter address;
};
При выполнении данной процедуры, безвозвратно теряются данные процесса работы и ядро, фактически переходит на вектор запуска.
Опять же, в моём случае, процедура переноса векторов прерывания, происходит прямо в самом приложении (а так же в загрузчике) самостоятельно, потому изначально загрузчику за этим следить не нужно.
Делаю я это так:
Код: Выделить всё
uint32_t i;
i = (uint32_t)(&main); // Получаем адрес main()
SCB->VTOR = (i & 0xFF030000);
Всё. Две инструкции в коде.
Естественно, необходимо следить за тем, чтобы адрес main попадал в секцию.
Как уже говорил выше, таблица прерываний располагается (у меня) в начале секции приложения. Соответсвенно, адрес main будет указывать на нужный диапазон, затем накладывается маска и получается адрес. Это случай с тремя независимыми версиями прошивки во Flash памяти.
Либо же, приложение можно собрать с опцией VECT_TAB_SRAM и тогда начальный код позаботится о том, чтобы таблица векторов прерываний оказалась в начале RAM.
И уже не нужно будет переносить самостоятельно что-то ещё.