打印

通过bootloader在线串口烧写用户程序后程序没运行问题的请教

[复制链接]
1439|18
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
liangzaixl|  楼主 | 2020-10-19 21:58 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 liangzaixl 于 2020-10-19 22:03 编辑

各位大佬好,
      因为项目需要,自己做了个booloader程序和一个电脑串口上位机来实现通过串口烧写用户程序的功能(其实之前已经在ST平台上实现功能,使用没问题,现在是要移植到GD平台上,然后发现存在问题)。
      芯片用的是GD32F130C8,仿真器用的是ST-LINK,开发环境用的是Keil 5。用户程序中,用timer0做了个定时1ms中断(示波器测试过没问题),然后再在主循环中做一个1s的LED闪烁处理(通过LED闪烁可以看出用户程序有没有运行)。       用户程序测试过如果直接用仿真器烧写进去是可以正常运行的。
       然后尝试通过自己写的bootloader来烧写程序。因为这样烧写后,程序上电是从bootloader跳到用户程序运行的,所以需要重新给用户程序指定存放地址,这里设置0x08005000以上存放用户程序,以下是存放bootloader的。而且这个涉及到中断向量重映射,所以在用户程序main函数开开头加了下面两句代码:
    Memcpy((void*)0x20000000, (void*)0x08005000, 0x168);
    nvic_vector_table_set(NVIC_VECTTAB_RAM, 0);

       现在遇到的问题是,通过串口烧写用户程序之后,发现用户程序没有运行(LED不闪烁),然后如果把在timer0中调用的某个函数(该函数是在其他.c文件定义的,且是空函数),重新烧写用户程序就可以运行。重新加上此空函数的调用,用户程序又不运行了。

       请教下,是不是我哪里写的有问题,或者是重映射中断向量有问题?感谢指点!

       (备注:用户程序通过bootloader串口烧写,和直接通过仿真器烧写,已经用仿真器再读取出来并用代码对比软件对比,用户程序是没有烧写出错的)

使用特权

评论回复
沙发
sonicll| | 2020-10-20 09:07 | 只看该作者
你拷贝中断向量表的这个操作,Memcpy((void*)0x20000000, (void*)0x08005000, 0x168); 感觉有点儿问题,一般来说,RAM里会存放程序使用的静态变量,你这个复制操作,不是把RAM里的静态变量给覆盖了吗?你需要确保你使用的这段RAM,是专门给中断向量表用的,没有被其他变量占用

使用特权

评论回复
评论
liangzaixl 2020-10-20 12:29 回复TA
多谢回复,我是有重新设置了用户程序的RAM起始地址是从0x20000168开始的,0x20000000起始存放的是bootloader程序的变量的,所以这样写是会把bootloader的RAM覆盖了,因为考虑到跳转到用户程序后,bootloader就不再执行了,所以就把它的区间覆盖了,这样这部分空间不会浪费了。 
板凳
jekey| | 2020-10-20 12:54 | 只看该作者
bootloader和应用程序是分开的程序,只需要设置应用程序存放地址和中断偏移地址,ram完全是可以重叠的。

使用特权

评论回复
地板
liangzaixl|  楼主 | 2020-10-20 13:33 | 只看该作者
jekey 发表于 2020-10-20 12:54
bootloader和应用程序是分开的程序,只需要设置应用程序存放地址和中断偏移地址,ram完全是可以重叠的。 ...

是的,所以我是把bootloader的ram区间用来存放应用程序的中断向量了,因为跳转到应用程序之后,bootloader就没用了

使用特权

评论回复
5
jekey| | 2020-10-20 14:51 | 只看该作者
liangzaixl 发表于 2020-10-20 13:33
是的,所以我是把bootloader的ram区间用来存放应用程序的中断向量了,因为跳转到应用程序之后,bootloade ...

是的什么编译器?我用IAR,设置应用程序的地址后,不用自己拷贝中断向量的啊。难道你是在ram中运行程序?

使用特权

评论回复
6
liangzaixl|  楼主 | 2020-10-20 15:29 | 只看该作者
jekey 发表于 2020-10-20 14:51
是的什么编译器?我用IAR,设置应用程序的地址后,不用自己拷贝中断向量的啊。难道你是在ram中运行程序? ...

Keil5, 你不用重新映射中断向量表?我相当于是把startup_gd32f1x0里边的代码COPY到RAM里边了。

使用特权

评论回复
7
liangzaixl|  楼主 | 2020-10-20 15:47 | 只看该作者
jekey 发表于 2020-10-20 14:51
是的什么编译器?我用IAR,设置应用程序的地址后,不用自己拷贝中断向量的啊。难道你是在ram中运行程序? ...

我刚尝试了按你那种做法,直接把中断向量表重映射在FLASH中其他地方,nvic_vector_table_set(NVIC_VECTTAB_FLASH, 0x5000);(我的应用程序起始地址是0x08005000),一样的现象。只要调用那个空函数,程序就不运行,不调用就可以运行。空函数其实原本不为空,只不过我怕是否是因为函数里边的处理导致出现的问题所以把里边的代码全屏蔽了。

使用特权

评论回复
8
jekey| | 2020-10-20 16:07 | 只看该作者
liangzaixl 发表于 2020-10-20 15:47
我刚尝试了按你那种做法,直接把中断向量表重映射在FLASH中其他地方,nvic_vector_table_set(NVIC_VECTTA ...

bootloader用了中断吗? 在跳转到应用前,把中断全部停止。

使用特权

评论回复
9
liangzaixl|  楼主 | 2020-10-20 17:25 | 只看该作者
jekey 发表于 2020-10-20 16:07
bootloader用了中断吗? 在跳转到应用前,把中断全部停止。

试过了,中断关不关现象都是一样的。我在关中断前是有把所有bootloader使用的外设全都按缺省初始化了一遍的。

使用特权

评论回复
10
liangzaixl|  楼主 | 2020-10-21 20:25 | 只看该作者
jekey 发表于 2020-10-20 16:07
bootloader用了中断吗? 在跳转到应用前,把中断全部停止。

发现问题所在,从bootloader跳转到应用程序之后,代码执行时间变长了,导致一直挂在timer0定时中断里边出不去。相同的代码,用仿真器直接烧,程序执行时间大概两三微秒,通过bootloader烧,时间长达60几微秒。但是两种方式的中断定时时间都是对的,说明系统时钟应该是没错(72M)。不知道你有没遇到这种问题?

使用特权

评论回复
11
jekey| | 2020-10-21 22:05 | 只看该作者
liangzaixl 发表于 2020-10-21 20:25
发现问题所在,从bootloader跳转到应用程序之后,代码执行时间变长了,导致一直挂在timer0定时中断里边出 ...

未遇到个这样的情况。

使用特权

评论回复
12
〽️〽️〽️| | 2021-3-3 14:13 | 只看该作者
liangzaixl 发表于 2020-10-21 20:25
发现问题所在,从bootloader跳转到应用程序之后,代码执行时间变长了,导致一直挂在timer0定时中断里边出 ...

我遇到和你一样的情况,请问什么问题呢?
也是 boot里面用了中断,但我都关了

然后 main里 中断向量也设置对了, 中断也开了

用的外部晶振。  就是出现不用bootloader时 ,正常程序OK的
但是bootloader跳到app后 就变慢了

使用特权

评论回复
13
单片小菜| | 2021-3-3 14:58 | 只看该作者
感谢楼主耐心细致的讲解,谢谢了。

使用特权

评论回复
14
hujianming| | 2021-3-5 12:03 | 只看该作者
〽️〽️〽️ 发表于 2021-3-3 14:13
我遇到和你一样的情况,请问什么问题呢?
也是 boot里面用了中断,但我都关了

不知道你用的什么芯片,有些芯片不同的地址空间,CPU指令执行的时间是不一样的。有些空间是零等待,有些不是。这个会有影响的,bootloader和APP的地址分配需要注意这个情况。不知道你的问题是否是这个原因。仅供参考

使用特权

评论回复
评论
〽️〽️〽️ 2021-3-5 13:34 回复TA
谢谢,150G8, boot16k app 超过30k, 总的超32k, 目前还在零等待和32K外 找问题确认,好像也不是这样问题。 
15
西夏晨曦| | 2021-4-23 16:10 | 只看该作者
菜鸟诚心请教,通过bootloader在线串口烧写用户程序具体是怎么实现的呀,感觉GD这方面的资料好少

使用特权

评论回复
16
rocket3370| | 2021-4-29 14:57 | 只看该作者
要用bootloader,一般先把flash空间分配好,比如 16K给bootloader,其他的给app。因为GD的芯片都M3,M4,或者M23,都有中断向量重映射功能,所以一般不考虑用ram运行bootloader。
bootloader就是一个最正常的代码,主要任务就是升级和跳转,跳转之前把所有寄存器,包括IO,UART,timer等都要复原都初始状态(有些可以不复原,但是必须disable),然后跳转到对应地址即可。
比如:
void close_peripherals(void)
{
        SysTick->CTRL = 0;
        NVIC->ICER[0] = 0xFFFFFFFF;
        NVIC->ICPR[0] = 0xFFFFFFFF;
        other_peripherals_close();
}

#define APP_ADDR 0x4000
void jump_to_app(void)
{
        void (*app)(void);
        __set_MSP(*(uint32_t *) APP_ADDR);
        SCB->VTOR = ((uint32_t) APP_ADDR & SCB_VTOR_TBLOFF_Msk);
        app = (void (*)(void))(unsigned *)(*(unsigned *)(APP_ADDR + 4));
        app();
}

app先按照正常代码写,验证没问题后,只需要改两个地方:
1、在system_gd32xxxx.c中,把中断向量重新映射一下。
即修改这个值VECT_TAB_OFFSET为0x4000
/* Vector Table base offset */
#define VECT_TAB_OFFSET  0x4000                 
2、在keil或者IAR里面把link的字段改成0x4000就好了。
一般app升级好了后,也可以在app代码工程里面在线debug调试哦。

使用特权

评论回复
17
rocket3370| | 2021-4-29 15:19 | 只看该作者
忘了初始地址了,#define APP_ADDR 0x4000修改为#define APP_ADDR 0x8004000才对

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

5

主题

21

帖子

0

粉丝