关于自制 STM8 Bootloader

由于本人项目需要,要做STM8L052R8的bootloader,用于远程程序升级功能,为了安全考虑,不使用ST自带的bootloader,而是自制bootloader。

基本的功能是这样的,首先程序运行在一个V1.0的版本上,且带了BOOT,当程序收到一条命令后,程序跑入死循环,等待硬件看门狗复位;程序复位后进入bootload区,等待第二条命令的接收,接收到正确的数据帧后,bootloader开始擦除FLASH,并接收数据包,直到最后一个数据包接收完毕,通过指示灯以2HZ的频率闪烁,指示升级完成。
          第一步:boot区程序设计,首先修改link文件,

    define region NearFuncCode = [from 0x8000 to 0xAFFF];
          define region FarFuncCode = [from 0x8000 to 0xAFFF];
          define region HugeFuncCode = [from 0x8000 to 0xAFFF];
          place at start of NearFuncCode  { block INTVEC };

以上是link文件部分,可以看出flash地址为0x8000开始,结束于0x17FFF; 长度为64kB,中断向量地址为0x8000,
这样,知道了这个我们就可以修改BOOT程序的link和主程序的link了,这里我把BOOTLOAD区划分为8K,应用区为48K
设置link文件如下,这样把boot区和APP区分开,互不干扰,你也可以根据需要调整他们的大小。

          program:
          define region NearFuncCode = [from 0xB000 to 0xFFFF];
          define region FarFuncCode = [from 0xB000 to 0xFFFF]| [from 0x10000 to 0x17FFF];
          define region HugeFuncCode = [from 0xB000 to 0x17FFF];
          place at start of NearFuncCode  { block INTVEC };
         bootload:
          define region NearFuncCode = [from 0x8000 to 0xAFFF];
          define region FarFuncCode =    [from 0x8000 to 0xAFFF];
          define region HugeFuncCode = [from 0x8000 to 0xAFFF];
          place at start of NearFuncCode  { block INTVEC };

像STM32这样的芯片中断向量地址可以任意定,所有boot区和APP区都可以使用中断,且互不干扰,但是STM8的中断向量表固定在0X8000地址,不能修改,所以BOOT区不能开中断,否则会和APP区的中断打架,但是APP区的一但开启中断后就会跳转到0x8000地址,这样就跳到了BOOT区,因此需要使用跳转指令将中断跳回到APP区,

__root const long reintvec[]@".intvec"=
{ 0x82008080,0x8200b004,0x8200b008,0x8200b00c, //当应用程序地址不是0xB000时则要相应改掉除第一个
        0x8200b010,0x8200b014,0x8200b018,0x8200b01c, //0x82008080以外的数值
        0x8200b020,0x8200b024,0x8200b028,0x8200b02c,
        0x8200b030,0x8200b034,0x8200b038,0x8200b03c,
        0x8200b040,0x8200b044,0x8200b048,0x8200b04c,
        0x8200b050,0x8200b054,0x8200b058,0x8200b05c,
        0x8200b060,0x8200b064,0x8200b068,0x8200b06c,
        0x8200b070,0x8200b074,0x8200b078,0x8200b07c,
}; 

这里大概的含义就是重定义STM8的中断,STM8中断向量重定义,至于这里为什么这样写,请网上自己去看,我也不是很清楚。
    
          第二步:芯片上电后,从bootload start 跳转到 program start
          当我们上电时,我们往往不需要用到bootload ,但是程序起来就先跑到ROM的起始地址,因此需要做一个跳转
从bootload start 跳转到 program start。设计如下

asm("LDW X,  SP ");
asm("LD  A,  $FF");
asm("LD  XL, A ");
asm("LDW SP, X ");
asm("JPF $B000");

这里我们用B000,表示上电以后BOOT区没有接收到升级请求则直接跳转到APP区,0XB000是我的APP的起始地址,你可以根据自己的要求定义。
        第三步:在线擦写flash

 void Boot_EraseChip(void)
{
  U16 usCnt;
  /* Define flash programming Time*/
  FLASH_SetProgrammingTime(FLASH_ProgramTime_Standard);
  Boot_UnLock();
  /*擦除FLASH*/
  LED_ALARM_H();
  LED_RUN_L();
  for(usCnt = USER_FLASE_ALL_OF_BLOCK;usCnt >0;usCnt-- )
  {
    HD_Clear_WDT();

    FLASH_EraseBlock(USER_FLASH_START_BLOCK+(usCnt-1), FLASH_MemType_Program);
    /* Wait until End of high voltage flag is set*/
    while (FLASH_GetFlagStatus(FLASH_FLAG_HVOFF) == RESET)
    {}
  }
  LED_ALARM_L();
  LED_RUN_H();
  Boot_Lock();
}

这个函数里面我的BOOT程序一旦接收到升级命令后,先将FLASH擦除,这里用到了一个库函数,
STM8 的lib 库里面有stm8l15x_flash.h stm8l15x_flash.c
这个文件里面有一段注释,如下所示,意思是要使用flash的擦写,必须要在stm8l15x.h里面定义

#define RAM_EXECUTION  (1)  ,flash 擦写的函数都是定义在ram地址中的,所以在这些函数前都有个in_ram
  * To enable execution from RAM you can either uncomment the following define
  * in the stm8l15x.h file or define it in your toolchain compiler preprocessor
  * - #define RAM_EXECUTION  (1) 

并且由于 stm8的库对不同芯片处理不同,还需要定义你使用的芯片型号,这里我用的芯片是
STM8L052,因此使用的宏为 :

#define STM8L05X_HD_VL

这样就可以调用擦写函数去升级APP程序了,其他的工做就是在BOOT 区进行数据的收发等待,数据校验等工做了,没什么特别的东西。不管用什么芯片,只要是FLASH是分块的,都可以做boot,去加载APP。

时间: 2024-10-03 13:09:48

关于自制 STM8 Bootloader的相关文章

STM8不用手动复位进入自带Bootloader方法(串口下载)

源:STM8不用手动复位进入自带Bootloader方法(串口下载) STM8不用手动复位进入自带Bootloader方法(串口下载)除非STM8片子的空的,如果复位运行的是自带Bootloader,而且要通过串口下载程序的话,必须在1s内点击上位机,要不然就运行用户程序了. 这一步很麻烦,所以想把它给省掉. 后来发现上位机Flash Loader Demonstrator在启动画面点击Next后,会先从串口的DTR.RTS输出一个大概100多毫秒的脉冲,TTL电平就是负脉冲了,之后才会和单片机

怎么写stm8的IAP升级的bootloader和app

因为之前写个stm32的IAP升级程序,所以我总结了做IAP升级的三个主要的难点: 1.如何设置中断向量,也就是说中断向量的重定向 2.如何配置程序的起始地址 3.如何从IAP跳转到APP程序 4.使用库函数要注意的地方(防止被坑) 说文章的时候我已经完成了一个最简单的IAP升级程序,可以通过串口接收bin文件写入到flash里面,然后再运行. 1.如何设置中断向量,也就是说中断向量的重定向 stm8不像stm32那样有个一寄存器管理着中断向量的地址,所以stm32的中断可以任意设置(符合要求的

关于 开机启动加密破坏修复 自制linux系统

开机破坏并且修复之      自制linux系统            CentOS 6启动流程:POST --> Boot Sequence(BIOS) --> Boot Loader -->Kernel(ramdisk) --> rootfs --> switchroot --> /sbin/init -->(/etc/inittab, /etc/init/*.conf) --> 设定默认运行级别--> 系统初始化脚本rc.sysinit --&g

操作系统内核Hack:(三)BootLoader制作

操作系统内核Hack:(三)BootLoader制作 关于本文涉及到的完整源码请参考MiniOS的v1_bootloader分支. 1.制作方法 现在我们已经了解了关于BootLoader的一切知识,让我们开始动手做一个BootLoader吧!但真正开始之前,我们还要做出一个选择,在之前的讨论中我们曾说过,有两种学习和制作引导程序和操作系统内核的路线:1)<Orange's:一个操作系统的实现>书中的路线:2)Linux 0.11的路线. 1.1 两种实现思路 具体来说,第一种路线就是将Boo

CentOS 6系统下自制小Linux

以CentOS 6为基础制作小Linux过程: 首先我们需要知道CentOS 6系统的启动流程为POST(加电自检)-->BIOS(系统选择启动设备的先后顺序,默认顺序为光盘.U盘.硬盘)-->Bootloader(系统引导程序,使用grub加载器)-->kernel(初始化内核)-->/sbin/init(运行init程序). 首先需要一块全新的硬盘来装配制作一个启动Linux系统最基本的启动程序以及其配置文件:包括grub程序及其库文件.复制内核文件以及ramdisk文件.将/

使用U盘自制Linux操作系统

章节导航: 前言 Linux系统启动流程 实验前的准备 实验过程 拷贝命令脚本 一.前言 我们生活中离不开电脑,时时刻刻在跟操作系统打交道,有时候会被系统中出现的错误搞得头昏脑胀,使用操作系统,不如亲自动手组建一个自己的简单的系统,体验一下制作操作系统的乐趣.在系统的学习了Linux操作系统之后,就有了理论基础,所以,迫不及待的想做一个自己的简单的Linux小系统,有兴趣的同学也可以来动手做一做. 在接下来的文章中,小编会先从Linux系统的启动流程入手,将启动过程一一展示出来,再进行实验指导.

CentOS 6.5玩转自制Linux、远程登录及Nginx安装测试

前言    系统定制在前面的博文中我们就有谈到过了,不过那个裁减制作有简单了点,只是能让系统跑起来而,没有太多的功能,也没的用户登录入口,而这里我们将详细 和深入的来谈谈Linux系统的详细定制过程和实现用户例如.远程登录和Nginx安装过程.一步一步从头开始定制属于我们自己的系统. 正文    首先我们先来简单的介绍一下我们这里定制属于自己的Linux系统的基本元素.而其实一些相关的信息也可以参考我前面写过的博文:总结之:CentOS 6.4系统裁减详解及装载网卡步骤 一个定制的linux内核

Linux内核+Busybox自制linux系统

实验环境 1.centos7图形化界面安装 2.busybox:busybox-1.30.0.tar.bz2 官网 https://busybox.net 下载地址:https://busybox.net/downloads/busybox-1.30.0.tar.bz2 3.一块新添加的硬盘 Busybox 是一个开源项目,遵循GPL v2协议.Busybox将众多的UNIX命令集合进一个 很小的可执行程序中,其中包括了三百多个最常用Linux命令和工具 一.编译安装busybox [[emai

[小小Pi] AVR Bootloader~烧烧烧

布洛德 烧~烧~烧~ ?? 树莓派碎碎念?? ? Arduino?? ? My Android/EV3 toolchain? ? WinAVR toolchain?? ? AVR Bootloader~烧烧烧??? USB/USB 串口/Wiring??? Serial/ISP/ICSP/Hacking? E06-AVR/ATmega8/ATmega8L | ATtiny85 | ATmega88 | ATmega168/ATmega328/328p | ATmega32U4 | ATmega8