mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'bugfix/ticks_to_wait_for_uart_and_i2c' into 'master'
driver: Fix ticks_to_wait for uart and i2c Closes IDFGH-964 See merge request idf/esp-idf!5021
This commit is contained in:
commit
2331597ed2
@ -1386,13 +1386,18 @@ int i2c_slave_write_buffer(i2c_port_t i2c_num, uint8_t* data, int size, TickType
|
||||
|
||||
portBASE_TYPE res;
|
||||
int cnt = 0;
|
||||
portTickType ticks_end = xTaskGetTickCount() + ticks_to_wait;
|
||||
portTickType ticks_start = xTaskGetTickCount();
|
||||
|
||||
res = xSemaphoreTake(p_i2c->slv_tx_mux, ticks_to_wait);
|
||||
if (res == pdFALSE) {
|
||||
return 0;
|
||||
}
|
||||
ticks_to_wait = ticks_end - xTaskGetTickCount();
|
||||
TickType_t ticks_end = xTaskGetTickCount();
|
||||
if (ticks_end - ticks_start > ticks_to_wait) {
|
||||
ticks_to_wait = 0;
|
||||
} else {
|
||||
ticks_to_wait = ticks_to_wait - (ticks_end - ticks_start);
|
||||
}
|
||||
res = xRingbufferSend(p_i2c->tx_ring_buf, data, size, ticks_to_wait);
|
||||
if (res == pdFALSE) {
|
||||
cnt = 0;
|
||||
@ -1427,18 +1432,28 @@ int i2c_slave_read_buffer(i2c_port_t i2c_num, uint8_t* data, size_t max_size, Ti
|
||||
|
||||
i2c_obj_t* p_i2c = p_i2c_obj[i2c_num];
|
||||
portBASE_TYPE res;
|
||||
portTickType ticks_end = xTaskGetTickCount() + ticks_to_wait;
|
||||
portTickType ticks_start = xTaskGetTickCount();
|
||||
res = xSemaphoreTake(p_i2c->slv_rx_mux, ticks_to_wait);
|
||||
if (res == pdFALSE) {
|
||||
return 0;
|
||||
}
|
||||
ticks_to_wait = ticks_end - xTaskGetTickCount();
|
||||
TickType_t ticks_end = xTaskGetTickCount();
|
||||
if (ticks_end - ticks_start > ticks_to_wait) {
|
||||
ticks_to_wait = 0;
|
||||
} else {
|
||||
ticks_to_wait = ticks_to_wait - (ticks_end - ticks_start);
|
||||
}
|
||||
int cnt = i2c_slave_read(i2c_num, data, max_size, ticks_to_wait);
|
||||
if (cnt > 0) {
|
||||
I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]);
|
||||
I2C[i2c_num]->int_ena.rx_fifo_full = 1;
|
||||
I2C_EXIT_CRITICAL(&i2c_spinlock[i2c_num]);
|
||||
ticks_to_wait = ticks_end - xTaskGetTickCount();
|
||||
ticks_end = xTaskGetTickCount();
|
||||
if (ticks_end - ticks_start > ticks_to_wait) {
|
||||
ticks_to_wait = 0;
|
||||
} else {
|
||||
ticks_to_wait = ticks_to_wait - (ticks_end - ticks_start);
|
||||
}
|
||||
if (cnt < max_size && ticks_to_wait > 0) {
|
||||
cnt += i2c_slave_read(i2c_num, data + cnt, max_size - cnt, ticks_to_wait);
|
||||
}
|
||||
|
@ -505,3 +505,67 @@ static void i2c_slave_repeat_read()
|
||||
}
|
||||
|
||||
TEST_CASE_MULTIPLE_DEVICES("I2C repeat write test", "[i2c][test_env=UT_T2_I2C][timeout=150]", i2c_master_repeat_write, i2c_slave_repeat_read);
|
||||
|
||||
static volatile bool exit_flag;
|
||||
static bool test_read_func;
|
||||
|
||||
static void test_task(void *pvParameters)
|
||||
{
|
||||
xSemaphoreHandle *sema = (xSemaphoreHandle *) pvParameters;
|
||||
|
||||
uint8_t *data = (uint8_t *) malloc(DATA_LENGTH);
|
||||
i2c_config_t conf_slave = i2c_slave_init();
|
||||
TEST_ESP_OK(i2c_param_config( I2C_SLAVE_NUM, &conf_slave));
|
||||
TEST_ESP_OK(i2c_driver_install(I2C_SLAVE_NUM, I2C_MODE_SLAVE,
|
||||
I2C_SLAVE_RX_BUF_LEN,
|
||||
I2C_SLAVE_TX_BUF_LEN, 0));
|
||||
while (exit_flag == false) {
|
||||
if (test_read_func) {
|
||||
i2c_slave_read_buffer(I2C_SLAVE_NUM, data, DATA_LENGTH, 0);
|
||||
} else {
|
||||
i2c_slave_write_buffer(I2C_SLAVE_NUM, data, DATA_LENGTH, 0);
|
||||
}
|
||||
}
|
||||
|
||||
free(data);
|
||||
xSemaphoreGive(*sema);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
TEST_CASE("test i2c_slave_read_buffer is not blocked when ticks_to_wait=0", "[i2c]")
|
||||
{
|
||||
xSemaphoreHandle exit_sema = xSemaphoreCreateBinary();
|
||||
exit_flag = false;
|
||||
|
||||
test_read_func = true;
|
||||
xTaskCreate(test_task, "tsk1", 2048, &exit_sema, 5, NULL);
|
||||
|
||||
printf("Waiting for 5 sec\n");
|
||||
vTaskDelay(5000 / portTICK_PERIOD_MS);
|
||||
exit_flag = true;
|
||||
if (xSemaphoreTake(exit_sema, 1000 / portTICK_PERIOD_MS) == pdTRUE) {
|
||||
vSemaphoreDelete(exit_sema);
|
||||
} else {
|
||||
TEST_FAIL_MESSAGE("i2c_slave_read_buffer is blocked");
|
||||
}
|
||||
TEST_ESP_OK(i2c_driver_delete(I2C_SLAVE_NUM));
|
||||
}
|
||||
|
||||
TEST_CASE("test i2c_slave_write_buffer is not blocked when ticks_to_wait=0", "[i2c]")
|
||||
{
|
||||
xSemaphoreHandle exit_sema = xSemaphoreCreateBinary();
|
||||
exit_flag = false;
|
||||
|
||||
test_read_func = false;
|
||||
xTaskCreate(test_task, "tsk1", 2048, &exit_sema, 5, NULL);
|
||||
|
||||
printf("Waiting for 5 sec\n");
|
||||
vTaskDelay(5000 / portTICK_PERIOD_MS);
|
||||
exit_flag = true;
|
||||
if (xSemaphoreTake(exit_sema, 1000 / portTICK_PERIOD_MS) == pdTRUE) {
|
||||
vSemaphoreDelete(exit_sema);
|
||||
} else {
|
||||
TEST_FAIL_MESSAGE("i2c_slave_write_buffer is blocked");
|
||||
}
|
||||
TEST_ESP_OK(i2c_driver_delete(I2C_SLAVE_NUM));
|
||||
}
|
||||
|
@ -118,6 +118,56 @@ static void uart_config(uint32_t baud_rate, bool use_ref_tick)
|
||||
uart_driver_install(UART_NUM1, BUF_SIZE * 2, BUF_SIZE * 2, 20, NULL, 0);
|
||||
}
|
||||
|
||||
static volatile bool exit_flag;
|
||||
|
||||
static void test_task(void *pvParameters)
|
||||
{
|
||||
xSemaphoreHandle *sema = (xSemaphoreHandle *) pvParameters;
|
||||
char* data = (char *) malloc(256);
|
||||
|
||||
while (exit_flag == false) {
|
||||
uart_tx_chars(UART_NUM1, data, 256);
|
||||
// The uart_wait_tx_done() function does not block anything if ticks_to_wait = 0.
|
||||
uart_wait_tx_done(UART_NUM1, 0);
|
||||
}
|
||||
|
||||
free(data);
|
||||
xSemaphoreGive(*sema);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
static void test_task2(void *pvParameters)
|
||||
{
|
||||
while (exit_flag == false) {
|
||||
// This task obstruct a setting tx_done_sem semaphore in the UART interrupt.
|
||||
// It leads to waiting the ticks_to_wait time in uart_wait_tx_done() function.
|
||||
uart_disable_intr_mask(UART_NUM1, UART_TX_DONE_INT_ENA_M);
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
TEST_CASE("test uart_wait_tx_done is not blocked when ticks_to_wait=0", "[uart]")
|
||||
{
|
||||
uart_config(UART_BAUD_11520, false);
|
||||
|
||||
xSemaphoreHandle exit_sema = xSemaphoreCreateBinary();
|
||||
exit_flag = false;
|
||||
|
||||
xTaskCreate(test_task, "tsk1", 2048, &exit_sema, 5, NULL);
|
||||
xTaskCreate(test_task2, "tsk2", 2048, NULL, 5, NULL);
|
||||
|
||||
printf("Waiting for 5 sec\n");
|
||||
vTaskDelay(5000 / portTICK_PERIOD_MS);
|
||||
exit_flag = true;
|
||||
|
||||
if (xSemaphoreTake(exit_sema, 1000 / portTICK_PERIOD_MS) == pdTRUE) {
|
||||
vSemaphoreDelete(exit_sema);
|
||||
} else {
|
||||
TEST_FAIL_MESSAGE("uart_wait_tx_done is blocked");
|
||||
}
|
||||
TEST_ESP_OK(uart_driver_delete(UART_NUM1));
|
||||
}
|
||||
|
||||
TEST_CASE("test uart get baud-rate", "[uart]")
|
||||
{
|
||||
uint32_t baud_rate1 = 0;
|
||||
|
@ -1038,20 +1038,25 @@ esp_err_t uart_wait_tx_done(uart_port_t uart_num, TickType_t ticks_to_wait)
|
||||
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
|
||||
UART_CHECK((p_uart_obj[uart_num]), "uart driver error", ESP_FAIL);
|
||||
BaseType_t res;
|
||||
portTickType ticks_end = xTaskGetTickCount() + ticks_to_wait;
|
||||
portTickType ticks_start = xTaskGetTickCount();
|
||||
//Take tx_mux
|
||||
res = xSemaphoreTake(p_uart_obj[uart_num]->tx_mux, (portTickType)ticks_to_wait);
|
||||
if(res == pdFALSE) {
|
||||
return ESP_ERR_TIMEOUT;
|
||||
}
|
||||
ticks_to_wait = ticks_end - xTaskGetTickCount();
|
||||
xSemaphoreTake(p_uart_obj[uart_num]->tx_done_sem, 0);
|
||||
ticks_to_wait = ticks_end - xTaskGetTickCount();
|
||||
if(UART[uart_num]->status.txfifo_cnt == 0) {
|
||||
xSemaphoreGive(p_uart_obj[uart_num]->tx_mux);
|
||||
return ESP_OK;
|
||||
}
|
||||
uart_enable_intr_mask(uart_num, UART_TX_DONE_INT_ENA_M);
|
||||
|
||||
TickType_t ticks_end = xTaskGetTickCount();
|
||||
if (ticks_end - ticks_start > ticks_to_wait) {
|
||||
ticks_to_wait = 0;
|
||||
} else {
|
||||
ticks_to_wait = ticks_to_wait - (ticks_end - ticks_start);
|
||||
}
|
||||
//take 2nd tx_done_sem, wait given from ISR
|
||||
res = xSemaphoreTake(p_uart_obj[uart_num]->tx_done_sem, (portTickType)ticks_to_wait);
|
||||
if(res == pdFALSE) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user