Skip to content

Commit 33f7009

Browse files
author
Zim Kalinowski
committed
Merge branch 'bugfix/i2c_spiram_bug_v4.4' into 'release/v4.4'
i2c: fix buffer check when SPIRAM used as a heap (backport v4.4) See merge request espressif/esp-idf!17098
2 parents d483bd9 + 98647cf commit 33f7009

File tree

1 file changed

+15
-14
lines changed

1 file changed

+15
-14
lines changed

components/driver/i2c.c

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1375,16 +1375,18 @@ static void IRAM_ATTR i2c_master_cmd_begin_static(i2c_port_t i2c_num)
13751375
//Check whether read or write buffer in cmd_link is internal.
13761376
static bool is_cmd_link_buffer_internal(const i2c_cmd_link_t *link)
13771377
{
1378-
const i2c_cmd_link_t *cmd_link = link;
1379-
while (cmd_link != NULL) {
1380-
if (cmd_link->cmd.hw_cmd.op_code == I2C_LL_CMD_WRITE || cmd_link->cmd.hw_cmd.op_code == I2C_LL_CMD_READ) {
1381-
if (cmd_link->cmd.data != NULL && !esp_ptr_internal(cmd_link->cmd.data)) {
1382-
return false;
1383-
}
1384-
}
1385-
cmd_link = cmd_link->next;
1378+
bool is_internal = true;
1379+
for (const i2c_cmd_link_t *cmd_link = link;
1380+
cmd_link != NULL && is_internal;
1381+
cmd_link = cmd_link->next)
1382+
{
1383+
/* A command node has a valid pointer if it is a read command or a write command with more than one byte. */
1384+
const bool data_pointer = (cmd_link->cmd.hw_cmd.op_code == I2C_LL_CMD_WRITE && !i2c_cmd_is_single_byte(&cmd_link->cmd))
1385+
|| cmd_link->cmd.hw_cmd.op_code == I2C_LL_CMD_READ;
1386+
/* Check if the (non-NULL) pointer points to internal memory. */
1387+
is_internal &= !data_pointer || cmd_link->cmd.data == NULL || esp_ptr_internal(cmd_link->cmd.data);
13861388
}
1387-
return true;
1389+
return is_internal;
13881390
}
13891391
#endif
13901392

@@ -1398,11 +1400,10 @@ esp_err_t i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle,
13981400
#if CONFIG_SPIRAM_USE_MALLOC
13991401
//If the i2c read or write buffer is not in internal RAM, we will return ESP_FAIL
14001402
//to avoid the ISR handler function crashing when the cache is disabled.
1401-
if ((p_i2c_obj[i2c_num]->intr_alloc_flags & ESP_INTR_FLAG_IRAM)) {
1402-
if (!is_cmd_link_buffer_internal(((const i2c_cmd_desc_t *)cmd_handle)->head) ) {
1403-
ESP_LOGE(I2C_TAG, I2C_PSRAM_BUFFER_WARN_STR);
1404-
return ESP_ERR_INVALID_ARG;
1405-
}
1403+
if ( (p_i2c_obj[i2c_num]->intr_alloc_flags & ESP_INTR_FLAG_IRAM) &&
1404+
!is_cmd_link_buffer_internal(((const i2c_cmd_desc_t *)cmd_handle)->head) ) {
1405+
ESP_LOGE(I2C_TAG, I2C_PSRAM_BUFFER_WARN_STR);
1406+
return ESP_ERR_INVALID_ARG;
14061407
}
14071408
#endif
14081409
// Sometimes when the FSM get stuck, the ACK_ERR interrupt will occur endlessly until we reset the FSM and clear bus.

0 commit comments

Comments
 (0)