完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
一、背景
公司在开发假智能眼镜,使用STM32L0系列芯片作为主控芯片,蓝牙连接,看起来不是很复杂。在客户测试的时候发现了一些问题,需要重装程序。人员只要两三下的事情,在客户那里可能会遇到麻烦的事情。所以给设备添加在线升级,通过蓝牙将新的功能更新到主控芯片里,而bootloader中不可OTA或缺的一部分。 二,实现思路 引导程序其实就是一段启动程序,它在芯片启动的时候首先被执行,它可以用来做一些硬件的初始化,当初始化完成之后跳转到对应的应用程序中去。 我们可以将内存分为两个区,一个是启动程序区(0x0800 0000 - 0x0800 2000 )大小为8K Bytes,剩下的为应用程序区(0x0800 2000 - 0x0801 0000)。 芯片上电时程序启动运行,然后跳转到应用程序区执行应用程序。 三、程序跳转 引导加载程序就是一个主要的功能首先的程序。在STM32中只要将要跳转的地址直接写入PC读取,就可以到对应跳转的。 怎么实现呢? 当我们实现一个函数的时候,这个函数最终会占用一段内存,而它的函数名代表的就是那段内存的地址。这段会将 内存的首地址(函数名对应的地址)加载到PC寄存器中,从而跳转到这段代码来执行。那么我们也可以利用这个原理,定义一个函数指针,这个将指针指向我们 想要的地址,然后调用这个函数,就可以实现程序跳转了。 代码如下: #define APP_ADDR 0x08002000 //应用程序首地址定义 typedef void (*APP_FUNC)(); //函数指针类型定义 APP_FUNC jump2app; //定义一个函数指针 jump2app = ( APP_FUNC )(APP_ADDR + 4); //给函数指针赋值 jump2app(); //调用函数指针,实现程序跳转 上面的代码实现了我们要跳转的功能,而是要跳转到(APP_ADDR + 4)这个地址,而不是APP_ADDR呢? 首先我们要了解主控芯片的启动过程。以STM32为例,在芯片上电的时候,首先会从内存地址0x0800 0000(由启动模式决定)的地方加载栈顶地址(4字节),从0x0800 0004的地方加载程序复位地址( 4字节),然后跳转到对应的复位地址去执行。 所以上面的程序会中,jump2app这个函数路径的地址为(APP_ADDR + 4),调用这个函数路径的时候,内核内核会自动跳转到这个目的指针的内存地址,也就是应用堆栈的内存地址。 四、加载地址 实际运行会发现,因为上面的程序可能会出现问题。我们还减少了一个堆栈地址的加载,也芯片上这里要用到一点点的知识: __asm void MSR_MSP(uint32_t addr) { MSR MSP, r0 BX r14; } __asm void MSR_MSP(uint32_t addr) 是MDK内置形式。 MSR MSP, r0 的英文是将 r0 寄存器参数中的值加载到 MSP(主栈缓存,默认使用时)寄存器中,r0 中保存的是值,添加的值 BX r14即跳转到连接寄存器保存的地址中,即退出函数,跳转到函数调用地址 完整的程序如下: #define APP_ADDR 0x08002000 //应用程序首地址定义 typedef void (*APP_FUNC)(); //函数指针类型定义/** * @brief * @param * @retval */ __asm void MSR_MSP(uint32_t addr) { MSR MSP, r0 BX r14; } /** * @brief * @param * @retval */ void run_app(uint32_t app_addr) { uint32_t reset_addr = 0; APP_FUNC jump2app; /* 跳转之前关闭相应的中断 */ NVIC_DisableIRQ(SysTick_IRQn); NVIC_DisableIRQ(LPUART_IRQ); /* 栈顶地址是否合法(这里sram大小为8k) */ if(((*(uint32_t *)app_addr)&0x2FFFE000) == 0x20000000) { /* 设置栈指针 */ MSR_MSP(app_addr); /* 获取复位地址 */ reset_addr = *(uint32_t *)(app_addr+4); jump2app = ( APP_FUNC )reset_addr; jump2app(); } else { printf(“APP Not Found!n”); } } 五、编译设置 我们需要在设置界面将默认(0x8000000)改为我们的应用程序地址(0x8002000) 六、中断表重映射 完成了上面的工作,实际测试发现程序还是无法正确运行原因是我们没有进行中断向量表的重映射向量表映射什么时候有做过这个工作,我们来看一下:? .S文件里有如下代码: 这种代码表示,程序在执行main函数之前,会先执行SystemInit这个程序。下面看看这个函数到底是什么东西: /** * @brief Setup the microcontroller system. * @param None * @retval None */ void SystemInit (void) { /*!《 Set MSION bit */ RCC-》CR |= (uint32_t)0x00000100U; /*!《 Reset SW[1:0], HPRE[3:0], PPRE1[2:0], PPRE2[2:0], MCOSEL[2:0] and MCOPRE[2:0] bits */ RCC-》CFGR &= (uint32_t) 0x88FF400CU; /*!《 Reset HSION, HSIDIVEN, HSEON, CSSON and PLLON bits */ RCC-》CR &= (uint32_t)0xFEF6FFF6U; /*!《 Reset HSI48ON bit */ RCC-》CRRCR &= (uint32_t)0xFFFFFFFEU; /*!《 Reset HSEBYP bit */ RCC-》CR &= (uint32_t)0xFFFBFFFFU; /*!《 Reset PLLSRC, PLLMUL[3:0] and PLLDIV[1:0] bits */ RCC-》CFGR &= (uint32_t)0xFF02FFFFU; /*!《 Disable all interrupts */ RCC-》CIER = 0x00000000U; /* Configure the Vector Table location add offset address ------------------*/ #ifdef VECT_TAB_SRAM SCB-》VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */ #else SCB-》VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */ #endif } 从上面的代码可以看到,这个函数主要是有可能会触发的初始化和中断,还有就是中断动画表的映射,最后那 一段代码再看看FLASH_BASE和VECT_TAB_OFFSET的定义: 哈哈,这里默认映射的地址就是FLASH的最终地址,只要将其改成我们程序的目的就:SCB=-》V0x0802000 编译,下载,完美运行! 七、 总结程序跳转完成,对于引导加载程序来说剩下的需要根据自己的需要去完善一下相应的功能了,比如我在线升级里功能,做点需要和在网上的功能。这里有一点需要特别注意,跳转程序之前最好把你用到的中断都关了,不然跳转之后的程序没有对应的中断处理函数,那就又可能使得程序进入死循环中。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1537 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1490 浏览 1 评论
910 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
654 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1538 浏览 2 评论
1845浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
596浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
499浏览 3评论
499浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
483浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-5 14:22 , Processed in 0.726173 second(s), Total 45, Slave 38 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号