sync(template): 回合 capsule_mb 通用驱动修复

- uart_ring_buffer: PRIMASK 位检查从 ==0 改为 &0x1 修正
- i2c: 新增 i2c_read_raw() 无子地址读函数
- 全局: volatile 统一替换为 __IO (CMSIS 风格)
This commit is contained in:
2026-06-30 11:03:22 +08:00
parent 03810e9cad
commit bfa311b70f
5 changed files with 181 additions and 14 deletions
+157
View File
@@ -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