硬汉嵌入式论坛

 找回密码
 立即注册
查看: 471|回复: 7
收起左侧

[BOOT/IAP] 为什么Bootloader+APP使用AC6编译必须开优化?否则跳转失败!

[复制链接]

0

主题

2

回帖

2

积分

新手上路

积分
2
发表于 2025-9-29 09:45:41 | 显示全部楼层 |阅读模式
本帖最后由 LeenixP 于 2025-9-29 09:47 编辑

如果不开优化Bootloader程序将无法跳转,直接进入HardFault_Handler中断。

而且进入调试查看AppJump的地址是错误的!
PixPin_2025-09-29_09-40-59.jpg
开启优化之后地址就是正确的!
PixPin_2025-09-29_09-45-20.jpg
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
119430
QQ
发表于 2025-9-29 09:49:41 | 显示全部楼层
初步确诊MDK AC6的0级优化是个大坑,玩不顺手的话,慎用(2022-10-23)
https://forum.anfulai.cn/forum.p ... 9584&fromuid=58
(出处: 硬汉嵌入式论坛)
回复

使用道具 举报

0

主题

2

回帖

2

积分

新手上路

积分
2
 楼主| 发表于 2025-9-29 09:53:48 | 显示全部楼层
eric2013 发表于 2025-9-29 09:49
初步确诊MDK AC6的0级优化是个大坑,玩不顺手的话,慎用(2022-10-23)
https://forum.anfulai.cn/forum.p ...

感谢大哥,昨天困扰了我一下午
回复

使用道具 举报

0

主题

59

回帖

59

积分

初级会员

积分
59
发表于 2025-9-29 10:43:50 | 显示全部楼层
eric2013 发表于 2025-9-29 09:49
初步确诊MDK AC6的0级优化是个大坑,玩不顺手的话,慎用(2022-10-23)
https://forum.anfulai.cn/forum.p ...

确实,我用AC6编译S32K的程序也有类似情况
回复

使用道具 举报

1

主题

80

回帖

83

积分

初级会员

积分
83
发表于 2025-9-29 12:08:43 | 显示全部楼层
AppJump 函数指针怎么定义的,要定义成全局变量,避免使用堆栈,因为你中途修改了堆栈地址


譬如:

[C] 纯文本查看 复制代码

static void jump2app(void)
{
   uint32_t stack = *(uint32_t*)APP_ADDR;
   uint32_t func = *(uint32_t*)(APP_ADDR + 4);

   SysTick->CTRL = 0; // disable systick irq
   printf("j app ...\n");
   while (!(USART_STAT(USART1) & USART_STAT_TC));

   __set_MSP(stack); // init stack pointer
   ((void(*)()) func)();
   while (true);
}



改为:


[C] 纯文本查看 复制代码

static void jump2app(void)
{
    static uint32_t func; // not on stack (MSP switches before use)
    uint32_t stack = *(uint32_t*)APP_ADDR;
    func = *(uint32_t*)(APP_ADDR + 4);

    SysTick->CTRL = 0; // disable systick irq
    printf("j app ...\n");
    while (!(USART_STAT(USART1) & USART_STAT_TC));

    __set_MSP(stack); // init stack pointer
    ((void(*)()) func)();
    while (true);
}




回复

使用道具 举报

0

主题

2

回帖

2

积分

新手上路

积分
2
 楼主| 发表于 2025-9-29 14:15:13 | 显示全部楼层
dukelec 发表于 2025-9-29 12:08
AppJump 函数指针怎么定义的,要定义成全局变量,避免使用堆栈,因为你中途修改了堆栈地址

已经解决了,我是这样定义的:
[C] 纯文本查看 复制代码
/* 外部QSPI Flash的起始地址 */
#define EX_QSPI_FLASH_BASE     0x90000000

/* 定义应用程序入口函数类型 */
typedef void (*pAppFunction)(void);

void Bootloader_JumpToApp(void)
{
    #if BOOTLOADER_DEBUG
    printf("[BL] Bootloader_JumpToApp\r\n");
    #endif
    
    /* 安全地读取应用程序向量表 */
    volatile uint32_t *pAppVectorTable = (volatile uint32_t *)EX_QSPI_FLASH_BASE;
    
    /* 安全读取向量表中的值 */
    __DSB();
    uint32_t appStackPtr = pAppVectorTable[0];    /* 读取栈顶指针的值 */
    __DSB();
    uint32_t appResetAddr = pAppVectorTable[1];   /* 读取复位向量的值 */
    __DSB();
    
    #if BOOTLOADER_DEBUG
    printf("[BL] App Stack Pointer: 0x%08X\r\n", (unsigned int)appStackPtr);
    printf("[BL] App Reset Address: 0x%08X\r\n", (unsigned int)appResetAddr);
    #endif
    
    /* 检查读取的值是否有效 */
    if (appStackPtr == 0xFFFFFFFF || appResetAddr == 0xFFFFFFFF || 
        appStackPtr == 0x00000000 || appResetAddr == 0x00000000) {
        #if BOOTLOADER_DEBUG
        printf("[BL] No valid application found in external Flash!\r\n");
        #endif
        return;
    }
    
    /* 检查栈指针是否在有效RAM范围内 */
    if ((appStackPtr & 0xF0000000) != 0x20000000 && (appStackPtr & 0xF0000000) != 0x24000000) {
        #if BOOTLOADER_DEBUG
        printf("[BL] Invalid stack pointer: 0x%08X\r\n", (unsigned int)appStackPtr);
        #endif
        return;
    }
    
    /* 检查复位向量是否有效(应在外部Flash范围且为奇数地址) */
    if ((appResetAddr & 0xF0000000) != 0x90000000 || (appResetAddr & 0x01) == 0) {
        #if BOOTLOADER_DEBUG
        printf("[BL] Invalid reset vector: 0x%08X\r\n", (unsigned int)appResetAddr);
        #endif
        return;
    }
    
    #if BOOTLOADER_DEBUG
    printf("[BL] Application validation passed!\r\n");
    #endif

    /* 关闭全局中断 */
    __disable_irq();

	/* 关闭滴答定时器,复位到默认值 */
	SysTick->CTRL = 0;
    SysTick->LOAD = 0;
    SysTick->VAL = 0;

	/* 关闭所有中断,清除所有中断标志 */
	for (int i = 0; i < 8; i++) {
		NVIC->ICER[i] = 0xFFFFFFFF;
		NVIC->ICPR[i] = 0xFFFFFFFF;
	}
	
	/* 使能全局中断 */
	__enable_irq();
    
    /* 设置堆栈指针 */
    __set_MSP(appStackPtr);
    
    /* 设置控制寄存器,使用MSP,特权模式 */
    __set_CONTROL(0);
	
    /* 创建跳转函数指针 */
    pAppFunction JumpToApp = (pAppFunction)appResetAddr;

    #if BOOTLOADER_DEBUG
    printf("[BL] Jumping to Application...\r\n");
    #endif

	/* 跳转到应用程序APP */
	JumpToApp(); 

    #if BOOTLOADER_DEBUG
    printf("[BL] Jumping Application Failed !!!\r\n");
    #endif

    /* 如果跳转失败则进入死循环 */
	while (1) {}
}
回复

使用道具 举报

0

主题

62

回帖

62

积分

初级会员

积分
62
发表于 2025-9-29 17:20:16 | 显示全部楼层
不是ac6的锅吧
回复

使用道具 举报

5

主题

134

回帖

149

积分

初级会员

积分
149
发表于 2025-9-29 18:58:01 | 显示全部楼层
根据 [KAN298] Migrate from ARM C/C++ Compiler 5 to ARM Compiler 6 文档,-O0 优化是不推荐的。

无标题.png
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-11-22 04:11 , Processed in 0.043398 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表