16. Uart (Receive) FreeRTOS

В операционной системе 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); //создаем задачу приема
}

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *