From bfa311b70f23c33e696bf22eca29a670fcfa7f71 Mon Sep 17 00:00:00 2001 From: yelvlab Date: Tue, 30 Jun 2026 11:03:22 +0800 Subject: [PATCH] =?UTF-8?q?sync(template):=20=E5=9B=9E=E5=90=88=20capsule?= =?UTF-8?q?=5Fmb=20=E9=80=9A=E7=94=A8=E9=A9=B1=E5=8A=A8=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - uart_ring_buffer: PRIMASK 位检查从 ==0 改为 &0x1 修正 - i2c: 新增 i2c_read_raw() 无子地址读函数 - 全局: volatile 统一替换为 __IO (CMSIS 风格) --- Inc/i2c.h | 10 +++ Src/i2c.c | 157 +++++++++++++++++++++++++++++++++++++++++ Src/system_gd32e23x.c | 2 +- Src/systick.c | 8 +-- Src/uart_ring_buffer.c | 18 ++--- 5 files changed, 181 insertions(+), 14 deletions(-) diff --git a/Inc/i2c.h b/Inc/i2c.h index 0145015..ab42e62 100644 --- a/Inc/i2c.h +++ b/Inc/i2c.h @@ -129,6 +129,16 @@ i2c_result_t i2c_write(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data, uint */ i2c_result_t i2c_read(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data, uint8_t length); +/* Pure read response without sub-address phase (for commands that already sent read request parameters) */ +/*! + \brief read data from I2C device without register/sub-address phase + \param[in] slave_addr: slave device address (7-bit) + \param[out] data: pointer to data buffer + \param[in] length: number of bytes to read (1-255) + \retval i2c_result_t: operation result +*/ +i2c_result_t i2c_read_raw(uint8_t slave_addr, uint8_t *data, uint8_t length); + #ifdef DEBUG_VERBOSE /*! \brief get status string for debugging diff --git a/Src/i2c.c b/Src/i2c.c index 049a37b..66c9dcd 100644 --- a/Src/i2c.c +++ b/Src/i2c.c @@ -1110,6 +1110,163 @@ i2c_result_t i2c_read(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data, uint8 return I2C_RESULT_TIMEOUT; } +/*! + \brief read data from I2C device without register/sub-address phase + \param[in] slave_addr: slave device address (7-bit) + \param[out] data: pointer to data buffer + \param[in] length: number of bytes to read (1-255) + \retval i2c_result_t: operation result +*/ +i2c_result_t i2c_read_raw(uint8_t slave_addr, uint8_t *data, uint8_t length) +{ + i2c_state_t state = I2C_STATE_START; + uint16_t timeout = 0; + uint8_t retry_count = 0; + uint8_t data_index = 0; + + if (data == NULL || slave_addr > 0x7F || length == 0) { + return I2C_RESULT_INVALID_PARAM; + } + + i2c_ack_config(I2C0, I2C_ACK_ENABLE); + + while (retry_count < (uint8_t)I2C_MAX_RETRY) { + switch (state) { + case I2C_STATE_START: + timeout = 0; + data_index = 0; + + if (_i2c_wait_flag_clear_timeout(I2C_FLAG_I2CBSY) != I2C_RESULT_SUCCESS) { + state = I2C_STATE_ERROR; + break; + } + + i2c_start_on_bus(I2C0); + state = I2C_STATE_SEND_ADDRESS; + break; + + case I2C_STATE_SEND_ADDRESS: + if (_i2c_wait_flag_timeout(I2C_FLAG_SBSEND) != I2C_RESULT_SUCCESS) { + state = I2C_STATE_ERROR; + break; + } + + i2c_master_addressing(I2C0, (slave_addr << 1), I2C_RECEIVER); + state = I2C_STATE_CLEAR_ADDRESS; + timeout = 0; + break; + + case I2C_STATE_CLEAR_ADDRESS: + while ((!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) && (!i2c_flag_get(I2C0, I2C_FLAG_AERR)) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if (timeout >= I2C_TIME_OUT) { + state = I2C_STATE_ERROR; + break; + } + if (i2c_flag_get(I2C0, I2C_FLAG_AERR)) { + i2c_flag_clear(I2C0, I2C_FLAG_AERR); + i2c_stop_on_bus(I2C0); + return I2C_RESULT_NACK; + } + + if (length == 1) { + i2c_ack_config(I2C0, I2C_ACK_DISABLE); + } else if (length == 2) { + i2c_ackpos_config(I2C0, I2C_ACKPOS_NEXT); + i2c_ack_config(I2C0, I2C_ACK_DISABLE); + } else { + i2c_ack_config(I2C0, I2C_ACK_ENABLE); + } + + i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); + state = I2C_STATE_RECEIVE_DATA; + timeout = 0; + break; + + case I2C_STATE_RECEIVE_DATA: + if (length == 1) { + if (_i2c_wait_flag_timeout(I2C_FLAG_RBNE) != I2C_RESULT_SUCCESS) { + state = I2C_STATE_ERROR; + break; + } + data[0] = i2c_data_receive(I2C0); + state = I2C_STATE_STOP; + } else if (length == 2) { + if (_i2c_wait_flag_timeout(I2C_FLAG_BTC) != I2C_RESULT_SUCCESS) { + state = I2C_STATE_ERROR; + break; + } + i2c_stop_on_bus(I2C0); + data[0] = i2c_data_receive(I2C0); + data[1] = i2c_data_receive(I2C0); + state = I2C_STATE_STOP; + } else { + while (data_index < length) { + if (data_index < length - 2) { + if (_i2c_wait_flag_timeout(I2C_FLAG_RBNE) != I2C_RESULT_SUCCESS) { + state = I2C_STATE_ERROR; + break; + } + data[data_index++] = i2c_data_receive(I2C0); + } else if (data_index == length - 2) { + if (_i2c_wait_flag_timeout(I2C_FLAG_BTC) != I2C_RESULT_SUCCESS) { + state = I2C_STATE_ERROR; + break; + } + i2c_ack_config(I2C0, I2C_ACK_DISABLE); + i2c_stop_on_bus(I2C0); + data[data_index++] = i2c_data_receive(I2C0); + } else { + if (_i2c_wait_flag_timeout(I2C_FLAG_RBNE) != I2C_RESULT_SUCCESS) { + state = I2C_STATE_ERROR; + break; + } + data[data_index++] = i2c_data_receive(I2C0); + } + } + if (state == I2C_STATE_ERROR) break; + state = I2C_STATE_STOP; + } + break; + + case I2C_STATE_STOP: + while ((I2C_CTL0(I2C0) & I2C_CTL0_STOP) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if (timeout >= I2C_TIME_OUT) { + state = I2C_STATE_ERROR; + break; + } + + i2c_ack_config(I2C0, I2C_ACK_ENABLE); + i2c_ackpos_config(I2C0, I2C_ACKPOS_CURRENT); + return I2C_RESULT_SUCCESS; + + case I2C_STATE_ERROR: + i2c_bus_reset(); + i2c_ack_config(I2C0, I2C_ACK_ENABLE); + i2c_ackpos_config(I2C0, I2C_ACKPOS_CURRENT); + + retry_count++; + if (retry_count >= I2C_MAX_RETRY) { + return I2C_RESULT_ERROR; + } + + state = I2C_STATE_START; + timeout = 0; + delay_10us(10); + break; + + default: + state = I2C_STATE_START; + break; + } + } + + return I2C_RESULT_TIMEOUT; +} + #ifdef DEBUG_VERBOSE /*! \brief get status string for debugging diff --git a/Src/system_gd32e23x.c b/Src/system_gd32e23x.c index 480e817..5e0296a 100644 --- a/Src/system_gd32e23x.c +++ b/Src/system_gd32e23x.c @@ -53,7 +53,7 @@ It is strongly recommended to include it to avoid issues caused by self-removal. */ #define RCU_MODIFY(__delay) do{ \ - volatile uint32_t i,reg; \ + __IO uint32_t i,reg; \ if(0 != __delay){ \ reg = RCU_CFG0; \ reg &= ~(RCU_CFG0_AHBPSC); \ diff --git a/Src/systick.c b/Src/systick.c index fd3d707..71ec437 100644 --- a/Src/systick.c +++ b/Src/systick.c @@ -12,7 +12,7 @@ #include "gd32e23x.h" #include "systick.h" -volatile static uint32_t delay_count = 0; +static __IO uint32_t delay_count = 0; /** * ************************************************************************ @@ -47,7 +47,7 @@ void delay_10us(uint32_t count) uint32_t loops_per_10us = SystemCoreClock / 1700000; // 粗略估计,每10微秒的循环次数 for(uint32_t i = 0; i < count; i++) { - for(volatile uint32_t j = 0; j < loops_per_10us; j++); + for(__IO uint32_t j = 0; j < loops_per_10us; j++); } } @@ -95,7 +95,7 @@ void delay_decrement(void) // uint32_t loops_per_ms = SystemCoreClock / 14000; // 粗略估计 // for(uint32_t i = 0; i < count; i++) { -// for(volatile uint32_t j = 0; j < loops_per_ms; j++); +// for(__IO uint32_t j = 0; j < loops_per_ms; j++); // } // } @@ -113,6 +113,6 @@ void delay_decrement(void) // uint32_t loops_per_us = SystemCoreClock / 22000000; // 粗略估计,每微秒的循环次数 // for(uint32_t i = 0; i < count; i++) { -// for(volatile uint32_t j = 0; j < loops_per_us; j++); +// for(__IO uint32_t j = 0; j < loops_per_us; j++); // } // } \ No newline at end of file diff --git a/Src/uart_ring_buffer.c b/Src/uart_ring_buffer.c index d8c915f..9181c03 100644 --- a/Src/uart_ring_buffer.c +++ b/Src/uart_ring_buffer.c @@ -8,10 +8,10 @@ #include "uart_ring_buffer.h" #include "gd32e23x.h" -static volatile uint8_t uart_rx_buffer[UART_RX_BUFFER_SIZE]; -static volatile uint8_t write_index = 0; -static volatile uint8_t read_index = 0; -static volatile uint32_t dropped_bytes = 0; +static __IO uint8_t uart_rx_buffer[UART_RX_BUFFER_SIZE]; +static __IO uint8_t write_index = 0; +static __IO uint8_t read_index = 0; +static __IO uint32_t dropped_bytes = 0; static inline uint32_t irq_save(void) { uint32_t primask = __get_PRIMASK(); @@ -20,7 +20,7 @@ static inline uint32_t irq_save(void) { } static inline void irq_restore(uint32_t primask) { - if (primask == 0U) { + if ((primask & 0x1) == 0) { __enable_irq(); } } @@ -44,9 +44,9 @@ static void uart_ring_buffer_reset_state(void) { * @ingroup RingBuffer */ void uart_ring_buffer_init(void) { - uint32_t irq_key = irq_save(); + uint32_t primask = irq_save(); uart_ring_buffer_reset_state(); - irq_restore(irq_key); + irq_restore(primask); } /** @@ -105,9 +105,9 @@ bool uart_ring_buffer_put(uint8_t data) { * @ingroup RingBuffer */ void uart_ring_buffer_clear(void) { - uint32_t irq_key = irq_save(); + uint32_t primask = irq_save(); uart_ring_buffer_reset_state(); - irq_restore(irq_key); + irq_restore(primask); } /**