完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
stm32
stm32启动方式分为(根据boot0,boot1的配置选择): 1)主闪存存储器= 芯片内置的Flash。这也是正常工作模式 2)SRAM = 芯片内置的RAM 区,就是内存啦。 3)系统存储器= 芯片内部一块特定的区域,芯片出厂时在这个区域预置了一段Bootloader,就是通常说 的ISP 程序。这个区域的内容在芯片出厂后没有人能够修改或擦除,即它是一个ROM 区。 第3种方式,是运行厂商自己的引导程序,用来从串口烧写程序,一般没什么用,我们一般使用第1种方式启动stm32 。但是i.mx6ull就不一样了,i.mx的厂商程序是一般都要运行的,它的负责选择从sd卡、nandflash、EMMC等启动,甚至需要负责初始化DDR3芯片,比stm32的厂商引导程序强大的多 stm32一般要实现类似i.max厂商引导程序这样的功能,需要自己实现,一般的实现方式是讲片上ROM分成两部分,0x0800 0000开始烧写自己实现的bootloader(这个bootloader一般用来ota升级使用),0x0800 2000开始烧写真正的程序,具体实现方式如下: 注意: 从0x0800 0000开始64个字节存放的是bootloader的bin文件指定的中断向量表 从0x0800 2000开始64个字节存放的是真正的程序bin文件指定的中断向量表 这些中断向量表都是在汇编文件startup_stm32f071xb.s中指定的 stm32上电,硬件这时自动从0x0800 0000位置处(中断向量表)读取数据赋给栈指针SP(这里存放的是栈顶指针),然后自动从0x0800 0004位置处读取数据赋给PC(这里存放的是复位中断服务程序),完成复位,也就是刚上电和按复位按钮的效果是一致的。 这里的SP和PC初始化都是烧写的Bootloader程序里面指定的,在bootloader程序运行完毕之前需要我们手动讲SP和PC初始化为0x0800 2000处中断向量表指定的值,也就是真正程序指定的值。 我们来看一下一份bootloader示例代码: #include #include #include "flash_map.h" #include #include "crc32.h" #include "ota.h" #include "crc16.h" #include "adp_flash.h" #include "bsp_clock.h" #include "debug.h" int main(void) { uint16_t tmp_crc16 = 0; bool err_program = false; stUpdataData_t ota_para; clock_hsi_config(); HAL_MspInit(); //初始化外置flash ext_flash_init(); //负责校验外置flash中的bin文件,并烧写到内置flash的0x0802 0000处 int ret = ota_begin(); if(ret == 0) //编程OK { ota_jpapp(); } else //编程失败 { NVIC_SystemReset();//重启 while(1); } } #define APPLICATION_ADDRESS 0x08002000 typedef void (*pFunction)(void); pFunction Jump_To_Application; uint32_t JumpAddress; void ota_jpapp(void) { JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4); Jump_To_Application = (pFunction) JumpAddress; __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS); Jump_To_Application(); } 可以看到,bootloader完成ota功能之后,调用了ota_japp()函数,从0x0800 2000处读取栈顶指针付给MSP(也就是SP),从0x0800 2004处读取复位中断服务程序 函数指针付给PC。 这样真正的程序就开始运行了,但是运行之前还需要做一件事,现在生效的中断向量表仍然是bootloader的中断向量表(0x0800 0000处的),需要让真正程序(0x0800 2000处)的中断向量表生效。如果是cortex-m3内核的stm32,比较简单,直接修改中断向量表偏移寄存器SCB->VTOR 为0x2000,即可让0x0800 2000处的中断向量表生效,即调用一下函数(ST官方库函数): void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset){ assert_param(IS_NVIC_VECTTAB(NVIC_VectTab)); assert_param(IS_NVIC_OFFSET(Offset)); SCB->VTOR = NVIC_VectTab | (Offset & (uint32_t)0x1FFFFF80); } 但是,cortex-m0内核没有SCB->VTOR这个寄存器,所以只支持中断向量表位于 ROM起始处(0x0800 000),或者ram起始处(0x2000 0000),无法设置偏移,而且ROM起始处已经被bootloader的中断向量表占用了,下一次芯片上电还要用,不能动,所以只能将0x0800 2000处的中断向量表 拷贝到 RAM起始处(0x2000 0000),并设置,中断向量表从RAM起始处生效。如下(这里0x0800 2000处跑的是rtthread系统,所以将拷贝中断向量表的任务放在main函数中,运行完会startup_stm32f071xb.s汇编文件就会运行此main函数): int $Sub$$main(void) { //拷贝0x0800 0000处中断向量表到0x2000 0000,即RAM起始处 ota_iap_set(); rt_hw_interrupt_disable(); rtthread_startup(); return 0; } void ota_iap_set(void) { uint32_t i = 0; for(i = 0; i < 64; i++) { *((uint32_t*)(0x20000000 + (i << 2))) = *(__IO uint32_t*)(APPLICATION_ADDRESS + (i<<2)); } __HAL_RCC_SYSCFG_CLK_ENABLE(); __HAL_SYSCFG_REMAPMEMORY_SRAM();//设置中断向量表从RAM起始处生效,而不是ROM起始处 } 设置中断向量表从RAM起始处生效,而不是ROM起始处} 至此,stm32的启动方式就讲完了 I.mx6ull I.mx6ull也是可以根据BOOT_MODEL[0:1]引脚选择启动方式: 00:Boot From Fuses(熔丝)一般不用 01:Serial Downloader(从串口或者u***下载程序用) 10:Internal Boot(厂商引导程序) I.mx6ull一般选择10,从内部boot rom启动(和stm32还是有区别的,stm32一般不用厂商引导程序,而6ull一般都是通过厂商引导程序启动),厂商自己的引导程序可以直接把我们的功能代码拷贝到指定的位置,并且支持多种启动设备。我们只需要用正点原子提供的烧录工具 imxdownload 将bin文件烧录到sd卡即可,此工具会为bin文件加一个头部,厂商自己的引导程序根据这个头部信息初始化ddr3,并根据这个头部信息拷贝代码到指定的ddr3地址。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1614 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1541 浏览 1 评论
970 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
682 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1592 浏览 2 评论
1863浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
644浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
515浏览 3评论
531浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
504浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 01:38 , Processed in 0.832701 second(s), Total 77, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号