STM32 BootLoader 刷新项目 (四) 通信协议

STM32 BootLoader 刷新项目 (四) 通信协议


前面几章节,我们已经介绍了BootLoader的整体程序框架,方案设计,以及STM32CubdeMX的配置操作。下面切入整个BootLoader项目的核心内容,通信协议。

我理解的通信协议,其实就是双方提前约定好的暗号。比如说到了提前约定好的地方,一个人逢人便说:“天王盖地虎”。只有懂他暗号对接的人才知道,这是他要找的人,另外一个人就回:”小鸡炖蘑菇“。至此,这两个便通过暗号,传达到了他们配对的信息。

所以,在我们进入到BootLoader模式的时候,必须得发送Host主机端和从机定义好的协议进行通讯,二者才能执行正确的行为。

1. 通信流程

下图便是整个通信的流程,显示主机通过UART发送命令指令,从机收到主机发送的命令,如果是正确的命令,则回复ACK,错误的话则回复NACK,然后在回复之后从机会回复多少字节数据。然后再回复结果。

image-20240714102347637

2. 支持指令

下面是整个Customer BootLoader支持的指令,其中比较重要的是0x55(BL跳转固定地址),0x56(指定擦除扇区),0x57(在不同内存写数据)。后续将详细介绍整个Customer BootLoader的方案实现和代码实现。

主机发送 命令码 BootLoader回复 备注
BL_GET_VER 0x51 BootLoader版本号(1 byte) 从MCU中读BootLoader的版本号
BL_GET_HELP 0x52 所有支持的命令码(10 bytes) 列出BootLoader支持的所有命令
BL_GET_CID 0x53 Chip identification number(2 bytes) 读芯片的识别号
BL_GET_RDP_STATUS 0x54 返回芯片读保护等级(1 byte) 读行骗Flash的读保护等级
BL_GO_TO_ADDR 0x55 返回成功或错误(1 byte) BL跳转固定地址
BL_FLASH_ERASE 0x56 返回成功或错误(1 byte) 指定擦除扇区
BL_MEM_WRITE 0x57 返回成功或错误(1 byte) 在不同内存写数据
BL_EN_R_W_PROTECT 0x58 返回成功或错误(1 byte) 使能读/写保护
BL_MEM_READ 0x59 主机请求的内存内容长度 TO DO
BL_READ_SECTOR_STATUS 0x5A 所有Sector状态 读所有扇区的保护状态
BL_OTP_READ 0x5B OTP contents TO DO
BL_DIS_R_W_PROTECT 0x5C 返回成功或错误(1 byte) 该命令用于禁用用户Flash的不同扇区的读写保护功能。该命令将保护状态恢复为默认状态。

下图是上位机的操作界面,是由Python脚本进行编写的,执行脚本后,先输入和开发板对应的串口号,进行连接。然后可以看到支持的指令,通过输入相应的数字,即可向从机发送相应的命令。

image-20240713104433991

3. 通信流程

下面我们来介绍一下,BootLoader通信协议的命令组成,首先第一个字节为接下来要发送数据的长度,第二个字节是命令,第3-6字节为四个字节的CRC校验码。

当从机收到数据后,先收第一字节数据,得到接下来发送数据的长度,然后更具接收数据的长度,在确定接下来应该接收多少字节的数据。将收到的数据解析,第一个字节(除掉一开始收到的长度位)为命令,通过swich case指令,来判断应该执行哪种命令的操作。代码如下图所示:

    while (1)
    {
    	memset(bl_rx_buffer, 0, 200);
    	//here we will read and decode the commands coming from host
    	//first read only one byte from the host , which is the "length" field of the command packet
    	HAL_UART_Receive(C_UART,bl_rx_buffer,1,HAL_MAX_DELAY);
    	rcv_len= bl_rx_buffer[0];
    	HAL_UART_Receive(C_UART,&bl_rx_buffer[1],rcv_len,HAL_MAX_DELAY);
    	switch(bl_rx_buffer[1])
    	{
    		case BL_GET_VER:
    			bootloader_handle_getver_cmd(bl_rx_buffer);
    			break;

            case BL_GET_HELP:
                bootloader_handle_gethelp_cmd(bl_rx_buffer);
                break;

            case BL_GET_CID:
                bootloader_handle_getcid_cmd(bl_rx_buffer);
                break;

            case BL_GET_RDP_STATUS:
                bootloader_handle_getrdp_cmd(bl_rx_buffer);
                break;

            case BL_GO_TO_ADDR:
                bootloader_handle_go_cmd(bl_rx_buffer);
                break;

            case BL_FLASH_ERASE:
                bootloader_handle_flash_erase_cmd(bl_rx_buffer);
                break;

            case BL_MEM_WRITE:
                bootloader_handle_mem_write_cmd(bl_rx_buffer);
                break;

            case BL_EN_RW_PROTECT:
                bootloader_handle_en_rw_protect(bl_rx_buffer);
                break;

            case BL_MEM_READ:
                bootloader_handle_mem_read(bl_rx_buffer);
                break;

            case BL_READ_SECTOR_P_STATUS:
                bootloader_handle_read_sector_protection_status(bl_rx_buffer);
                break;

            case BL_OTP_READ:
                bootloader_handle_read_otp(bl_rx_buffer);
                break;

			case BL_DIS_R_W_PROTECT:
				bootloader_handle_dis_rw_protect(bl_rx_buffer);
				break;

            default:
            	printmsg("BL_DEBUG_MSG:Invalid command code received from host \n");
            	break;
    	}
    }

下图为整个Customer BootLoader运行的整个过程:

BootLoader_Flow

4. 指令结构

下图展示了BootLoader支持的所有指令结构:

BL_GET_VER指令为获取软件版本号:

image-20240714102542277

image-20240714162041966

可以看到上图,发送的数据为0x05, 0x51, 0xe7, 0xe9, 0xab, 0x7c.

启动第一个字节,为接下来要发送数据的长度,即为5个字节,第二个字节为0x51,即为上面获取软件版本号的指令,后四位为前两位的CRC校验位。

下面为了更清晰的指导整个协议发送过程的逻辑,展示了获取软件版本号的代码,如下所示:

/**************Implementation of Boot-loader Command Handle functions *********/

/*Helper function to handle BL_GET_VER command */
void bootloader_handle_getver_cmd(uint8_t *bl_rx_buffer)
{
	uint8_t bl_version;

    // 1) verify the checksum
	printmsg("BL_DEBUG_MSG:bootloader_handle_getver_cmd\n");

	//Total length of the command packet
	uint32_t command_packet_len = bl_rx_buffer[0]+1 ;

	//extract the CRC32 sent by the Host
	uint32_t host_crc = *((uint32_t * ) (bl_rx_buffer+command_packet_len - 4) ) ;

    if (! bootloader_verify_crc(&bl_rx_buffer[0],command_packet_len-4,host_crc))
    {
        printmsg("BL_DEBUG_MSG:checksum success !!\n");
        // checksum is correct..
        bootloader_send_ack(bl_rx_buffer[0], 1);
        bl_version = get_bootloader_version();
        printmsg("BL_DEBUG_MSG:BL_VER : %d %#x\n",bl_version,bl_version);
        bootloader_uart_write_data(&bl_version,1);

    }else
    {
        printmsg("BL_DEBUG_MSG:checksum fail !!\n");
        //checksum is wrong send nack
        bootloader_send_nack();
    }
}

当CRC校验位没有问题,则发送ACK,并且发送软件版本号,否则发送NACK。

BL_GET_HELP:获取帮助

image-20240714102528030

image-20240714162801126

下面的命令后续文章再一一讲解:
image-20240714102613163

image-20240714102625964

image-20240714102640901

image-20240714102653304

image-20240714102705943

image-20240714102716603

image-20240714102728108

image-20240714102738998

image-20240714102751460

5. 操作演示

下面打开上位机,连接上位机和开发板连接的串口,根据显示的指令,进行相应的操作。

image-20240713104433991

下面我们展示一下读取版本号的功能,输入1,获取版本号为0x10.

image-20240713104633571

下面我们在试一个刷新命令。下面是录制的一整个执行的流程。

BootLoader串口刷新

如果大家有什么疑问,请随时私信联系我。

相关推荐

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-14 17:52:04       66 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-14 17:52:04       70 阅读
  3. 在Django里面运行非项目文件

    2024-07-14 17:52:04       57 阅读
  4. Python语言-面向对象

    2024-07-14 17:52:04       68 阅读

热门阅读

  1. 华为 NAT 技术介绍及配置

    2024-07-14 17:52:04       21 阅读
  2. prompt第三讲-PromptTemplate

    2024-07-14 17:52:04       18 阅读
  3. 微信小程序的目录结构

    2024-07-14 17:52:04       26 阅读
  4. Nmap端口扫描工具

    2024-07-14 17:52:04       22 阅读
  5. 如何设计一个C语言面向结构体的内存数据库

    2024-07-14 17:52:04       19 阅读
  6. NSIS 之 NsDialogs 常见问题解答

    2024-07-14 17:52:04       20 阅读
  7. Nginx配置缺少导致CSS不起作用

    2024-07-14 17:52:04       21 阅读
  8. 抽象代数精解【1】

    2024-07-14 17:52:04       18 阅读
  9. c#协变逆变

    2024-07-14 17:52:04       15 阅读