瑞萨RL78簇bootloader深入探讨(一)
前言
bootloader是单片机开发重要的一环,近期笔者需要完成一个瑞萨相关的bootloader项目,然而ARM有关bootloader的开发资料网上能找到很多,但是瑞萨相关的资料相对而言就少很多了。经过一周多从各处收集资料,总结,实验,现将近期完成的一些工作整理成本文,以便日后翻查和给其他人一些经验。
当然,本项目也是东拼西凑,仅供交流学习,许多错误之处也请多多批评指正。
注:本文代码部分均来自网络以及自编,侵删。
概述
本文的目标是完成一个由boot区和user区共同组成的完整工程,user区即用户应用程序,boot区则是程序引导区,主要是为了更新用户程序使用。然后程序复位后能够进入boot程序检查更新,然后跳转进入user程序。
相信许多看到这篇文章的同学对BootLoader都有一定了解,这里不在赘述。
user工程建立
1.新建一个新工程,MCU笔者选择R5F100LG
2.使用代码快速生成工具生成代码
为了展示中断向量表的重映射,这里专门加入几个常用中断响应。主要配置如下:
2.1 LED灯输出P14.0
2.2 串口0收发中断
2.3 ADC中断
2.4 定时器0中断
3.点击生成工程
3.1 r_main.c的初始化中启动三个中断
3.2 ADC中断中插入处理动作
3.3 在定时器中断中加入定时功能:分别是1s LED闪烁一次,2s ADC启动一次转换。(注意函数声明和加入adc的库文件)
3.4 烧录测试,测试结果是灯正常闪烁,adc中断能正常进入。证明用户基础工程建立完毕。
user工程加入启动文件、地址偏移文件、中断向量映射文件。
R5F100LG的FLASH空间是128K (0x0000 ~ 0x1FFFF),笔者将0x0000 ~ 0x2000作为boot区。0x4000 ~ 0x1FFFF作为user区。
下图是RL78G13中断向量表(节选),我们要将中断向量表映射到0x4000开始的位置。
记住我们用到得4个中断源分别是:0x1E串口0发送中断标志、0x20串口0接收中断标志、0x2C定时器0中断标志、0x34ADC中断标志。我们后续需要处理这几个中断向量。
1.加入启动文件cstart.asm及相关的def.inc、macro.inc
文件可以在C:\Program Files (x86)\Renesas Electronics\CS+\CACX\CA78K0R\V1.72\Src\cc78k0r\src目录下找到
其中cstart.asm文件中这一段要屏蔽掉,让该地址跟随我们重新定义的U_ROM地址分配。
- 在工程Startup中加入cstart.asm文件,并在Debug tool设置中设置为cstart启动,生成堆栈解决方案符号设置为Yes。
到这里如果再次进行调试,可以看到程序是从cstart.asm启动的,并在第294行跳转到main()函数
3. 新建并加入分区文件boot.dr,输入以下内容用于分区
MEMORY ROM : ( 000000H, 02000H )
MEMORY U_ROM : ( 004000H, 01C000H )
merge @@CNST :=U_ROM
merge @@CNSTL :=U_ROM
merge @@R_INIT :=U_ROM
merge @@R_INIS :=U_ROM
merge @@RLINIT :=U_ROM
merge @@CODE :=U_ROM
merge @@LCODE :=U_ROM
merge @@BASE :=U_ROM
merge @@CODEL :=U_ROM
新建int_vect.asm,用于中断跳转声明,输入下列内容:
NAME INT_VECT
EXTRN _@cstart
EXTRN AVT_RST
EXTRN AVT_E00
EXTRN AVT_E01
EXTRN AVT_E02
EXTRN AVT_E03
EXTRN AVT_E04
EXTRN AVT_E05
EXTRN AVT_E06
EXTRN AVT_E07
EXTRN AVT_E08
EXTRN AVT_E09
EXTRN AVT_E10
EXTRN AVT_E11
EXTRN AVT_E12
EXTRN AVT_E13
EXTRN AVT_E14
EXTRN AVT_E15
EXTRN AVT_E16
EXTRN AVT_E17
EXTRN AVT_E18
EXTRN AVT_E19
EXTRN AVT_E20
EXTRN AVT_E21
EXTRN AVT_E22
EXTRN AVT_E23
EXTRN AVT_E24
EXTRN AVT_E25
EXTRN AVT_E26
EXTRN AVT_E27
EXTRN AVT_E28
EXTRN AVT_E29
EXTRN AVT_E30
EXTRN AVT_E31
EXTRN AVT_E32
EXTRN AVT_E33
EXTRN AVT_E34
EXTRN AVT_E35
EXTRN AVT_E36
EXTRN AVT_E37
EXTRN AVT_E38
EXTRN AVT_E39
EXTRN AVT_E40
EXTRN AVT_E41
EXTRN AVT_E42
EXTRN AVT_E43
EXTRN AVT_E44
EXTRN AVT_E45
EXTRN AVT_E46
EXTRN AVT_E47
EXTRN AVT_E48
EXTRN AVT_E49
EXTRN AVT_E50
EXTRN AVT_E51
EXTRN AVT_E52
EXTRN AVT_E53
EXTRN AVT_BRK
@@VECT_RST CSEG AT 0000H
DW AVT_RST
@@VECT00 CSEG AT 0004H
DW AVT_E00 ; 0x04
@@VECT01 CSEG AT 0006H
DW AVT_E01 ; 0x06
@@VECT02 CSEG AT 0008H
DW AVT_E02 ; 0x08
@@VECT03 CSEG AT 000AH
DW AVT_E03 ; 0x0A
@@VECT04 CSEG AT 000CH
DW AVT_E04 ; 0x0C
@@VECT05 CSEG AT 000EH
DW AVT_E05 ; 0x0E
@@VECT06 CSEG AT 0010H
DW AVT_E06 ; 0x10
@@VECT07 CSEG AT 0012H
DW AVT_E07 ; 0x12
@@VECT08 CSEG AT 0014H
DW AVT_E08 ; 0x14
@@VECT09 CSEG AT 0016H
DW AVT_E09 ; 0x16
@@VECT10 CSEG AT 0018H
DW AVT_E10 ; 0x18
@@VECT11 CSEG AT 001AH
DW AVT_E11 ; 0x1A
@@VECT12 CSEG AT 001CH
DW AVT_E12 ; 0x1C
@@VECT13 CSEG AT 001EH
DW AVT_E13 ; 0x1E
@@VECT14 CSEG AT 0020H
DW AVT_E14 ; 0x20
@@VECT15 CSEG AT 0022H
DW AVT_E15 ; 0x22
@@VECT16 CSEG AT 0024H
DW AVT_E16 ; 0x24
@@VECT17 CSEG AT 0026H
DW AVT_E17 ; 0x26
@@VECT18 CSEG AT 0028H
DW AVT_E18 ; 0x28
@@VECT19 CSEG AT 002AH
DW AVT_E19 ; 0x2A
@@VECT20 CSEG AT 002CH
DW AVT_E20 ; 0x2C
@@VECT21 CSEG AT 002EH
DW AVT_E21 ; 0x2E
@@VECT22 CSEG AT 0030H
DW AVT_E22 ; 0x30
@@VECT23 CSEG AT 0032H
DW AVT_E23 ; 0x32
@@VECT24 CSEG AT 0034H
DW AVT_E24 ; 0x34
@@VECT25 CSEG AT 0036H
DW AVT_E25 ; 0x36
@@VECT26 CSEG AT 0038H
DW AVT_E26 ; 0x38
@@VECT27 CSEG AT 003AH
DW AVT_E27 ; 0x3A
@@VECT28 CSEG AT 003CH
DW AVT_E28 ; 0x3C
@@VECT29 CSEG AT 003EH
DW AVT_E29 ; 0x3E
@@VECT30 CSEG AT 0040H
DW AVT_E30 ; 0x40
@@VECT31 CSEG AT 0042H
DW AVT_E31 ; 0x42
@@VECT32 CSEG AT 0044H
DW AVT_E32 ; 0x44
@@VECT33 CSEG AT 0046H
DW AVT_E33 ; 0x46
@@VECT34 CSEG AT 0048H
DW AVT_E34 ; 0x48
@@VECT35 CSEG AT 004AH
DW AVT_E35 ; 0x4A
@@VECT36 CSEG AT 004CH
DW AVT_E36 ; 0x4C
@@VECT37 CSEG AT 004EH
DW AVT_E37 ; 0x4E
@@VECT38 CSEG AT 0050H
DW AVT_E38 ; 0x50
@@VECT39 CSEG AT 0052H
DW AVT_E39 ; 0x52
@@VECT40 CSEG AT 0054H
DW AVT_E40 ; 0x54
@@VECT41 CSEG AT 0056H
DW AVT_E41 ; 0x56
@@VECT42 CSEG AT 0058H
DW AVT_E42 ; 0x58
@@VECT43 CSEG AT 005AH
DW AVT_E43 ; 0x5A
@@VECT44 CSEG AT 005CH
DW AVT_E44 ; 0x5C
@@VECT45 CSEG AT 005EH
DW AVT_E45 ; 0x5E
@@VECT46 CSEG AT 0060H
DW AVT_E46 ; 0x60
@@VECT47 CSEG AT 0062H
DW AVT_E47 ; 0x62
@@VECT48 CSEG AT 0064H
DW AVT_E48 ; 0x64
@@VECT49 CSEG AT 0066H
DW AVT_E49 ; 0x66
@@VECT50 CSEG AT 0068H
DW AVT_E50 ; 0x68
@@VECT51 CSEG AT 006AH
DW AVT_E51 ; 0x6A
@@VECT52 CSEG AT 006CH
DW AVT_E52 ; 0x6C
@@VECT53 CSEG AT 006EH
DW AVT_E53 ; 0x6E
@@VECT_BRK CSEG AT 007EH
DW AVT_BRK ; 0x7E
END
屏蔽中断函数的声明和静态声明,用于接下来得外部调用,以r_adc_user.c为例。
新建vect_table.asm用于映射中断跳转。输入以下内容,主要是中断响应函数声明和中断向量对应的中断响应函数。
NAME VECT_TABLE
; External symbols ----------------------------------------------------------
EXTRN _@cstart
EXTRN _r_tau0_channel0_interrupt
EXTRN _r_adc_interrupt
EXTRN _r_uart0_interrupt_send
EXTRN _r_uart0_interrupt_receive
BR_VALUE EQU 0EDh ;RL78 BR opcode
; Public symbols ------------------------------------------------------------
PUBLIC AVT_RST
PUBLIC AVT_E00
PUBLIC AVT_E01
PUBLIC AVT_E02
PUBLIC AVT_E03
PUBLIC AVT_E04
PUBLIC AVT_E05
PUBLIC AVT_E06
PUBLIC AVT_E07
PUBLIC AVT_E08
PUBLIC AVT_E09
PUBLIC AVT_E10
PUBLIC AVT_E11
PUBLIC AVT_E12
PUBLIC AVT_E13
PUBLIC AVT_E14
PUBLIC AVT_E15
PUBLIC AVT_E16
PUBLIC AVT_E17
PUBLIC AVT_E18
PUBLIC AVT_E19
PUBLIC AVT_E20
PUBLIC AVT_E21
PUBLIC AVT_E22
PUBLIC AVT_E23
PUBLIC AVT_E24
PUBLIC AVT_E25
PUBLIC AVT_E26
PUBLIC AVT_E27
PUBLIC AVT_E28
PUBLIC AVT_E29
PUBLIC AVT_E30
PUBLIC AVT_E31
PUBLIC AVT_E32
PUBLIC AVT_E33
PUBLIC AVT_E34
PUBLIC AVT_E35
PUBLIC AVT_E36
PUBLIC AVT_E37
PUBLIC AVT_E38
PUBLIC AVT_E39
PUBLIC AVT_E40
PUBLIC AVT_E41
PUBLIC AVT_E42
PUBLIC AVT_E43
PUBLIC AVT_E44
PUBLIC AVT_E45
PUBLIC AVT_E46
PUBLIC AVT_E47
PUBLIC AVT_E48
PUBLIC AVT_E49
PUBLIC AVT_E50
PUBLIC AVT_E51
PUBLIC AVT_E52
PUBLIC AVT_E53
PUBLIC AVT_BRK
; Application Vector Table --------------------------------------------------
SEC_APP CSEG AT 4000H
AVT_RST:
DB BR_VALUE ; BR
DW _@cstart ; Reset vector
AVT_E00:
DB BR_VALUE ; BR 0x04
DW _@cstart ; Interrupt Service Routine
AVT_E01:
DB BR_VALUE ; BR 0x06
DW _@cstart ; Interrupt Service Routine
AVT_E02:
DB BR_VALUE ; BR 0x08
DW _@cstart ; Interrupt Service Routine
AVT_E03:
DB BR_VALUE ; BR 0x0A
DW _@cstart ; Interrupt Service Routine
AVT_E04:
DB BR_VALUE ; BR 0x0C
DW _@cstart ; Interrupt Service Routine
AVT_E05:
DB BR_VALUE ; BR 0x0E
DW _@cstart ; Interrupt Service Routine
AVT_E06:
DB BR_VALUE ; BR 0x10
DW _@cstart ; Interrupt Service Routine
AVT_E07:
DB BR_VALUE ; BR 0x12
DW _@cstart ; Interrupt Service Routine
AVT_E08:
DB BR_VALUE ; BR 0x14
DW _@cstart ; Interrupt Service Routine
AVT_E09:
DB BR_VALUE ; BR 0x16
DW _@cstart
;DW _@cstart ; Interrupt Service Routine
AVT_E10:
DB BR_VALUE ; BR 0x18
DW _@cstart ; Interrupt Service Routine
AVT_E11:
DB BR_VALUE ; BR 0x1A
DW _@cstart ; Interrupt Service Routine
AVT_E12:
DB BR_VALUE ; BR 0x1C
DW _@cstart ; Interrupt Service Routine
AVT_E13:
DB BR_VALUE ; BR 0x1E
DW _r_uart0_interrupt_send ; Interrupt Service Routine
AVT_E14:
DB BR_VALUE ; BR 0x20
DW _r_uart0_interrupt_receive ; Interrupt Service Routine
AVT_E15:
DB BR_VALUE ; BR 0x22
DW _@cstart ; Interrupt Service Routine
AVT_E16:
DB BR_VALUE ; BR 0x24
DW _@cstart ; Interrupt Service Routine
AVT_E17:
DB BR_VALUE ; BR 0x26
DW _@cstart ; Interrupt Service Routine
AVT_E18:
DB BR_VALUE ; BR 0x28
DW _@cstart ; Interrupt Service Routine
AVT_E19:
DB BR_VALUE ; BR 0x2A
DW _@cstart ; Interrupt Service Routine
AVT_E20:
DB BR_VALUE ; BR 0x2C
DW _r_tau0_channel0_interrupt
;DW _@cstart ; Interrupt Service Routine
AVT_E21:
DB BR_VALUE ; BR 0x2E
DW _@cstart
;DW _@cstart ; Interrupt Service Routine
AVT_E22:
DB BR_VALUE ; BR 0x30
DW _@cstart ; Interrupt Service Routine
AVT_E23:
DB BR_VALUE ; BR 0x32
DW _@cstart ; Interrupt Service Routine
AVT_E24:
DB BR_VALUE ; BR 0x34
DW _r_adc_interrupt ; Interrupt Service Routine
AVT_E25:
DB BR_VALUE ; BR 0x36
DW _@cstart ; Interrupt Service Routine
AVT_E26:
DB BR_VALUE ; BR 0x38
DW _@cstart ; Interrupt Service Routine
AVT_E27:
DB BR_VALUE ; BR 0x3A
DW _@cstart ; Interrupt Service Routine
AVT_E28:
DB BR_VALUE ; BR 0x3C
DW _@cstart ; Interrupt Service Routine
AVT_E29:
DB BR_VALUE ; BR 0x3E
DW _@cstart ; Interrupt Service Routine
AVT_E30:
DB BR_VALUE ; BR 0x40
DW _@cstart ; Interrupt Service Routine
AVT_E31:
DB BR_VALUE ; BR 0x42
DW _@cstart ; Interrupt Service Routine
AVT_E32:
DB BR_VALUE ; BR 0x44
DW _@cstart ; Interrupt Service Routine
AVT_E33:
DB BR_VALUE ; BR 0x46
DW _@cstart ; Interrupt Service Routine
AVT_E34:
DB BR_VALUE ; BR 0x48
DW _@cstart ; Interrupt Service Routine
AVT_E35:
DB BR_VALUE ; BR 0x4A
DW _@cstart ; Interrupt Service Routine
AVT_E36:
DB BR_VALUE ; BR 0x4C
DW _@cstart ; Interrupt Service Routine
AVT_E37:
DB BR_VALUE ; BR 0x4E
DW _@cstart ; Interrupt Service Routine
AVT_E38:
DB BR_VALUE ; BR 0x50
DW _@cstart ; Interrupt Service Routine
AVT_E39:
DB BR_VALUE ; BR 0x52
DW _@cstart ; Interrupt Service Routine
AVT_E40:
DB BR_VALUE ; BR 0x54
DW _@cstart ; Interrupt Service Routine
AVT_E41:
DB BR_VALUE ; BR 0x56
DW _@cstart ; Interrupt Service Routine
AVT_E42:
DB BR_VALUE ; BR 0x58
DW _@cstart ; Interrupt Service Routine
AVT_E43:
DB BR_VALUE ; BR 0x5A
DW _@cstart ; Interrupt Service Routine
AVT_E44:
DB BR_VALUE ; BR 0x5C
DW _@cstart ; Interrupt Service Routine
AVT_E45:
DB BR_VALUE ; BR 0x5E
DW _@cstart ; Interrupt Service Routine
AVT_E46:
DB BR_VALUE ; BR 0x60
DW _@cstart ; Interrupt Service Routine
AVT_E47:
DB BR_VALUE ; BR 0x62
DW _@cstart ; Interrupt Service Routine
AVT_E48:
DB BR_VALUE ; BR 0x64
DW _@cstart ; Interrupt Service Routine
AVT_E49:
DB BR_VALUE ; BR 0x66
DW _@cstart ; Interrupt Service Routine
AVT_E50:
DB BR_VALUE ; BR 0x68
DW _@cstart ; Interrupt Service Routine
AVT_E51:
DB BR_VALUE ; BR 0x6A
DW _@cstart ; Interrupt Service Routine
AVT_E52:
DB BR_VALUE ; BR 0x6C
DW _@cstart ; Interrupt Service Routine
AVT_E53:
DB BR_VALUE ; BR 0x6E
DW _@cstart ; Interrupt Service Routine
AVT_BRK:
DB BR_VALUE ; BR
DW _@cstart ; Interrupt Service Routine
END
测试与分析
完整得工程目录如图所示:
下载并开始调试:
1.开始调试之后复位会默认进入0H的位置:
2.然后会跳转AVT_RST的声明处,也就是我们重映射的4000H地址:
3.按F11进行下一步,可以看到成功跳转到_@cstart标签,也就是启动文件。
4. 294行打下断点,可以看到启动文件即将进入main()函数:
5.在重映射的中断跳转函数中打下断点,按F5进行调试,等待100ms后可以看到程序进入了我们设的重映射中断中:
6. 同理可在adc中断打下断点进行测试。
总结
本章完成了user工程的Flash区分配,中断向量表的重映射,并且重新建工程开始一步一步展示如何操作。
下一章将准备介绍boot工程的建立。期(duan)待(geng) ε≡٩(๑>₃<)۶
参考
1.《【总结】cstart.asm,78K0R系列启动文件详解》
https://blog.csdn.net/iluzhiyong/article/details/51902297
2.《自定义瑞萨单片机RL78 启动文件的六个步骤》
http://diagram.eepw.com.cn/diagram/circuit/cid/138/cirid/125679
3.《Rl78 bootloader vector table application notes》