GD32E10x bootloader踩坑记

typedef xt_void (*FUNC)(xt_void);
FUNC jumpAddr = NULL;
int main(void)
{
  if (((*(volatile xt_u32 *)FLASH_APP_START_ADDR) & 0x2FFF0000) == 0x20000000) {
    __disable_irq();
    __set_MSP(*(volatile xt_u32 *)FLASH_APP_START_ADDR);
    jumpAddr = (FUNC)(*(volatile xt_u32 *)(FLASH_APP_START_ADDR + 4));
    jumpAddr();
  } else {
    printf("invalid stack addr:%#X\n", *(volatile xt_u32 *)FLASH_APP_START_ADDR);
    return XERROR;
  }
}
在system_gd32e10x.c库文件中定义使用的晶振是哪个
/* select a system clock by uncommenting the following line */
/* use IRC8M */
//#define __SYSTEM_CLOCK_IRC8M                    (uint32_t)(__IRC8M)
//#define __SYSTEM_CLOCK_48M_PLL_IRC8M            (uint32_t)(48000000)
//#define __SYSTEM_CLOCK_72M_PLL_IRC8M            (uint32_t)(72000000)
//#define __SYSTEM_CLOCK_108M_PLL_IRC8M           (uint32_t)(108000000)
#define __SYSTEM_CLOCK_120M_PLL_IRC8M           (uint32_t)(120000000)

/* use HXTAL(CK_HXTAL = 8M) */
//#define __SYSTEM_CLOCK_HXTAL                    (uint32_t)(__HXTAL)
//#define __SYSTEM_CLOCK_48M_PLL_HXTAL            (uint32_t)(48000000)
//#define __SYSTEM_CLOCK_72M_PLL_HXTAL            (uint32_t)(72000000)
//#define __SYSTEM_CLOCK_108M_PLL_HXTAL           (uint32_t)(108000000)
//#define __SYSTEM_CLOCK_120M_PLL_HXTAL           (uint32_t)(120000000)

简直让人难过,应用程序使用的是__SYSTEM_CLOCK_120M_PLL_HXTAL
bootloader采用的是__SYSTEM_CLOCK_120M_PLL_IRC8M
所以无法跳转过去,上帝,忙了我一整天。
总结以下几个注意事项:
(1)bootloader和应用程序使用的外部晶振需要一样。
(2)需要正确设置flash下载地址,因为跳转之前需要设置栈指针,可执行文件bin中的前四字节表示栈顶指针
         后四字节表示程序入口地址。跳转就是把程序入口地址给到PC指针,程序入口地址是复位中断后执行的
        第一条指令,在ARM中通常是指SystemInit函数。所以从bootloader跳转到应用程序后,系统是会重新初始化的
        相当于系统复位了一下。

Reset_Handler   PROC
                EXPORT  Reset_Handler                     [WEAK]
                IMPORT  SystemInit
                IMPORT  __main
                LDR     R0, =SystemInit
                BLX     R0
                LDR     R0, =__main
                BX      R0
                ENDP

(3)如果有采用分散加载,在分散加配制文件.scf中可以指定应用程序的起始地址,这个与在keil中进行设置效果是一样的。采用了分散加载后,程序是按.scf文件来指定flash启始地址,还是按keil中配制没试过。
(4)中断向量要设置正确,一般程序下载的flash地址,就是放置中断向量的地址。
(5)记得在设置栈之前把所有中断禁止__disable_irq();
(6)GD32芯片,中断向量设置时,它的flash地址必须满足0x200对齐,没仔细研究可能所有芯片都有这个限制。
(7)在设置新的栈指针后,局部变量的内容会被修改,如果需要保存一些内容,改用全局变量或者static修饰。

You may also like...

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据