了解更多关于 bootloader 的 C 语言实现, 请加我 QQ: 1273623966 (验证信息请填 bootloader), 欢迎咨询或定制 bootloader(在线升级程序).
前段时间完成的 hyperboot_rl78, 是专门为 Renesas 16-bit 单片机 RL78 通过串口更新程序的 bootloader. 由于它是通过超级终端采用 Send File 的方式来传送 Hex 文件, 文本原文传送, 没有协议, 所以基本上 hyperboot_rl78 是不会使用到产品上, 只能在实验室用用. 但是今天我要介绍的 RL78 bootloader 是可靠性非常高的一款串口 bootloader. 它分两部分, 一部分是 RL78 MCU 端 boot 程序 rl78Boot, 另一部分是 PC 端 host 程序 rl78Loader. 他们之间有通信协定, 所以快速, 可靠, 可以使用到最终的产品上.
rl78Boot 是使用 CS+ 和 CC-RL 开发的 boot 程序, rl78Boot 和 application 的 memory map 设计和 hyperboot_rl78 是一样的, interrupt vector remap 也和 hyperboot_rl78 一样, 详见我上一篇博文. rl78Boot 上电的时候就运行, 3~4 秒后如果没有接收到 PC 端 host 程序 rl78Loader 发过来的更新程序请求. 就跳转到正常的 application 去. 如果接收到更新请求, 就接收 rl78Loader 发送过来的数据, 并根据数据中的命令字段来执行相应的动作, 并根据结果返回 ACK (0x15) 或 NACK (0x51).
命令字段有以下几种
- 0x6F: HAND_SHAKE (握手, 或叫更新请求)
- 0x02: WR_MEM (Flash 烧写)
- 0x03: ER_MEM (Flash 擦除)
- 0x04: VF_MEM (Flash 验证)
- 0x1F: RUN_APP (跳转到 application)
rl78Boot 的程序框架如下
- void BTLD_BootProcess(void)
- {
- if (R_UART0_RcvFlag())
- {
- if (BTLD_FramePtr == 0)
- {
- uint8_t sof = R_UART0_FlagedReceive();
- if ( sof != 0x02 && sof != 0x03 && sof != 0x04 && sof != 0x1F )
- {
- ;
- }
- else
- {
- BTLD_ReceiveFrame[BTLD_FramePtr++] = sof;
- }
- }
- else
- {
- BTLD_ReceiveFrame[BTLD_FramePtr++] = R_UART0_FlagedReceive();
- }
- }
- if (BTLD_FramePtr == FRAME_BUFF_SIZE)
- {
- uint8_t cmd = BTLD_ReceiveFrame[CMD_INDEX];
- uint8_t addL = BTLD_ReceiveFrame[ADDRL_INDEX];
- uint8_t addH = BTLD_ReceiveFrame[ADDRH_INDEX];
- uint8_t addU = BTLD_ReceiveFrame[ADDRU_INDEX];
- uint32_t add32 = ((uint32_t)addU <<16)|((uint32_t)addH << 8) | addL;
- BTLD_FramePtr = 0;
- switch (cmd)
- {
- case ER_MEM:
- BTLD_FlashErase(add32);
- resetDataBuffer(BTLD_ReceiveFrame, FRAME_BUFF_SIZE);
- break;
- case WR_MEM:
- BTLD_FlashWrite(add32);
- resetDataBuffer(BTLD_ReceiveFrame, FRAME_BUFF_SIZE);
- break;
- case VF_MEM:
- BTLD_FlashVerify(add32);
- break;
- case RUN_APP:
- Jump_To_Application(add32);
- break;
- default:
- break;
- }
- }
- }
rl78Loader 是使用 Visual Studio 2013 和 C# 开发的带 UI 界面的 PC 端 host 程序, rl78Loader 界面上可以选择 COM 口, Baud rate, 加载要烧写的 hex(目前只支持 Motorola S-Record 格式). 并将 record 数据转换成 Bin 数据. 我为 rl78Loader 和 rl78Boot 之间的交互, 设计总共 5 种类型的帧分别对应到 5 种不同的命令, 也就是 HAND_SHAKE, WR_MEM, ER_MEM, VF_MEM, RUN_APP. 5 种帧的统一格式如下:
<CMD><ADDR_L><ADDR_H><ADDR_U><DATA_1><DATA_2>.....<DATA_n><CHECK_SUM>
上面就是自定义的通信协定, 规定了每个帧包含命令字段一个 (<CMD>), 地址字段三个 (<ADDR_L>, <ADDR_H > 和 < ADDR_U>), 组合起来就是 24-bit 地址. 数据字段 n 个 < DATA_1>....<DATA_n>, 以及最后的校验和 < CHECK_SUM>. 每个字段都是 1 个 Byte(8-bit). 当某些字段不用时, 可以填充 0xFF. 比如握手帧在 < CMD > 段为 0x6F, 在 < ADDR_L>, <ADDR_H>, <ADDR_U > 都为 0xFF, 因为握手帧不需要地址内容.
UI 界面上 "Start" 按钮按下后, 首先发送握手帧 (CMD=0x6F), 并重复多次, 如果重复多次仍然没接受到 ACK, Log 窗口就会打印 "bootloader not found".
但握手时一旦接收到 ACK, 就会接着发送擦除帧 (CMD=0x03), 并等待 ACK, 接着就是烧写帧 (CMD=0x02), 验证帧 (CMD=0x04), 最后是跳转帧 (CMD=0x1F). 这个就是整个烧写流程.
rl78Loader 的 UI 界面如下:
来源: https://www.cnblogs.com/geekygeek/p/rl78bootloader.html