diff --git a/core/newlib_syscalls.c b/core/newlib_syscalls.c index 767dd2d..cce4f49 100644 --- a/core/newlib_syscalls.c +++ b/core/newlib_syscalls.c @@ -50,8 +50,9 @@ long _write_r(struct _reent *r, int fd, const char *ptr, int len ) /* syscall implementation for stdio read from UART at the moment UART functionality is all still in the binary SDK + but there is support for IRQ driven UART0 RX in extras/serial-driver */ -long _read_r( struct _reent *r, int fd, char *ptr, int len ) +long __attribute__((weak)) _read_r( struct _reent *r, int fd, char *ptr, int len ) { if(fd != r->_stdin->_file) { r->_errno = EBADF; diff --git a/examples/terminal/FreeRTOSConfig.h b/examples/terminal/FreeRTOSConfig.h new file mode 100644 index 0000000..0a9a6b7 --- /dev/null +++ b/examples/terminal/FreeRTOSConfig.h @@ -0,0 +1,12 @@ +/* Terminal FreeRTOSConfig overrides. + + This is intended as an example of overriding some of the default FreeRTOSConfig settings, + which are otherwise found in FreeRTOS/Source/include/FreeRTOSConfig.h +*/ + +/* The serial driver depends on counting semaphores */ +#define configUSE_COUNTING_SEMAPHORES 1 + +/* Use the defaults for everything else */ +#include_next + diff --git a/examples/terminal/Makefile b/examples/terminal/Makefile new file mode 100644 index 0000000..b784f87 --- /dev/null +++ b/examples/terminal/Makefile @@ -0,0 +1,3 @@ +PROGRAM=terminal +EXTRA_COMPONENTS=extras/serial-driver +include ../../common.mk diff --git a/examples/terminal/terminal.c b/examples/terminal/terminal.c new file mode 100644 index 0000000..45d0fce --- /dev/null +++ b/examples/terminal/terminal.c @@ -0,0 +1,37 @@ +/* Serial terminal example + * UART RX is interrupt driven + * Read characters until \n and echo back + * + * This sample code is in the public domain. + */ + +#include +#include +#include +#include +#include + +#define BUFFER_SIZE (81) + +void user_init(void) +{ + char buffer[BUFFER_SIZE]; + uint32_t i = 0; + sdk_uart_div_modify(0, UART_CLK_FREQ / 115200); + while(1) { + char ch; + // The thread will block here until there is data available + // NB. read(...) may be called from user_init or from a thread + // We can check how many characters are available in the RX buffer + // with uint32_t uart0_num_char(void); + if (read(0, (void*)&ch, 1)) { // 0 is stdin + if (i == BUFFER_SIZE-2 || ch == '\n') { + buffer[i] = 0; + printf("Unknown command: %s\n", (char*) buffer); + i = 0; + } else { + buffer[i++] = ch; + } + } + } +} diff --git a/extras/serial-driver/component.mk b/extras/serial-driver/component.mk new file mode 100644 index 0000000..bb17970 --- /dev/null +++ b/extras/serial-driver/component.mk @@ -0,0 +1,11 @@ +# Component makefile for extras/serial-driver +# +# See examples/terminal for usage + +INC_DIRS += $(ROOT)extras/serial-driver + +# args for passing into compile rule generation +extras/serial-driver_INC_DIR = $(ROOT)extras/serial-driver +extras/serial-driver_SRC_DIR = $(ROOT)extras/serial-driver + +$(eval $(call component_compile_rules,extras/serial-driver)) diff --git a/extras/serial-driver/serial_driver.c b/extras/serial-driver/serial_driver.c new file mode 100644 index 0000000..800f717 --- /dev/null +++ b/extras/serial-driver/serial_driver.c @@ -0,0 +1,120 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Johan Kanflo (github.com/kanflo) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include + +#if (configUSE_COUNTING_SEMAPHORES == 0) + #error "You need to define configUSE_COUNTING_SEMAPHORES in a local FreeRTOSConfig.h, see examples/terminal/FreeRTOSConfig.h" +#endif + +// IRQ driven UART RX driver for ESP8266 written for use with esp-open-rtos +// TODO: Handle UART1 + +#define UART0_RX_SIZE (81) + +#ifndef UART0 +#define UART0 (0) +#endif + +static xSemaphoreHandle uart0_sem = NULL; +static char rx_buf[UART0_RX_SIZE]; +static uint8_t rd_pos = 0; +static uint8_t wr_pos = 0; +static bool inited = false; + +static void uart0_rx_init(void); + + +IRAM void uart0_rx_handler(void) +{ + // TODO: Handle UART1, see reg 0x3ff20020, bit2, bit0 represents uart1 and uart0 respectively + if (!UART(UART0).INT_STATUS & UART_INT_STATUS_RXFIFO_FULL) { + return; + } + UART(UART0).INT_CLEAR = UART_INT_CLEAR_RXFIFO_FULL; + while (UART(UART0).STATUS & (UART_STATUS_RXFIFO_COUNT_M << UART_STATUS_RXFIFO_COUNT_S)) { + char ch = UART(UART0).FIFO & (UART_FIFO_DATA_M << UART_FIFO_DATA_S); + uint8_t wr_next = (wr_pos+1) % UART0_RX_SIZE; + if (wr_next != rd_pos) { + rx_buf[wr_pos] = ch; + wr_pos = (wr_pos+1) % UART0_RX_SIZE; + xSemaphoreGiveFromISR(uart0_sem, NULL); + } + } +} + +uint32_t uart0_num_char(void) +{ + uint32_t count; + if (!inited) uart0_rx_init(); + _xt_isr_mask(1 << INUM_UART); + if (rd_pos > wr_pos) count = rd_pos - wr_pos; + else count = wr_pos - rd_pos; + _xt_isr_unmask(1 << INUM_UART); + return count; +} + +// _read_r in core/newlib_syscalls.c will be skipped in favour of this function +long _read_r(struct _reent *r, int fd, char *ptr, int len) +{ + if (!inited) uart0_rx_init(); + for(int i = 0; i < len; i++) { + char ch; + if (xSemaphoreTake(uart0_sem, portMAX_DELAY)) { + _xt_isr_mask(1 << INUM_UART); + ch = rx_buf[rd_pos]; + rd_pos = (rd_pos+1) % UART0_RX_SIZE; + _xt_isr_unmask(1 << INUM_UART); + ptr[i] = ch; + } + } + return len; +} + +static void uart0_rx_init(void) +{ + int trig_lvl = 1; + uart0_sem = xSemaphoreCreateCounting(UART0_RX_SIZE, 0); + + _xt_isr_attach(INUM_UART, uart0_rx_handler); + _xt_isr_unmask(1 << INUM_UART); + + //clear rx and tx fifo,not ready + UART(UART0).CONF0 = UART_CONF0_RXFIFO_RESET | UART_CONF0_TXFIFO_RESET; + UART(UART0).CONF0 &= ~(UART_CONF0_RXFIFO_RESET | UART_CONF0_TXFIFO_RESET); + + //set rx fifo trigger + UART(UART0).CONF1 &= ~(UART_CONF1_RXFIFO_FULL_THRESHOLD_M << UART_CONF1_RXFIFO_FULL_THRESHOLD_S); + UART(UART0).CONF1 |= (trig_lvl & UART_CONF1_RXFIFO_FULL_THRESHOLD_M) << UART_CONF1_RXFIFO_FULL_THRESHOLD_S; + + //clear all interrupt + UART(UART0).INT_CLEAR = 0x1ff; + + //enable rx_interrupt + UART(UART0).INT_ENABLE = UART_INT_ENABLE_RXFIFO_FULL; + + inited = true; +} diff --git a/extras/serial-driver/serial_driver.h b/extras/serial-driver/serial_driver.h new file mode 100644 index 0000000..10491ac --- /dev/null +++ b/extras/serial-driver/serial_driver.h @@ -0,0 +1,33 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Johan Kanflo (github.com/kanflo) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef __I2C_H__ +#define __I2C_H__ +#endif + +#include +#include + +// Return number of characters waiting in UART0 +uint32_t uart0_num_char(void);