历史上的今天
返回首页

历史上的今天

今天是:2025年03月30日(星期日)

正在发生

2021年03月30日 | freescale飞思卡尔 HCS12 系列单片机bootloader详解(一)

2021-03-30 来源:eefocus

  最近在做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

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的第一步,划分储存空间。


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


       (未完待续)


推荐阅读

史海拾趣

大毅科技公司的发展小趣事

大毅科技于1989年成立,是台湾的一家新兴企业。在公司成立的初期,大毅科技就专注于晶片电阻的研发与生产,这在当时是一个相对新兴且竞争激烈的领域。创始人凭借对技术的深刻理解和敏锐的市场洞察力,带领公司逐步在市场中站稳脚跟。通过不断的技术创新和产品优化,大毅科技逐渐获得了客户的认可,并在行业中树立了自己的品牌。

Heidenhain Corp公司的发展小趣事

在全球化背景下,海德汉公司不断拓展其国际市场版图。通过参加国际展会、建立海外分支机构等方式,海德汉成功将其高精度数控系统和自动化解决方案推向全球电子市场。特别是在亚洲、欧洲和北美等电子产业发达的地区,海德汉的产品和技术得到了广泛应用和认可。这一市场拓展战略不仅提升了海德汉的品牌知名度和市场份额,也为其在电子行业的长期发展奠定了坚实基础。

需要注意的是,以上故事虽基于事实背景构建,但具体细节和案例可能有所虚构或简化,以符合问题要求和字数限制。

Headland Technology Product Group公司的发展小趣事

在电子行业中,产品质量是企业生存和发展的基石。HBControls深知这一点,因此始终将品质管理放在首位。公司建立了完善的质量管理体系,从原材料采购、生产加工到成品检验,每一个环节都严格把关。此外,HBControls还定期对员工进行质量意识培训,确保每一位员工都能将品质理念融入到日常工作中。正是凭借卓越的产品质量和优质的服务,HBControls赢得了众多客户的信赖和好评。

恒连电子(EVERCOM)公司的发展小趣事

恒连电子成立于XX年代初,当时正值电子行业的快速发展期。创始人张先生凭借对电子技术的敏锐洞察力和对市场趋势的精准把握,决定投身于电子行业。然而,初创时期的公司面临着资金短缺、技术团队匮乏以及市场竞争激烈等多重挑战。张先生带领团队日夜兼程,通过自主研发和不断创新,逐渐在市场中站稳脚跟。他们首先推出了几款性能稳定、价格合理的电子产品,赢得了客户的信赖。随着产品的逐步推广,恒连电子逐渐在市场中打开了局面。

DLG Hanbit公司的发展小趣事

面对数字化转型的浪潮,DLG Hanbit公司积极拥抱变革。公司加大了对云计算、大数据、人工智能等技术的研发投入,推出了一系列智能电子产品和解决方案。同时,公司还加强了与互联网企业、电信运营商等合作伙伴的合作,共同打造智能生态圈。未来,DLG Hanbit公司将继续秉承创新、品质、环保的理念,致力于成为全球领先的半导体设计和制造企业。

amcc [applied micro circuits corp]公司的发展小趣事

随着技术的不断进步和市场需求的增长,DLG Hanbit公司意识到技术创新是保持竞争力的关键。公司加大了对研发的投入,引进了一批高端人才,并建立了完善的研发体系。经过几年的努力,公司成功开发出了一系列具有自主知识产权的半导体产品,如高性能的处理器、存储器等。这些产品凭借卓越的性能和稳定的品质,在市场上赢得了良好的口碑,公司也逐渐拓展了市场份额。

问答坊 | AI 解惑

新警世格言!

0)领导的逻辑:领导说让你看着办,不是不让你办,而是让你抓紧办;领导说再想想,不是他没想好,而是要你别再想了;领导征求你的意见,不是真的广开言路,而是在寻求同谋;领导找你吃饭,不是让你品评美食,而是让你去买单;领导表扬你,不是因为 ...…

查看全部问答>

求救——嵌入式系统!急

各位大侠,我是大二的学生。现在要申请创新项目。针对聋哑人交流不方便的情况,想做一个智能的设备——聋哑人输入文字到设备中,系统自动将它转化为语音传达给对方。对方的话又可以通过该系统转化成文字显示在设备上。就是具体怎么做还没有头绪。是 ...…

查看全部问答>

工作

我想了解下福州有哪些有单片机开发的公司,比较好一点的。…

查看全部问答>

新开了群组

http://groups.eeworld.net/VxWorks 大家踊跃用哦!…

查看全部问答>

转让ARM开发板

   我上个月买的一块smart arm2200开发块一块,由于之前我已经把,,,看了好几遍,再加上周立功公司的强大的技术支持(我有什么不懂的,直接打电话问即时得到解决).所以到现在,我已把以上几本书的实验做完了,对驱动开发有了较好的了解,已经能 ...…

查看全部问答>

关于帖子不能编辑的建议....

现在的帖子发布一段时间以后(具体是多少忘了,两天?)就不能编辑了,这样当然有道理,避免作者随便修改引起回帖的混乱,但是有时候不能修改确实也有些麻烦,比如之前做DIY的时候,一有新进展就需要新开一个帖子,既让论坛显得有些混乱,也不便于 ...…

查看全部问答>

今天小用了一下ECAP的捕获功能

void InitECapture(){   ECap1Regs.ECEINT.all = 0x0000;             // Disable all capture interrupts   ECap1Regs.ECCLR.all = 0xFFFF;   & ...…

查看全部问答>

求助啊!!!!!!STM32的IO速度与指令执行速度的问题??

72Mhz的STM32 ,PLCK2=72Mhz用逻辑分析仪测试,得到的速度为0.24us/指令,理论上应该是0.14us/指令(模拟器验证)请问这个速度为什么会这么慢72Mhz的STM32F103实际只有40Mhz左右测试代码          ldr r3, =GPI ...…

查看全部问答>

欢迎大家加入C\C++深度剖析群

linux C qt C++的爱好者加入吧  256401284…

查看全部问答>