-
-
Save shaielc/28a94b39dbd232974a6d78e384d44b0f to your computer and use it in GitHub Desktop.
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD | |
// | |
// Licensed under the Apache License, Version 2.0 (the "License"); | |
// you may not use this file except in compliance with the License. | |
// You may obtain a copy of the License at | |
// http://www.apache.org/licenses/LICENSE-2.0 | |
// | |
// Unless required by applicable law or agreed to in writing, software | |
// distributed under the License is distributed on an "AS IS" BASIS, | |
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
// See the License for the specific language governing permissions and | |
// limitations under the License. | |
#include "esp32-hal-uart.h" | |
#include "esp32-hal.h" | |
#include "freertos/FreeRTOS.h" | |
#include "freertos/task.h" | |
#include "freertos/queue.h" | |
#include "freertos/semphr.h" | |
#include "rom/ets_sys.h" | |
#include "esp_attr.h" | |
#include "esp_intr.h" | |
#include "rom/uart.h" | |
#include "soc/uart_reg.h" | |
#include "soc/uart_struct.h" | |
#include "soc/io_mux_reg.h" | |
#include "soc/gpio_sig_map.h" | |
#include "soc/dport_reg.h" | |
#include "esp_intr_alloc.h" | |
#define UART_REG_BASE(u) ((u==0)?DR_REG_UART_BASE:( (u==1)?DR_REG_UART1_BASE:( (u==2)?DR_REG_UART2_BASE:0))) | |
#define UART_RXD_IDX(u) ((u==0)?U0RXD_IN_IDX:( (u==1)?U1RXD_IN_IDX:( (u==2)?U2RXD_IN_IDX:0))) | |
#define UART_TXD_IDX(u) ((u==0)?U0TXD_OUT_IDX:( (u==1)?U1TXD_OUT_IDX:( (u==2)?U2TXD_OUT_IDX:0))) | |
#define UART_INTR_SOURCE(u) ((u==0)?ETS_UART0_INTR_SOURCE:( (u==1)?ETS_UART1_INTR_SOURCE:((u==2)?ETS_UART2_INTR_SOURCE:0))) | |
static int s_uart_debug_nr = 0; | |
struct uart_struct_t { | |
uart_dev_t * dev; | |
#if !CONFIG_DISABLE_HAL_LOCKS | |
xSemaphoreHandle lock; | |
#endif | |
uint8_t num; | |
xQueueHandle queue; | |
intr_handle_t intr_handle; | |
}; | |
#if CONFIG_DISABLE_HAL_LOCKS | |
#define UART_MUTEX_LOCK() | |
#define UART_MUTEX_UNLOCK() | |
static uart_t _uart_bus_array[3] = { | |
{(volatile uart_dev_t *)(DR_REG_UART_BASE), 0, NULL, NULL}, | |
{(volatile uart_dev_t *)(DR_REG_UART1_BASE), 1, NULL, NULL}, | |
{(volatile uart_dev_t *)(DR_REG_UART2_BASE), 2, NULL, NULL} | |
}; | |
#else | |
#define UART_MUTEX_LOCK() do {} while (xSemaphoreTake(uart->lock, portMAX_DELAY) != pdPASS) | |
#define UART_MUTEX_UNLOCK() xSemaphoreGive(uart->lock) | |
static uart_t _uart_bus_array[3] = { | |
{(volatile uart_dev_t *)(DR_REG_UART_BASE), NULL, 0, NULL, NULL}, | |
{(volatile uart_dev_t *)(DR_REG_UART1_BASE), NULL, 1, NULL, NULL}, | |
{(volatile uart_dev_t *)(DR_REG_UART2_BASE), NULL, 2, NULL, NULL} | |
}; | |
#endif | |
static void IRAM_ATTR _uart_isr(void *arg) | |
{ | |
uint8_t i, c; | |
BaseType_t xHigherPriorityTaskWoken; | |
uart_t* uart; | |
if(arg != NULL) | |
(*((void(**)())arg))(); | |
for(i=0;i<3;i++){ | |
uart = &_uart_bus_array[i]; | |
if(uart->intr_handle == NULL){ | |
continue; | |
} | |
uart->dev->int_clr.rxfifo_full = 1; | |
uart->dev->int_clr.frm_err = 1; | |
uart->dev->int_clr.rxfifo_tout = 1; | |
while(uart->dev->status.rxfifo_cnt) { | |
c = uart->dev->fifo.rw_byte; | |
if(uart->queue != NULL && !xQueueIsQueueFullFromISR(uart->queue)) { | |
xQueueSendFromISR(uart->queue, &c, &xHigherPriorityTaskWoken); | |
} | |
} | |
} | |
if (xHigherPriorityTaskWoken) { | |
portYIELD_FROM_ISR(); | |
} | |
} | |
void uartEnableInterrupt(uart_t* uart,void * func) | |
{ | |
UART_MUTEX_LOCK(); | |
uart->dev->conf1.rxfifo_full_thrhd = 112; | |
uart->dev->conf1.rx_tout_thrhd = 2; | |
uart->dev->conf1.rx_tout_en = 1; | |
uart->dev->int_ena.rxfifo_full = 1; | |
uart->dev->int_ena.frm_err = 1; | |
uart->dev->int_ena.rxfifo_tout = 1; | |
uart->dev->int_clr.val = 0xffffffff; | |
esp_intr_alloc(UART_INTR_SOURCE(uart->num), (int)ESP_INTR_FLAG_IRAM, _uart_isr, func, &uart->intr_handle); | |
UART_MUTEX_UNLOCK(); | |
} | |
void uartDisableInterrupt(uart_t* uart) | |
{ | |
UART_MUTEX_LOCK(); | |
uart->dev->conf1.val = 0; | |
uart->dev->int_ena.val = 0; | |
uart->dev->int_clr.val = 0xffffffff; | |
esp_intr_free(uart->intr_handle); | |
uart->intr_handle = NULL; | |
UART_MUTEX_UNLOCK(); | |
} | |
void uartDetachRx(uart_t* uart) | |
{ | |
if(uart == NULL) { | |
return; | |
} | |
pinMatrixInDetach(UART_RXD_IDX(uart->num), false, false); | |
uartDisableInterrupt(uart); | |
} | |
void uartDetachTx(uart_t* uart) | |
{ | |
if(uart == NULL) { | |
return; | |
} | |
pinMatrixOutDetach(UART_TXD_IDX(uart->num), false, false); | |
} | |
void uartAttachRx(uart_t* uart, uint8_t rxPin, bool inverted) | |
{ | |
if(uart == NULL || rxPin > 39) { | |
return; | |
} | |
pinMode(rxPin, INPUT); | |
pinMatrixInAttach(rxPin, UART_RXD_IDX(uart->num), inverted); | |
uartEnableInterrupt(uart,NULL); | |
} | |
void uartAttachTx(uart_t* uart, uint8_t txPin, bool inverted) | |
{ | |
if(uart == NULL || txPin > 39) { | |
return; | |
} | |
pinMode(txPin, OUTPUT); | |
pinMatrixOutAttach(txPin, UART_TXD_IDX(uart->num), inverted, false); | |
} | |
uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rxPin, int8_t txPin, uint16_t queueLen, bool inverted) | |
{ | |
if(uart_nr > 2) { | |
return NULL; | |
} | |
if(rxPin == -1 && txPin == -1) { | |
return NULL; | |
} | |
uart_t* uart = &_uart_bus_array[uart_nr]; | |
#if !CONFIG_DISABLE_HAL_LOCKS | |
if(uart->lock == NULL) { | |
uart->lock = xSemaphoreCreateMutex(); | |
if(uart->lock == NULL) { | |
return NULL; | |
} | |
} | |
#endif | |
if(queueLen && uart->queue == NULL) { | |
uart->queue = xQueueCreate(queueLen, sizeof(uint8_t)); //initialize the queue | |
if(uart->queue == NULL) { | |
return NULL; | |
} | |
} | |
if(uart_nr == 1){ | |
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UART1_CLK_EN); | |
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART1_RST); | |
} else if(uart_nr == 2){ | |
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UART2_CLK_EN); | |
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART2_RST); | |
} else { | |
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UART_CLK_EN); | |
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART_RST); | |
} | |
uartFlush(uart); | |
uartSetBaudRate(uart, baudrate); | |
UART_MUTEX_LOCK(); | |
uart->dev->conf0.val = config; | |
#define TWO_STOP_BITS_CONF 0x3 | |
#define ONE_STOP_BITS_CONF 0x1 | |
if ( uart->dev->conf0.stop_bit_num == TWO_STOP_BITS_CONF) { | |
uart->dev->conf0.stop_bit_num = ONE_STOP_BITS_CONF; | |
uart->dev->rs485_conf.dl1_en = 1; | |
} | |
UART_MUTEX_UNLOCK(); | |
if(rxPin != -1) { | |
uartAttachRx(uart, rxPin, inverted); | |
} | |
if(txPin != -1) { | |
uartAttachTx(uart, txPin, inverted); | |
} | |
return uart; | |
} | |
void uartEnd(uart_t* uart) | |
{ | |
if(uart == NULL) { | |
return; | |
} | |
UART_MUTEX_LOCK(); | |
if(uart->queue != NULL) { | |
uint8_t c; | |
while(xQueueReceive(uart->queue, &c, 0)); | |
vQueueDelete(uart->queue); | |
uart->queue = NULL; | |
} | |
uart->dev->conf0.val = 0; | |
UART_MUTEX_UNLOCK(); | |
uartDetachRx(uart); | |
uartDetachTx(uart); | |
} | |
uint32_t uartAvailable(uart_t* uart) | |
{ | |
if(uart == NULL || uart->queue == NULL) { | |
return 0; | |
} | |
return uxQueueMessagesWaiting(uart->queue); | |
} | |
uint8_t uartRead(uart_t* uart) | |
{ | |
if(uart == NULL || uart->queue == NULL) { | |
return 0; | |
} | |
uint8_t c; | |
if(xQueueReceive(uart->queue, &c, 0)) { | |
return c; | |
} | |
return 0; | |
} | |
uint8_t uartPeek(uart_t* uart) | |
{ | |
if(uart == NULL || uart->queue == NULL) { | |
return 0; | |
} | |
uint8_t c; | |
if(xQueuePeek(uart->queue, &c, 0)) { | |
return c; | |
} | |
return 0; | |
} | |
void uartWrite(uart_t* uart, uint8_t c) | |
{ | |
if(uart == NULL) { | |
return; | |
} | |
UART_MUTEX_LOCK(); | |
while(uart->dev->status.txfifo_cnt == 0x7F); | |
uart->dev->fifo.rw_byte = c; | |
UART_MUTEX_UNLOCK(); | |
} | |
void uartWriteBuf(uart_t* uart, const uint8_t * data, size_t len) | |
{ | |
if(uart == NULL) { | |
return; | |
} | |
UART_MUTEX_LOCK(); | |
while(len) { | |
while(len && uart->dev->status.txfifo_cnt < 0x7F) { | |
uart->dev->fifo.rw_byte = *data++; | |
len--; | |
} | |
} | |
UART_MUTEX_UNLOCK(); | |
} | |
void uartFlush(uart_t* uart) | |
{ | |
if(uart == NULL) { | |
return; | |
} | |
UART_MUTEX_LOCK(); | |
while(uart->dev->status.txfifo_cnt); | |
uart->dev->conf0.txfifo_rst = 1; | |
uart->dev->conf0.txfifo_rst = 0; | |
uart->dev->conf0.rxfifo_rst = 1; | |
uart->dev->conf0.rxfifo_rst = 0; | |
UART_MUTEX_UNLOCK(); | |
} | |
void uartSetBaudRate(uart_t* uart, uint32_t baud_rate) | |
{ | |
if(uart == NULL) { | |
return; | |
} | |
UART_MUTEX_LOCK(); | |
uint32_t clk_div = ((UART_CLK_FREQ<<4)/baud_rate); | |
uart->dev->clk_div.div_int = clk_div>>4 ; | |
uart->dev->clk_div.div_frag = clk_div & 0xf; | |
UART_MUTEX_UNLOCK(); | |
} | |
uint32_t uartGetBaudRate(uart_t* uart) | |
{ | |
if(uart == NULL) { | |
return 0; | |
} | |
uint32_t clk_div = (uart->dev->clk_div.div_int << 4) | (uart->dev->clk_div.div_frag & 0x0F); | |
return ((UART_CLK_FREQ<<4)/clk_div); | |
} | |
static void IRAM_ATTR uart0_write_char(char c) | |
{ | |
while(((ESP_REG(0x01C+DR_REG_UART_BASE) >> UART_TXFIFO_CNT_S) & 0x7F) == 0x7F); | |
ESP_REG(DR_REG_UART_BASE) = c; | |
} | |
static void IRAM_ATTR uart1_write_char(char c) | |
{ | |
while(((ESP_REG(0x01C+DR_REG_UART1_BASE) >> UART_TXFIFO_CNT_S) & 0x7F) == 0x7F); | |
ESP_REG(DR_REG_UART1_BASE) = c; | |
} | |
static void IRAM_ATTR uart2_write_char(char c) | |
{ | |
while(((ESP_REG(0x01C+DR_REG_UART2_BASE) >> UART_TXFIFO_CNT_S) & 0x7F) == 0x7F); | |
ESP_REG(DR_REG_UART2_BASE) = c; | |
} | |
void uartSetDebug(uart_t* uart) | |
{ | |
if(uart == NULL || uart->num > 2) { | |
s_uart_debug_nr = -1; | |
ets_install_putc1(NULL); | |
return; | |
} | |
if(s_uart_debug_nr == uart->num) { | |
return; | |
} | |
s_uart_debug_nr = uart->num; | |
switch(s_uart_debug_nr) { | |
case 0: | |
ets_install_putc1((void (*)(char)) &uart0_write_char); | |
break; | |
case 1: | |
ets_install_putc1((void (*)(char)) &uart1_write_char); | |
break; | |
case 2: | |
ets_install_putc1((void (*)(char)) &uart2_write_char); | |
break; | |
default: | |
ets_install_putc1(NULL); | |
break; | |
} | |
} | |
int uartGetDebug() | |
{ | |
return s_uart_debug_nr; | |
} | |
int log_printf(const char *format, ...) | |
{ | |
if(s_uart_debug_nr < 0){ | |
return 0; | |
} | |
static char loc_buf[64]; | |
char * temp = loc_buf; | |
int len; | |
va_list arg; | |
va_list copy; | |
va_start(arg, format); | |
va_copy(copy, arg); | |
len = vsnprintf(NULL, 0, format, arg); | |
va_end(copy); | |
if(len >= sizeof(loc_buf)){ | |
temp = (char*)malloc(len+1); | |
if(temp == NULL) { | |
return 0; | |
} | |
} | |
vsnprintf(temp, len+1, format, arg); | |
#if !CONFIG_DISABLE_HAL_LOCKS | |
if(_uart_bus_array[s_uart_debug_nr].lock){ | |
while (xSemaphoreTake(_uart_bus_array[s_uart_debug_nr].lock, portMAX_DELAY) != pdPASS); | |
ets_printf("%s", temp); | |
xSemaphoreGive(_uart_bus_array[s_uart_debug_nr].lock); | |
} else { | |
ets_printf("%s", temp); | |
} | |
#else | |
ets_printf("%s", temp); | |
#endif | |
va_end(arg); | |
if(len > 64){ | |
free(temp); | |
} | |
return len; | |
} |
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD | |
// | |
// Licensed under the Apache License, Version 2.0 (the "License"); | |
// you may not use this file except in compliance with the License. | |
// You may obtain a copy of the License at | |
// http://www.apache.org/licenses/LICENSE-2.0 | |
// | |
// Unless required by applicable law or agreed to in writing, software | |
// distributed under the License is distributed on an "AS IS" BASIS, | |
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
// See the License for the specific language governing permissions and | |
// limitations under the License. | |
#ifndef MAIN_ESP32_HAL_UART_H_ | |
#define MAIN_ESP32_HAL_UART_H_ | |
#ifdef __cplusplus | |
extern "C" { | |
#endif | |
#include <stdint.h> | |
#include <stdbool.h> | |
#include <stdlib.h> | |
#define SERIAL_5N1 0x8000010 | |
#define SERIAL_6N1 0x8000014 | |
#define SERIAL_7N1 0x8000018 | |
#define SERIAL_8N1 0x800001c | |
#define SERIAL_5N2 0x8000030 | |
#define SERIAL_6N2 0x8000034 | |
#define SERIAL_7N2 0x8000038 | |
#define SERIAL_8N2 0x800003c | |
#define SERIAL_5E1 0x8000012 | |
#define SERIAL_6E1 0x8000016 | |
#define SERIAL_7E1 0x800001a | |
#define SERIAL_8E1 0x800001e | |
#define SERIAL_5E2 0x8000032 | |
#define SERIAL_6E2 0x8000036 | |
#define SERIAL_7E2 0x800003a | |
#define SERIAL_8E2 0x800003e | |
#define SERIAL_5O1 0x8000013 | |
#define SERIAL_6O1 0x8000017 | |
#define SERIAL_7O1 0x800001b | |
#define SERIAL_8O1 0x800001f | |
#define SERIAL_5O2 0x8000033 | |
#define SERIAL_6O2 0x8000037 | |
#define SERIAL_7O2 0x800003b | |
#define SERIAL_8O2 0x800003f | |
struct uart_struct_t; | |
typedef struct uart_struct_t uart_t; | |
uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rxPin, int8_t txPin, uint16_t queueLen, bool inverted); | |
void uartEnd(uart_t* uart); | |
uint32_t uartAvailable(uart_t* uart); | |
uint8_t uartRead(uart_t* uart); | |
uint8_t uartPeek(uart_t* uart); | |
void uartWrite(uart_t* uart, uint8_t c); | |
void uartWriteBuf(uart_t* uart, const uint8_t * data, size_t len); | |
void uartFlush(uart_t* uart); | |
void uartSetBaudRate(uart_t* uart, uint32_t baud_rate); | |
uint32_t uartGetBaudRate(uart_t* uart); | |
void uartSetDebug(uart_t* uart); | |
int uartGetDebug(); | |
#ifdef __cplusplus | |
} | |
#endif | |
void uartDisableInterrupt(uart_t* uart); | |
void uartEnableInterrupt(uart_t* uart,void * func ); | |
#endif /* MAIN_ESP32_HAL_UART_H_ */ |
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD | |
// | |
// Licensed under the Apache License, Version 2.0 (the "License"); | |
// you may not use this file except in compliance with the License. | |
// You may obtain a copy of the License at | |
// http://www.apache.org/licenses/LICENSE-2.0 | |
// | |
// Unless required by applicable law or agreed to in writing, software | |
// distributed under the License is distributed on an "AS IS" BASIS, | |
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
// See the License for the specific language governing permissions and | |
// limitations under the License. | |
#include "esp32-hal-uart.h" | |
#include "esp32-hal.h" | |
#include "freertos/FreeRTOS.h" | |
#include "freertos/task.h" | |
#include "freertos/queue.h" | |
#include "freertos/semphr.h" | |
#include "rom/ets_sys.h" | |
#include "esp_attr.h" | |
#include "esp_intr.h" | |
#include "rom/uart.h" | |
#include "soc/uart_reg.h" | |
#include "soc/uart_struct.h" | |
#include "soc/io_mux_reg.h" | |
#include "soc/gpio_sig_map.h" | |
#include "soc/dport_reg.h" | |
#include "esp_intr_alloc.h" | |
#define UART_REG_BASE(u) ((u==0)?DR_REG_UART_BASE:( (u==1)?DR_REG_UART1_BASE:( (u==2)?DR_REG_UART2_BASE:0))) | |
#define UART_RXD_IDX(u) ((u==0)?U0RXD_IN_IDX:( (u==1)?U1RXD_IN_IDX:( (u==2)?U2RXD_IN_IDX:0))) | |
#define UART_TXD_IDX(u) ((u==0)?U0TXD_OUT_IDX:( (u==1)?U1TXD_OUT_IDX:( (u==2)?U2TXD_OUT_IDX:0))) | |
#define UART_INTR_SOURCE(u) ((u==0)?ETS_UART0_INTR_SOURCE:( (u==1)?ETS_UART1_INTR_SOURCE:((u==2)?ETS_UART2_INTR_SOURCE:0))) | |
static int s_uart_debug_nr = 0; | |
struct uart_struct_t { | |
uart_dev_t * dev; | |
#if !CONFIG_DISABLE_HAL_LOCKS | |
xSemaphoreHandle lock; | |
#endif | |
uint8_t num; | |
xQueueHandle queue; | |
intr_handle_t intr_handle; | |
}; | |
#if CONFIG_DISABLE_HAL_LOCKS | |
#define UART_MUTEX_LOCK() | |
#define UART_MUTEX_UNLOCK() | |
static uart_t _uart_bus_array[3] = { | |
{(volatile uart_dev_t *)(DR_REG_UART_BASE), 0, NULL, NULL}, | |
{(volatile uart_dev_t *)(DR_REG_UART1_BASE), 1, NULL, NULL}, | |
{(volatile uart_dev_t *)(DR_REG_UART2_BASE), 2, NULL, NULL} | |
}; | |
#else | |
#define UART_MUTEX_LOCK() do {} while (xSemaphoreTake(uart->lock, portMAX_DELAY) != pdPASS) | |
#define UART_MUTEX_UNLOCK() xSemaphoreGive(uart->lock) | |
static uart_t _uart_bus_array[3] = { | |
{(volatile uart_dev_t *)(DR_REG_UART_BASE), NULL, 0, NULL, NULL}, | |
{(volatile uart_dev_t *)(DR_REG_UART1_BASE), NULL, 1, NULL, NULL}, | |
{(volatile uart_dev_t *)(DR_REG_UART2_BASE), NULL, 2, NULL, NULL} | |
}; | |
#endif | |
static void IRAM_ATTR _uart_isr(void *arg) | |
{ | |
uint8_t i, c; | |
BaseType_t xHigherPriorityTaskWoken; | |
uart_t* uart; | |
if(arg != NULL) | |
(*((void(**)())arg))(); | |
for(i=0;i<3;i++){ | |
uart = &_uart_bus_array[i]; | |
if(uart->intr_handle == NULL){ | |
continue; | |
} | |
uart->dev->int_clr.rxfifo_full = 1; | |
uart->dev->int_clr.frm_err = 1; | |
uart->dev->int_clr.rxfifo_tout = 1; | |
while(uart->dev->status.rxfifo_cnt) { | |
c = uart->dev->fifo.rw_byte; | |
if(uart->queue != NULL && !xQueueIsQueueFullFromISR(uart->queue)) { | |
xQueueSendFromISR(uart->queue, &c, &xHigherPriorityTaskWoken); | |
} | |
} | |
} | |
if (xHigherPriorityTaskWoken) { | |
portYIELD_FROM_ISR(); | |
} | |
} | |
void uartEnableInterrupt(uart_t* uart,void * func) | |
{ | |
UART_MUTEX_LOCK(); | |
uart->dev->conf1.rxfifo_full_thrhd = 112; | |
uart->dev->conf1.rx_tout_thrhd = 2; | |
uart->dev->conf1.rx_tout_en = 1; | |
uart->dev->int_ena.rxfifo_full = 1; | |
uart->dev->int_ena.frm_err = 1; | |
uart->dev->int_ena.rxfifo_tout = 1; | |
uart->dev->int_clr.val = 0xffffffff; | |
esp_intr_alloc(UART_INTR_SOURCE(uart->num), (int)ESP_INTR_FLAG_IRAM, _uart_isr, func, &uart->intr_handle); | |
UART_MUTEX_UNLOCK(); | |
} | |
void uartDisableInterrupt(uart_t* uart) | |
{ | |
UART_MUTEX_LOCK(); | |
uart->dev->conf1.val = 0; | |
uart->dev->int_ena.val = 0; | |
uart->dev->int_clr.val = 0xffffffff; | |
esp_intr_free(uart->intr_handle); | |
uart->intr_handle = NULL; | |
UART_MUTEX_UNLOCK(); | |
} | |
void uartDetachRx(uart_t* uart) | |
{ | |
if(uart == NULL) { | |
return; | |
} | |
pinMatrixInDetach(UART_RXD_IDX(uart->num), false, false); | |
uartDisableInterrupt(uart); | |
} | |
void uartDetachTx(uart_t* uart) | |
{ | |
if(uart == NULL) { | |
return; | |
} | |
pinMatrixOutDetach(UART_TXD_IDX(uart->num), false, false); | |
} | |
void uartAttachRx(uart_t* uart, uint8_t rxPin, bool inverted) | |
{ | |
if(uart == NULL || rxPin > 39) { | |
return; | |
} | |
pinMode(rxPin, INPUT); | |
pinMatrixInAttach(rxPin, UART_RXD_IDX(uart->num), inverted); | |
uartEnableInterrupt(uart,NULL); | |
} | |
void uartAttachTx(uart_t* uart, uint8_t txPin, bool inverted) | |
{ | |
if(uart == NULL || txPin > 39) { | |
return; | |
} | |
pinMode(txPin, OUTPUT); | |
pinMatrixOutAttach(txPin, UART_TXD_IDX(uart->num), inverted, false); | |
} | |
uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rxPin, int8_t txPin, uint16_t queueLen, bool inverted) | |
{ | |
if(uart_nr > 2) { | |
return NULL; | |
} | |
if(rxPin == -1 && txPin == -1) { | |
return NULL; | |
} | |
uart_t* uart = &_uart_bus_array[uart_nr]; | |
#if !CONFIG_DISABLE_HAL_LOCKS | |
if(uart->lock == NULL) { | |
uart->lock = xSemaphoreCreateMutex(); | |
if(uart->lock == NULL) { | |
return NULL; | |
} | |
} | |
#endif | |
if(queueLen && uart->queue == NULL) { | |
uart->queue = xQueueCreate(queueLen, sizeof(uint8_t)); //initialize the queue | |
if(uart->queue == NULL) { | |
return NULL; | |
} | |
} | |
if(uart_nr == 1){ | |
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UART1_CLK_EN); | |
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART1_RST); | |
} else if(uart_nr == 2){ | |
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UART2_CLK_EN); | |
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART2_RST); | |
} else { | |
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UART_CLK_EN); | |
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART_RST); | |
} | |
uartFlush(uart); | |
uartSetBaudRate(uart, baudrate); | |
UART_MUTEX_LOCK(); | |
uart->dev->conf0.val = config; | |
#define TWO_STOP_BITS_CONF 0x3 | |
#define ONE_STOP_BITS_CONF 0x1 | |
if ( uart->dev->conf0.stop_bit_num == TWO_STOP_BITS_CONF) { | |
uart->dev->conf0.stop_bit_num = ONE_STOP_BITS_CONF; | |
uart->dev->rs485_conf.dl1_en = 1; | |
} | |
UART_MUTEX_UNLOCK(); | |
if(rxPin != -1) { | |
uartAttachRx(uart, rxPin, inverted); | |
} | |
if(txPin != -1) { | |
uartAttachTx(uart, txPin, inverted); | |
} | |
return uart; | |
} | |
void uartEnd(uart_t* uart) | |
{ | |
if(uart == NULL) { | |
return; | |
} | |
UART_MUTEX_LOCK(); | |
if(uart->queue != NULL) { | |
uint8_t c; | |
while(xQueueReceive(uart->queue, &c, 0)); | |
vQueueDelete(uart->queue); | |
uart->queue = NULL; | |
} | |
uart->dev->conf0.val = 0; | |
UART_MUTEX_UNLOCK(); | |
uartDetachRx(uart); | |
uartDetachTx(uart); | |
} | |
uint32_t uartAvailable(uart_t* uart) | |
{ | |
if(uart == NULL || uart->queue == NULL) { | |
return 0; | |
} | |
return uxQueueMessagesWaiting(uart->queue); | |
} | |
uint8_t uartRead(uart_t* uart) | |
{ | |
if(uart == NULL || uart->queue == NULL) { | |
return 0; | |
} | |
uint8_t c; | |
if(xQueueReceive(uart->queue, &c, 0)) { | |
return c; | |
} | |
return 0; | |
} | |
uint8_t uartPeek(uart_t* uart) | |
{ | |
if(uart == NULL || uart->queue == NULL) { | |
return 0; | |
} | |
uint8_t c; | |
if(xQueuePeek(uart->queue, &c, 0)) { | |
return c; | |
} | |
return 0; | |
} | |
void uartWrite(uart_t* uart, uint8_t c) | |
{ | |
if(uart == NULL) { | |
return; | |
} | |
UART_MUTEX_LOCK(); | |
while(uart->dev->status.txfifo_cnt == 0x7F); | |
uart->dev->fifo.rw_byte = c; | |
UART_MUTEX_UNLOCK(); | |
} | |
void uartWriteBuf(uart_t* uart, const uint8_t * data, size_t len) | |
{ | |
if(uart == NULL) { | |
return; | |
} | |
UART_MUTEX_LOCK(); | |
while(len) { | |
while(len && uart->dev->status.txfifo_cnt < 0x7F) { | |
uart->dev->fifo.rw_byte = *data++; | |
len--; | |
} | |
} | |
UART_MUTEX_UNLOCK(); | |
} | |
void uartFlush(uart_t* uart) | |
{ | |
if(uart == NULL) { | |
return; | |
} | |
UART_MUTEX_LOCK(); | |
while(uart->dev->status.txfifo_cnt); | |
uart->dev->conf0.txfifo_rst = 1; | |
uart->dev->conf0.txfifo_rst = 0; | |
uart->dev->conf0.rxfifo_rst = 1; | |
uart->dev->conf0.rxfifo_rst = 0; | |
UART_MUTEX_UNLOCK(); | |
} | |
void uartSetBaudRate(uart_t* uart, uint32_t baud_rate) | |
{ | |
if(uart == NULL) { | |
return; | |
} | |
UART_MUTEX_LOCK(); | |
uint32_t clk_div = ((UART_CLK_FREQ<<4)/baud_rate); | |
uart->dev->clk_div.div_int = clk_div>>4 ; | |
uart->dev->clk_div.div_frag = clk_div & 0xf; | |
UART_MUTEX_UNLOCK(); | |
} | |
uint32_t uartGetBaudRate(uart_t* uart) | |
{ | |
if(uart == NULL) { | |
return 0; | |
} | |
uint32_t clk_div = (uart->dev->clk_div.div_int << 4) | (uart->dev->clk_div.div_frag & 0x0F); | |
return ((UART_CLK_FREQ<<4)/clk_div); | |
} | |
static void IRAM_ATTR uart0_write_char(char c) | |
{ | |
while(((ESP_REG(0x01C+DR_REG_UART_BASE) >> UART_TXFIFO_CNT_S) & 0x7F) == 0x7F); | |
ESP_REG(DR_REG_UART_BASE) = c; | |
} | |
static void IRAM_ATTR uart1_write_char(char c) | |
{ | |
while(((ESP_REG(0x01C+DR_REG_UART1_BASE) >> UART_TXFIFO_CNT_S) & 0x7F) == 0x7F); | |
ESP_REG(DR_REG_UART1_BASE) = c; | |
} | |
static void IRAM_ATTR uart2_write_char(char c) | |
{ | |
while(((ESP_REG(0x01C+DR_REG_UART2_BASE) >> UART_TXFIFO_CNT_S) & 0x7F) == 0x7F); | |
ESP_REG(DR_REG_UART2_BASE) = c; | |
} | |
void uartSetDebug(uart_t* uart) | |
{ | |
if(uart == NULL || uart->num > 2) { | |
s_uart_debug_nr = -1; | |
ets_install_putc1(NULL); | |
return; | |
} | |
if(s_uart_debug_nr == uart->num) { | |
return; | |
} | |
s_uart_debug_nr = uart->num; | |
switch(s_uart_debug_nr) { | |
case 0: | |
ets_install_putc1((void (*)(char)) &uart0_write_char); | |
break; | |
case 1: | |
ets_install_putc1((void (*)(char)) &uart1_write_char); | |
break; | |
case 2: | |
ets_install_putc1((void (*)(char)) &uart2_write_char); | |
break; | |
default: | |
ets_install_putc1(NULL); | |
break; | |
} | |
} | |
int uartGetDebug() | |
{ | |
return s_uart_debug_nr; | |
} | |
int log_printf(const char *format, ...) | |
{ | |
if(s_uart_debug_nr < 0){ | |
return 0; | |
} | |
static char loc_buf[64]; | |
char * temp = loc_buf; | |
int len; | |
va_list arg; | |
va_list copy; | |
va_start(arg, format); | |
va_copy(copy, arg); | |
len = vsnprintf(NULL, 0, format, arg); | |
va_end(copy); | |
if(len >= sizeof(loc_buf)){ | |
temp = (char*)malloc(len+1); | |
if(temp == NULL) { | |
return 0; | |
} | |
} | |
vsnprintf(temp, len+1, format, arg); | |
#if !CONFIG_DISABLE_HAL_LOCKS | |
if(_uart_bus_array[s_uart_debug_nr].lock){ | |
while (xSemaphoreTake(_uart_bus_array[s_uart_debug_nr].lock, portMAX_DELAY) != pdPASS); | |
ets_printf("%s", temp); | |
xSemaphoreGive(_uart_bus_array[s_uart_debug_nr].lock); | |
} else { | |
ets_printf("%s", temp); | |
} | |
#else | |
ets_printf("%s", temp); | |
#endif | |
va_end(arg); | |
if(len > 64){ | |
free(temp); | |
} | |
return len; | |
} | |
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD | |
// | |
// Licensed under the Apache License, Version 2.0 (the "License"); | |
// you may not use this file except in compliance with the License. | |
// You may obtain a copy of the License at | |
// http://www.apache.org/licenses/LICENSE-2.0 | |
// | |
// Unless required by applicable law or agreed to in writing, software | |
// distributed under the License is distributed on an "AS IS" BASIS, | |
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
// See the License for the specific language governing permissions and | |
// limitations under the License. | |
#ifndef MAIN_ESP32_HAL_UART_H_ | |
#define MAIN_ESP32_HAL_UART_H_ | |
#ifdef __cplusplus | |
extern "C" { | |
#endif | |
#include <stdint.h> | |
#include <stdbool.h> | |
#include <stdlib.h> | |
#define SERIAL_5N1 0x8000010 | |
#define SERIAL_6N1 0x8000014 | |
#define SERIAL_7N1 0x8000018 | |
#define SERIAL_8N1 0x800001c | |
#define SERIAL_5N2 0x8000030 | |
#define SERIAL_6N2 0x8000034 | |
#define SERIAL_7N2 0x8000038 | |
#define SERIAL_8N2 0x800003c | |
#define SERIAL_5E1 0x8000012 | |
#define SERIAL_6E1 0x8000016 | |
#define SERIAL_7E1 0x800001a | |
#define SERIAL_8E1 0x800001e | |
#define SERIAL_5E2 0x8000032 | |
#define SERIAL_6E2 0x8000036 | |
#define SERIAL_7E2 0x800003a | |
#define SERIAL_8E2 0x800003e | |
#define SERIAL_5O1 0x8000013 | |
#define SERIAL_6O1 0x8000017 | |
#define SERIAL_7O1 0x800001b | |
#define SERIAL_8O1 0x800001f | |
#define SERIAL_5O2 0x8000033 | |
#define SERIAL_6O2 0x8000037 | |
#define SERIAL_7O2 0x800003b | |
#define SERIAL_8O2 0x800003f | |
struct uart_struct_t; | |
typedef struct uart_struct_t uart_t; | |
uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rxPin, int8_t txPin, uint16_t queueLen, bool inverted); | |
void uartEnd(uart_t* uart); | |
uint32_t uartAvailable(uart_t* uart); | |
uint8_t uartRead(uart_t* uart); | |
uint8_t uartPeek(uart_t* uart); | |
void uartWrite(uart_t* uart, uint8_t c); | |
void uartWriteBuf(uart_t* uart, const uint8_t * data, size_t len); | |
void uartFlush(uart_t* uart); | |
void uartSetBaudRate(uart_t* uart, uint32_t baud_rate); | |
uint32_t uartGetBaudRate(uart_t* uart); | |
void uartSetDebug(uart_t* uart); | |
int uartGetDebug(); | |
#ifdef __cplusplus | |
} | |
#endif | |
void uartDisableInterrupt(uart_t* uart); | |
void uartEnableInterrupt(uart_t* uart,void * func ); | |
#endif /* MAIN_ESP32_HAL_UART_H_ */ | |
#include <stdlib.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include <inttypes.h> | |
#include "HardwareSerial.h" | |
HardwareSerial Serial(0); | |
HardwareSerial::HardwareSerial(int uart_nr) : _uart_nr(uart_nr), _uart(NULL) {} | |
void HardwareSerial::setInterrupt(void(*arg)() ) | |
{ | |
uartDisableInterrupt(_uart); | |
intr = arg; | |
uartEnableInterrupt(_uart,&intr); | |
} | |
void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, int8_t txPin, bool invert) | |
{ | |
if(0 > _uart_nr || _uart_nr > 2) { | |
log_e("Serial number is invalid, please use 0, 1 or 2"); | |
return; | |
} | |
if(_uart) { | |
end(); | |
} | |
if(_uart_nr == 0 && rxPin < 0 && txPin < 0) { | |
rxPin = 3; | |
txPin = 1; | |
} | |
if(_uart_nr == 1 && rxPin < 0 && txPin < 0) { | |
rxPin = 9; | |
txPin = 10; | |
} | |
if(_uart_nr == 2 && rxPin < 0 && txPin < 0) { | |
rxPin = 16; | |
txPin = 17; | |
} | |
_uart = uartBegin(_uart_nr, baud, config, rxPin, txPin, 256, invert); | |
} | |
void HardwareSerial::end() | |
{ | |
if(uartGetDebug() == _uart_nr) { | |
uartSetDebug(0); | |
} | |
uartEnd(_uart); | |
_uart = 0; | |
} | |
void HardwareSerial::setDebugOutput(bool en) | |
{ | |
if(_uart == 0) { | |
return; | |
} | |
if(en) { | |
uartSetDebug(_uart); | |
} else { | |
if(uartGetDebug() == _uart_nr) { | |
uartSetDebug(0); | |
} | |
} | |
} | |
int HardwareSerial::available(void) | |
{ | |
return uartAvailable(_uart); | |
} | |
int HardwareSerial::peek(void) | |
{ | |
if (available()) { | |
return uartPeek(_uart); | |
} | |
return -1; | |
} | |
int HardwareSerial::read(void) | |
{ | |
if(available()) { | |
return uartRead(_uart); | |
} | |
return -1; | |
} | |
void HardwareSerial::flush() | |
{ | |
uartFlush(_uart); | |
} | |
size_t HardwareSerial::write(uint8_t c) | |
{ | |
uartWrite(_uart, c); | |
return 1; | |
} | |
size_t HardwareSerial::write(const uint8_t *buffer, size_t size) | |
{ | |
uartWriteBuf(_uart, buffer, size); | |
return size; | |
} | |
uint32_t HardwareSerial::baudRate() | |
{ | |
return uartGetBaudRate(_uart); | |
} | |
HardwareSerial::operator bool() const | |
{ | |
return true; | |
} | |
/* | |
HardwareSerial.h - Hardware serial library for Wiring | |
Copyright (c) 2006 Nicholas Zambetti. All right reserved. | |
This library is free software; you can redistribute it and/or | |
modify it under the terms of the GNU Lesser General Public | |
License as published by the Free Software Foundation; either | |
version 2.1 of the License, or (at your option) any later version. | |
This library is distributed in the hope that it will be useful, | |
but WITHOUT ANY WARRANTY; without even the implied warranty of | |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
Lesser General Public License for more details. | |
You should have received a copy of the GNU Lesser General Public | |
License along with this library; if not, write to the Free Software | |
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
Modified 28 September 2010 by Mark Sproul | |
Modified 14 August 2012 by Alarus | |
Modified 3 December 2013 by Matthijs Kooijman | |
Modified 18 December 2014 by Ivan Grokhotkov (esp8266 platform support) | |
Modified 31 March 2015 by Markus Sattler (rewrite the code for UART0 + UART1 support in ESP8266) | |
Modified 25 April 2015 by Thomas Flayols (add configuration different from 8N1 in ESP8266) | |
*/ | |
#ifndef HardwareSerial_h | |
#define HardwareSerial_h | |
#include <inttypes.h> | |
#include "Stream.h" | |
#include "esp32-hal.h" | |
class HardwareSerial: public Stream | |
{ | |
public: | |
HardwareSerial(int uart_nr); | |
void setInterrupt(void (*arg)() ); | |
void begin(unsigned long baud, uint32_t config=SERIAL_8N1, int8_t rxPin=-1, int8_t txPin=-1, bool invert=false); | |
void end(); | |
int available(void); | |
int peek(void); | |
int read(void); | |
void flush(void); | |
size_t write(uint8_t); | |
size_t write(const uint8_t *buffer, size_t size); | |
inline size_t write(const char * s) | |
{ | |
return write((uint8_t*) s, strlen(s)); | |
} | |
inline size_t write(unsigned long n) | |
{ | |
return write((uint8_t) n); | |
} | |
inline size_t write(long n) | |
{ | |
return write((uint8_t) n); | |
} | |
inline size_t write(unsigned int n) | |
{ | |
return write((uint8_t) n); | |
} | |
inline size_t write(int n) | |
{ | |
return write((uint8_t) n); | |
} | |
uint32_t baudRate(); | |
operator bool() const; | |
void setDebugOutput(bool); | |
protected: | |
void (*intr)() ; | |
int _uart_nr; | |
uart_t* _uart; | |
}; | |
extern HardwareSerial Serial; | |
#endif |
#include <stdlib.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include <inttypes.h> | |
#include "HardwareSerial.h" | |
HardwareSerial Serial(0); | |
HardwareSerial::HardwareSerial(int uart_nr) : _uart_nr(uart_nr), _uart(NULL) {} | |
void HardwareSerial::setInterrupt(void(*arg)() ) | |
{ | |
uartDisableInterrupt(_uart); | |
intr = arg; | |
uartEnableInterrupt(_uart,&intr); | |
} | |
void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, int8_t txPin, bool invert) | |
{ | |
if(0 > _uart_nr || _uart_nr > 2) { | |
log_e("Serial number is invalid, please use 0, 1 or 2"); | |
return; | |
} | |
if(_uart) { | |
end(); | |
} | |
if(_uart_nr == 0 && rxPin < 0 && txPin < 0) { | |
rxPin = 3; | |
txPin = 1; | |
} | |
if(_uart_nr == 1 && rxPin < 0 && txPin < 0) { | |
rxPin = 9; | |
txPin = 10; | |
} | |
if(_uart_nr == 2 && rxPin < 0 && txPin < 0) { | |
rxPin = 16; | |
txPin = 17; | |
} | |
_uart = uartBegin(_uart_nr, baud, config, rxPin, txPin, 256, invert); | |
} | |
void HardwareSerial::end() | |
{ | |
if(uartGetDebug() == _uart_nr) { | |
uartSetDebug(0); | |
} | |
uartEnd(_uart); | |
_uart = 0; | |
} | |
void HardwareSerial::setDebugOutput(bool en) | |
{ | |
if(_uart == 0) { | |
return; | |
} | |
if(en) { | |
uartSetDebug(_uart); | |
} else { | |
if(uartGetDebug() == _uart_nr) { | |
uartSetDebug(0); | |
} | |
} | |
} | |
int HardwareSerial::available(void) | |
{ | |
return uartAvailable(_uart); | |
} | |
int HardwareSerial::peek(void) | |
{ | |
if (available()) { | |
return uartPeek(_uart); | |
} | |
return -1; | |
} | |
int HardwareSerial::read(void) | |
{ | |
if(available()) { | |
return uartRead(_uart); | |
} | |
return -1; | |
} | |
void HardwareSerial::flush() | |
{ | |
uartFlush(_uart); | |
} | |
size_t HardwareSerial::write(uint8_t c) | |
{ | |
uartWrite(_uart, c); | |
return 1; | |
} | |
size_t HardwareSerial::write(const uint8_t *buffer, size_t size) | |
{ | |
uartWriteBuf(_uart, buffer, size); | |
return size; | |
} | |
uint32_t HardwareSerial::baudRate() | |
{ | |
return uartGetBaudRate(_uart); | |
} | |
HardwareSerial::operator bool() const | |
{ | |
return true; | |
} |
/* | |
HardwareSerial.h - Hardware serial library for Wiring | |
Copyright (c) 2006 Nicholas Zambetti. All right reserved. | |
This library is free software; you can redistribute it and/or | |
modify it under the terms of the GNU Lesser General Public | |
License as published by the Free Software Foundation; either | |
version 2.1 of the License, or (at your option) any later version. | |
This library is distributed in the hope that it will be useful, | |
but WITHOUT ANY WARRANTY; without even the implied warranty of | |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
Lesser General Public License for more details. | |
You should have received a copy of the GNU Lesser General Public | |
License along with this library; if not, write to the Free Software | |
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
Modified 28 September 2010 by Mark Sproul | |
Modified 14 August 2012 by Alarus | |
Modified 3 December 2013 by Matthijs Kooijman | |
Modified 18 December 2014 by Ivan Grokhotkov (esp8266 platform support) | |
Modified 31 March 2015 by Markus Sattler (rewrite the code for UART0 + UART1 support in ESP8266) | |
Modified 25 April 2015 by Thomas Flayols (add configuration different from 8N1 in ESP8266) | |
*/ | |
#ifndef HardwareSerial_h | |
#define HardwareSerial_h | |
#include <inttypes.h> | |
#include "Stream.h" | |
#include "esp32-hal.h" | |
class HardwareSerial: public Stream | |
{ | |
public: | |
HardwareSerial(int uart_nr); | |
void setInterrupt(void (*arg)() ); | |
void begin(unsigned long baud, uint32_t config=SERIAL_8N1, int8_t rxPin=-1, int8_t txPin=-1, bool invert=false); | |
void end(); | |
int available(void); | |
int peek(void); | |
int read(void); | |
void flush(void); | |
size_t write(uint8_t); | |
size_t write(const uint8_t *buffer, size_t size); | |
inline size_t write(const char * s) | |
{ | |
return write((uint8_t*) s, strlen(s)); | |
} | |
inline size_t write(unsigned long n) | |
{ | |
return write((uint8_t) n); | |
} | |
inline size_t write(long n) | |
{ | |
return write((uint8_t) n); | |
} | |
inline size_t write(unsigned int n) | |
{ | |
return write((uint8_t) n); | |
} | |
inline size_t write(int n) | |
{ | |
return write((uint8_t) n); | |
} | |
uint32_t baudRate(); | |
operator bool() const; | |
void setDebugOutput(bool); | |
protected: | |
void (*intr)() ; | |
int _uart_nr; | |
uart_t* _uart; | |
}; | |
extern HardwareSerial Serial; | |
#endif |
void IRAM_ATTR serialEvent(){ | |
while(Serial.available()) | |
Serial.print((char)Serial.read()); | |
if(!Serial.available()) | |
Serial.print('1'); | |
} | |
void setup() { | |
// put your setup code here, to run once: | |
Serial.begin(115200); | |
Serial.print("test"); | |
Serial.setInterrupt(&serialEvent); | |
} | |
String x = ""; | |
void loop() { | |
// put your main code here, to run repeatedly: | |
//serialEvent(); | |
} |
I tested this Patches and Works very well...
This is a resume of patch:
esp32-hal-uart.h
change function to allow one second parameter
void uartEnableInterrupt(uart_t* uart,void * func );
.
.
.
.
#ifdef __cplusplus
}
#endif
void uartDisableInterrupt(uart_t* uart);
void uartEnableInterrupt(uart_t* uart,void * func );
#endif /* MAIN_ESP32_HAL_UART_H_ */
esp32-hal-uart.h
changes on function _uart_isr
and
uartEnableInterrupt(uart_t* uart,void * func );
static void IRAM_ATTR _uart_isr(void arg)
{
uint8_t i, c;
BaseType_t xHigherPriorityTaskWoken;
uart_t uart;
if(arg != NULL) {
(*((void(**)())arg))();
}
for(i=0;i<3;i++){
uart = &_uart_bus_array[i];
if(uart->intr_handle == NULL){
continue;
}
uart->dev->int_clr.rxfifo_full = 1;
uart->dev->int_clr.frm_err = 1;
uart->dev->int_clr.rxfifo_tout = 1;
while(uart->dev->status.rxfifo_cnt || (uart->dev->mem_rx_status.wr_addr != uart->dev->mem_rx_status.rd_addr)) {
c = uart->dev->fifo.rw_byte;
if(uart->queue != NULL && !xQueueIsQueueFullFromISR(uart->queue)) {
xQueueSendFromISR(uart->queue, &c, &xHigherPriorityTaskWoken);
}
}
}
if (xHigherPriorityTaskWoken) {
portYIELD_FROM_ISR();
}
}
void uartEnableInterrupt(uart_t* uart,void * func)
{
UART_MUTEX_LOCK();
uart->dev->conf1.rxfifo_full_thrhd = 112;
uart->dev->conf1.rx_tout_thrhd = 2;
uart->dev->conf1.rx_tout_en = 1;
uart->dev->int_ena.rxfifo_full = 1;
uart->dev->int_ena.frm_err = 1;
uart->dev->int_ena.rxfifo_tout = 1;
uart->dev->int_clr.val = 0xffffffff;
esp_intr_alloc(UART_INTR_SOURCE(uart->num), (int)ESP_INTR_FLAG_IRAM, _uart_isr, func, &uart->intr_handle);
UART_MUTEX_UNLOCK();
}
HardwareSerial.h
add public function
void setInterrupt(void (*arg)() );
and
protected
void (*intr)() ;
class HardwareSerial: public Stream
{
public:
HardwareSerial(int uart_nr);
void setInterrupt(void (*arg)() );
void begin(unsigned long baud, uint32_t config=SERIAL_8N1, int8_t rxPin=-1, int8_t txPin=-1, bool invert=false, unsigned long timeout_ms = 20000UL);
void end();
void updateBaudRate(unsigned long baud);
int available(void);
int availableForWrite(void);
int peek(void);
int read(void);
void flush(void);
size_t write(uint8_t);
size_t write(const uint8_t *buffer, size_t size);
inline size_t write(const char * s)
{
return write((uint8_t*) s, strlen(s));
}
inline size_t write(unsigned long n)
{
return write((uint8_t) n);
}
inline size_t write(long n)
{
return write((uint8_t) n);
}
inline size_t write(unsigned int n)
{
return write((uint8_t) n);
}
inline size_t write(int n)
{
return write((uint8_t) n);
}
uint32_t baudRate();
operator bool() const;
size_t setRxBufferSize(size_t);
void setDebugOutput(bool);
protected:
void (intr)() ;
int _uart_nr;
uart_t _uart;
};
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL)
extern HardwareSerial Serial;
extern HardwareSerial Serial1;
extern HardwareSerial Serial2;
#endif
#endif
HardwareSerial.c
add function
void setInterrupt(void (*arg)() );
void HardwareSerial::setInterrupt(void(*arg)() )
{
uartDisableInterrupt(_uart);
intr = arg;
uartEnableInterrupt(_uart,&intr);
}
FINISH!!!
Example of USE
Serial1.begin(9600,SERIAL_8N1, 17, 16); //RX,TX
Serial1.setInterrupt(&SerialEvent1);
void IRAM_ATTR SerialEvent1(){ // ocorre quando o arduino recebe uma transmissão no RX1
while (Serial1.available()>0) {
Serial.print(Serial1.read());
}
Serial.println();
}
Thanks for the author!!!!!
Hi, nice to see this is useful and still working. didn't get notification for the last comment if this is still an issue feel free to make a pull request I won't because I don't have access to an esp currently.
I've been trying to implement the Serial.setInterrupt(&event) function but it doesn't seem native available in the ESP32 stack for Arduino IDE. (Using package from https://dl.espressif.com/dl/package_esp32_index.json)
Is there any chance it will propagate to that package?
Hello
Having played around trying to make serialEvent work on ESP32, I finally came across this gist and it fixed the problem.
I'd like to suggest that you submit a pull request for your changes (although probably realign with the current code before doing so). If you're not interested in submitting a pull request, I'm sure you wouldn't mind if I did one myself, with your changes, credited accordingly.
Thanks
Kev