Skip to content

Commit

Permalink
silabs_uart_hotfix (#25890)
Browse files Browse the repository at this point in the history
  • Loading branch information
jepenven-silabs authored Mar 30, 2023
1 parent a27bc8c commit 5a1b371
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 38 deletions.
97 changes: 60 additions & 37 deletions examples/platform/silabs/efr32/uart.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,9 @@ static uint16_t lastCount; // Nb of bytes already processed from the active dmaB
#define UART_TX_MAX_BUF_LEN (258)
#endif

TaskHandle_t sUartTaskHandle;
StackType_t uartStack[UART_TASK_SIZE * sizeof(StackType_t)];
StaticTask_t uartTaskStruct;
static TaskHandle_t sUartTaskHandle;
static StackType_t uartStack[UART_TASK_SIZE * sizeof(StackType_t)];
static StaticTask_t uartTaskStruct;

typedef struct
{
Expand All @@ -127,19 +127,19 @@ typedef struct
} UartTxStruct_t;

uint8_t sUartTxQueueBuffer[UART_MAX_QUEUE_SIZE * sizeof(UartTxStruct_t)];
StaticQueue_t sUartTxQueueStruct;
QueueHandle_t sUartTxQueue;
static StaticQueue_t sUartTxQueueStruct;
static QueueHandle_t sUartTxQueue;

EventGroupHandle_t sUartEventGroup;
StaticEventGroup_t sUartEventGroupStruct;
static EventGroupHandle_t sUartEventGroup;
static StaticEventGroup_t sUartEventGroupStruct;

// Rx buffer for the receive Fifo
static uint8_t sRxFifoBuffer[MAX_BUFFER_SIZE];
static Fifo_t sReceiveFifo;

static void UART_rx_callback(UARTDRV_Handle_t handle, Ecode_t transferStatus, uint8_t * data, UARTDRV_Count_t transferCount);
static void UART_tx_callback(struct UARTDRV_HandleData * handle, Ecode_t transferStatus, uint8_t * data,
UARTDRV_Count_t transferCount);
// static void UART_tx_callback(struct UARTDRV_HandleData * handle, Ecode_t transferStatus, uint8_t * data,
// UARTDRV_Count_t transferCount);
static void uartSendBytes(uint8_t * buffer, uint16_t nbOfBytes);

static bool InitFifo(Fifo_t * fifo, uint8_t * pDataBuffer, uint16_t bufferSize)
Expand Down Expand Up @@ -252,6 +252,12 @@ static uint16_t RetrieveFromFifo(Fifo_t * fifo, uint8_t * pData, uint16_t SizeTo
*/
void uartConsoleInit(void)
{
if (sUartTaskHandle != NULL)
{
// Init was already done
return;
}

sl_board_enable_vcom();
// Init a fifo for the data received on the uart
InitFifo(&sReceiveFifo, sRxFifoBuffer, MAX_BUFFER_SIZE);
Expand All @@ -260,6 +266,19 @@ void uartConsoleInit(void)
UARTDRV_Receive(vcom_handle, sRxDmaBuffer, MAX_DMA_BUFFER_SIZE, UART_rx_callback);
UARTDRV_Receive(vcom_handle, sRxDmaBuffer2, MAX_DMA_BUFFER_SIZE, UART_rx_callback);

uint32_t struct_size = sizeof(UartTxStruct_t);

sUartTxQueue = xQueueCreateStatic(UART_MAX_QUEUE_SIZE, struct_size, sUartTxQueueBuffer, &sUartTxQueueStruct);

sUartEventGroup = xEventGroupCreateStatic(&sUartEventGroupStruct);

// Start App task.
sUartTaskHandle = xTaskCreateStatic(uartMainLoop, UART_TASK_NAME, UART_TASK_SIZE, nullptr, 30, uartStack, &uartTaskStruct);

assert(sUartTaskHandle);
assert(sUartEventGroup);
assert(sUartTxQueue);

// Enable USART0/EUSART0 interrupt to wake OT task when data arrives
NVIC_ClearPendingIRQ(USART_IRQ);
NVIC_EnableIRQ(USART_IRQ);
Expand All @@ -276,28 +295,12 @@ void uartConsoleInit(void)
#else
USART_IntEnable(SL_UARTDRV_USART_VCOM_PERIPHERAL, USART_IF_RXDATAV);
#endif // EFR32MG24

uint32_t struct_size = sizeof(UartTxStruct_t);

sUartTxQueue = xQueueCreateStatic(UART_MAX_QUEUE_SIZE, struct_size, sUartTxQueueBuffer, &sUartTxQueueStruct);

sUartEventGroup = xEventGroupCreateStatic(&sUartEventGroupStruct);

// Start App task.
sUartTaskHandle = xTaskCreateStatic(uartMainLoop, UART_TASK_NAME, UART_TASK_SIZE, nullptr, 30, uartStack, &uartTaskStruct);

assert(sUartTaskHandle);
assert(sUartEventGroup);
assert(sUartTxQueue);
}

void USART_IRQHandler(void)
{
#ifdef ENABLE_CHIP_SHELL
chip::NotifyShellProcessFromISR();
#endif
#if defined(SL_WIFI)
/* TODO */
#elif !defined(PW_RPC_ENABLED)
otSysEventSignalPending();
#endif
Expand All @@ -318,7 +321,7 @@ void USART_IRQHandler(void)
void UART_tx_callback(struct UARTDRV_HandleData * handle, Ecode_t transferStatus, uint8_t * data, UARTDRV_Count_t transferCount)
{
BaseType_t xHigherPriorityTaskWoken;
/* Was the message posted successfully? */

if (xEventGroupSetBitsFromISR(sUartEventGroup, UART_TX_COMPLETE_BIT, &xHigherPriorityTaskWoken) == pdPASS)
{
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
Expand All @@ -343,9 +346,6 @@ static void UART_rx_callback(UARTDRV_Handle_t handle, Ecode_t transferStatus, ui

#ifdef ENABLE_CHIP_SHELL
chip::NotifyShellProcessFromISR();
#endif
#if defined(SL_WIFI)
/* TODO */
#elif !defined(PW_RPC_ENABLED)
otSysEventSignalPending();
#endif
Expand All @@ -364,16 +364,25 @@ int16_t uartConsoleWrite(const char * Buf, uint16_t BufLength)
{
return UART_CONSOLE_ERR;
}
// Do NOT wait for logs. Better to lost some logging than block
// an unknow task that might be critical.

UartTxStruct_t workBuffer;
memcpy(workBuffer.data, Buf, BufLength);
workBuffer.length = BufLength;

if (pdTRUE == xQueueSend(sUartTxQueue, &workBuffer, 0))
if (xPortIsInsideInterrupt())
{
BaseType_t xHigherPriorityTaskWoken;
xQueueSendFromISR(sUartTxQueue, &workBuffer, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
return BufLength;
}
else
{
if (pdTRUE == xQueueSend(sUartTxQueue, &workBuffer, portMAX_DELAY))
{
return BufLength;
}
}

return UART_CONSOLE_ERR;
}
Expand All @@ -397,10 +406,20 @@ int16_t uartLogWrite(const char * log, uint16_t length)
memcpy(workBuffer.data + length, "\r\n", 2);
workBuffer.length = length + 2;

if (pdTRUE == xQueueSend(sUartTxQueue, &workBuffer, 0))
if (xPortIsInsideInterrupt())
{
BaseType_t xHigherPriorityTaskWoken;
xQueueSendFromISR(sUartTxQueue, &workBuffer, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
return length;
}
else
{
if (pdTRUE == xQueueSend(sUartTxQueue, &workBuffer, 0))
{
return length;
}
}

return UART_CONSOLE_ERR;
}
Expand Down Expand Up @@ -439,9 +458,12 @@ void uartMainLoop(void * args)

while (1)
{
while (pdTRUE == xQueueReceive(sUartTxQueue, &workBuffer, portMAX_DELAY))

BaseType_t eventReceived = xQueueReceive(sUartTxQueue, &workBuffer, portMAX_DELAY);
while (eventReceived == pdTRUE)
{
uartSendBytes(workBuffer.data, workBuffer.length);
eventReceived = xQueueReceive(sUartTxQueue, &workBuffer, 0);
}
}
}
Expand All @@ -454,6 +476,7 @@ void uartMainLoop(void * args)
*/
void uartSendBytes(uint8_t * buffer, uint16_t nbOfBytes)
{

#if defined(SL_CATALOG_POWER_MANAGER_PRESENT)
sl_power_manager_add_em_requirement(SL_POWER_MANAGER_EM1);
#endif
Expand All @@ -462,7 +485,9 @@ void uartSendBytes(uint8_t * buffer, uint16_t nbOfBytes)
pre_uart_transfer();
#endif /* EFR32MG24 && WF200_WIFI */

UARTDRV_Transmit(vcom_handle, (uint8_t *) buffer, nbOfBytes, UART_tx_callback);
// TODO FIXME Swap to iostream driver since UARTDRV is deprecated.
// TODO Do no use blocking transmit (hotfix).
UARTDRV_TransmitB(vcom_handle, (uint8_t *) buffer, nbOfBytes);

#if (defined(EFR32MG24) && defined(WF200_WIFI))
post_uart_transfer();
Expand All @@ -471,8 +496,6 @@ void uartSendBytes(uint8_t * buffer, uint16_t nbOfBytes)
#if defined(SL_CATALOG_POWER_MANAGER_PRESENT)
sl_power_manager_remove_em_requirement(SL_POWER_MANAGER_EM1);
#endif

xEventGroupWaitBits(sUartEventGroup, UART_TX_COMPLETE_BIT, pdTRUE, pdFALSE, portMAX_DELAY);
}

#ifdef __cplusplus
Expand Down
2 changes: 1 addition & 1 deletion src/platform/silabs/efr32/ThreadStackManagerImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ extern "C" void efr32UartProcess(void)
#if !defined(PW_RPC_ENABLED) && !defined(ENABLE_CHIP_SHELL)
uint8_t tempBuf[128] = { 0 };
// will read the data available up to 128bytes
uint16_t count = uartConsoleRead((char *) tempBuf, 128);
int16_t count = uartConsoleRead((char *) tempBuf, 128);
if (count > 0)
{
// ot process Received data for CLI cmds
Expand Down

0 comments on commit 5a1b371

Please sign in to comment.