В операционной системе FreeRTOS необходимо в прерывании создать специальную очередь, в нее передать данные и уже в определенной задаче эти данные «забирать из очереди».
После #incude
xQueueHandle xQueueUart; //создаем указатель на очередь
Далее пишем:
Функция «прерывания» по uart0
LOCAL void uart0_rx_intr_handler(void *para)
{
uint8 fifo_len = 0; //переменная - длина буфера
uint8 buf_idx = 0; //индекс внутри буфера =0
uint8 fifo_tmp[128] = {0};
portBASE_TYPE xHigherPriorityTaskWoken;
uint8 RcvChar;
uint32 uart_intr_status = READ_PERI_REG(UART_INT_ST(UART0)); //считываем регистр состояний uart
while (uart_intr_status != 0x0)
{
//Обработка регистра состояний
if (UART_FRM_ERR_INT_ST == (uart_intr_status & UART_FRM_ERR_INT_ST)) //если "прочие" ошибки - сбрасываем флаг
{
WRITE_PERI_REG(UART_INT_CLR(UART0), UART_FRM_ERR_INT_CLR);
}
else if (UART_RXFIFO_FULL_INT_ST == (uart_intr_status & UART_RXFIFO_FULL_INT_ST)) //если приемный буфер полон
{
fifo_len = (READ_PERI_REG(UART_STATUS(UART0)) >> UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT; //определяем длину
buf_idx = 0; //ставим индекс =0
while (buf_idx < fifo_len)
{
RcvChar = (char) READ_PERI_REG(UART_FIFO(UART0)) & 0xFF;
buf_idx++;
xQueueSendFromISR(xQueueUart, (void *)&RcvChar, &xHigherPriorityTaskWoken); //формируем очередь из прерывания
portEND_SWITCHING_ISR(xHigherPriorityTaskWoken); //переключаемся на задачу-приемник (ставим ее следующей в очереди)
}
WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_FULL_INT_CLR); //очищаем флаг что буфер полон
}
else if (UART_RXFIFO_TOUT_INT_ST == (uart_intr_status & UART_RXFIFO_TOUT_INT_ST)) //прерывание по таймауту приема
{
fifo_len = (READ_PERI_REG(UART_STATUS(UART0)) >> UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT;
buf_idx = 0;
while (buf_idx < fifo_len)
{
RcvChar = (char) READ_PERI_REG(UART_FIFO(UART0)) & 0xFF;
buf_idx++;
xQueueSendFromISR(xQueueUart, (void *)&RcvChar, &xHigherPriorityTaskWoken); //формируем очередь из прерывания
portEND_SWITCHING_ISR(xHigherPriorityTaskWoken); //переключаемся на задачу-приемник (ставим ее следующей в очереди)
}
WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_TOUT_INT_CLR);
}
else if (UART_TXFIFO_EMPTY_INT_ST == (uart_intr_status & UART_TXFIFO_EMPTY_INT_ST)) //опустошение буфера передачи
{
WRITE_PERI_REG(UART_INT_CLR(UART0), UART_TXFIFO_EMPTY_INT_CLR);
CLEAR_PERI_REG_MASK(UART_INT_ENA(UART0), UART_TXFIFO_EMPTY_INT_ENA); //сброс бита в регистре прерываний по передаче
}
uart_intr_status = READ_PERI_REG(UART_INT_ST(UART0)); //считываем регистр с флагами
}
}
Задача с функцией приема из очереди
void ICACHE_FLASH_ATTR uart_task_Rx(void *pvParameters)
{
char c;
for (;;)
{
if (xQueueReceive(xQueueUart, (void *)&c, (portTickType)portMAX_DELAY)) //принимаем данные в переменную "с", с максимальным временем ожидания
{
//Code
}
}
}
В функции user_init()
void ICACHE_FLASH_ATTR user_init()
{
UART_SetBaudrate(UART0,BIT_RATE_115200); //настраиваем uart0
UART_SetBaudrate(UART1,BIT_RATE_115200); //настраиваем uart1
UART_WaitTxFifoEmpty(UART0) //ждем пока освободится буфер передачи
UART_WaitTxFifoEmpty(UART1) //ждем пока освободится буфер передачи
//выполняем настройку uart
UART_ConfigTypeDef uart_config;
uart_config.baud_rate = BIT_RATE_115200;
uart_config.data_bits = UART_WordLength_8b;
uart_config.parity = USART_Parity_None;
uart_config.stop_bits = USART_StopBits_1;
uart_config.flow_ctrl = USART_HardwareFlowControl_None;
uart_config.UART_RxFlowThresh = 120;
uart_config.UART_InverseMask = UART_None_Inverse;
UART_ParamConfig(UART0, &uart_config); //прописываем структуру с настройками
UART_IntrConfTypeDef uart_intr;
ETS_UART_INTR_DISABLE(); //выключаем прерывания по uart
uart_intr.UART_IntrEnMask = UART_RXFIFO_TOUT_INT_ENA | UART_FRM_ERR_INT_ENA | UART_RXFIFO_FULL_INT_ENA | UART_TXFIFO_EMPTY_INT_ENA; //прописываем "варианты" прерываний
uart_intr.UART_RX_FifoFullIntrThresh = 10;
uart_intr.UART_RX_TimeOutIntrThresh = 2;
uart_intr.UART_TX_FifoEmptyIntrThresh = 20;
UART_IntrConfig(UART0, &uart_intr); //прописываем настройки
UART_SetPrintPort(UART0); //прописываем порт для вывода отладочной информации
UART_intr_handler_register(uart0_rx_intr_handler, NULL); //прописываем callback функцию для прерываний
ETS_UART_INTR_ENABLE(); //включаем прерывания
xQueueUart = xQueueCreate( uxQueueLength, uxItemSize ); // очередь из uxQueueLength элементов размером uxItemSize Байт.
xTaskCreate(uart_task_Rx, "uTask", size_in_u32, NULL, 2, NULL); //создаем задачу приема
}