From 2331310611ed90926f69e5f49901b4e0fb549794 Mon Sep 17 00:00:00 2001 From: Terje Io Date: Tue, 26 Dec 2023 10:17:48 +0100 Subject: [PATCH] Refactored UART driver code to use framework provided low-level calls instead of direct MCU register access. --- driver.json | 2 +- main/uart_serial.c | 555 +++++++++++++++++++++------------------------ main/uart_serial.h | 69 ++---- 3 files changed, 273 insertions(+), 353 deletions(-) diff --git a/driver.json b/driver.json index db58621..bfed664 100644 --- a/driver.json +++ b/driver.json @@ -152,7 +152,7 @@ "URL": "https://www.fysetc.com/products/fysetc-e4-board-with-built-in-wi-fi-and-bluetooth-4-pcs-tmc2209-240mhz-16m-flash-3d-printer-control-board-based-for-3d-printer?variant=37558333341871", "MAP": "main/fysetc_e4_map.h", "caps": { - "axes": 3, + "axes": 4, "digital_in": 0, "digital_out": 0, "safety_door": 0, diff --git a/main/uart_serial.c b/main/uart_serial.c index d852950..60b1885 100644 --- a/main/uart_serial.c +++ b/main/uart_serial.c @@ -1,17 +1,25 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// Copyright 2018-2023 Terje Io : Modifications for grblHAL -// -// 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. + uart_serial.c - driver code for ESP32 + + Part of grblHAL + + Copyright (c) 2023 Terje Io + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Grbl 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . + +*/ #include #include @@ -34,7 +42,7 @@ #include "hal/uart_ll.h" #include "esp_intr_alloc.h" -#include "uart_serial.h" +#include "driver.h" #include "grbl/hal.h" #include "grbl/protocol.h" @@ -50,52 +58,55 @@ typedef void (*uart_isr_ptr)(void *arg); typedef struct { - uart_dev_t *dev; +#if GRBL_ESP32S3 + uart_dev_t *dev; +#else + volatile uart_dev_t *dev; +#endif #if !CONFIG_DISABLE_HAL_LOCKS xSemaphoreHandle lock; #endif uint8_t num; intr_handle_t intr_handle; + uint32_t tx_len; } uart_t; static int16_t serialRead (void); #if CONFIG_DISABLE_HAL_LOCKS + #define UART_MUTEX_LOCK(u) #define UART_MUTEX_UNLOCK(u) -#if GRBL_ESP32S3 -static uart_t _uart_bus_array[3] = { - {(uart_dev_t *)(DR_REG_UART_BASE), 0, NULL}, - {(uart_dev_t *)(DR_REG_UART1_BASE), 1, NULL}, - {(uart_dev_t *)(DR_REG_UART2_BASE), 2, NULL} -}; -#else -static uart_t _uart_bus_array[3] = { - {(volatile uart_dev_t *)(DR_REG_UART_BASE), 0, NULL}, - {(volatile uart_dev_t *)(DR_REG_UART1_BASE), 1, NULL}, - {(volatile uart_dev_t *)(DR_REG_UART2_BASE), 2, NULL} + +static const uart_t _uart_bus_array[3] = { + { (uart_dev_t *)(DR_REG_UART_BASE), 0, NULL, SOC_UART_FIFO_LEN }, + { (uart_dev_t *)(DR_REG_UART1_BASE), 1, NULL, SOC_UART_FIFO_LEN }, + { (uart_dev_t *)(DR_REG_UART2_BASE), 2, NULL, SOC_UART_FIFO_LEN } }; -#endif + #else -#define UART_MUTEX_LOCK(u) do {} while (xSemaphoreTake(u->lock, portMAX_DELAY) != pdPASS) -#define UART_MUTEX_UNLOCK(u) xSemaphoreGive(u->lock) -static uart_t _uart_bus_array[3] = { - {(volatile uart_dev_t *)(DR_REG_UART_BASE), NULL, 0, NULL}, - {(volatile uart_dev_t *)(DR_REG_UART1_BASE), NULL, 1, NULL}, - {(volatile uart_dev_t *)(DR_REG_UART2_BASE), NULL, 2, NULL} +#define UART_MUTEX_LOCK(u) do {} while (xSemaphoreTake((u)->lock, portMAX_DELAY) != pdPASS) +#define UART_MUTEX_UNLOCK(u) xSemaphoreGive((u)->lock) + +static const uart_t _uart_bus_array[3] = { + { (uart_dev_t *)(DR_REG_UART_BASE), NULL, 0, NULL, SOC_UART_FIFO_LEN }, + { (uart_dev_t *)(DR_REG_UART1_BASE), NULL, 1, NULL, SOC_UART_FIFO_LEN }, + { (uart_dev_t *)(DR_REG_UART2_BASE), NULL, 2, NULL, SOC_UART_FIFO_LEN } }; + #endif static const DRAM_ATTR uint16_t RX_BUFFER_SIZE_MASK = RX_BUFFER_SIZE - 1; +static const DRAM_ATTR uint32_t rx_int_flags = UART_INTR_RXFIFO_FULL|UART_INTR_RXFIFO_OVF|UART_INTR_RXFIFO_TOUT|UART_INTR_FRAM_ERR; -static uart_t *uart1 = NULL; +static uart_t uart1; static stream_rx_buffer_t rxbuffer = {0}; static enqueue_realtime_command_ptr enqueue_realtime_command = protocol_enqueue_realtime_command; static const io_stream_t *serialInit (uint32_t baud_rate); #if SERIAL2_ENABLE -static uart_t *uart2 = NULL; +static uart_t uart2; static stream_rx_buffer_t rxbuffer2 = {0}; static enqueue_realtime_command_ptr enqueue_realtime_command2 = protocol_enqueue_realtime_command; static const io_stream_t *serial2Init (uint32_t baud_rate); @@ -109,6 +120,7 @@ static io_stream_properties_t serial[] = { .flags.claimed = Off, .flags.connected = On, .flags.can_set_baud = On, + .flags.modbus_ready = On, .claim = serialInit }, #if SERIAL2_ENABLE @@ -154,7 +166,7 @@ void serialRegisterStreams (void) #if GRBL_ESP32S3 .pin = 44, #else - .pin = 34, + .pin = 34, #endif .mode = { .mask = PINMODE_NONE }, .description = "Primary UART" @@ -192,125 +204,13 @@ void serialRegisterStreams (void) stream_register_streams(&streams); } -#if GRBL_ESP32S3 - -IRAM_ATTR static void _uart1_isr (void *arg) -{ - uint8_t c; - - uart1->dev->int_clr.rxfifo_full_int_clr = 1; - uart1->dev->int_clr.frm_err_int_clr = 1; - uart1->dev->int_clr.rxfifo_tout_int_clr = 1; - - while(uart1->dev->status.rxfifo_cnt /*|| (uart1->dev->mem_rx_status.wr_addr != uart1->dev->mem_rx_status.rd_addr)*/) { - - c = uart1->dev->fifo.rxfifo_rd_byte; - - if(!enqueue_realtime_command(c)) { - - uint32_t bptr = (rxbuffer.head + 1) & RX_BUFFER_SIZE_MASK; // Get next head pointer - - if(bptr == rxbuffer.tail) // If buffer full - rxbuffer.overflow = 1; // flag overflow, - else { - rxbuffer.data[rxbuffer.head] = (char)c; // else add data to buffer - rxbuffer.head = bptr; // and update pointer - } - } - } -} - -static void uartEnableInterrupt (uart_t *uart, uart_isr_ptr isr, bool enable_rx) -{ - UART_MUTEX_LOCK(uart); - - esp_intr_alloc(UART_INTR_SOURCE(uart->num), (int)ESP_INTR_FLAG_IRAM, isr, NULL, &uart->intr_handle); - - uart->dev->conf1.rxfifo_full_thrhd = 112; -// uart->dev->conf1.rx_tout_thrhd = 50; - uart->dev->conf1.rx_tout_en = 1; - uart->dev->int_ena.rxfifo_full_int_ena = enable_rx; - uart->dev->int_ena.frm_err_int_ena = enable_rx; - uart->dev->int_ena.rxfifo_tout_int_ena = enable_rx; - uart->dev->int_clr.val = 0xffffffff; - - UART_MUTEX_UNLOCK(uart); -} - -#else - -IRAM_ATTR static void _uart1_isr (void *arg) -{ - uint8_t c; - - uart1->dev->int_clr.rxfifo_full = 1; - uart1->dev->int_clr.frm_err = 1; - uart1->dev->int_clr.rxfifo_tout = 1; - - while(uart1->dev->status.rxfifo_cnt || (uart1->dev->mem_rx_status.wr_addr != uart1->dev->mem_rx_status.rd_addr)) { - - c = uart1->dev->fifo.rw_byte; - - if(!enqueue_realtime_command(c)) { - - uint32_t bptr = (rxbuffer.head + 1) & RX_BUFFER_SIZE_MASK; // Get next head pointer - - if(bptr == rxbuffer.tail) // If buffer full - rxbuffer.overflow = 1; // flag overflow, - else { - rxbuffer.data[rxbuffer.head] = (char)c; // else add data to buffer - rxbuffer.head = bptr; // and update pointer - } - } - } -} - -static void uartEnableInterrupt (uart_t *uart, uart_isr_ptr isr, bool enable_rx) -{ - UART_MUTEX_LOCK(uart); - - esp_intr_alloc(UART_INTR_SOURCE(uart->num), (int)ESP_INTR_FLAG_IRAM, isr, NULL, &uart->intr_handle); - - uart->dev->conf1.rxfifo_full_thrhd = 112; - uart->dev->conf1.rx_tout_thrhd = 50; - uart->dev->conf1.rx_tout_en = 1; - uart->dev->int_ena.rxfifo_full = enable_rx; - uart->dev->int_ena.frm_err = enable_rx; - uart->dev->int_ena.rxfifo_tout = enable_rx; - uart->dev->int_clr.val = 0xffffffff; - - UART_MUTEX_UNLOCK(uart); -} - -#endif - -/* -static void uartDisableInterrupt (uart_t *uart) -{ - UART_MUTEX_LOCK(); - rx_uart->dev->conf1.val = 0; - rx_uart->dev->int_ena.val = 0; - rx_uart->dev->int_clr.val = 0xffffffff; - - esp_intr_free(rx_uart->intr_handle); - rx_uart->intr_handle = NULL; - - UART_MUTEX_UNLOCK(); -} -*/ static void uartSetBaudRate (uart_t *uart, uint32_t baud_rate) { if(uart == NULL) return; UART_MUTEX_LOCK(uart); -#if GRBL_ESP32S3 uart_ll_set_baudrate(uart->dev, baud_rate); -#else - 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; -#endif UART_MUTEX_UNLOCK(uart); } @@ -323,6 +223,10 @@ static void uartConfig (uart_t *uart, uint32_t baud_rate) return; } #endif + +// uart->tx_len = 128; + uart_ll_set_mode(uart->dev, UART_MODE_UART); + #if GRBL_ESP32S3 #else switch(uart->num) { @@ -347,12 +251,10 @@ static void uartConfig (uart_t *uart, uint32_t baud_rate) uartSetBaudRate(uart, baud_rate); UART_MUTEX_LOCK(uart); - uart->dev->conf0.val = SERIAL_8N2; - 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_ll_set_data_bit_num(uart->dev, UART_DATA_8_BITS); + uart_ll_set_stop_bits(uart->dev, UART_STOP_BITS_2); + uart_ll_set_parity(uart->dev, UART_PARITY_DISABLE); // Note: UART0 pin mappings are set at boot, no need to set here unless override is required @@ -368,22 +270,88 @@ static void uartConfig (uart_t *uart, uint32_t baud_rate) UART_MUTEX_UNLOCK(uart); } -IRAM_ATTR static void flush (uart_t *uart) +static void uartEnableInterrupt (uart_t *uart, uart_isr_ptr isr, bool enable_rx) { - while(uart->dev->status.txfifo_cnt); + UART_MUTEX_LOCK(uart); - //Due to hardware issue, we can not use fifo_rst to reset uart fifo. - //See description about UART_TXFIFO_RST and UART_RXFIFO_RST in <> v2.6 or later. + if(!uart->intr_handle) + esp_intr_alloc(UART_INTR_SOURCE(uart->num), (int)ESP_INTR_FLAG_IRAM, isr, NULL, &uart->intr_handle); - // we read the data out and make `fifo_len == 0 && rd_addr == wr_addr`. -#if GRBL_ESP32S3 - while(uart->dev->status.rxfifo_cnt || (uart->dev->mem_rx_status.rx_waddr != uart->dev->mem_rx_status.apb_rx_raddr)) - READ_PERI_REG(UART_FIFO_REG(uart->num)); -#else - while(uart->dev->status.rxfifo_cnt || (uart->dev->mem_rx_status.wr_addr != uart->dev->mem_rx_status.rd_addr)) - READ_PERI_REG(UART_FIFO_REG(uart->num)); + uart_ll_set_rxfifo_full_thr(uart->dev, 112); + uart_ll_set_rx_tout(uart->dev, enable_rx ? 50 : 0); + uart_ll_clr_intsts_mask(uart->dev, rx_int_flags); + if(enable_rx) + uart_ll_ena_intr_mask(uart->dev, rx_int_flags); + else + uart_ll_disable_intr_mask(uart->dev, rx_int_flags); + + UART_MUTEX_UNLOCK(uart); +} + +IRAM_ATTR static void _uart_flush (uart_t *uart, bool tx_only) +{ + uart_ll_txfifo_rst(uart->dev); + while(!uart_ll_is_tx_idle(uart->dev)); + + if(!tx_only) + uart_ll_rxfifo_rst(uart->dev); +} + +FORCE_INLINE_ATTR uint8_t _uart_ll_read_rxfifo (uart_dev_t *hw) +{ + uint8_t c; + //Get the UART APB fifo addr. Read fifo, we use APB address + uint32_t fifo_addr = (hw == &UART0) ? UART_FIFO_REG(0) : (hw == &UART1) ? UART_FIFO_REG(1) : UART_FIFO_REG(2); + + c = READ_PERI_REG(fifo_addr); +#ifdef CONFIG_COMPILER_OPTIMIZATION_PERF + __asm__ __volatile__("nop"); #endif - uart_ll_rxfifo_rst(uart->dev); + + return c; +} + +FORCE_INLINE_ATTR void _uart_ll_write_txfifo (uart_dev_t *hw, const uint8_t c) +{ + //Get the UART AHB fifo addr, Write fifo, we use AHB address + uint32_t fifo_addr = (hw == &UART0) ? UART_FIFO_AHB_REG(0) : (hw == &UART1) ? UART_FIFO_AHB_REG(1) : UART_FIFO_AHB_REG(2); + + WRITE_PERI_REG(fifo_addr, c); +} + +FORCE_INLINE_ATTR uint32_t _uart_ll_get_txfifo_count (uart_dev_t *hw) +{ + return HAL_FORCE_READ_U32_REG_FIELD(hw->status, txfifo_cnt); +} + +// UART0 + +IRAM_ATTR static void _uart1_isr (void *arg) +{ + uint32_t c, cnt = uart_ll_get_rxfifo_len(uart1.dev), iflags = uart_ll_get_intsts_mask(uart1.dev); + + uart_ll_clr_intsts_mask(uart1.dev, iflags); + + if(iflags & UART_INTR_RXFIFO_OVF) + rxbuffer.overflow = On; + + while(cnt) { + + cnt--; + c = _uart_ll_read_rxfifo(uart1.dev); + + if(!enqueue_realtime_command(c)) { + + uint32_t bptr = (rxbuffer.head + 1) & RX_BUFFER_SIZE_MASK; // Get next head pointer + + if(bptr == rxbuffer.tail) // If buffer full + rxbuffer.overflow = On; // flag overflow, + else { + rxbuffer.data[rxbuffer.head] = (char)c; // else add data to buffer + rxbuffer.head = bptr; // and update pointer + } + } + } } static uint16_t serialAvailable (void) @@ -393,26 +361,26 @@ static uint16_t serialAvailable (void) return BUFCOUNT(head, tail, RX_BUFFER_SIZE); } +uint16_t static serialTxCount (void) +{ + return uart_ll_is_tx_idle(uart1.dev) ? 0 : (uint16_t)_uart_ll_get_txfifo_count(uart1.dev) + 1; +} + static uint16_t serialRXFree (void) { uint16_t head = rxbuffer.head, tail = rxbuffer.tail; return (RX_BUFFER_SIZE - 1) - BUFCOUNT(head, tail, RX_BUFFER_SIZE); } -/* -static uint32_t serialAvailableForWrite (void) -{ - return uart1 ? 0x7f - uart1->dev->status.txfifo_cnt : 0; -} -*/ + static int16_t serialRead (void) { int16_t data; uint16_t bptr = rxbuffer.tail; - if(bptr == rxbuffer.head) {; + if(bptr == rxbuffer.head) return -1; // no data available else EOF - } + data = rxbuffer.data[bptr++]; // Get next character, increment tmp pointer rxbuffer.tail = bptr & (RX_BUFFER_SIZE - 1); // and update pointer @@ -421,16 +389,12 @@ static int16_t serialRead (void) static bool serialPutC (const char c) { - while(uart1->dev->status.txfifo_cnt == 0x7F) { + while(_uart_ll_get_txfifo_count(uart1.dev) == uart1.tx_len) { if(!hal.stream_blocking_callback()) return false; } -#if GRBL_ESP32S3 - uart1->dev->fifo.rxfifo_rd_byte = c; -#else - uart1->dev->fifo.rw_byte = c; -#endif + _uart_ll_write_txfifo(uart1.dev, c); return true; } @@ -439,82 +403,86 @@ static void serialWriteS (const char *data) { char c, *ptr = (char *)data; -// uart_ll_write_txfifo(uart1->dev, (uint8_t *)data, 5); while((c = *ptr++) != '\0') serialPutC(c); } +// +// Writes a number of characters from a buffer to the serial output stream, blocks if buffer full +// +void static serialWrite (const char *s, uint16_t length) +{ + char *ptr = (char *)s; + + while(length--) + serialPutC(*ptr++); +} + IRAM_ATTR static void serialFlush (void) { - UART_MUTEX_LOCK(uart1); + UART_MUTEX_LOCK(&uart1); + + _uart_flush(&uart1, false); - flush(uart1); rxbuffer.tail = rxbuffer.head; + rxbuffer.overflow = Off; - UART_MUTEX_UNLOCK(uart1); + UART_MUTEX_UNLOCK(&uart1); +} + +IRAM_ATTR static void serialTxFlush (void) +{ + UART_MUTEX_LOCK(&uart1); + + _uart_flush(&uart1, true); + + UART_MUTEX_UNLOCK(&uart1); } IRAM_ATTR static void serialCancel (void) { -// UART_MUTEX_LOCK(uart1); + UART_MUTEX_LOCK(&uart1); + rxbuffer.data[rxbuffer.head] = ASCII_CAN; rxbuffer.tail = rxbuffer.head; rxbuffer.head = (rxbuffer.tail + 1) & (RX_BUFFER_SIZE - 1); -// UART_MUTEX_UNLOCK(uart1); + + UART_MUTEX_UNLOCK(&uart1); } IRAM_ATTR static bool serialSuspendInput (bool suspend) { - bool ok; - UART_MUTEX_LOCK(uart1); - ok = stream_rx_suspend(&rxbuffer, suspend); - UART_MUTEX_UNLOCK(uart1); + UART_MUTEX_LOCK(&uart1); + + bool ok = stream_rx_suspend(&rxbuffer, suspend); + + UART_MUTEX_UNLOCK(&uart1); return ok; } IRAM_ATTR static bool serialDisable (bool disable) { - UART_MUTEX_LOCK(uart1); -#if GRBL_ESP32S3 - if(disable) { - // Disable interrupts - uart1->dev->int_ena.rxfifo_full_int_ena = 0; - uart1->dev->int_ena.frm_err_int_ena = 0; - uart1->dev->int_ena.rxfifo_tout_int_ena = 0; - } else { - // Clear and enable interrupts - uart1->dev->int_ena.rxfifo_full_int_ena = 0; - uart1->dev->int_clr.rxfifo_full_int_clr = 1; - uart1->dev->int_clr.frm_err_int_clr = 1; - uart1->dev->int_clr.rxfifo_tout_int_clr = 1; - flush(uart1); - rxbuffer.tail = rxbuffer.head; - uart1->dev->int_ena.rxfifo_full_int_ena = 1; - uart1->dev->int_ena.frm_err_int_ena = 1; - uart1->dev->int_ena.rxfifo_tout_int_ena = 1; - } -#else - if(disable) { - // Disable interrupts - uart1->dev->int_ena.rxfifo_full = 0; - uart1->dev->int_ena.frm_err = 0; - uart1->dev->int_ena.rxfifo_tout = 0; - } else { + UART_MUTEX_LOCK(&uart1); + + uart_ll_disable_intr_mask(uart1.dev, rx_int_flags); + + if(!disable) { // Clear and enable interrupts - uart1->dev->int_ena.rxfifo_full = 0; - uart1->dev->int_clr.rxfifo_full = 1; - uart1->dev->int_clr.frm_err = 1; - uart1->dev->int_clr.rxfifo_tout = 1; - flush(uart1); + _uart_flush(&uart1, false); rxbuffer.tail = rxbuffer.head; - uart1->dev->int_ena.rxfifo_full = 1; - uart1->dev->int_ena.frm_err = 1; - uart1->dev->int_ena.rxfifo_tout = 1; + uart_ll_clr_intsts_mask(uart1.dev, rx_int_flags); + uart_ll_ena_intr_mask(uart1.dev, rx_int_flags); } -#endif - UART_MUTEX_UNLOCK(uart1); + UART_MUTEX_UNLOCK(&uart1); + + return true; +} + +static bool serialSetBaudRate (uint32_t baud_rate) +{ + uartSetBaudRate(&uart1, baud_rate); return true; } @@ -541,17 +509,17 @@ static const io_stream_t *serialInit (uint32_t baud_rate) .state.connected = true, .read = serialRead, .write = serialWriteS, -// .write_n = serialWrite, + .write_n = serialWrite, .write_char = serialPutC, .enqueue_rt_command = serialEnqueueRtCommand, .get_rx_buffer_free = serialRXFree, .get_rx_buffer_count = serialAvailable, -// .get_tx_buffer_count = serialTxCount, -// .reset_write_buffer = serialTxFlush, + .get_tx_buffer_count = serialTxCount, + .reset_write_buffer = serialTxFlush, .reset_read_buffer = serialFlush, .cancel_read_buffer = serialCancel, .suspend_read = serialSuspendInput, - // .set_baud_rate = serialSetBaudRate + .set_baud_rate = serialSetBaudRate, .disable_rx = serialDisable, .set_enqueue_rt_handler = serialSetRtHandler }; @@ -561,12 +529,12 @@ static const io_stream_t *serialInit (uint32_t baud_rate) serial[0].flags.claimed = On; - uart1 = &_uart_bus_array[0]; // use UART 0 + memcpy(&uart1, &_uart_bus_array[0], sizeof(uart_t)); // use UART 0 - uartConfig(uart1, baud_rate); + uartConfig(&uart1, baud_rate); serialFlush(); - uartEnableInterrupt(uart1, _uart1_isr, true); + uartEnableInterrupt(&uart1, _uart1_isr, true); return &stream; } @@ -575,42 +543,30 @@ static const io_stream_t *serialInit (uint32_t baud_rate) static void IRAM_ATTR _uart2_isr (void *arg) { - uint8_t c; + uint32_t c, cnt = uart_ll_get_rxfifo_len(uart2.dev), iflags = uart_ll_get_intsts_mask(uart2.dev); - uart2->dev->int_clr.rxfifo_full = 1; - uart2->dev->int_clr.frm_err = 1; - uart2->dev->int_clr.rxfifo_tout = 1; + uart_ll_clr_intsts_mask(uart2.dev, iflags); -#if MODBUS_ENABLE & MODBUS_RTU_DIR_ENABLED - if(uart2->dev->int_st.tx_done) { - // uart2->dev->int_clr.tx_done = 1; - uart2->dev->int_ena.tx_done = 0; - gpio_set_level(MODBUS_DIRECTION_PIN, false); - } -#endif + if(iflags & UART_INTR_RXFIFO_OVF) + rxbuffer2.overflow = On; - while(uart2->dev->status.rxfifo_cnt || (uart2->dev->mem_rx_status.wr_addr != uart2->dev->mem_rx_status.rd_addr)) { + while(cnt) { - c = uart2->dev->fifo.rw_byte; + cnt--; + c = _uart_ll_read_rxfifo(uart2.dev); if(!enqueue_realtime_command2(c)) { uint32_t bptr = (rxbuffer2.head + 1) & RX_BUFFER_SIZE_MASK; // Get next head pointer if(bptr == rxbuffer2.tail) // If buffer full - rxbuffer2.overflow = 1; // flag overflow, + rxbuffer2.overflow = On; // flag overflow, else { rxbuffer2.data[rxbuffer2.head] = (char)c; // else add data to buffer rxbuffer2.head = bptr; // and update pointer } } } - -/* - if (xHigherPriorityTaskWoken) { - portYIELD_FROM_ISR(); - } - */ } uint16_t static serial2Available (void) @@ -620,9 +576,9 @@ uint16_t static serial2Available (void) return BUFCOUNT(head, tail, RX_BUFFER_SIZE); } -uint16_t static serial2txCount (void) +uint16_t static serial2TxCount (void) { - return (uint16_t)uart2->dev->status.txfifo_cnt + (uart2->dev->status.st_utx_out ? 1 : 0); + return uart_ll_is_tx_idle(uart2.dev) ? 0 : (uint16_t)_uart_ll_get_txfifo_count(uart2.dev) + 1; } uint16_t static serial2RXFree (void) @@ -634,13 +590,16 @@ uint16_t static serial2RXFree (void) bool static serial2PutC (const char c) { - UART_MUTEX_LOCK(uart2); + UART_MUTEX_LOCK(&uart2); - while(uart2->dev->status.txfifo_cnt == 0x7F); + while(_uart_ll_get_txfifo_count(uart2.dev) == uart2.tx_len) { + if(!hal.stream_blocking_callback()) + return false; + } - uart2->dev->fifo.rw_byte = c; + _uart_ll_write_txfifo(uart2.dev, c); - UART_MUTEX_UNLOCK(uart2); + UART_MUTEX_UNLOCK(&uart2); return true; } @@ -660,101 +619,97 @@ void static serial2Write (const char *s, uint16_t length) { char *ptr = (char *)s; -#if MODBUS_ENABLE & MODBUS_RTU_DIR_ENABLED - gpio_set_level(MODBUS_DIRECTION_PIN, true); -#endif - while(length--) serial2PutC(*ptr++); - -#if MODBUS_ENABLE & MODBUS_RTU_DIR_ENABLED - uart2->dev->int_clr.tx_done = 1; - uart2->dev->int_ena.tx_done = 1; -#endif } int16_t static serial2Read (void) { - UART_MUTEX_LOCK(uart2); + UART_MUTEX_LOCK(&uart2); int16_t data; uint16_t bptr = rxbuffer2.tail; if(bptr == rxbuffer2.head) { - UART_MUTEX_UNLOCK(uart2); + UART_MUTEX_UNLOCK(&uart2); return -1; // no data available else EOF } data = rxbuffer2.data[bptr++]; // Get next character, increment tmp pointer rxbuffer2.tail = bptr & (RX_BUFFER_SIZE - 1); // and update pointer - UART_MUTEX_UNLOCK(uart2); + UART_MUTEX_UNLOCK(&uart2); return data; } IRAM_ATTR static void serial2Flush (void) { - UART_MUTEX_LOCK(uart2); + UART_MUTEX_LOCK(&uart2); + + _uart_flush(&uart2, false); - flush(uart2); rxbuffer2.tail = rxbuffer2.head; + rxbuffer2.overflow = Off; - UART_MUTEX_UNLOCK(uart2); + UART_MUTEX_UNLOCK(&uart2); +} + +IRAM_ATTR static void serial2TxFlush (void) +{ + UART_MUTEX_LOCK(&uart2); + + _uart_flush(&uart2, true); + + UART_MUTEX_UNLOCK(&uart2); } IRAM_ATTR static void serial2Cancel (void) { -// UART_MUTEX_LOCK(uart2); + UART_MUTEX_LOCK(&uart2); + rxbuffer2.data[rxbuffer2.head] = ASCII_CAN; rxbuffer2.tail = rxbuffer2.head; rxbuffer2.head = (rxbuffer2.tail + 1) & (RX_BUFFER_SIZE - 1); -// UART_MUTEX_UNLOCK(uart2); + + UART_MUTEX_UNLOCK(&uart2); } static bool serial2SuspendInput (bool suspend) { bool ok; - UART_MUTEX_LOCK(uart2); + UART_MUTEX_LOCK(&uart2); ok = stream_rx_suspend(&rxbuffer2, suspend); - UART_MUTEX_UNLOCK(uart2); + UART_MUTEX_UNLOCK(&uart2); return ok; } IRAM_ATTR static bool serial2Disable (bool disable) { - UART_MUTEX_LOCK(uart2); + UART_MUTEX_LOCK(&uart2); + + uart_ll_disable_intr_mask(uart2.dev, rx_int_flags); - if(disable) { - // Disable interrupts - uart2->dev->int_ena.rxfifo_full = 0; - uart2->dev->int_ena.frm_err = 0; - uart2->dev->int_ena.rxfifo_tout = 0; - } else { + if(!disable) { // Clear and enable interrupts - uart2->dev->int_ena.rxfifo_full = 0; - uart2->dev->int_clr.rxfifo_full = 1; - uart2->dev->int_clr.frm_err = 1; - uart2->dev->int_clr.rxfifo_tout = 1; - flush(uart2); + _uart_flush(&uart2, false); rxbuffer2.tail = rxbuffer2.head; - uart2->dev->int_ena.rxfifo_full = 1; - uart2->dev->int_ena.frm_err = 1; - uart2->dev->int_ena.rxfifo_tout = 1; + uart_ll_clr_intsts_mask(uart2.dev, rx_int_flags); + uart_ll_ena_intr_mask(uart2.dev, rx_int_flags); } - UART_MUTEX_UNLOCK(uart2); + UART_MUTEX_UNLOCK(&uart2); return true; } static bool serial2SetBaudRate (uint32_t baud_rate) { - uartSetBaudRate(uart2, baud_rate); + uartSetBaudRate(&uart2, baud_rate); return true; } @@ -787,8 +742,8 @@ static const io_stream_t *serial2Init (uint32_t baud_rate) .enqueue_rt_command = serial2EnqueueRtCommand, .get_rx_buffer_free = serial2RXFree, .get_rx_buffer_count = serial2Available, - .get_tx_buffer_count = serial2txCount, - .reset_write_buffer = serial2Flush, + .get_tx_buffer_count = serial2TxCount, + .reset_write_buffer = serial2TxFlush, .reset_read_buffer = serial2Flush, .cancel_read_buffer = serial2Cancel, .suspend_read = serial2SuspendInput, @@ -802,15 +757,15 @@ static const io_stream_t *serial2Init (uint32_t baud_rate) serial[1].flags.claimed = On; - uart2 = &_uart_bus_array[1]; // use UART 1 + memcpy(&uart2, &_uart_bus_array[1], sizeof(uart_t)); // use UART 1 - uartConfig(uart2, baud_rate); + uartConfig(&uart2, baud_rate); serial2Flush(); #ifdef UART2_TX_PIN - uartEnableInterrupt(uart2, _uart2_isr, true); + uartEnableInterrupt(&uart2, _uart2_isr, true); #else - uartEnableInterrupt(uart2, _uart2_isr, false); + uartEnableInterrupt(&uart2, _uart2_isr, false); #endif return &stream; diff --git a/main/uart_serial.h b/main/uart_serial.h index c3b667e..64a40f8 100644 --- a/main/uart_serial.h +++ b/main/uart_serial.h @@ -1,64 +1,29 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// Copyright 2018-2023 Terje Io : Modifications for grbl -// -// 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. + uart_serial.h - driver code for ESP32 -#ifndef MAIN_ESP32_HAL_UART_H_ -#define MAIN_ESP32_HAL_UART_H_ + Part of grblHAL -#ifdef __cplusplus -extern "C" { -#endif + Copyright (c) 2023 Terje Io -#include -#include -#include + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. -#include "driver.h" + Grbl 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 General Public License for more details. -#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 + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . -#define ESP_REG(addr) *((volatile uint32_t *)(addr)) +*/ -#define DEBUG_PRINT(string) uartWriteS(string) +#ifndef _UART_SERIAL_H_ +#define _UART_SERIAL_H_ void serialRegisterStreams (void); -#ifdef __cplusplus -} #endif - -#endif /* MAIN_ESP32_HAL_UART_H_ */