/* * Copyright (C) 2014 -2016 Espressif System * */ #include "esp_common.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/queue.h" #include "uart.h" enum { UART_EVENT_RX_CHAR, UART_EVENT_MAX }; typedef struct _os_event_ { uint32 event; uint32 param; } os_event_t; xTaskHandle xUartTaskHandle; xQueueHandle xQueueUart; LOCAL STATUS uart_tx_one_char(uint8 uart, uint8 TxChar) { while (true) { uint32 fifo_cnt = READ_PERI_REG(UART_STATUS(uart)) & (UART_TXFIFO_CNT << UART_TXFIFO_CNT_S); if ((fifo_cnt >> UART_TXFIFO_CNT_S & UART_TXFIFO_CNT) < 126) { break; } } WRITE_PERI_REG(UART_FIFO(uart) , TxChar); return OK; } LOCAL void uart1_write_char(char c) { if (c == '\n') { uart_tx_one_char(UART1, '\r'); uart_tx_one_char(UART1, '\n'); } else if (c == '\r') { } else { uart_tx_one_char(UART1, c); } } LOCAL void uart_rx_intr_handler_ssc(void) { /* uart0 and uart1 intr combine togther, when interrupt occur, see reg 0x3ff20020, bit2, bit0 represents * uart1 and uart0 respectively */ os_event_t e; portBASE_TYPE xHigherPriorityTaskWoken; uint8 RcvChar; uint8 uart_no = 0; if (UART_RXFIFO_FULL_INT_ST != (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_FULL_INT_ST)) { return; } RcvChar = READ_PERI_REG(UART_FIFO(uart_no)) & 0xFF; WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_RXFIFO_FULL_INT_CLR); e.event = UART_EVENT_RX_CHAR; e.param = RcvChar; xQueueSendFromISR(xQueueUart, (void *)&e, &xHigherPriorityTaskWoken); portEND_SWITCHING_ISR(xHigherPriorityTaskWoken); } LOCAL void ICACHE_FLASH_ATTR uart_config(uint8 uart_no, UartDevice *uart) { if (uart_no == UART1) { PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_U1TXD_BK); } else { /* rcv_buff size if 0x100 */ _xt_isr_attach(ETS_UART_INUM, uart_rx_intr_handler_ssc); PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U); PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD); } uart_div_modify(uart_no, UART_CLK_FREQ / (uart->baut_rate)); WRITE_PERI_REG(UART_CONF0(uart_no), uart->exist_parity | uart->parity | (uart->stop_bits << UART_STOP_BIT_NUM_S) | (uart->data_bits << UART_BIT_NUM_S)); //clear rx and tx fifo,not ready SET_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST); CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST); if (uart_no == UART0) { //set rx fifo trigger WRITE_PERI_REG(UART_CONF1(uart_no), ((0x01 & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S)); } else { WRITE_PERI_REG(UART_CONF1(uart_no), ((0x01 & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S)); } //clear all interrupt WRITE_PERI_REG(UART_INT_CLR(uart_no), 0xffff); //enable rx_interrupt SET_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_FULL_INT_ENA); } LOCAL void ICACHE_FLASH_ATTR uart_task(void *pvParameters) { os_event_t e; for (;;) { if (xQueueReceive(xQueueUart, (void *)&e, (portTickType)portMAX_DELAY)) { switch (e.event) { case UART_EVENT_RX_CHAR: printf("%c", e.param); break; default: break; } } } vTaskDelete(NULL); } void ICACHE_FLASH_ATTR uart_init(void) { while (READ_PERI_REG(UART_STATUS(0)) & (UART_TXFIFO_CNT << UART_TXFIFO_CNT_S)); while (READ_PERI_REG(UART_STATUS(1)) & (UART_TXFIFO_CNT << UART_TXFIFO_CNT_S)); UartDevice uart; uart.baut_rate = BIT_RATE_74880; uart.data_bits = EIGHT_BITS; uart.flow_ctrl = NONE_CTRL; uart.exist_parity = STICK_PARITY_DIS; uart.parity = NONE_BITS; uart.stop_bits = ONE_STOP_BIT; uart_config(UART0, &uart); uart_config(UART1, &uart); os_install_putc1(uart1_write_char); _xt_isr_unmask(1 << ETS_UART_INUM); xQueueUart = xQueueCreate(32, sizeof(os_event_t)); xTaskCreate(uart_task, (uint8 const *)"uTask", 512, NULL, tskIDLE_PRIORITY + 2, &xUartTaskHandle); }