一、例程分析
E:\原子资料\【正点原子】北极星stm32h750开发板资料\4,程序源码\新建文件夹\2,标准例程-HAL库版本\实验56 串口IAP实验\IAP Bootloader V1.0_FLASH\USER
boot例程分析:
- 例程使用750XB
- ram rom
- User下无需生成bin
- c++, level 2
- 使用了分散加载
- 750xb烧写算法,注意自己板子qspi烧写算法!
- 本例程的功能是将iap程序拷贝到0x00000000地址,即ITCM。
iap程序在bl_itcm.c中,使用const定义,存储在qspi中,由分散加载文件决定。
- 程序上电后,会初始化Stm32_Clock_Init,里面初始化并启动了qspi的映射模式QSPI_Enable_Memmapmode,注意自己板子qspi的引脚!
- 拷贝iap程序到ITCM
- 判断中断向量地址 是否是从0开始,猜测:iap程序的rom地址应该为0x0了。
if((((vu32)(BOOTLOADER_RUN_ADDR+4))&0xFF000000)==0x00000000) - 跳转判断程序的栈顶地址为2000 0000,猜测:iap程序的ram地址应该是0x2000 0000
if((((vu32)appxaddr)&0x2FF00000)==0x20000000)
IAP程序分析:
-
target,rom地址是800 0000,跟之前猜测的不一样,这样的话,就无法跳转iap了。
if((((vu32)(BOOTLOADER_RUN_ADDR+4))&0xFF000000)==0x00000000) 假
ram地址,ram1 ram2都有勾选 ,具体如何分配就看map文件了。下图,ram使用了2400 0000,这样的话,if((((vu32)appxaddr)&0x2FF00000)==0x20000000) 也为假,这还咋跳转??
-
iap竟然还用了分散加载,生成俩bin,这咋放在boot程序 const 数组里呢??
怀疑历程在打包过程出现问题。。。。
二、例程修改
boot程序
u32 tempreg=0;
vu32 *data_reg=&QUADSPI->DR;
GPIO_InitTypeDef qspi_gpio;
RCC->AHB4ENR|=1<<1; //使能GPIOB时钟
RCC->AHB4ENR|=1<<3; //使能GPIOD时钟
RCC->AHB4ENR|=1<<4; //使能GPIOE时钟
RCC->AHB3ENR|=1<<14; //QSPI时钟使能
//初始化PB6 片选信号
qspi_gpio.Pin=GPIO_PIN_6;
qspi_gpio.Mode=GPIO_MODE_AF_PP; //复用
qspi_gpio.Pull=GPIO_PULLUP;
qspi_gpio.Speed=GPIO_SPEED_FREQ_VERY_HIGH; //高速
qspi_gpio.Alternate=GPIO_AF10_QUADSPI; //复用为QSPI
HAL_GPIO_Init(GPIOB,&qspi_gpio);
//初始化PB2 时钟信号
qspi_gpio.Pin=GPIO_PIN_2;
qspi_gpio.Mode=GPIO_MODE_AF_PP; //复用
qspi_gpio.Pull=GPIO_NOPULL;
qspi_gpio.Speed=GPIO_SPEED_FREQ_VERY_HIGH; //高速
qspi_gpio.Alternate=GPIO_AF9_QUADSPI; //复用为QSPI
HAL_GPIO_Init(GPIOB,&qspi_gpio);
//PD11-- QUADSPI_BK1_IO0 PD12-- QUADSPI_BK1_IO1 PD13-- QUADSPI_BK1_IO3
qspi_gpio.Pin=GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13;
qspi_gpio.Mode=GPIO_MODE_AF_PP; //复用
qspi_gpio.Pull=GPIO_NOPULL;
qspi_gpio.Speed=GPIO_SPEED_FREQ_VERY_HIGH; //高速
qspi_gpio.Alternate=GPIO_AF9_QUADSPI; //复用为QSPI
HAL_GPIO_Init(GPIOD,&qspi_gpio);
//PE2-- QUADSPI_BK1_IO2
qspi_gpio.Pin=GPIO_PIN_2;
qspi_gpio.Mode=GPIO_MODE_AF_PP; //复用
qspi_gpio.Pull=GPIO_NOPULL;
qspi_gpio.Speed=GPIO_SPEED_FREQ_VERY_HIGH; //高速
qspi_gpio.Alternate=GPIO_AF9_QUADSPI; //复用为QSPI
HAL_GPIO_Init(GPIOE,&qspi_gpio);
问题
-
cannot load
解决:
改大一点
-
download failed
再去下载的话 会出现
解决:
问题是因为 Stm32_Clock_Init,QSPI_Enable_Memmapmode 没有修改qspi引脚 导致内存映射死机 连程序都无法下载。此时需要复位+快速点击download按钮,一定要快!!! -
download failed 每次下载都会出现 但是程序也下载进去了
下载过程,会先擦除片内,再下载片内,然后片外,但最后报错片外内容不匹配:9000B86EH!
原因是效验错误 ,把烧进去的和生成的hex/bin进行对比,不一样的话就报错了。
还有一点,如果片外的代码小一点,也不会报错,比如2k外部就报错,1.9k就不报错了。。。我用的flash也是w25q64,跟例程一样,分散加载文件里 m_qspiflash_size 大小就是8M,不用修改。然后看一下这个地址,0x9000 b86e,在看map文件,qspi地址最后在0x90001058 长度 43004字节(0xa7fc) ,加一起就是(qspi的使用情况 b854 = 47188字节)
报错的地址在这个地址后面,应该没有用到啊,为啥还进行效验呢?难道是按块进行效验的?如果按块效验的,这个块的后半部分的可能装过其他程序,特别是上一个程序比当前程序大的情况下,那我把qspi全部擦除在重新下载是不是就不报错了呢?有待测试
解决:
不清楚~!可以把效验的勾去掉。。。
iap程序
-
修改结果如下,只修改了画线部分
如何计算的呢?根据boot例程iap程序bin文件,它生成的这个bin是符合前面的两个猜测的,if也为真,是可以跳转的。
如果不加修改,iap例程是编译不出下面的bin数据的,由此可见,应该是打包错误。。。
-
去掉分散加载
-
生成bin
fromelf --bin -o "$L@L.bin" "#L"
-
bin转为c,经过对比,跳转应该是没问题了
-
替换boot程序中的iap代码 烧写测试 发现串口有输出 打印了lcd的型号 然后死掉了 至少说明正常跳转了
-
找问题,发现QSPI_Enable_Memmapmode函数中 qspi引脚初始化没改,
qspi.c 中 HAL_QSPI_MspInit 引脚修改