mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
bugfix: i2c driver not working in 'RELEASE' configuration
This issue is reported from https://github.com/espressif/esp-idf/issues/304. We found that when we operate the hw command registers in I2C struct, sometimes the behaviour would be different in DEBUG/RELEASE optimisation level: The code looks like this: I2C[i2c_num]->command[p_i2c->cmd_idx].byte_num -= 0; In DEBUG configuration: I2C[i2c_num]->command[p_i2c->cmd_idx].byte_num -= 0; 400f3ab0: 3388 l32i.n a8, a3, 12 400f3ab2: 14c882 addi a8, a8, 20 400f3ab5: a08840 addx4 a8, a8, a4 400f3ab8: 0020c0 memw 400f3abb: 2898 l32i.n a9, a8, 8 400f3abd: 0020c0 memw 400f3ac0: 28b8 l32i.n a11, a8, 8 400f3ac2: 74a090 extui a10, a9, 0, 8 400f3ac5: 00af92 movi a9, 0xffffff00 400f3ac8: 109b90 and a9, a11, a9 400f3acb: 2099a0 or a9, a9, a10 400f3ace: 0020c0 memw 400f3ad1: 2899 s32i.n a9, a8, 8 In RELEASE configuration: I2C[i2c_num]->command[p_i2c->cmd_idx].byte_num -= 0; 400f2ba2: 580572 l8ui a7, a5, 88 400f2ba5: 747070 extui a7, a7, 0, 8 400f2ba8: 0020c0 memw 400f2bab: 584572 s8i a7, a5, 88 Looks like the compiler will make it a 8bit operation after optimisation. But the register value changes from 0x901 to 0x101. After this 8-bit optimisation, the 11th bit changed from 1 to zero, which caused this error. We are still trying to find out why that happens, because there might be some risk when operating the register struct. This is a workaround to avoid "-=" operation on I2C register struct fields.
This commit is contained in:
parent
57486a1f61
commit
94b91ee4af
@ -862,19 +862,23 @@ static void IRAM_ATTR i2c_master_cmd_begin_static(i2c_port_t i2c_num)
|
|||||||
I2C[i2c_num]->command[p_i2c->cmd_idx].byte_num = cmd->byte_num;
|
I2C[i2c_num]->command[p_i2c->cmd_idx].byte_num = cmd->byte_num;
|
||||||
I2C[i2c_num]->command[p_i2c->cmd_idx].op_code = cmd->op_code;
|
I2C[i2c_num]->command[p_i2c->cmd_idx].op_code = cmd->op_code;
|
||||||
if (cmd->op_code == I2C_CMD_WRITE) {
|
if (cmd->op_code == I2C_CMD_WRITE) {
|
||||||
|
uint32_t wr_filled = 0;
|
||||||
//TODO: to reduce interrupt number
|
//TODO: to reduce interrupt number
|
||||||
if (cmd->data) {
|
if (cmd->data) {
|
||||||
while (p_i2c->tx_fifo_remain > 0 && cmd->byte_num > 0) {
|
while (p_i2c->tx_fifo_remain > 0 && cmd->byte_num > 0) {
|
||||||
WRITE_PERI_REG(I2C_DATA_APB_REG(i2c_num), *cmd->data++);
|
WRITE_PERI_REG(I2C_DATA_APB_REG(i2c_num), *cmd->data++);
|
||||||
p_i2c->tx_fifo_remain--;
|
p_i2c->tx_fifo_remain--;
|
||||||
cmd->byte_num--;
|
cmd->byte_num--;
|
||||||
|
wr_filled++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
WRITE_PERI_REG(I2C_DATA_APB_REG(i2c_num), cmd->byte_cmd);
|
WRITE_PERI_REG(I2C_DATA_APB_REG(i2c_num), cmd->byte_cmd);
|
||||||
p_i2c->tx_fifo_remain--;
|
p_i2c->tx_fifo_remain--;
|
||||||
cmd->byte_num--;
|
cmd->byte_num--;
|
||||||
|
wr_filled ++;
|
||||||
}
|
}
|
||||||
I2C[i2c_num]->command[p_i2c->cmd_idx].byte_num -= cmd->byte_num;
|
//Workaround for register field operation.
|
||||||
|
I2C[i2c_num]->command[p_i2c->cmd_idx].byte_num = wr_filled;
|
||||||
I2C[i2c_num]->command[p_i2c->cmd_idx + 1].val = 0;
|
I2C[i2c_num]->command[p_i2c->cmd_idx + 1].val = 0;
|
||||||
I2C[i2c_num]->command[p_i2c->cmd_idx + 1].op_code = I2C_CMD_END;
|
I2C[i2c_num]->command[p_i2c->cmd_idx + 1].op_code = I2C_CMD_END;
|
||||||
p_i2c->tx_fifo_remain = I2C_FIFO_LEN;
|
p_i2c->tx_fifo_remain = I2C_FIFO_LEN;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user