Thread 中讨论的其他器件:MSPM0G3507、MSPM0-SDK
工具/软件:
您好:
我正在使用 MSPM0G3507的自定义引导加载程序。 该引导加载程序使用 UART 实现、并在将新的十六进制文件写入闪存之前执行 CRC 和版本检查。
在我的引导加载程序中、重置引导加载程序后首先运行、然后在所需位置检查应用程序是否存在(如果不存在)、则跳转到该应用程序、如果不存在、则运行正常的引导加载程序代码。
如果接收到的代码的完整 CRC 和计算出的本地 CRC 匹配、则它最后会跳转到已刷写的新应用程序、但问题是当我通过跳转函数跳转、跳转应用程序的中断不起作用时、它将重置 UC 并从引导加载程序应用程序从0开始。 我之前说过、它将再次检查并跳转到该应用程序。
所以主要的错误是我的中断处理程序从不被执行,从不写入 bootcmd(1 at flash loc 0x0001F058 )。 每次中断我给出 GPIO 中断时、它都会重复。
因为我找不到这个问题、这是我的第一个引导加载程序代码、所以有人能帮我解决这个问题吗? 我附加了跳转函数和 IRQ 处理程序以及链接器文件。
链接器命令文件
#include "ti_msp_dl_config.h"
#include "string.h"
#include "stdio.h"
#include "core_cm0plus.h"
#define BOOTLOADER_VECTOR_TABLE_ADDRESS 0x00000000
#define BOOTLOADER_INT_LOCATION 0x0001F058 /* At this location flag set by applicant who wish to turn on boot mode to flesh nex hex */
#define VTOR_OFFSET (uint32_t *)0x00003E80
#define NO_ERROR 0
#define ERROR_WRITE_32_BIT 6
void jump_to_app(uint32_t);
uint8_t BootCmdWrite(uint32_t);
volatile uint8_t gErrorType = NO_ERROR;
volatile DL_FLASHCTL_COMMAND_STATUS gCmdStatus;
uint32_t gCmd32 = 0x00000001;
uint32_t gCmdTemp;
int main(void) {
//early_irq_enable();
SYSCFG_DL_init();
SCB->VTOR = (uint32_t)VTOR_OFFSET;
__enable_irq();
NVIC_ClearPendingIRQ(USR_BOOT_INT_IRQN);
NVIC_EnableIRQ(USR_BOOT_INT_IRQN);
while (1) {
DL_GPIO_togglePins(USER_LED_PORT, USER_LED_RED_LED_PIN);
delay_cycles(16000000);
}
}
void GROUP1_IRQHandler(void)
{
switch (DL_Interrupt_getPendingGroup(DL_INTERRUPT_GROUP_1)) {
case USR_BOOT_INT_IIDX:
/* If SW is high, turn the LED off */
if (DL_GPIO_readPins(USR_BOOT_PORT, USR_BOOT_BT_PIN_PIN)) {
BootCmdWrite(gCmd32);
DL_GPIO_togglePins(RGB_PORT, RGB_GREEN_LED_PIN);
delay_cycles(64000000);
jump_to_app(BOOTLOADER_VECTOR_TABLE_ADDRESS);
// NVIC_SystemReset();
}
break;
default :
break;
}
}
uint8_t BootCmdWrite(uint32_t cmd) {
if (gErrorType == NO_ERROR) {
DL_FlashCTL_unprotectSector(FLASHCTL, BOOTLOADER_INT_LOCATION, DL_FLASHCTL_REGION_SELECT_MAIN);
// gCmdStatus = DL_FlashCTL_programMemoryFromRAM64WithECCGenerated(
// FLASHCTL, BOOTLOADER_INT_LOCATION, &cmd32[0]);
DL_FlashCTL_programMemoryFromRAM32WithECCGenerated(
FLASHCTL, BOOTLOADER_INT_LOCATION, &cmd);
// Ensure write is fully committed
__DSB(); // Data Synchronization Barrier
__ISB(); // Instruction Synchronization Barrier
if (gCmdStatus == DL_FLASHCTL_COMMAND_STATUS_FAILED)
{
/* If command was not successful, set error flag */
gErrorType = ERROR_WRITE_32_BIT;
}
DL_FlashCTL_protectSector(FLASHCTL, BOOTLOADER_INT_LOCATION, DL_FLASHCTL_REGION_SELECT_MAIN);
gCmdTemp = *(uint32_t *)BOOTLOADER_INT_LOCATION;
}
return gErrorType;
}
void HardFault_Handler(void)
{
// Debug indicator - blink LED or breakpoint
while (1)
{
DL_GPIO_togglePins(RGB_PORT, RGB_GREEN_LED_PIN);
for (volatile int i = 0; i < 100000; i++); // Simple delay
}
}
void jump_to_app(uint32_t app_addr) {
__disable_irq();
// Disable and clear all interrupts
for (uint32_t i = 0; i < 8; i++) {
NVIC->ICER[i] = 0xFFFFFFFF; // Disable IRQs
NVIC->ICPR[i] = 0xFFFFFFFF; // Clear pending IRQs
}
__DSB();
__ISB();
// Reset SysTick just in case
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;
uint32_t sp = *((uint32_t *)app_addr); // Stack pointer
uint32_t reset = *((uint32_t *)(app_addr + 4)); // Reset handler
__set_MSP(sp);
SCB->VTOR = app_addr; // If needed
((void (*)(void))reset)(); // Jump to reset handler
}

