mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'bugfix/uart_custom_isr_broken_v4.3' into 'release/v4.3'
UART: fix a bug preventing the user from freeing a previously registered ISR See merge request espressif/esp-idf!17217
This commit is contained in:
commit
cbca71a4e7
@ -333,7 +333,7 @@ esp_err_t uart_enable_rx_intr(uart_port_t uart_num);
|
||||
esp_err_t uart_disable_rx_intr(uart_port_t uart_num);
|
||||
|
||||
/**
|
||||
* @brief Disable UART TX interrupt (TX_FULL & TX_TIMEOUT INTERRUPT)
|
||||
* @brief Disable UART TX interrupt (TXFIFO_EMPTY INTERRUPT)
|
||||
*
|
||||
* @param uart_num UART port number
|
||||
*
|
||||
@ -344,7 +344,7 @@ esp_err_t uart_disable_rx_intr(uart_port_t uart_num);
|
||||
esp_err_t uart_disable_tx_intr(uart_port_t uart_num);
|
||||
|
||||
/**
|
||||
* @brief Enable UART TX interrupt (TX_FULL & TX_TIMEOUT INTERRUPT)
|
||||
* @brief Enable UART TX interrupt (TXFIFO_EMPTY INTERRUPT)
|
||||
*
|
||||
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
|
||||
* @param enable 1: enable; 0: disable
|
||||
|
@ -7,6 +7,8 @@
|
||||
#include "esp_system.h" // for uint32_t esp_random()
|
||||
#include "esp_rom_gpio.h"
|
||||
#include "soc/uart_periph.h"
|
||||
#include "hal/uart_ll.h"
|
||||
#include "hal/uart_hal.h"
|
||||
|
||||
#define UART_TAG "Uart"
|
||||
#define UART_NUM1 (UART_NUM_1)
|
||||
@ -427,3 +429,103 @@ TEST_CASE("uart int state restored after flush", "[uart]")
|
||||
TEST_ESP_OK(uart_driver_delete(uart_echo));
|
||||
free(data);
|
||||
}
|
||||
|
||||
/* Global variable shared between the ISR and the test function */
|
||||
volatile uint32_t uart_isr_happened = 0;
|
||||
|
||||
static void uart_custom_isr(void* arg) {
|
||||
(void) arg;
|
||||
|
||||
/* Clear interrupt status and disable TX interrupt here in order to
|
||||
* prevent an infinite call loop. Use the LL function to prevent
|
||||
* entering a critical section from an interrupt. */
|
||||
uart_ll_disable_intr_mask(UART_LL_GET_HW(1), UART_INTR_TXFIFO_EMPTY);
|
||||
uart_clear_intr_status(UART_NUM_1, UART_INTR_TXFIFO_EMPTY);
|
||||
|
||||
/* Mark the interrupt as serviced */
|
||||
uart_isr_happened = 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This function shall always be executed by core 0.
|
||||
* This is required by `uart_isr_free`.
|
||||
*/
|
||||
static void uart_test_custom_isr_core0(void* param) {
|
||||
/**
|
||||
* Setup the UART1 and make sure we can register and free a custom ISR
|
||||
*/
|
||||
uart_config_t uart_config = {
|
||||
.baud_rate = 115200,
|
||||
.data_bits = UART_DATA_8_BITS,
|
||||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_1,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
.source_clk = UART_SCLK_APB,
|
||||
};
|
||||
|
||||
const uart_port_t uart_echo = UART_NUM_1;
|
||||
const int uart_tx = 4;
|
||||
const int uart_rx = 5;
|
||||
const int buf_size = 256;
|
||||
const int intr_alloc_flags = 0;
|
||||
const char msg[] = "hello world\n";
|
||||
uart_isr_handle_t handle = NULL;
|
||||
|
||||
TEST_ESP_OK(uart_driver_install(uart_echo, buf_size * 2, 0, 0, NULL, intr_alloc_flags));
|
||||
TEST_ESP_OK(uart_param_config(uart_echo, &uart_config));
|
||||
TEST_ESP_OK(uart_set_pin(uart_echo, uart_tx, uart_rx, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
|
||||
|
||||
/* Prevent the custom ISR handler from being called if UART_INTR_BRK_DET interrupt occurs.
|
||||
* It shall only be called for TX interrupts. */
|
||||
uart_disable_intr_mask(uart_echo, UART_INTR_BRK_DET);
|
||||
|
||||
/* Unregister the default ISR setup by the function call above */
|
||||
TEST_ESP_OK(uart_isr_free(uart_echo));
|
||||
TEST_ESP_OK(uart_isr_register(uart_echo, uart_custom_isr, NULL, intr_alloc_flags, &handle));
|
||||
/* Set the TX FIFO empty threshold to the size of the message we are sending,
|
||||
* make sure it is never 0 in any case */
|
||||
TEST_ESP_OK(uart_enable_tx_intr(uart_echo, true, MAX(sizeof(msg), 1)));
|
||||
uart_write_bytes(uart_echo, msg, sizeof(msg));
|
||||
|
||||
/* 10ms will be enough to receive the interrupt */
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
|
||||
/* Make sure the ISR occured */
|
||||
TEST_ASSERT_EQUAL(uart_isr_happened, 1);
|
||||
esp_rom_printf("ISR happened: %d\n", uart_isr_happened);
|
||||
TEST_ESP_OK(uart_isr_free(uart_echo));
|
||||
TEST_ESP_OK(uart_driver_delete(uart_echo));
|
||||
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
TaskHandle_t* parent_task = (TaskHandle_t*) param;
|
||||
esp_rom_printf("Notifying caller\n");
|
||||
TEST_ASSERT(xTaskNotify(*parent_task, 0, eNoAction));
|
||||
vTaskDelete(NULL);
|
||||
#else
|
||||
(void) param;
|
||||
#endif //!CONFIG_FREERTOS_UNICORE
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("uart can register and free custom ISRs", "[uart]")
|
||||
{
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
TaskHandle_t task_handle;
|
||||
TaskHandle_t current_handler = xTaskGetCurrentTaskHandle();
|
||||
/* Run the test on a determianted core, do not allow the core to be changed
|
||||
* as we will manipulate ISRs. */
|
||||
BaseType_t ret = xTaskCreatePinnedToCore(uart_test_custom_isr_core0,
|
||||
"uart_test_custom_isr_core0_task",
|
||||
2048,
|
||||
¤t_handler,
|
||||
5,
|
||||
&task_handle,
|
||||
0);
|
||||
TEST_ASSERT(ret);
|
||||
TEST_ASSERT(xTaskNotifyWait(0, 0, NULL, 1000 / portTICK_PERIOD_MS));
|
||||
(void) task_handle;
|
||||
#else
|
||||
uart_test_custom_isr_core0(NULL);
|
||||
#endif //!CONFIG_FREERTOS_UNICORE
|
||||
}
|
||||
|
@ -611,6 +611,9 @@ esp_err_t uart_disable_tx_intr(uart_port_t uart_num)
|
||||
|
||||
esp_err_t uart_enable_tx_intr(uart_port_t uart_num, int enable, int thresh)
|
||||
{
|
||||
if (enable == 0) {
|
||||
return uart_disable_tx_intr(uart_num);
|
||||
}
|
||||
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
|
||||
UART_CHECK((thresh < SOC_UART_FIFO_LEN), "empty intr threshold error", ESP_FAIL);
|
||||
uart_hal_clr_intsts_mask(&(uart_context[uart_num].hal), UART_INTR_TXFIFO_EMPTY);
|
||||
@ -627,6 +630,9 @@ esp_err_t uart_isr_register(uart_port_t uart_num, void (*fn)(void *), void *arg,
|
||||
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
|
||||
UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock));
|
||||
ret = esp_intr_alloc(uart_periph_signal[uart_num].irq, intr_alloc_flags, fn, arg, handle);
|
||||
if (ret == ESP_OK) {
|
||||
p_uart_obj[uart_num]->intr_handle = *handle;
|
||||
}
|
||||
UART_EXIT_CRITICAL(&(uart_context[uart_num].spinlock));
|
||||
return ret;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user