freescale飞思卡尔 HCS12 系列单片机bootloader详解(一)

  最近在做freescale HCS12系列单片机的bootloader,毕竟是新手,对这方面的入门知识还是欠缺。尽管NXP官网已经有了相当丰富的文档与例程,可是无奈例程太过复杂,不知道如何下手第一行代码。这里先感谢经验丰富的某位高人醍醐灌顶的指导,为了让再入门的新学者能够有个参考,所以就将本次开发bootloader的过程学习过程记录下来以其能够对大家有所启发。因为本人自己也是新学者,所以有问题可以留言讨论。

  这里单片机的bootloader与我们广义的Linux以及windows的bootloader是不同的。这种大型操作系统的bootloader是为了做操作系统与硬件之间的桥梁:初始化硬件系统、为操作系统的引导做准备。但是单片机的bootloader主要作用却是为烧录程序提供一种新的方式,即可以让单片机可以通过串口,蓝牙,CAN, LIN等通讯方式更新烧写在Flash中的程序以及参数。这样做的好处很多,比如一个串口烧录的bootloader可以通过串口向单片机的Flash烧录程序而不需要再额外用专用的烧录器来操作,丰富了修改程序的方式,使烧录更加方便。我们常使用的慧净51系列单片机以及Arduino能够通过一根简单的串口线就烧录程序原理都是如此,在这些板子出厂时的原程序是通过专门烧录器烧录的,但由于bootloader的存在,后续用户的程序就可以通过串口烧录。再比如单片机的bootloader在实际使用时可以远程更新单片机程序,为实用的场景提供程序更新的功能,尽管做到这一点对通用计算机非常简单,无非是卸载程序重新安装,但是对于Flash空间较小的单片机而言,就需要通过bootloader这样的程序来提供这种功能。

  单片机的bootloader基本概念实际上也非常的简单,就是把单片机的存储空间(Memory,包括RAM以及Flash)都合理的分配。把Flash的程序存储空间分为bootloader区域以及user application区域。bootloader程序一般是不修改的,一次烧录后可以一直使用(当然也可以有bootloader程序自身的更新,但是原理是一样的),但是user application区域却是可以重复由bootloader修改的。这里的user application区域就是我们通常的应用代码,它是为了实现单片机的功能的主要代码。bootloader区域代码却是为了实现对user application区域的控制而存在的,它的程序逻辑是明确的:与上位机建立bootloader专用的通讯,通过串口等简单通讯方式修改Flash或者EEPROM中的程序内容,完成修改后跳出bootloader执行user application的程序内容。

  这里笔者要假设读者对freescale的HCS12单片机有了一定程度的了解,关于Bootloader的内容以及文本中的部分实例程序均来自NXP公开的AN3275以及AN4258文档以及文档的样例程序,更多的介绍可以去NXP官网下载。

  一个HCS12系列单片机的工程是由多个文件类型构成的。

  .c ——程序文件

  .h ——头文件

      .prm ——内存划分,内存块名称声明以及中断向量声明文件

      所以这里很明显的,开发bootloader最重要的就是对.prm文件进行操作了。这里使用AN3275的例程中prm文件

NAMES END

SEGMENTS
    //RAM = READ_WRITE 0x5000 TO 0x57FF;
    RAM = READ_WRITE 0x5000 TO 0x5322;
    FLASHROUTINES = READ_WRITE 0x5323 TO 0x53C8;  //157 bytes Flash_Cmd & Unsecure
    /* unbanked FLASH ROM */
    //ROM_4000 = READ_ONLY  0x4000 TO 0x7FFF;
    ROM_UPDATE = READ_ONLY 0xF000 TO 0xF0AF RELOCATE_TO 0xE000;     /*Update Section, 224 bytes*/
    ROM_ERASELOADER = READ_ONLY 0xF0B0 TO 0xF0BF;
    ROM_C000 = READ_ONLY  0xF0C0 TO 0xFE50;         /* Code may reach only up to 0xFE50 because of limitation on
                                                * the amount of Flash that is backed-up 
                                                */
    
    /* banked FLASH ROM */
/*    PAGE_3F = READ_ONLY  0x3F8000 TO 0x3FBFFF; not used: equivalent to ROM_C000 */
END

PLACEMENT
    _PRESTART,                   /* Used in HIWARE format: jump to _Startup at the code start */
    STARTUP,                     /* startup data structures */
    ROM_VAR,                     /* constant variables */
    STRINGS,                     /* string literals */
    VIRTUAL_TABLE_SEGMENT,       /* C++ virtual table segment */
    NON_BANKED,                  /* runtime routines which must not be banked */
    DEFAULT_ROM,
    COPY,                        /* copy down information: how to initialize variables */
                                 /* in case you want to use ROM_4000 here as well, make sure
                                    that all files (incl. library files) are compiled with the
                                    option: -OnB=b */
                                 INTO  ROM_C000/*, ROM_4000*/;
//    DEFAULT_ROM                  INTO  PAGE_30,PAGE_31,PAGE_32,PAGE_33,PAGE_34,PAGE_35,PAGE_36,PAGE_37,PAGE_38,PAGE_39,PAGE_3A,PAGE_3B,PAGE_3C,PAGE_3D;
    DEFAULT_RAM                  INTO  RAM;
    UPDATE_SECTION               INTO  ROM_UPDATE;
    ERASELOADER_SECTION          INTO  ROM_ERASELOADER;
    ROUTINESINRAM                INTO FLASHROUTINES;
END

ENTRIES
     vfnpUpdateFn;
     gi16FlashSecurity;
END

STACKTOP 0x53FF

VECTOR 0 _Startup /* reset vector: this is the default entry point for a C/C++ application. */
//VECTOR 0 Entry  /* reset vector: this is the default entry point for a Assembly application. */
//INIT Entry      /* for assembly applications: that this is as well the initialisation entry point */

 

  这里主要先介绍内存划分的内容:

  1)SEGMENTS关键词包含的内容是对Memory(存储空间)的分配,先看第一句:

RAM = READ_WRITE 0x5000 TO 0x5322;

  这个第一句是将所有存储空间0x5000到0x5322的部分命名为RAM, 这部分的操作方式为读写(READ_WRITE)

    FLASHROUTINES = READ_WRITE 0x5323 TO 0x53C8;  //157 bytes Flash_Cmd & Unsecure
    /* unbanked FLASH ROM */
    //ROM_4000 = READ_ONLY  0x4000 TO 0x7FFF;
    ROM_UPDATE = READ_ONLY 0xF000 TO 0xF0AF RELOCATE_TO 0xE000;     /*Update Section, 224 bytes*/
    ROM_ERASELOADER = READ_ONLY 0xF0B0 TO 0xF0BF;
    ROM_C000 = READ_ONLY  0xF0C0 TO 0xFE50;

  后面部分是一致的,关于RELOCATE_TO语句,help文档中搜索可以得到如下说明

Defining a Relocation Rule 
Use the relocation rule if a segment is moved to a different location at runtime. With the relocation rule, you instruct the linker to use different runtime addresses for all objects in a segment. 

当一个segment在运行时需要移动到一个不同的位置可以使用重定位规则。通过使用重定位规则,你可以指示连接器让某个segment中的程序在运行时使用不同的程序地址

This is useful when at runtime the code is copied and executed at a different address than the linked location. One example is a Flash programmer which must run out of RAM. Another example is a boot loader, which moves the actual application to a different address before running it. 


Specify a relocation rule as follows: 

RELOCATE_TO Address
Use <Address> to specify the runtime address of the object. 

Example 
SEGMENTS
    CODE_RELOC  = READ_ONLY 0x8000 TO 0x8FFF RELOCATE_TO 0x1000;
...
END
In this example, references to functions in CODE_RELOC use addresses from 0x1000 to 0x1FFF area, but the code is programmed from 0x8000 to 0x8FFF. 

在这个例子中,CODE_RELOC中的内容在运行时使用地址0x1000到0x1FFF的区域,但实际程序是放在0x8000到0x8FFF的区域中

With RELOCATE_TO, you can execute code at an address different from where it was allocated. The code need not be position independent (PIC), however, non-PIC code may not run at its allocation address, as all references in the code refer to the RELOCATE_TO address.  

  2)在SEGMENTS模块中将存储空间分配以后,在PLACEMENTS中对已经定义的SEGMENTS进行进一步的定义,这里先看PLACEMENTS中的第一项

    _PRESTART,                   /* Used in HIWARE format: jump to _Startup at the code start */
    STARTUP,                     /* startup data structures */
    ROM_VAR,                     /* constant variables */
    STRINGS,                     /* string literals */
    VIRTUAL_TABLE_SEGMENT,       /* C++ virtual table segment */
    NON_BANKED,                  /* runtime routines which must not be banked */
    DEFAULT_ROM,
    COPY,                        /* copy down information: how to initialize variables */
                                 /* in case you want to use ROM_4000 here as well, make sure
                                    that all files (incl. library files) are compiled with the
                                    option: -OnB=b */
                                 INTO  ROM_C000/*, ROM_4000*/;

  上述的_PRESTART,STARTUP等内容是预定义的程序块,这条语句实际上就是指示连接器将上述的这些定义的块放在SEGMENTS中已经定义过的ROM_C000区域。当中的NON_BANKED块熟悉S12的读者应该都知道,我们通常定义的中断函数都放在这个区域内。PALCEMENTS中其余语句为:

    DEFAULT_RAM                  INTO  RAM;
    UPDATE_SECTION               INTO  ROM_UPDATE;
    ERASELOADER_SECTION          INTO  ROM_ERASELOADER;
    ROUTINESINRAM                INTO FLASHROUTINES;

  即,将SEGMENTS中定义的RAM,ROM_UPDATE等区域依次命名为DEFAULT_RAM,UPDATE_SECTION等块。

    到这里,实际上我们基本上已经明确了SEGMENTS语句以及PLACEMENTS语句的作用了,这里总结如下:

           1)SEGMENTS语句按照程序的存储空间定义(datasheet中有物理空间对应存储器分布)将存储空间声明为不同的存储区域

      2)PLACEMENTS语句按照SEGMENTS中的定义对各块进行进一步的划分以及布置

  这也就是bootloader的第一步,划分储存空间。

  那么,存储空间划分好了以后我们要怎么做才能将我们的程序放到这些块中并让它们依次执行呢?

       (未完待续)

      注: 本系列文章均为原创,如有转载引用请标明来源

 

转载于:https://www.cnblogs.com/15821216114sw/p/9127351.html

  • 3
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 飞思卡尔 HCS12 系列单片机Bootloader 是一种程序,它允许用户通过特定的接口对单片机进行编程和调试,而不需要使用外部的编程器或者仿真器。Bootloader 可以通过串口、CAN、USB 等多种通信方式与单片机通信,通过读取或者写入特定的内存区域,实现对单片机程序的更新或者下载。 Bootloader 主要由以下几个部分组成: 1. 启动代码:负责初始化芯片、设置中断向量表、判断是否需要进入 Bootloader 模式等。 2. 通信协议:定义 Bootloader 与 PC 或者其他设备之间的通信协议,例如帧格式、数据传输方式等。 3. 数据处理程序:负责接收 PC 发送的数据,进行校验和解析,根据数据类型进行相应的处理。 4. 程序烧录程序:将接收到的数据写入指定的内存区域,实现程序的更新或者下载。 使用 Bootloader 有以下优点: 1. 省去外部编程器或者仿真器的成本和复杂性,提高开发效率。 2. 允许在线更新程序,方便远程维护。 3. 支持多种通信方式,具有较强的灵活性。 4. 可以通过修改 Bootloader 程序,实现自定义的功能,例如加密、签名等。 需要注意的是,由于 Bootloader 是一种开发人员自行编写的程序,因此需要谨慎设计和实现,避免出现安全漏洞或者其他问题。 ### 回答2: freescale飞思卡尔 hcs12 系列单片机是一种常用于嵌入式系统中的微处理器,其具有较高的性能和可信性。然而,在实际应用中,由于各种原因,可能需要在运行中更新单片机程序,这时候就需要用到bootloaderbootloader是指系统启动的一段程序,其目的是负责加载操作系统或应用程序,同时还可以提供其他的系统维护和管理功能。在嵌入式系统中,bootloader可以用来升级设备的固件或软件版本。 freescale飞思卡尔 hcs12 系列单片机bootloader的主要作用是提供一种方便、安全的方式来更新单片机的程序,而不必拆下整个系统或者芯片。这样可以大大减少维护所需的时间和成本。 hcs12系列单片机bootloader的实现涉及到许多方面的知识,包括内存的分配、程序存储器的管理、通信协议等。在实现时,需要考虑到不同的应用场景,选择适合的通信方式和协议,同时还要保证系统的安全性,避免因误操作或人为破坏而带来的风险。 在使用hcs12系列单片机bootloader时,需要注意以下几个方面: 1.选择合适的bootloader协议。 常见的bootloader协议有IAP、CAN、UART等,每种协议都有自己的特点和适用范围。在选择时,需要根据具体情况进行评估和比较。 2.确保程序存储器的安全性。 程序存储器是单片机程序的核心所在,如果被恶意修改或破坏,可能会导致系统运行不正常。因此,需要采取一些措施来保护程序存储器的安全性,例如加密、校验等。 3.保证通信的稳定性和可靠性。 如果通信不稳定或者出现错误,可能会导致程序烧录失败或者出现其他问题。因此,需要进行充分的测试和验证,确保通信的稳定性和可靠性。 总之,hcs12系列单片机bootloader嵌入式系统中非常重要的组成部分,其实现涉及到多个方面的知识和技能。只有在充分理解和掌握相应的技术和方法之后,才能有效地应用到实际的开发和维护中。 ### 回答3: Freescale飞思卡尔hcs12系列单片机bootloader是一种运行在芯片上的小程序,它可以加载和升级单片机的程序代码。它的作用相当于计算机的BIOS,它使得单片机可以通过外部接口更新程序代码,而无需通过编程器进行操作,这使得单片机的开发和维护变得更加方便。 Freescale飞思卡尔hcs12系列单片机bootloader由两个部分组成,一个是引导程序,另一个是应用程序。引导程序是在芯片制造商出厂时预先生产的程序,它负责从外部接口读取应用程序,并将其加载到单片机中。应用程序则是用户编写的程序,它可以通过外部接口更新或升级,这使得单片机的功能可以不断扩展和迭代。 Freescale飞思卡尔hcs12系列单片机bootloader支持多种通信接口,包括串口、CAN总线、以太网等。用户可以根据自己的需求选择合适的接口进行通信。通信时,用户需要发送特定的命令和数据,以达到读取或写入设备的目的。这些命令和数据需要符合Freescale飞思卡尔hcs12系列单片机bootloader的协议规定,否则将无法完成通信。 总之,Freescale飞思卡尔hcs12系列单片机bootloader是一种非常重要的工具,它使得单片机的开发和维护变得更加方便。了解和掌握这一工具的使用方法,对于单片机开发人员来说是非常重要的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值