fix(vfs/uart): Add support for multi-task call to uart select

This commit is contained in:
sonika.rathi
2023-08-17 09:36:32 +02:00
parent 30f32f6de6
commit d1593b82b0
2 changed files with 113 additions and 19 deletions

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -21,6 +21,7 @@
#include "esp_rom_uart.h"
#include "soc/soc_caps.h"
#include "hal/uart_ll.h"
#include "freertos/semphr.h"
#define UART_NUM SOC_UART_HP_NUM
@@ -55,6 +56,7 @@ static int uart_rx_char(int fd);
// Functions for sending and receiving bytes which use UART driver
static void uart_tx_char_via_driver(int fd, int c);
static int uart_rx_char_via_driver(int fd);
static SemaphoreHandle_t uart_select_mutex[UART_NUM];
typedef struct {
// Pointers to UART peripherals
@@ -150,6 +152,8 @@ static int uart_open(const char *path, int flags, int mode)
return -1;
}
uart_select_mutex[fd] = xSemaphoreCreateMutex();
xSemaphoreGive(uart_select_mutex[fd]);
s_ctx[fd]->non_blocking = ((flags & O_NONBLOCK) == O_NONBLOCK);
return fd;
@@ -298,6 +302,7 @@ static int uart_fstat(int fd, struct stat * st)
static int uart_close(int fd)
{
assert(fd >=0 && fd < 3);
vSemaphoreDelete(uart_select_mutex[fd]);
return 0;
}
@@ -437,6 +442,7 @@ static esp_err_t uart_start_select(int nfds, fd_set *readfds, fd_set *writefds,
esp_vfs_select_sem_t select_sem, void **end_select_args)
{
const int max_fds = MIN(nfds, UART_NUM);
int fd = -1;
*end_select_args = NULL;
for (int i = 0; i < max_fds; ++i) {
@@ -444,6 +450,7 @@ static esp_err_t uart_start_select(int nfds, fd_set *readfds, fd_set *writefds,
if (!uart_is_driver_installed(i)) {
return ESP_ERR_INVALID_STATE;
}
fd = i;
}
}
@@ -464,14 +471,11 @@ static esp_err_t uart_start_select(int nfds, fd_set *readfds, fd_set *writefds,
FD_ZERO(writefds);
FD_ZERO(exceptfds);
xSemaphoreTake(uart_select_mutex[fd], portMAX_DELAY);
portENTER_CRITICAL(uart_get_selectlock());
//uart_set_select_notif_callback sets the callbacks in UART ISR
for (int i = 0; i < max_fds; ++i) {
if (FD_ISSET(i, &args->readfds_orig) || FD_ISSET(i, &args->writefds_orig) || FD_ISSET(i, &args->errorfds_orig)) {
uart_set_select_notif_callback(i, select_notif_callback_isr);
}
}
uart_set_select_notif_callback(fd, select_notif_callback_isr);
for (int i = 0; i < max_fds; ++i) {
if (FD_ISSET(i, &args->readfds_orig)) {
@@ -500,17 +504,23 @@ static esp_err_t uart_start_select(int nfds, fd_set *readfds, fd_set *writefds,
static esp_err_t uart_end_select(void *end_select_args)
{
uart_select_args_t *args = end_select_args;
int fd = -1;
portENTER_CRITICAL(uart_get_selectlock());
esp_err_t ret = unregister_select(args);
for (int i = 0; i < UART_NUM; ++i) {
uart_set_select_notif_callback(i, NULL);
if (FD_ISSET(i, &args->readfds_orig) || FD_ISSET(i, &args->writefds_orig) || FD_ISSET(i, &args->errorfds_orig)) {
uart_set_select_notif_callback(i, NULL);
fd = i;
break;
}
}
portEXIT_CRITICAL(uart_get_selectlock());
if (args) {
free(args);
}
xSemaphoreGive(uart_select_mutex[fd]);
return ret;
}