kopia lustrzana https://github.com/espressif/esp-idf
driver: fixes context switch while sending cause rts reset before send (backport v4.4)
rodzic
c41208550a
commit
6bf650c159
|
@ -4,6 +4,7 @@
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <sys/param.h>
|
||||||
#include "esp_types.h"
|
#include "esp_types.h"
|
||||||
#include "esp_attr.h"
|
#include "esp_attr.h"
|
||||||
#include "esp_intr_alloc.h"
|
#include "esp_intr_alloc.h"
|
||||||
|
@ -64,6 +65,9 @@ static const char *UART_TAG = "uart";
|
||||||
| (UART_INTR_BRK_DET) \
|
| (UART_INTR_BRK_DET) \
|
||||||
| (UART_INTR_PARITY_ERR))
|
| (UART_INTR_PARITY_ERR))
|
||||||
|
|
||||||
|
|
||||||
|
#define UART_ENTER_CRITICAL_SAFE(mux) portENTER_CRITICAL_SAFE(mux)
|
||||||
|
#define UART_EXIT_CRITICAL_SAFE(mux) portEXIT_CRITICAL_SAFE(mux)
|
||||||
#define UART_ENTER_CRITICAL_ISR(mux) portENTER_CRITICAL_ISR(mux)
|
#define UART_ENTER_CRITICAL_ISR(mux) portENTER_CRITICAL_ISR(mux)
|
||||||
#define UART_EXIT_CRITICAL_ISR(mux) portEXIT_CRITICAL_ISR(mux)
|
#define UART_EXIT_CRITICAL_ISR(mux) portEXIT_CRITICAL_ISR(mux)
|
||||||
#define UART_ENTER_CRITICAL(mux) portENTER_CRITICAL(mux)
|
#define UART_ENTER_CRITICAL(mux) portENTER_CRITICAL(mux)
|
||||||
|
@ -803,6 +807,19 @@ static int UART_ISR_ATTR uart_find_pattern_from_last(uint8_t *buf, int length, u
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t UART_ISR_ATTR uart_enable_tx_write_fifo(uart_port_t uart_num, const uint8_t *pbuf, uint32_t len)
|
||||||
|
{
|
||||||
|
uint32_t sent_len = 0;
|
||||||
|
UART_ENTER_CRITICAL_SAFE(&(uart_context[uart_num].spinlock));
|
||||||
|
if (UART_IS_MODE_SET(uart_num, UART_MODE_RS485_HALF_DUPLEX)) {
|
||||||
|
uart_hal_set_rts(&(uart_context[uart_num].hal), 0);
|
||||||
|
uart_hal_ena_intr_mask(&(uart_context[uart_num].hal), UART_INTR_TX_DONE);
|
||||||
|
}
|
||||||
|
uart_hal_write_txfifo(&(uart_context[uart_num].hal), pbuf, len, &sent_len);
|
||||||
|
UART_EXIT_CRITICAL_SAFE(&(uart_context[uart_num].spinlock));
|
||||||
|
return sent_len;
|
||||||
|
}
|
||||||
|
|
||||||
//internal isr handler for default driver code.
|
//internal isr handler for default driver code.
|
||||||
static void UART_ISR_ATTR uart_rx_intr_handler_default(void *param)
|
static void UART_ISR_ATTR uart_rx_intr_handler_default(void *param)
|
||||||
{
|
{
|
||||||
|
@ -872,19 +889,9 @@ static void UART_ISR_ATTR uart_rx_intr_handler_default(void *param)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (p_uart->tx_len_tot > 0 && p_uart->tx_ptr && p_uart->tx_len_cur > 0) {
|
if (p_uart->tx_len_tot > 0 && p_uart->tx_ptr && p_uart->tx_len_cur > 0) {
|
||||||
//To fill the TX FIFO.
|
// To fill the TX FIFO.
|
||||||
uint32_t send_len = 0;
|
uint32_t send_len = uart_enable_tx_write_fifo(uart_num, (const uint8_t *) p_uart->tx_ptr,
|
||||||
// Set RS485 RTS pin before transmission if the half duplex mode is enabled
|
MIN(p_uart->tx_len_cur, tx_fifo_rem));
|
||||||
if (UART_IS_MODE_SET(uart_num, UART_MODE_RS485_HALF_DUPLEX)) {
|
|
||||||
UART_ENTER_CRITICAL_ISR(&(uart_context[uart_num].spinlock));
|
|
||||||
uart_hal_set_rts(&(uart_context[uart_num].hal), 0);
|
|
||||||
uart_hal_ena_intr_mask(&(uart_context[uart_num].hal), UART_INTR_TX_DONE);
|
|
||||||
UART_EXIT_CRITICAL_ISR(&(uart_context[uart_num].spinlock));
|
|
||||||
}
|
|
||||||
uart_hal_write_txfifo(&(uart_context[uart_num].hal),
|
|
||||||
(const uint8_t *)p_uart->tx_ptr,
|
|
||||||
(p_uart->tx_len_cur > tx_fifo_rem) ? tx_fifo_rem : p_uart->tx_len_cur,
|
|
||||||
&send_len);
|
|
||||||
p_uart->tx_ptr += send_len;
|
p_uart->tx_ptr += send_len;
|
||||||
p_uart->tx_len_tot -= send_len;
|
p_uart->tx_len_tot -= send_len;
|
||||||
p_uart->tx_len_cur -= send_len;
|
p_uart->tx_len_cur -= send_len;
|
||||||
|
@ -1088,6 +1095,7 @@ static void UART_ISR_ATTR uart_rx_intr_handler_default(void *param)
|
||||||
// Workaround for RS485: If the RS485 half duplex mode is active
|
// Workaround for RS485: If the RS485 half duplex mode is active
|
||||||
// and transmitter is in idle state then reset received buffer and reset RTS pin
|
// and transmitter is in idle state then reset received buffer and reset RTS pin
|
||||||
// skip this behavior for other UART modes
|
// skip this behavior for other UART modes
|
||||||
|
uart_hal_clr_intsts_mask(&(uart_context[uart_num].hal), UART_INTR_TX_DONE);
|
||||||
UART_ENTER_CRITICAL_ISR(&(uart_context[uart_num].spinlock));
|
UART_ENTER_CRITICAL_ISR(&(uart_context[uart_num].spinlock));
|
||||||
uart_hal_disable_intr_mask(&(uart_context[uart_num].hal), UART_INTR_TX_DONE);
|
uart_hal_disable_intr_mask(&(uart_context[uart_num].hal), UART_INTR_TX_DONE);
|
||||||
if (UART_IS_MODE_SET(uart_num, UART_MODE_RS485_HALF_DUPLEX)) {
|
if (UART_IS_MODE_SET(uart_num, UART_MODE_RS485_HALF_DUPLEX)) {
|
||||||
|
@ -1095,7 +1103,6 @@ static void UART_ISR_ATTR uart_rx_intr_handler_default(void *param)
|
||||||
uart_hal_set_rts(&(uart_context[uart_num].hal), 1);
|
uart_hal_set_rts(&(uart_context[uart_num].hal), 1);
|
||||||
}
|
}
|
||||||
UART_EXIT_CRITICAL_ISR(&(uart_context[uart_num].spinlock));
|
UART_EXIT_CRITICAL_ISR(&(uart_context[uart_num].spinlock));
|
||||||
uart_hal_clr_intsts_mask(&(uart_context[uart_num].hal), UART_INTR_TX_DONE);
|
|
||||||
xSemaphoreGiveFromISR(p_uart_obj[uart_num]->tx_done_sem, &HPTaskAwoken);
|
xSemaphoreGiveFromISR(p_uart_obj[uart_num]->tx_done_sem, &HPTaskAwoken);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1164,13 +1171,7 @@ int uart_tx_chars(uart_port_t uart_num, const char *buffer, uint32_t len)
|
||||||
}
|
}
|
||||||
int tx_len = 0;
|
int tx_len = 0;
|
||||||
xSemaphoreTake(p_uart_obj[uart_num]->tx_mux, (portTickType)portMAX_DELAY);
|
xSemaphoreTake(p_uart_obj[uart_num]->tx_mux, (portTickType)portMAX_DELAY);
|
||||||
if (UART_IS_MODE_SET(uart_num, UART_MODE_RS485_HALF_DUPLEX)) {
|
tx_len = (int)uart_enable_tx_write_fifo(uart_num, (const uint8_t *) buffer, len);
|
||||||
UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock));
|
|
||||||
uart_hal_set_rts(&(uart_context[uart_num].hal), 0);
|
|
||||||
uart_hal_ena_intr_mask(&(uart_context[uart_num].hal), UART_INTR_TX_DONE);
|
|
||||||
UART_EXIT_CRITICAL(&(uart_context[uart_num].spinlock));
|
|
||||||
}
|
|
||||||
uart_hal_write_txfifo(&(uart_context[uart_num].hal), (const uint8_t *) buffer, len, (uint32_t *)&tx_len);
|
|
||||||
xSemaphoreGive(p_uart_obj[uart_num]->tx_mux);
|
xSemaphoreGive(p_uart_obj[uart_num]->tx_mux);
|
||||||
return tx_len;
|
return tx_len;
|
||||||
}
|
}
|
||||||
|
@ -1208,14 +1209,7 @@ static int uart_tx_all(uart_port_t uart_num, const char *src, size_t size, bool
|
||||||
while (size) {
|
while (size) {
|
||||||
//semaphore for tx_fifo available
|
//semaphore for tx_fifo available
|
||||||
if (pdTRUE == xSemaphoreTake(p_uart_obj[uart_num]->tx_fifo_sem, (portTickType)portMAX_DELAY)) {
|
if (pdTRUE == xSemaphoreTake(p_uart_obj[uart_num]->tx_fifo_sem, (portTickType)portMAX_DELAY)) {
|
||||||
uint32_t sent = 0;
|
uint32_t sent = uart_enable_tx_write_fifo(uart_num, (const uint8_t *) src, size);
|
||||||
if (UART_IS_MODE_SET(uart_num, UART_MODE_RS485_HALF_DUPLEX)) {
|
|
||||||
UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock));
|
|
||||||
uart_hal_set_rts(&(uart_context[uart_num].hal), 0);
|
|
||||||
uart_hal_ena_intr_mask(&(uart_context[uart_num].hal), UART_INTR_TX_DONE);
|
|
||||||
UART_EXIT_CRITICAL(&(uart_context[uart_num].spinlock));
|
|
||||||
}
|
|
||||||
uart_hal_write_txfifo(&(uart_context[uart_num].hal), (const uint8_t *)src, size, &sent);
|
|
||||||
if (sent < size) {
|
if (sent < size) {
|
||||||
p_uart_obj[uart_num]->tx_waiting_fifo = true;
|
p_uart_obj[uart_num]->tx_waiting_fifo = true;
|
||||||
uart_enable_tx_intr(uart_num, 1, UART_EMPTY_THRESH_DEFAULT);
|
uart_enable_tx_intr(uart_num, 1, UART_EMPTY_THRESH_DEFAULT);
|
||||||
|
|
Ładowanie…
Reference in New Issue