Follow the reference to port the bootloader

This commit is contained in:
2025-09-28 01:14:06 +08:00
parent 422c27846f
commit bd541d585e
23 changed files with 712 additions and 1638 deletions

View File

@@ -1,14 +1,7 @@
#ifndef BOARD_CONFIG_H
#define BOARD_CONFIG_H
#define GD32E23XF4 0x10
#define GD32E23XF6 0x20
#define GD32E23XF8 0x40
/* >>>>>>>>>>>>>>>>>>>>[RS485 PHY DEFINE]<<<<<<<<<<<<<<<<<<<< */
// #define RS485_MAX13487 // RS485 PHY : MAX13487 (AutoDir)
#undef RS485_MAX13487 // RS485 PHY : SP3487 (no AutoDir)
#include <stdint.h>
/* >>>>>>>>>>>>>>>>>>>>[IIC TYPE DEFINE]<<<<<<<<<<<<<<<<<<<< */
@@ -25,22 +18,11 @@
// #define EDDY_DRIVE_CURRENT_DETECTION // Eddy Drive Current Detection : Enable
#undef EDDY_DRIVE_CURRENT_DETECTION // Eddy Drive Current Detection : Disable
/******************************************************************************/
/* >>>>>>>>>>>>>>>>>>>[BOARD TYPE CONFIG]<<<<<<<<<<<<<<<<<<<< */
/* Dynamic USART Configuration Structure */
typedef struct {
uint32_t rcu_usart;
uint32_t usart_periph;
IRQn_Type irq_type;
void (*irq_handler)(void); // 函数指针:指向中断处理函数
} usart_config_t;
#define ULTRASONIC_BOARD
// #define EDDY_BOARD
extern usart_config_t g_usart_config;
extern uint8_t g_mcu_flash_size;
/* USART中断处理函数声明 */
void usart0_irq_handler(void);
void usart1_irq_handler(void);
/******************************************************************************/
@@ -56,15 +38,25 @@ void usart1_irq_handler(void);
/******************************************************************************/
#ifdef ULTRASONIC_BOARD
#define LED_RCU RCU_GPIOA
#define LED_PORT GPIOA
#define LED_PIN GPIO_PIN_9
#elif EDDY_BOARD
#define LED_RCU RCU_GPIOA
#define LED_PORT GPIOA
#define LED_PIN GPIO_PIN_7
#endif
/******************************************************************************/
#define RS485_RCU (g_usart_config.rcu_usart)
#define RS485_PHY (g_usart_config.usart_periph)
#define RS485_IRQ (g_usart_config.irq_type)
/* GD32E230F8 Fixed Configuration */
#define RS485_RCU RCU_USART1
#define RS485_PHY USART1
#define RS485_IRQ USART1_IRQn
#define RS485_GPIO_RCU RCU_GPIOA
#define RS485_GPIO_PORT GPIOA
#define RS485_EN_PIN GPIO_PIN_1
@@ -74,7 +66,4 @@ void usart1_irq_handler(void);
/******************************************************************************/
void mcu_detect_and_config(void);
uint8_t get_flash_size(void);
#endif //BOARD_CONFIG_H

57
Inc/bootloader.h Normal file
View File

@@ -0,0 +1,57 @@
#ifndef BOOTLOADER_H
#define BOOTLOADER_H
#include <stdint.h>
#define FLASH_BASE_ADDRESS 0x08000000
#define FLASH_END_ADDRESS 0x08010000 // GD32E230F8: 64KB Flash
#define APP_FLASH_END_ADDRESS 0x0800EFFF // End of application flash
#define APPLICATION_ADDRESS 0x08002000 // Application starts at 8KB (adjust as needed)
#define FLASH_FLAG_ADDRESS 0x0800FFFC // Address to check if application is present
#define BOOTLOADER_SIZE 0x2000 // 8KB for bootloader
// Ymodem协议常量
#define PACKET_HEADER 3 // 数据包头大小
#define PACKET_1K_SIZE 1024 // 1K数据包大小
#define FILE_NAME_LENGTH 256 // 文件名长度
#define FILE_SIZE_LENGTH 16 // 文件大小字符串长度
// Ymodem控制字符
#define SOH 0x01 // 128字节数据包开始
#define STX 0x02 // 1K字节数据包开始
#define EOT 0x04 // 传输结束
#define ACK 0x06 // 确认
#define NAK 0x15 // 否认
#define CA 0x18 // 取消传输
#define CRC16 0x43 // 'C' - 请求CRC16模式
#define YMODEM_RX_BUFFER_SIZE 1100 // 接收缓冲区大小
#define ISVALIDHEX(c) (((c) >= '0' && (c) <= '9') || \
((c) >= 'A' && (c) <= 'F') || \
((c) >= 'a' && (c) <= 'f'))
#define CONVERTHEX(c) (((c) >= '0' && (c) <= '9') ? ((c) - '0') : \
(((c) >= 'A' && (c) <= 'F') ? ((c) - 'A' + 10) : \
((c) - 'a' + 10)))
#define ISVALIDDEC(c) ((c) >= '0' && (c) <= '9')
#define CONVERTDEC(c) ((c) - '0')
extern uint8_t ymodem_rx_buffer[YMODEM_RX_BUFFER_SIZE];
extern uint16_t ymodem_rx_count;
/* Function pointer type for application jump */
typedef void (*pFunction)(void);
/* Function declarations */
uint8_t check_flash_and_jump(uint8_t *buf);
uint32_t str_to_int(uint8_t *input_str, int32_t *int_num);
uint16_t crc16_update(uint16_t crc_in, uint8_t byte);
uint16_t crc16_calculate(const uint8_t* data, uint32_t size);
void ymodem_read_packet_data(void);
int32_t ymodem_receive(uint8_t *buf);
#endif

View File

@@ -1,81 +0,0 @@
/**
* @file command.h
* @brief 串口命令解析与处理模块接口声明。
* @details 提供基于环形缓冲区的串口协议解析、命令处理及状态管理功能,
* 支持格式为 D5 03 LEN [cmd] CRC 的命令帧解析与响应。
*/
#ifndef COMMAND_H
#define COMMAND_H
#include <stdint.h>
#include <stdbool.h>
/**
* @defgroup Command 命令处理模块
* @brief 串口命令解析与处理
* @{
*/
/**
* @section Command_Protocol 协议格式
* 接收命令帧格式:
* @code
* [0] HEADER = 0xD5 // 包头标识
* [1] BOARD_TYPE = 0x03 // 板卡类型标识
* [2] LEN = 数据区字节数 // 有效载荷长度
* [3..(3+LEN-1)] 数据 // 命令数据
* [last] CRC // 校验码从索引1累加到len-2的低8位
* @endcode
*
* 响应帧格式:
* @code
* [0] HEADER = 0xB5 // 响应包头
* [1] TYPE // 响应类型0xF0=成功0xF1..=错误类型)
* [2] LEN // 响应数据长度
* [3..(3+LEN-1)] 数据 // 响应数据
* [last] CRC // 校验码
* @endcode
*
* @section Command_Usage 使用说明
* 1) 初始化环形缓冲区:
* @code{.c}
* uart_ring_buffer_init();
* @endcode
*
* 2) 在主循环中调用命令处理:
* @code{.c}
* while(1) {
* command_process(); // 处理接收到的命令
* // 其他业务逻辑
* }
* @endcode
*
* 3) 查询传感器上报状态:
* @code{.c}
* if(get_sensor_report_enabled()) {
* // 执行传感器数据上报
* }
* @endcode
*/
/**
* @brief 处理串口环形缓冲区中的命令数据。
* @details 基于状态机的非阻塞协议解析器,处理完整的命令帧并自动响应。
* 每次调用处理缓冲区中所有可用数据,遇到错误时自动重置状态机。
* @note 使用静态变量维护解析状态,函数不可重入。
* @warning 依赖环形缓冲区正确实现,建议在主循环中周期调用。
* @ingroup Command
*/
void command_process(void);
/**
* @brief 解析并处理完整的命令帧。
* @param cmd 指向完整命令帧的缓冲区从包头0xD5开始
* @param len 命令帧总长度(字节)。
* @note 内部函数,由 command_process() 调用,一般不直接使用。
* @ingroup Command
*/
void handle_command(const uint8_t *cmd, uint8_t len);
/** @} */ // end of Command group
#endif // COMMAND_H

6
Inc/gpio.h Normal file
View File

@@ -0,0 +1,6 @@
#ifndef GPIO_H
#define GPIO_H
void gpio_init(void);
#endif // GPIO_H

127
Inc/i2c.h
View File

@@ -1,127 +0,0 @@
//
// Created by dell on 24-12-20.
//
#ifndef I2C_H
#define I2C_H
#include "gd32e23x_it.h"
#include "gd32e23x.h"
#include "systick.h"
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "board_config.h"
/******************************************************************************/
#define I2C_SPEED 100000U /* 100kHz */
#define I2C_TIME_OUT 5000U /* 5000 loops timeout */
#define I2C_MAX_RETRY 3U /* Maximum retry attempts */
#define I2C_DELAY_10US 10U /* Delay in microseconds for bus reset */
#define I2C_RECOVERY_CLOCKS 9U /* Clock pulses for bus recovery */
#define I2C_MASTER_ADDRESS 0x00U /* Master address (not used) */
/* Legacy compatibility */
#define I2C_OK 1
#define I2C_FAIL 0
#define I2C_END 1
/******************************************************************************/
/* I2C result enumeration */
typedef enum {
I2C_RESULT_SUCCESS = 0, /* Operation successful */
I2C_RESULT_TIMEOUT, /* Timeout occurred */
I2C_RESULT_NACK, /* No acknowledge received */
I2C_RESULT_BUS_BUSY, /* Bus is busy */
I2C_RESULT_ERROR, /* General error */
I2C_RESULT_INVALID_PARAM, /* Invalid parameter */
I2C_RECOVERY_OK,
I2C_RECOVERY_SDA_STUCK_LOW,
I2C_RECOVERY_SCL_STUCK_LOW
} i2c_result_t;
/* I2C state machine enumeration */
typedef enum {
I2C_STATE_IDLE = 0, /* Idle state */
I2C_STATE_START, /* Generate start condition */
I2C_STATE_SEND_ADDRESS, /* Send slave address */
I2C_STATE_CLEAR_ADDRESS, /* Clear address flag */
I2C_STATE_TRANSMIT_REG, /* Transmit register address */
I2C_STATE_TRANSMIT_DATA, /* Transmit data */
I2C_STATE_RESTART, /* Generate restart condition */
I2C_STATE_RECEIVE_DATA, /* Receive data */
I2C_STATE_STOP, /* Generate stop condition */
I2C_STATE_ERROR, /* Error state */
I2C_STATE_END
} i2c_state_t;
/******************************************************************************/
/* Function declarations */
/*!
\brief configure the I2C interface
\param[in] none
\param[out] none
\retval i2c_result_t
*/
i2c_result_t i2c_config(void);
/*!
\brief reset I2C bus with proper recovery
\param[in] none
\param[out] none
\retval i2c_result_t
*/
i2c_result_t i2c_bus_reset(void);
/*!
\brief scan I2C bus for devices
\param[in] none
\param[out] none
\retval none
*/
void i2c_scan(void);
/*!
\brief write 16-bit data to I2C device
\param[in] slave_addr: 7-bit slave address
\param[in] reg_addr: register address
\param[in] data: pointer to 2-byte data array
\param[out] none
\retval i2c_result_t
*/
i2c_result_t i2c_write_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t data[2]);
/*!
\brief read 16-bit data from I2C device
\param[in] slave_addr: 7-bit slave address
\param[in] reg_addr: register address
\param[out] data: pointer to 2-byte data buffer
\retval i2c_result_t
*/
i2c_result_t i2c_read_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data);
/*!
\brief read 16-bit data from I2C device
\param[in] slave_addr: 7-bit slave address
\param[in] reg_addr: register address
\param[out] data: pointer to 2-byte data buffer
\retval i2c_result_t
*/
i2c_result_t i2c_read_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data);
/*!
\brief get status string for debugging
\param[in] status: i2c_result_t value
\param[out] none
\retval const char* status string
*/
const char* i2c_get_status_string(i2c_result_t status);
#endif //I2C_H

View File

@@ -1,13 +0,0 @@
#ifndef LED_H
#define LED_H
#include "gd32e23x.h"
#include "board_config.h"
void led_init(void);
void led_on(void);
void led_off(void);
void led_toggle(void);
void led_heart_beat(void);
#endif // LED_H

View File

@@ -5,4 +5,8 @@
void rs485_init(void);
uint32_t rs485_send_byte(uint8_t data);
uint32_t rs485_send_str(uint8_t* str, uint16_t len);
#endif // UART_H

View File

@@ -10,12 +10,14 @@
#include <stdint.h>
#include <stdbool.h>
typedef struct uart_ring_buffer uart_ring_buffer_t;
/**
* @def UART_RX_BUFFER_SIZE
* @brief 接收环形缓冲区容量(单位:字节)。
* @note 采用“预留一格”区分空/满策略,最大可用容量为 UART_RX_BUFFER_SIZE-1。
*/
#define UART_RX_BUFFER_SIZE 64
#define UART_RX_BUFFER_SIZE 1100
/**
* @defgroup RingBuffer 环形缓冲区
@@ -101,19 +103,11 @@ bool uart_ring_buffer_put(uint8_t data);
/**
* @brief 清空环形缓冲区。
* @details 复位读/写索引与丢弃计数,相当于逻辑上丢弃所有已接收数据,不擦除数据区内容
* @details 复位读/写索引,相当于逻辑上丢弃所有已接收数据。
* @ingroup RingBuffer
*/
void uart_ring_buffer_clear(void);
/**
* @brief 获取因缓冲区满而被丢弃的字节累计数量。
* @details 该计数在 init/clear 时清零。
* @return 丢弃的累计字节数。
* @ingroup RingBuffer
*/
uint32_t uart_ring_buffer_drop_count(void);
/** @} */
#endif // UART_RING_BUFFER_H