2021-03-09 STM8L152 IAP 串口升级写入FALSH

文章目录

    一、介绍
        1) Boot 升级简述
        2)编写BootLoader注意事项
            1.重定向中断向量表
            2.Bootloader与Application的空间大小分配定义
            3.程序跳转到APP

       3)编写APP代码,实现升级中改写升级标志
    二、功能实现
        1)中断向量表
        2)数据写入
        3)程序实现

 

 

STM8L    IAP升级
芯片:STM8L152    64K  ROM   2K EEPROM  4KRAM           1页= 2块= 256字节
通讯方式:Uart
IDE: IAR for STM8

实现基于简单串口通信实现IAP升级,测试升级ok,因此写篇笔记记录一下整个过程。
 

一、介绍

1) IAP简介

所谓的IAP即应用程序中编程(In-application programming),即可以在产品出厂后,更新程序。既然可以更新程序,那么就要有程序负责这部分功能,这个程序就叫做BootLoader,而被更新的程序就叫做Application.

2)编写BootLoader注意事项

如果自己编写Bootloader,则需要注意几个方面:


1.中断向量表的重定向

参考文档《STM8L IAP 应用程序中编程指导.pdf》中的说明,点击下载,如下图
这里写图片描述

可以看到,当Application中发生中断的时候,会跳转到0x8000地址处,因此在Bootloader中需要将中断进行重定向,使之能够跳转到Application中的中断向量表中去。

2.Bootloader与Application的空间分配

boot:0x8000--0x8FFF

app:0x9000--0x17FFF

ICF 文件修改如下:

1.Boot程序的icf文件
 

define memory with size = 16M;

define region TinyData = [from 0x00 to 0xFF];

define region NearData = [from 0x0000 to 0x07FF];//RAM+בջ=2KB

define region Eeprom = [from 0x1000 to 0x13FF];  //ʁզǰʼַ֘   

define region BootROM = [from 0x6000 to 0x67FF];

define region NearFuncCode = [from 0x8000 to 0x8FFF];//FLASH=32KB

define region FarFuncCode = [from 0x8000 to 0x8FFF];

define region HugeFuncCode = [from 0x8000 to 0x8FFF];

2.APP 程序的icf文件
 

define memory with size = 16M;

define region TinyData = [from 0x00 to 0xFF];

define region NearData = [from 0x0000 to 0x07FF];//RAM+בջ=2KB

define region Eeprom = [from 0x1000 to 0x13FF];  //ʁզǰʼַ֘   

define region BootROM = [from 0x6000 to 0x67FF];

define region NearFuncCode = [from 0x9000 to 0xFFFF];//FLASH=32KB

define region FarFuncCode = [from 0x9000 to 0xFFFF];

define region HugeFuncCode = [from 0x9000 to 0xFFFF];

3.程序跳转

程序跳转可以分为Bootloader跳转到Application, Application跳转到Bootloader.

上电之后会先进入bootloader,然后再次跳转到app。

APP复位重启就可以重新进入boot。需要增加一个掉电不丢失的标志位。本次放到EEPROM 中
 

unsigned char ucBootStatusInEEPROM @0x1000;//16K

#define BOOT_APP_DFT2    0xFF
#define BOOT_APP_DFT1    0x00    //EEPROM默认状态
#define BOOT_APP_DONE    0x50    //APP区有完整的APP代码
#define BOOT_UPDATE      0x51    //APP区代码需要升级
#define BOOT_APP_NONE    0x52    //APP区代码不完整

void EEPROM_Write(unsigned char ucDat)
{
    FLASH_Unlock(FLASH_MemType_Data); // unlock Flash
    ucBootStatusInEEPROM=ucDat;
    FLASH_Lock(FLASH_MemType_Data); // lock Flash
}
unsigned char EEPROM_Read(void)
{
  return ucBootStatusInEEPROM;
}

//跳转函数
方法一:
void _ASM_JumpTo_App(void)
{

asm("LDW X,  SP ");

asm("LD  A,  $FF");

asm("LD  XL, A  ");

asm("LDW SP, X  ");

asm("JPF $9000");

}

 方法二:   asm("JP $9000");

 

3)APP实现升级重复测试

APP程序实现改写升级完成标志,以便重复测试升级功能

void main(void)
{
    unsigned char  Times = 0;

    //内部时钟作为时钟源  16MHZ
    CLK_HSICmd(ENABLE);
    while( (CLK->ICKCR&0x02) != 0x02 );//stably
    CLK_SYSCLKDivConfig(CLK_SYSCLKDiv_1); 
    CLK_SYSCLKSourceConfig(CLK_SYSCLKSource_HSI);	

    CLK_SYSCLKDivConfig(CLK_SYSCLKDiv_1);//内部时钟不分频

    GPIO_LED_MakeOutHIGH();
    GPIO_LED_On();

    delay_init(16);

    delay_ms(500);
    GPIO_LED_Off();

    Times = 0;
    while(1)
    {
#if   0
       delay_ms(50);
       GPIO_LED_Toggle();
       Times++;
       if(Times>100)
       {
         if(0x50==EEPROM_Read())
         {
           EEPROM_Write(0x51);
         }
         Times=100;
         delay_ms(2000);
       }
#else
       delay_ms(800);
       GPIO_LED_Toggle();
       Times++;
       if(Times>6)
       {
         if(0x50==EEPROM_Read())
         {
           EEPROM_Write(0x51);
         }
         Times=5;
         delay_ms(2000);
       }
#endif
    }
}

二、功能实现

1)重新定义中断向量表

boot中没有采用中断函数,定时查询接收串口的数据

uint32_t FLASH_ReadWord(u32 Address)//读Flash指定地址
{
   return(*(PointerAttr u32 *) (u16)Address);       
}
//重新初始化STM8的中断向量表  把它重新定义到APP的中断向量中
void STM8_HanderIqr_Init(void)
{
  disableInterrupts();   //关闭所有中断  
  
  u8 Index;	
  
  FLASH_Unlock(FLASH_MemType_Program);//解锁flash
  
  for(Index = 1; Index < 0X20;Index++)
  {
   if(FLASH_ReadWord(0X8000+4*Index)!=(0X82000000+USER_APP_START_ADD+Index*4))
   {
    FLASH_ProgramWord(0X8000+4*Index,0X82000000+USER_APP_START_ADD+Index*4);
   }
  }//用户APP起始地址:0x9000-----USER_APP_START_ADD
  FLASH_Lock(FLASH_MemType_Program);
}

2)数据写入FALSH中

我的写入测试,测试写入读取正常。注:FLASH 无需擦除就可以重复写入

void FlashTestOneByte(void)
{
  uint32_t  FlashAddress[15]={0xA000,0xB000,0xC000,0xD000,0xE000,0xF000,0x10000,0x11000,0x12000,0x13000,0x14000,0x15000,0x16000,0x17000};
  uint32_t  WFDWbuf[15]={0x10000001,0x10000002,0x10000003,0x10000004,0x10000005,0x10000006,0x10000007,0x10000008,0x10000009,0x10000010,0x10000011,0x10000012,0x10000013,0x10000014,0x10000015};
  uint32_t
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值