openBLT-系统结构及框架
- 前言
- 1 框架
- 1.1设备层
- 1.2中间件
- 1.2.1 COM
- 1.2.2 BACKDOOR
- 1.2.3 FILE
- 1.3应用层
前言
openBLT 是开源的小型嵌入式系统bootloader,目前支持ST、NXP、T、InfineonI等多个厂商的ARM、HSC12等内核MCU,非常小巧精致,整体代码整洁规范,下面就从整体上梳理下openBLT。
1 框架
先整体把握一下openBLT的框架,所谓一图胜千言,从上面的图基本就能大概看懂整体系统框架以及实现的机制了。接下来逐个击破。
1.1设备层
设备层是最接近硬件设备的部分,涵盖了在固件升级过程中会使用到的各个硬件接口,如:
- 通信接口:CAN、ETH、USART、USB、IIC、MMC等
- 外设模块:TIM、FLASH等
openBLT在设备层针对不同的MCU做了不同的硬件实现,每个硬件接口都做了统一了约定。
#ifndef CAN_H
#define CAN_H
#if (BOOT_COM_CAN_ENABLE > 0)
void CanInit(void);
void CanTransmitPacket(blt_int8u *data, blt_int8u len);
blt_bool CanReceivePacket(blt_int8u *data, blt_int8u *len);
#endif
#endif
#ifndef UART_H
#define UART_H
#if (BOOT_COM_UART_ENABLE > 0)
void UartInit(void);
void UartTransmitPacket(blt_int8u *data, blt_int8u len);
blt_bool UartReceivePacket(blt_int8u *data, blt_int8u *len);
#endif
#endif
类似的都对设备的硬件接口进行统一了封装,这样做的好处有二:
- 方便了接下来中间件实现更高一级的功能实现;
- 实现了中间件与不同硬件MCU的隔离,方便不同平台的移植。
所以这一层的文件下就会有各种各样的板级文件夹,里面实现了不同MCU底层驱动的封装:
.
├── ARM7_LPC2000
│ ├── can.c
│ ├── cpu.c
│ ├── flash.c
│ ├── flash.h
│ ├── GCC
│ │ └── cpu_comp.c
│ ├── nvm.c
│ ├── target.dox
│ ├── timer.c
│ ├── types.h
│ └── uart.c
├── ARMCM0_STM32F0
│ ├── can.c
│ ├── cpu.c
│ ├── flash.c
│ ├── flash.h
│ ├── GCC
│ │ └── cpu_comp.c
│ ├── IAR
│ │ └── cpu_comp.c
│ ├── Keil
│ │ └── cpu_comp.c
│ ├── nvm.c
│ ├── target.dox
│ ├── timer.c
│ ├── types.h
│ └── uart.c
├── ARMCM0_XMC1
│ ├── can.c
│ ├── cpu.c
│ ├── flash.c
│ ├── flash.h
│ ├── GCC
│ │ └── cpu_comp.c
│ ├── IAR
│ │ └── cpu_comp.c
│ ├── nvm.c
│ ├── target.dox
│ ├── timer.c
│ ├── types.h
│ └── uart.c
├── ARMCM3_EFM32
│ ├── cpu.c
│ ├── flash.c
│ ├── flash.h
│ ├── GCC
│ │ └── cpu_comp.c
│ ├── IAR
│ │ └── cpu_comp.c
│ ├── nvm.c
│ ├── target.dox
│ ├── timer.c
│ ├── types.h
│ └── uart.c
├── ARMCM3_LM3S
│ ├── can.c
│ ├── cpu.c
│ ├── flash.c
│ ├── flash.h
│ ├── GCC
│ │ └── cpu_comp.c
│ ├── IAR
│ │ └── cpu_comp.c
│ ├── nvm.c
│ ├── target.dox
│ ├── timer.c
│ ├── types.h
│ └── uart.c
├── ARMCM3_STM32F1
│ ├── can.c
│ ├── cpu.c
│ ├── flash.c
│ ├── flash.h
│ ├── GCC
│ │ └── cpu_comp.c
│ ├── IAR
│ │ └── cpu_comp.c
│ ├── Keil
│ │ └── cpu_comp.c
│ ├── nvm.c
│ ├── target.dox
│ ├── timer.c
│ ├── types.h
│ ├── uart.c
│ └── usb.c
├── ARMCM3_STM32F2
│ ├── can.c
│ ├── cpu.c
│ ├── flash.c
│ ├── flash.h
│ ├── GCC
│ │ └── cpu_comp.c
│ ├── IAR
│ │ └── cpu_comp.c
│ ├── nvm.c
│ ├── target.dox
│ ├── timer.c
│ ├── types.h
│ └── uart.c
├── ARMCM4_STM32F3
│ ├── can.c
│ ├── cpu.c
│ ├── flash.c
│ ├── flash.h
│ ├── GCC
│ │ └── cpu_comp.c
│ ├── IAR
│ │ └── cpu_comp.c
│ ├── nvm.c
│ ├── target.dox
│ ├── timer.c
│ ├── types.h
│ ├── uart.c
│ └── usb.c
├── ARMCM4_STM32F4
│ ├── can.c
│ ├── cpu.c
│ ├── flash.c
│ ├── flash.h
│ ├── GCC
│ │ └── cpu_comp.c
│ ├── IAR
│ │ └── cpu_comp.c
│ ├── nvm.c
│ ├── target.dox
│ ├── timer.c
│ ├── types.h
│ ├── uart.c
│ └── usb.c
├── ARMCM4_STM32L4
│ ├── can.c
│ ├── cpu.c
│ ├── flash.c
│ ├── flash.h
│ ├── GCC
│ │ └── cpu_comp.c
│ ├── IAR
│ │ └── cpu_comp.c
│ ├── nvm.c
│ ├── target.dox
│ ├── timer.c
│ ├── types.h
│ └── uart.c
├── ARMCM4_TM4C
│ ├── cpu.c
│ ├── flash.c
│ ├── flash.h
│ ├── IAR
│ │ └── cpu_comp.c
│ ├── nvm.c
│ ├── target.dox
│ ├── timer.c
│ ├── types.h
│ ├── uart.c
│ └── usb.c
├── ARMCM4_XMC4
│ ├── can.c
│ ├── cpu.c
│ ├── flash.c
│ ├── flash.h
│ ├── GCC
│ │ └── cpu_comp.c
│ ├── IAR
│ │ └── cpu_comp.c
│ ├── nvm.c
│ ├── target.dox
│ ├── timer.c
│ ├── types.h
│ └── uart.c
├── ARMCM7_STM32F7
│ ├── can.c
│ ├── cpu.c
│ ├── flash.c
│ ├── flash.h
│ ├── GCC
│ │ └── cpu_comp.c
│ ├── IAR
│ │ └── cpu_comp.c
│ ├── nvm.c
│ ├── target.dox
│ ├── timer.c
│ ├── types.h
│ └── uart.c
├── HCS12
│ ├── can.c
│ ├── CodeWarrior
│ │ └── cpu_comp.c
│ ├── cpu.c
│ ├── flash.c
│ ├── flash_ecc.c
│ ├── flash.h
│ ├── nvm.c
│ ├── target.dox
│ ├── timer.c
│ ├── types.h
│ └── uart.c
├── TRICORE_TC1798
│ ├── cpu.c
│ ├── flash.c
│ ├── flash.h
│ ├── GCC
│ │ ├── cpu_comp.c
│ │ └── cpu_comp.h
│ ├── nvm.c
│ ├── target.dox
│ ├── timer.c
│ ├── types.h
│ └── uart.c
1.2中间件
有了设备层的加持,中间件就可以实现更多高级的东西啦,在最开始的框图里面,我们在第二层里面能看到很多的中间件:
- COM,负责整个通信数据的收发
- 硬件层面,CAN、UART、ETH、USB等等;
- 应用协议,XCP;
- COP,看门狗;
- DOOR,后门,负责固件跳转、与主机端连接等工作;
- FILE,负责实现固件从文件系统(FatFS)中进行更新的逻辑;
- Assert,断言检测,出现异常后,保持正常喂看门狗,防止异常程序跑飞;
可以说中间件在设备层的支持下,基本实现了固件数据的获取(CAN、UART、USB、ETH、MMC等)以及固件更新(NVM);
1.2.1 COM
COM主要功能逻辑是通过硬件接口获取数数据、按照既定的协议进行数据的解包和封包,完成整个系统的数据交换;
#ifndef COM_H
#define COM_H
#if (BOOT_COM_ENABLE > 0)
#include "xcp.h"
#define BOOT_COM_RX_MAX_DATA (1)
#if (BOOT_COM_CAN_RX_MAX_DATA > BOOT_COM_RX_MAX_DATA)
#undef BOOT_COM_RX_MAX_DATA
#define BOOT_COM_RX_MAX_DATA (BOOT_COM_CAN_RX_MAX_DATA)
#endif
#if (BOOT_COM_UART_RX_MAX_DATA > BOOT_COM_RX_MAX_DATA)
#undef BOOT_COM_RX_MAX_DATA
#define BOOT_COM_RX_MAX_DATA (BOOT_COM_UART_RX_MAX_DATA)
#endif
#if (BOOT_COM_USB_RX_MAX_DATA > BOOT_COM_RX_MAX_DATA)
#undef BOOT_COM_RX_MAX_DATA
#define BOOT_COM_RX_MAX_DATA (BOOT_COM_USB_RX_MAX_DATA)
#endif
#if (BOOT_COM_NET_RX_MAX_DATA > BOOT_COM_RX_MAX_DATA)
#undef BOOT_COM_RX_MAX_DATA
#define BOOT_COM_RX_MAX_DATA (BOOT_COM_NET_RX_MAX_DATA)
#endif
#define BOOT_COM_TX_MAX_DATA (1)
#if (BOOT_COM_CAN_TX_MAX_DATA > BOOT_COM_TX_MAX_DATA)
#undef BOOT_COM_TX_MAX_DATA
#define BOOT_COM_TX_MAX_DATA (BOOT_COM_CAN_TX_MAX_DATA)
#endif
#if (BOOT_COM_UART_TX_MAX_DATA > BOOT_COM_TX_MAX_DATA)
#undef BOOT_COM_TX_MAX_DATA
#define BOOT_COM_TX_MAX_DATA (BOOT_COM_UART_TX_MAX_DATA)
#endif
#if (BOOT_COM_USB_TX_MAX_DATA > BOOT_COM_TX_MAX_DATA)
#undef BOOT_COM_TX_MAX_DATA
#define BOOT_COM_TX_MAX_DATA (BOOT_COM_USB_TX_MAX_DATA)
#endif
#if (BOOT_COM_NET_TX_MAX_DATA > BOOT_COM_TX_MAX_DATA)
#undef BOOT_COM_TX_MAX_DATA
#define BOOT_COM_TX_MAX_DATA (BOOT_COM_NET_TX_MAX_DATA)
#endif
#if (BOOT_COM_TX_MAX_DATA < 1)
#undef BOOT_COM_TX_MAX_DATA
#define BOOT_COM_TX_MAX_DATA (8)
#endif
#if (BOOT_COM_TX_MAX_DATA > 256)
#error "COM.H, BOOT_COM_TX_MAX_DATA cannot be larger than 256."
#endif
#if (BOOT_COM_RX_MAX_DATA < 1)
#undef BOOT_COM_RX_MAX_DATA
#define BOOT_COM_RX_MAX_DATA (8)
#endif
#if (BOOT_COM_RX_MAX_DATA > 65536)
#error "COM.H, BOOT_COM_RX_MAX_DATA cannot be larger than 65536."
#endif
typedef enum
{
COM_IF_UART,
COM_IF_CAN,
COM_IF_USB,
COM_IF_NET,
COM_IF_OTHER
} tComInterfaceId;
void ComInit(void);
#if (BOOT_COM_DEFERRED_INIT_ENABLE == 1)
void ComDeferredInit(void);
#endif
void ComTask(void);
void ComFree(void);
blt_int16u ComGetActiveInterfaceMaxRxLen(void);
blt_int16u ComGetActiveInterfaceMaxTxLen(void);
void ComTransmitPacket(blt_int8u *data, blt_int16u len);
blt_bool ComIsConnected(void);
#endif
#endif
/**********************************************************************************//
** \brief Updates the communication module by checking if new data was received
** and submitting the request to process newly received data.
** \return none
**
****************************************************************************************/
void ComTask(void);
主要是完成硬件接口的数据获取(调用设备层通信接口),然后调用XCP接口进行解析
/**********************************************************************************//
** \brief Releases the communication module.
** \return none
**
****************************************************************************************/
void ComFree(void);
调用硬件接口关闭底层通信
/**********************************************************************************//
** \brief Transmits the packet using the xcp transport layer.
** \param data Pointer to the byte buffer with packet data.
** \param len Number of data bytes that need to be transmitted.
** \return none
**
****************************************************************************************/
void ComTransmitPacket(blt_int8u *data, blt_int16u len)
调用XCP接口进行数据封包
1.2.2 BACKDOOR
Backdoor整体逻辑比较简单,主要判断是否满足程序跳转逻辑。
#ifndef BACKDOOR_H
#define BACKDOOR_H
void BackDoorInit(void);
void BackDoorCheck(void);
#if (BOOT_BACKDOOR_HOOKS_ENABLE == 0)
void BackDoorSetExtension(blt_int32u extension_ms);
blt_int32u BackDoorGetExtension(void);
void BackDoorRestartTimer(void);
#endif
#endif
1.2.3 FILE
file实现固件从文件系统中更新,依赖MMC、USB等设备接口的支持。
#ifndef FILE_H
#define FILE_H
#if (BOOT_FILE_SYS_ENABLE > 0)
#include "ff.h"
#define FILE_ERROR_CANNOT_OPEN_FIRMWARE_FILE (1)
#define FILE_ERROR_CANNOT_READ_FROM_FILE (2)
#define FILE_ERROR_INVALID_CHECKSUM_IN_FILE (3)
#define FILE_ERROR_REWINDING_FILE_READ_POINTER (4)
#define FILE_ERROR_CANNOT_ERASE_MEMORY (5)
#define FILE_ERROR_CANNOT_PROGRAM_MEMORY (6)
#define FILE_ERROR_CANNOT_WRITE_CHECKSUM (7)
#define MAX_CHARS_PER_LINE (256)
#define MAX_DATA_BYTES_PER_LINE (MAX_CHARS_PER_LINE/2)
#define ERROR_SREC_INVALID_CHECKSUM (-1)
typedef enum
{
LINE_TYPE_S1,
LINE_TYPE_S2,
LINE_TYPE_S3,
LINE_TYPE_UNSUPPORTED
} tSrecLineType;
typedef struct
{
blt_char line[MAX_CHARS_PER_LINE];
blt_int8u data[MAX_DATA_BYTES_PER_LINE];
blt_addr address;
} tSrecLineParseObject;
void FileInit(void);
void FileTask(void);
blt_bool FileIsIdle(void);
blt_bool FileHandleFirmwareUpdateRequest(void);
tSrecLineType FileSrecGetLineType(const blt_char *line);
blt_bool FileSrecVerifyChecksum(const blt_char *line);
blt_int16s FileSrecParseLine(const blt_char *line, blt_addr *address, blt_int8u *data);
#endif
#endif
1.3应用层
应用层主要是通过调用各个中间件来实现整个完整openBLT的应用逻辑。
#ifndef BOOT_H
#define BOOT_H
#define BOOT_VERSION_CORE_MAIN (1u)
#define BOOT_VERSION_CORE_MINOR (8u)
#define BOOT_VERSION_CORE_PATCH (0u)
#include "types.h"
#include "assert.h"
#ifdef PROJ_BLT_CONF_H
#include PROJ_BLT_CONF_H
#else
#include "blt_conf.h"
#endif
#include "plausibility.h"
#include "cpu.h"
#include "cop.h"
#include "nvm.h"
#include "timer.h"
#include "backdoor.h"
#include "file.h"
#include "com.h"
#include "led.h"
#if (ADDON_GATEWAY_MOD_ENABLE > 0)
#include "gateway.h"
#endif
void BootInit(void);
void BootTask(void);
#endif
整个代码运行的功能逻辑入口就在void BootTask(void);
void BootTask(void)
{
CopService();
TimerUpdate();
LedBlinkTask();
#if (BOOT_FILE_SYS_ENABLE > 0)
FileTask();
#endif
#if (BOOT_COM_ENABLE > 0)
ComTask();
#endif
#if (ADDON_GATEWAY_MOD_ENABLE > 0)
GatewayTask();
#endif
BackDoorCheck();
}
总体来说openBLT的代码层级非常清晰,也很简洁,是一个非常不错的bootloader。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)