STM32 SD bootloader实现

发布者:数据梦行者最新更新时间:2017-09-11 来源: eefocus关键字:STM32  bootloader 手机看文章 扫描二维码
随时随地手机看文章

前几天在网上看到了一个sd bootloader,但是下载需要积分。于是想着自己写个简单的sd卡的bootloader,实际上就是stm32的iap功能了。简单介绍一下stm32的iap吧,以下内容摘抄自网络。

IAP是In Application Programming的首字母缩写,IAP是用户自己的程序在运行过程中对User Flash的部分区域进行烧写,目的是为了在产品发布后可以方便地通过预留的通信口对产品中的固件程序进行更新升级。

通常在用户需要实现IAP功能时,即用户程序运行中作自身的更新操作,需要在设计固件程序时编写两个项目代码,第一个项目程序不执行正常的功能操作,而只是通过某种通信管道(如USB、USART)接收程序或数据,执行对第二部分代码的更新;第二个项目代码才是真正的功能代码。这两部分项目代码都同时烧录在User Flash中,当芯片上电后,首先是第一个项目代码开始运行,它作如下操作:

1)检查是否需要对第二部分代码进行更新
2)如果不需要更新则转到4)
3)执行更新操作
4)跳转到第二部分代码执行

第一部分代码必须通过其它手段,如JTAG或ISP烧入;第二部分代码可以使用第一部分代码IAP功能烧入,也可以和第一部分代码一道烧入,以后需要程序更新是再通过第一部分IAP代码更新。

对于STM32来说,因为它的中断向量表位于程序存储器的最低地址区,为了使第一部分代码能够正确地响应中断,通常会安排第一部分代码处于Flash的开始区域,而第二部分代码紧随其后。

在第二部分代码开始执行时,首先需要把CPU的中断向量表映像到自己的向量表,然后再执行其他的操作。

如果IAP程序被破坏,产品必须返厂才能重新烧写程序,这是很麻烦并且非常耗费时间和金钱的。针对这样的需求,STM32在对Flash区域实行读保护的同时,自动地对用户Flash区的开始4页设置为写保护,这样可以有效地保证IAP程序(第一部分代码)区域不会被意外地破坏。

stm32的iap功能,官方也有com,i2c以及基于USB的DFU,大致原理都是前面所说的那样。对于sd的bootloader,也就是前面所说的第一部分代码实现的主要过程是使用fatfs系统读取sd卡上的bin文件,并把数据写到第二部分代码的向量表起始位置,我的设定是0x8003000处。写完后读取flash校验。就是如此的简单,废话不多说上代码!


  1. /******************************************************************************* 

  2. * Function Name  : main. 

  3. * Description    : main routine. 

  4. * Input          : None. 

  5. * Output         : None. 

  6. * Return         : None. 

  7. *******************************************************************************/  

  8. int main(void)  

  9. {  

  10.     DFU_Button_Config();  

  11.       

  12.     /* Check if the Key push-button on STM3210x-EVAL Board is pressed */  

  13.     if (DFU_Button_Read() != 0x00)  

  14.     { /* Test if user code is programmed starting from address 0x8003000 */  

  15.         if (((*(__IO uint32_t*)ApplicationAddress) & 0x2FFE0000 ) == 0x20000000)  

  16.         { /* Jump to user application */  

  17.   

  18.           JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4);  

  19.           Jump_To_Application = (pFunction) JumpAddress;  

  20.           /* Initialize user application's Stack Pointer */  

  21.           __set_MSP(*(__IO uint32_t*) ApplicationAddress);  

  22.           Jump_To_Application();  

  23.         }  

  24.     } /* Otherwise enters DFU mode to allow user to program his application */  

  25.   

  26.     UsartInitilize();         

  27.     RCC_HSICmd(ENABLE);  

  28.     NVIC_Initilize();    

  29.   

  30.     ComPrint("**********************************\n");  

  31.     ComPrint("*       STM32 SD Bootloader      *\n");  

  32.     ComPrint("*              V1.0              *\n");  

  33.     ComPrint("**********************************\n");  

  34.       

  35.     ComPrint("\nSD-LODER: start flash program......\n");  

  36.   

  37.     if(SD_Initilize() == SD_OK)  

  38.     {  

  39.         FRESULT status = FR_OK;  

  40.         uint8_t flashProgramSuccess = 0;  

  41.         uint8_t checkSum = 0;  

  42.         uint32_t size = 0;  

  43.         uint32_t length = 0;  

  44.         uint32_t sectorAddr = 0;  

  45.         uint32_t i = 0, j = 0, k = 0, numberOfPage = 0;  

  46.           

  47.         f_mount(0, &fsrc);  

  48.         status = f_open(&fp, "upload.bin", FA_READ + FA_OPEN_EXISTING);  

  49.         if(status == FR_OK && (size = f_size(&fp)) != 0)  

  50.         {  

  51.             ComPrint("\nSD-LODER: open upload.bin success, size=%dKB\n\n", size/1024);  

  52.               

  53.             numberOfPage = size / FLASH_PAGE_SIZE + 1;  

  54.             Hal_Unlock();  

  55.             for(i = 0; i < numberOfPage; i++)  

  56.             {  

  57.                 ComPrint("*");  

  58.                 sectorAddr = ApplicationAddress + i*FLASH_PAGE_SIZE;  

  59.                 Hal_Erase(sectorAddr);  

  60.                 for(j = 0; j < FLASH_PAGE_SIZE/wTransferSize; j++)  

  61.                 {  

  62.                     memset(MAL_Buffer, 0x0, wTransferSize);  

  63.                     status = f_read(&fp, MAL_Buffer, wTransferSize, &length);  

  64.                     if(status != FR_OK || length == 0)  

  65.                     {  

  66.                         ComPrint("SD-LODER: \nread file failed when program page %d!\n", i);  

  67.                         goto End_Flash;  

  68.                     }  

  69.                       

  70.                     for(k = 0; k < length; k++)  

  71.                     {  

  72.                         checkSum += MAL_Buffer[k];  

  73.                     }  

  74.                       

  75.                     Hal_Write(sectorAddr + j*wTransferSize, length);  

  76.   

  77.                     if(f_eof(&fp))  

  78.                     {  

  79.                         ComPrint("\n\nSD-LOADER: flash program complete\n");  

  80.                         flashProgramSuccess = 1;  

  81.                         goto End_Flash;  

  82.                     }  

  83.                 }  

  84.   

  85.             }  

  86. End_Flash:            

  87.             f_close(&fp);  

  88.         }  

  89.         else  

  90.         {  

  91.         }  

  92.         f_mount(0, 0);  

  93.         Hal_Lock();  

  94.           

  95.         if(flashProgramSuccess)  

  96.         {  

  97.             uint8_t checkSumOfFlash = 0;  

  98.             for(k = 0; k < size; k++)  

  99.             {                        

  100.                 checkSumOfFlash += *Hal_Read(ApplicationAddress + k, 1);                  

  101.             }  

  102.   

  103.             ComPrint("\nSD-LOADER: flash check %s\n", (checkSumOfFlash == checkSum)? "success":"fail");  

  104.         }  

  105.           

  106.     }  

  107.     

  108.   /* Main loop */  

  109.   while (1)  

  110.   {}  

  111. }  


运行效果如图:



这下子好了,不需要连接数据线就可以在线update stm32的firmware了。插上IAP控制的IO跳线。。。看看是不是升级成功!


关键字:STM32  bootloader 引用地址:STM32 SD bootloader实现

上一篇:STM32中断向量表偏移量0x200详解
下一篇:STM32 USB的DFU功能

推荐阅读最新更新时间:2024-03-16 15:36

基于STM32微控制器的电机控制设计
  变频器的问世和先进的电机控制方法让三相无刷电机(交流感应电机或永磁同步电机)曾经在调速应用领域取得巨大成功。这些高性能的电机驱动器过去主要用于工厂自动化系统和机器人。十年来,电子元器件的大幅降价使得这些电机驱动器能够进入对成本敏感的市场,例如:家电、空调或个人医疗设备。本文将探讨基于ARM的标准微控制器如何在一个被DSP和FPGA长期垄断的市场上打破复杂的控制模式,我们将以意法半导体的基于Cortex-M3 内核的STM32系列微控制器为例论述这个过程。   首先,我们回顾一下电机控制的基本原理。在电机控制系统内,为什么处理器非常重要?我们为什么需要非常好的计算性能?毕竟,Nicolas Tesla在一个世纪前发明交流电机时不需
[单片机]
基于<font color='red'>STM32</font>微控制器的电机控制设计
STM32--基本定时器的应用
实验目的:使用基本定时器TIM6控制LED的亮灭。 void GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, &GPIO_InitStructure); } void TIM6_Init(void) { TIM_TimeBaseIn
[单片机]
[正点原子]STM32开发板F103 第41讲 RTC实时时钟备份区域BKP原理
RTC模块与 时钟配置系统在后备区域,在复位时候不会被清除(框图: 中文参考手册) 如何使用RTC实现时钟?RTCCLK RTC的时钟有几个来源有三种 32.768khz 8Mhz 40khz RTC_PRL是自动重装载寄存器 RTC_DIV 预分频余数寄存器 RTC_DIV的作用就是 可以提供一个更加精确的时钟, 时钟开启之后会给RTC_PRL写一个值(比如100),那么RTCCLK就会被 /100 之后得到 TR_CLK。 TR_CLK的一个周期有100个 RTCCLK ,RTC_DIV在你装载之后它的值就是100,他在 RTCCLK的控制下每一个时钟 减一, 假如RTCCLK=100hz,那么 RT
[单片机]
[正点原子]<font color='red'>STM32</font>开发板F103 第41讲 RTC实时时钟备份区域BKP原理
士兰微电子推出SD4872X系列电流模式PWM+PFM控制器
杭州士兰微电子近日推出了应用于开关电源的、电流模式PWM+PFM控制器——SD4872系列芯片。该系列芯片自身功耗低,采用节能模式调节开关频率,完善的保护功能,EMI特性好。可广泛应用于65W以下的机顶盒、电源适配器等整机产品中。 SD4872X的启动电流很低,仅为10A,因此可以快速启动。而外部启动电路则可以采用较大的启动电阻来减小待机电流,在保证启动正常的同时减小待机功耗。 芯片带软开关控制的图腾柱式驱动输出,并内置了抖频功能,确保芯片内部振荡频率在一个很小的范围内进行抖动,使集中的频谱能量分散化,减小在单一频率的对外辐射,从而改善了系统的EMI特性,简化了EMI设计。 众所周知,当芯片在轻负载或空载条件下工作时,MOSFET
[电源管理]
STM32 基础系列教程 21 - NVIC
前言 学习stm32 NVIC接口编程,学会使用常用的NVIC接口函数,优改中关优先级,开/关单个中断,开/关所有中断,开/关所有中断和异常,系统软件重启等功能。 示例详解 基于硬件平台: STM32F10C8T6最小系统板, MCU 的型号是 STM32F103c8t6, 使用stm32cubemx 工具自动产生的配置工程,使用KEIL5编译代码。 本示例所用的最小系统板原理图: 从本节开始,关于CUBEMX工具及KEIL工具的操作将不再细讲,如果还有不熟悉的可以查看之前的教程文档。下面直接介绍工程配置: 系统时钟树 NVIC器配置 开启exit-0外部中断和串口1中断, 串口1的配置
[单片机]
<font color='red'>STM32</font> 基础系列教程 21 - NVIC
STM32软件IIC的实现
接上篇,LIS331的例程终于可以正常运行了,接下来就是将其移植到STM32上了,不过第一次接触STM32的IIC,看例程比较简单,直接复制到工程后却读不出数据,一直停在等待从设备回复ACK的死循环。 经过一天的修改之后,终于还是舍去了硬件IIC改成了用软件实现,最终代码如下: .h文件 #include stm32f10x.h #define ANO_GPIO_I2C GPIOB #define I2C_Pin_SCL GPIO_Pin_3 #define I2C_Pin_SDA GPIO_Pin_4 #define ANO_RCC_I2C RCC_APB2Periph_GPIOB /*******
[单片机]
<font color='red'>STM32</font>软件IIC的实现
STM32 | 两块STM32之间的SPI主从通信实例
一、整体框图及说明 这里使用 STM32F429IGT6 作为主机,STM32F103ZET6 作为从机,都配置为全双工。本例要实现的功能就是主、从机之间的数据互传。 主机往从机发送的数据为: 从机往主机发送的数据为: 二、关键代码 主机关键代码: 从机关键代码: 可见,主机与从机的代码大多都一样。只是从机多了一步启动传输的操作,这一步很关键,少了这一步传输就不正常。这是为了制造主机发送的同时也要接收到数据的条件。这一点参考手册里也有相关说明: 此处,要营造这样的条件,必须先启动从机,然后再启动主机。只有保证主机发送的同时有接收到数据,才能保证其时序的正常,否则可能会产生数据错位,或者会产生多余数据
[单片机]
<font color='red'>STM32</font> | 两块<font color='red'>STM32</font>之间的SPI主从通信实例
stm32单片机待机模式的设计
一 待机模式简介 在stm32的低功耗模式中,待机模式可以实现系统的最低功耗,在这种模式下,只需要2uA左右的电流。 三 待机唤醒程序分析 实验现象: 将程序下载到开发板上后,LED灯会不断地亮灭,当按下KEY2键超过3s时,LED灯灭,标志着单片机进入待机模式,再按下KEY1键,这时唤醒单片机,LED又开始不断地亮灭亮灭。 程序中用到的一些宏定义 #definemacEXTI_GPIO_CLK(RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO) #definemacEXTI_GPIO_PORTGPIOC #definemacEXTI_GPIO_PINGPIO_Pin_13 #definem
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
更多每日新闻
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved