- 收藏
- 点赞
- 分享
- 举报
SD卡升级——SDIO_IAP实验
在嵌入式项目中,经常会用到SD卡升级这一方式来进行产品的软件升级。刚好最近做的项目也需要这一功能,由于之前未接触过IAP开发,刚好在这个时候可以学习一下,于是先到各大网站去搜索相关资料,两天下来,基本对于IAP的概念和编程步骤有了大致的了解。本人手里有块正点原子的开发板,前期的实验都是在这块开发板上实现的。在实现了SD卡IAP功能以后,立马将工程移植到项目中去,很快就把这个功能添加进去了,甚是高兴,对于以前的SD卡升级功能也不再那么神秘了。
本人是先看正点原子的超级战舰手册,先看的《第三十九章 FLASH模拟EEPROM实验》,了解了STM32片内FLASH编程的步骤,然后再看的《第五十三章 串口IAP实验》,学习IAP编程的思想,最后到阿莫电子论坛上搜索相关的资料,最终完成了SD卡IAP编程的学习,并解决了实际问题。
学习总结:
1.STM32片内FLASH编程步骤4步曲:解锁、擦除、编程、上锁;
2.设置IAP程序在FLASH的起始地址,设置用户程序的起始地址为IAP后面的地址,并修改ROM空间大小;
3.在用户程序中,设置中断向量偏移地址为用户程序的起始地址;
4.STM32大容量存储器的页大小为2K,起初总以为是512字节;
5.页擦除的时候,所有的页地址都是实际的字节地址,而并非常说的“第几页第几页”中的页编号;
6.页擦除的时候,如果指定的页地址没有和页边界对齐的话,擦除操作仍然有效,只是擦除的范围是指定地址所在的整页大小;
原子哥的IAP实验是基于串口的,由于串口的数据发送是不可调的,只能一次性将整个用户程序的BIN文件发送给bootloader,而且bootloader是将接收到的用户文件暂存在片内SRAM的,这就限值了用户程序的大小,不能大于SRAM的大小64K。而SD卡设计则不受用户程序大小限值,只要FLASH装得下就行。由于原子哥的代码很多都是寄存器版本的,而文件系统又是他自己独门的FAT32驱动,再加上他的开发板SD卡例程都基于SPI驱动的(只有一个扩展例程是SDIO的),而我的项目时间比较急,要求用最高的效率完成这项功能,于是就产生了以ST官方库函数为主导,以网上开源文件系统Fatfs作为SD卡文件系统驱动,以SDIO4位总线的DMA访问模式为SD卡驱动这样一个方案,一切都只为了开发的效率,同时,也将源代码与大家分享,相信也有很多人使用这样一种方案的。
本工程试验平台:
1.硬件:正点原子超级战舰开发板,由于购买时配套的3.5寸触摸屏,对于3.5以下的屏为测试过,但应该没问题,因为LCD驱动用的还是原子哥的驱动,是兼容2.4到3.5的。SanDisk 1G SD卡, MicroSD 2G。注意:要使用超级战舰开发板上的SDIO功能,必须将开发板上的P10跳线帽接到P11上,因为原子的SD卡驱动默认使用SPI接口的,所以这里必须要设置!
2.软件:ST官方库V3.0的,比较老了。
FatFs文件系统,注意:本人在ff.h配置中将宏_FS_READONLY配置为1,即只生成读操作的代码,不编译写操作的代码,目的是为了减小 bootloader的代码量,包括原子哥的LCD.C中的代码也删减了很多。
下面就将主要的源代码贴出,供大家参考。
[code]/***** 文件名 :main.c
文件描述:程序执行的主要文件,不用说也明白
创建人 :何小龙 博客:http://blog.csdn.net/hexiaolong2009
创建时间:2012.05.16
更改历史:2012.05.29
*****/
include "stm32f10x.h"
include "delay.h"
include "LED.h"
include "diskio.h"
include "ff.h"
include "lcd.h"
define FLASH_APP_ADDR 0x08010000 //第一个应用程序起始地址(存放在FLASH)
define STM_PAGE_SIZE 2048 //注意:STM32F103ZET6的FLASH页大小为2K
//****
//全局变量声明
FATFS Fs;
FIL file;
BYTE buffer[STM_PAGE_SIZE];
FRESULT res;
UINT br;
typedef void (*fun)(void); //定义一个函数类型的参数.
fun AppStart;
/***** 函数名 :Jump2App
功 能:从Bootloader跳转到用户APP程序地址空间
入口参数:Addr,用户APP的起始执行地址
出口参数:无
返回值 :无
*****/
void Jump2App(u32 Addr)
{
if((((vu32)Addr)&0x2FFE0000) == 0x20000000) //检查栈顶地址是否合法.
{
AppStart = (fun)((vu32)(Addr+4)); //用户代码区第二个字为程序开始地址(复位地址)
AppStart(); //跳转到APP.
}
}
/***** 函数名 :FirmwareUpdate
功 能:固件升级函数
入口参数:无
出口参数:无
返回值 :无 *****/ void FirmwareUpdate(void) { int PageOffest = 0; //页偏移,从APP的基地址到当前页起始位置的字节总数 int ByteOffest; //当前页内的字节偏移,从当前操作页的起始位置到正在写入位置的字节偏移 int a, b; u8 i = 0;
/*首先初始化SD卡*/
if(0 != disk_initialize(0)) return;
/*接着挂载文件系统对象*/
f_mount(0, &Fs);
/*查找是否存在要升级的BIN文件*/
res = f_open(&file, "RTC.bin", FA_OPEN_EXISTING | FA_READ);
if(FR_OK != res) return;
/*绘制进度条边框*/
LCD_DrawRectangle(50, 225, 250, 255);
/*初始化临时变量*/
a = file.fsize / 100; //100表示将进度条平均分成100份,由于进度条长度为200个像素,所以1份占用2个像素
a &= 0xfffffffe; //将文件平均分成100份,所以a表示一份文件所占的字节数,为确保该字节数为偶数,故做此转换
b = 0; //b表示当前已经更新了多少字节
/*执行主要的IAP功能*/
while(1)
{
/*每次读取一个页的数据到内存缓冲区,注意:STM32F103ZE的页大小为2K*/
res = f_read(&file, buffer, STM_PAGE_SIZE, &br);
if (res || br == 0) break;
/*然后就是永恒的4步骤:解锁、擦除、更新、上锁*/
FLASH_Unlock();
FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);
FLASH_ErasePage(FLASH_APP_ADDR + PageOffest);
for(ByteOffest = 0; ByteOffest < STM_PAGE_SIZE; ByteOffest += 2)
{
/*更新FLASH,注意当前操作的实际位置:APP基地址FLASH_APP_ADDR+页偏移字节PageOffest+当前页内的字节偏移ByteOffest*/
FLASH_ProgramHalfWord(FLASH_APP_ADDR + PageOffest + ByteOffest, *(u16*)(buffer + ByteOffest));
b += 2;
/*更新显示进度条,(b % a == 0)的目的是确保当前正好写完1份文件*/
if(b % a == 0)
{
LCD_Fill(50, 225, 50 + 2 * (b / a), 255, 0x7e0); //(b / a)表示已经写了几份文件
}
}
FLASH_Lock();
PageOffest += STM_PAGE_SIZE;
/*每更新完1页,让LED状态翻转一次*/
i = !i;
if(i)
GPIO_SetBits(GPIOB, GPIO_Pin_5);
else
GPIO_ResetBits(GPIOB, GPIO_Pin_5);
}
/*关闭文件,卸载文件系统*/
f_close(&file);
f_mount(0, 0);
}
/***** 函数名 :main
功 能:主程序入口函数
入口参数:无
出口参数:无
返回值 :int *****/ int main(void) { SystemInit(); delay_init(72); LED_Init(); LCD_Init(); FirmwareUpdate(); Jump2App(FLASH_APP_ADDR); while(1); }
[/code]
还要注意的地方:用户程序是放在FLASH地址0x08010000的位置的,而且该代码只识别SD卡根目录下的RTC.bin文件,如果要更改文件名,则只需将FirmwareUpdate函数中的“RTC.bin”文件改成你要升级的文件即可。
以下是运行效果:
[attach]1251[/attach] [attach]1252[/attach] 原帖: http://www.amobbs.com/forum.php?mod=viewthread&tid=5536390&extra=page%3D2%26filter%3Drecommend%26orderby%3Drecommends%26recommend%3D1%26recommend%3D1%26orderby%3Drecommends
Markdown 语法
- 加粗**内容**
- 斜体*内容*
- 删除线~~内容~~
- 引用> 引用内容
- 代码`代码`
- 代码块```编程语言↵代码```
- 链接[链接标题](url)
- 无序列表- 内容
- 有序列表1. 内容
- 缩进内容
- 图片![alt](url)
-
2013-12-10 20:29:42
-
2016-03-23 10:11:52
-
2016-08-03 12:43:05
-
2017-07-05 09:29:54
-
02012-12-24 15:16:01
-
22019-08-16 09:25:39
-
42015-10-08 09:15:23
-
12018-06-29 14:51:12
-
2020-04-25 11:00:17
-
2019-09-20 11:06:51
-
2023-08-29 09:45:44
-
2017-08-10 19:05:41
-
2021-10-25 11:11:24
-
2019-06-24 17:30:54
-
2013-08-25 16:25:40
-
2020-05-13 16:35:46
-
2020-06-13 17:05:07
-
2013-09-01 00:45:05
-
182018-08-10 20:29:34
-
50如何获取vpss chn的图像修改后发送至vo
-
5FPGA通过Bt1120传YUV422数据过来,vi接收不到数据——3516dv500
-
50SS928 运行PQtools 拼接 推到设备里有一半画面会异常
-
53536AV100的sample_vdec输出到CVBS显示
-
10海思板子mpp怎么在vi阶段改变视频数据尺寸
-
10HI3559AV100 多摄像头同步模式
-
9海思ss928单路摄像头vio中加入opencv处理并显示
-
10EB-RV1126-BC-191板子运行自己编码的程序
-
10求HI3519DV500_SDK_V2.0.1.1
-
5有偿求HI3516DV500 + OV5647驱动
举报类型
- 内容涉黄/赌/毒
- 内容侵权/抄袭
- 政治相关
- 涉嫌广告
- 侮辱谩骂
- 其他
详细说明