Cortex-M0+: не могу перейти с загрузчика на приложение
Я работаю над ATSAMC21 (ATSAMC21J18A) с Cortex-M0+, делаю мой загрузчик CAN. Моя IDE - студия ATMEL. Мигать мое приложение в порядке, но когда я вхожу в i, оно перестало работать (я пробовал с отладкой и без). В disaseembly это указывает на первую из этих двух строк:
*FFFFFFFE ?? ?? ??? Memory out of bounds or read error*
*00000000 a0.32 adds r2, #160*
Мое пространство загрузчика в моем компоновщике:
MEMORY
{
rom (rx) : ORIGIN = 0x00000000, LENGTH = 0x00008000
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
}
Место для моего приложения (или прошивки) в моем компоновщике:
MEMORY
{
rom (rx) : ORIGIN = 0x00010000, LENGTH = 0x00030000
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
}
Перед прыжком
Я отключил прерывание IRQ, определил мою точку входа и мой указатель стека и изменил VTOR. Вот мой код для перехода:
void JumpToApp(void) {
uint16_t i;
uint32_t startAddress, applicationStack;
/* Check if WDT is locked */
if (!(WDT->CTRLA.reg & WDT_CTRLA_ALWAYSON)) {
/* Disable the Watchdog module */
WDT->CTRLA.reg &= ~WDT_CTRLA_ENABLE;
}
//stop general IT
__disable_irq();
// Disable SysTick
SysTick->CTRL = 0;
// Disable IRQs & clear pending IRQs
for (i = 0; i < 8; i++) {
NVIC->ICER[i] = 0xFFFFFFFF;
NVIC->ICPR[i] = 0xFFFFFFFF;
}
// Pointer to the Application Section
void (*application_code_entry)(void);
startAddress = FLASH_APP_VADRESS; //HERE 0x00010000, my start App
applicationStack = (uint32_t) *(volatile unsigned int*) (startAddress);
application_code_entry = (void (*)(void))(unsigned *)(*(unsigned *)(FLASH_APP_VADRESS + 4)); //HERE 0x00010004
// Rebase the Stack Pointer
__DSB();
__ISB();
__set_MSP(*(uint32_t *)applicationStack); //HERE 0x00010000, my start App
// Rebase the vector table base address
SCB->VTOR = ((uint32_t)startAddress & SCB_VTOR_TBLOFF_Msk);
__DSB();
__ISB();
// Jump to user Reset Handler in the application
application_code_entry();
}
Я попытался добавить +1 в своем application_code_entry, как нечетный режим Thumb, я вижу это для Cortex-M3, но это не работает, не удается в общем IT.
Затем я переименовываю main () с помощью main_boot () и Reset_Handler() с помощью Reset_Handler_Boot() (и путем изменения в компоновщике флага пропити --entry=Reset_Handler_Boot)
Но все равно не прыгает.
Я не знаю, что я делаю плохо. Может быть, есть длинный прыжок, чтобы сделать? Разделить оперативку? Если у кого-нибудь есть идея?
Благодарю вас!!!!!!!!!!!!!!!!!!!
Спасибо (это была ошибка:)), но эта серьезная ошибка не разрешает мой прыжок (на самом деле я использовал адрес __set_MSP(*(uint32_t *)(FLASH_APP_VADRESS));
Мой MSP - это не 0x0000000, а 0x20003240, поэтому смещение применяется к моему новому MSP? (см. изображение связано)
Вот мой код для тестирования MSP
ReadMsp=__get_MSP(); //result 0x20003240, before change it
__DSB();
__ISB();
__set_MSP(*(uint32_t *)applicationStack);
// Rebase the vector table base address TODO: use RAM
SCB->VTOR = ((uint32_t)startAddress & SCB_VTOR_TBLOFF_Msk);
__DSB();
__ISB();
ReadMsp=__get_MSP(); //result is 0xFFFFFFFC , why ???
__DSB();
__ISB();
__set_MSP(0x00010000);
__DSB();
__ISB();
ReadMsp=__get_MSP(); //result is 0x00010000, better than my same #define FLASH_APP_VADRESS or *(uint32_t *)applicationStack in __MSP
//applicationEntry();
// Load the Reset Handler address of the application
//application_code_entry = (void (*)(void))(unsigned *)(*(unsigned *)(FLASH_APP_VADRESS ));
// Jump to user Reset Handler in the application
application_code_entry();
Должен ли я использовать (0x20003240 + 0x00010000) для моего нового MSP?
2 ответа
Вы разыменовываете SP
указатель стека дважды:
applicationStack = (uint32_t) *(volatile unsigned int*) (startAddress);
// ... --^
__set_MSP(*(uint32_t *)applicationStack);
// -^
Вы должны сделать это только один раз. Второй тайм SP
с большой вероятностью обнуление, что приводит к ошибке после использования стека.
Я нашел ответ!!!
Наконец, чтобы перейти, точно так же, как Atmel сказал НО, прежде чем мне нужно было неинициализировать какой-то модуль.
Итак: ATMEL часть:
*// Pointer to the Application Section
void (*application_code_entry)(void);
// Rebase the Stack Pointer
__set_MSP(*(uint32_t *)FLASH_APP_VADRESS);
// Rebase the vector table base address TODO: use RAM
SCB->VTOR = ((uint32_t)FLASH_APP_VADRESS & SCB_VTOR_TBLOFF_Msk);
// Load the Reset Handler address of the application
application_code_entry = (void (*)(void))(unsigned *)(*(unsigned *)
(FLASH_APP_VADRESS + 4));
// Jump to user Reset Handler in the application
application_code_entry();*
Моя часть перед выполнением этого:
*Flash_Deinit(); //flash uninit
config_TC_Deinit(); //time clock uninit, scheduler
can_deinit0(); // module CAN0
can_deinit1(); // module CAN1
Handle_Wdt_Disable();
__disable_irq();
// Disable SysTick
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;
// Disable IRQs & clear pending IRQs
for (i = 0; i < 8; i++) {
NVIC->IP[i] = 0x00000000;
}
NVIC->ICER[0] = 0xFFFFFFFF;
NVIC->ICPR[0] = 0xFFFFFFFF;*
Надеюсь это кому-нибудь поможет!!!:)