From efff445a03ef1c859824725bd071f5196349f437 Mon Sep 17 00:00:00 2001 From: Our Air Quality Date: Sat, 5 May 2018 12:56:21 +1000 Subject: [PATCH 1/8] stdin_uart_interrupt: add support for nonblock and a timeout. --- .../stdin_uart_interrupt.c | 32 ++++++++++++++++++- .../stdin_uart_interrupt.h | 12 ++++++- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/extras/stdin_uart_interrupt/stdin_uart_interrupt.c b/extras/stdin_uart_interrupt/stdin_uart_interrupt.c index 194fdda..71d2efc 100644 --- a/extras/stdin_uart_interrupt/stdin_uart_interrupt.c +++ b/extras/stdin_uart_interrupt/stdin_uart_interrupt.c @@ -43,6 +43,8 @@ static SemaphoreHandle_t uart0_sem = NULL; static bool inited = false; static void uart0_rx_init(void); +static int uart0_nonblock; +static TickType_t uart0_vtime; IRAM void uart0_rx_handler(void *arg) { @@ -75,6 +77,20 @@ uint32_t uart0_num_char(void) return count; } +int uart0_set_nonblock(int nonblock) +{ + int current = uart0_nonblock; + uart0_nonblock = nonblock; + return current; +} + +TickType_t uart0_set_vtime(TickType_t ticks) +{ + TickType_t current = uart0_vtime; + uart0_vtime = ticks; + return current; +} + // _read_stdin_r in core/newlib_syscalls.c will be skipped by the linker in favour // of this function long _read_stdin_r(struct _reent *r, int fd, char *ptr, int len) @@ -83,7 +99,21 @@ long _read_stdin_r(struct _reent *r, int fd, char *ptr, int len) for(int i = 0; i < len; i++) { if (!(UART(UART0).STATUS & (UART_STATUS_RXFIFO_COUNT_M << UART_STATUS_RXFIFO_COUNT_S))) { _xt_isr_unmask(1 << INUM_UART); - if (!xSemaphoreTake(uart0_sem, portMAX_DELAY)) { + if (uart0_nonblock) { + if (i > 0) { + return i; + } + r->_errno = EAGAIN; + return -1; + } + if (uart0_vtime) { + if (!xSemaphoreTake(uart0_sem, uart0_vtime)) { + if (i > 0) { + return i; + } + return 0; + } + } else if (!xSemaphoreTake(uart0_sem, portMAX_DELAY)) { printf("\nFailed to get sem\n"); } } diff --git a/extras/stdin_uart_interrupt/stdin_uart_interrupt.h b/extras/stdin_uart_interrupt/stdin_uart_interrupt.h index 05652bb..b15278b 100644 --- a/extras/stdin_uart_interrupt/stdin_uart_interrupt.h +++ b/extras/stdin_uart_interrupt/stdin_uart_interrupt.h @@ -27,6 +27,16 @@ #include -// Return number of characters waiting in UART0 +/* Return number of characters waiting in UART0. */ uint32_t uart0_num_char(void); + +/* Set UART0 input to nonblocking or blocking, returning the old state. */ +int uart0_set_nonblock(int); + +/* Set the UART0 input wait time in ticks, or zero to wait indefinitely, + * returning the old wait time. The wait time is only used when the input is + * blocking. + */ +TickType_t uart0_set_vtime(TickType_t ticks); + #endif From ee001e0231f94e6a206fe1367ec8f4412c7c05e2 Mon Sep 17 00:00:00 2001 From: Joost Nieuwenhuijse Date: Wed, 16 May 2018 17:53:17 +0200 Subject: [PATCH 2/8] Move large lib_a-svfwprintf to flash lib_a-svfwprintf may get included when linking against libstdc++ This will overflow IRAM https://github.com/SuperHouse/esp-open-rtos/issues/623 --- ld/program.ld | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ld/program.ld b/ld/program.ld index 0718d6f..5b9031f 100644 --- a/ld/program.ld +++ b/ld/program.ld @@ -113,7 +113,11 @@ SECTIONS *libc.a:*bzero.o(.literal .text .literal.* .text.*) *libc.a:*lock.o(.literal .text .literal.* .text.*) - *libc.a:*printf.o(.literal .text .literal.* .text.*) + *libc.a:*-printf.o(.literal .text .literal.* .text.*) + *libc.a:*-sprintf.o(.literal .text .literal.* .text.*) + *libc.a:*-fprintf.o(.literal .text .literal.* .text.*) + *libc.a:*-svfprintf.o(.literal .text .literal.* .text.*) + *libc.a:*-vfprintf.o(.literal .text .literal.* .text.*) *libc.a:*findfp.o(.literal .text .literal.* .text.*) *libc.a:*fputwc.o(.literal .text .literal.* .text.*) From 233f9a6a313a697071de8c3fe08dd3630e3e9785 Mon Sep 17 00:00:00 2001 From: Joost Nieuwenhuijse Date: Wed, 16 May 2018 17:54:56 +0200 Subject: [PATCH 3/8] Change linker script to support C++ exceptions See: https://github.com/espressif/esp-idf/issues/459 https://github.com/jcmvbkbc/crosstool-NG/issues/54 --- ld/program.ld | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ld/program.ld b/ld/program.ld index 5b9031f..e169abd 100644 --- a/ld/program.ld +++ b/ld/program.ld @@ -253,10 +253,13 @@ SECTIONS *(.gnu.linkonce.r.*) __XT_EXCEPTION_TABLE__ = ABSOLUTE(.); *(.xt_except_table) - *(.gcc_except_table) + *(.gcc_except_table .gcc_except_table.*) *(.gnu.linkonce.e.*) *(.gnu.version_r) - *(.eh_frame) + . = (. + 3) & ~ 3; + __eh_frame = ABSOLUTE(.); + KEEP(*(.eh_frame)) + . = (. + 7) & ~ 3; . = ALIGN(4); *(.dynamic) *(.gnu.version_d) From 2985d1d11ef28804fb1777e147aeefc2b7e5f8ca Mon Sep 17 00:00:00 2001 From: Joost Nieuwenhuijse Date: Wed, 16 May 2018 17:56:15 +0200 Subject: [PATCH 4/8] Make operator new / delete weak so you can implement your own, e.g. if you need a throwing operator new. --- core/cplusplus_operators.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/cplusplus_operators.cpp b/core/cplusplus_operators.cpp index 86f4477..b263838 100644 --- a/core/cplusplus_operators.cpp +++ b/core/cplusplus_operators.cpp @@ -4,22 +4,22 @@ #include #include -void *operator new(size_t size) +void * __attribute__((weak)) operator new(size_t size) { return malloc(size); } -void *operator new[](size_t size) +void * __attribute__((weak)) operator new[](size_t size) { return malloc(size); } -void operator delete(void * ptr) +void __attribute__((weak)) operator delete(void * ptr) { free(ptr); } -void operator delete[](void * ptr) +void __attribute__((weak)) operator delete[](void * ptr) { free(ptr); } From 4dc7d825bc2f7d8de2fa5500ec13f307a15b44e7 Mon Sep 17 00:00:00 2001 From: Zaltora Date: Sat, 19 May 2018 23:47:29 +0200 Subject: [PATCH 5/8] Initial HW PWM (Delta-Sigma) (#609) --- core/include/esp/gpio_regs.h | 22 +++---- examples/dsm_test/Makefile | 4 ++ examples/dsm_test/dsm_test.c | 67 +++++++++++++++++++++ extras/dsm/component.mk | 9 +++ extras/dsm/dsm.c | 111 +++++++++++++++++++++++++++++++++++ extras/dsm/dsm.h | 36 ++++++++++++ 6 files changed, 238 insertions(+), 11 deletions(-) create mode 100644 examples/dsm_test/Makefile create mode 100644 examples/dsm_test/dsm_test.c create mode 100644 extras/dsm/component.mk create mode 100644 extras/dsm/dsm.c create mode 100644 extras/dsm/dsm.h diff --git a/core/include/esp/gpio_regs.h b/core/include/esp/gpio_regs.h index c5a446c..167a4d1 100644 --- a/core/include/esp/gpio_regs.h +++ b/core/include/esp/gpio_regs.h @@ -70,7 +70,7 @@ struct GPIO_REGS { uint32_t volatile STATUS_SET; // 0x20 uint32_t volatile STATUS_CLEAR; // 0x24 uint32_t volatile CONF[16]; // 0x28 - 0x64 - uint32_t volatile PWM; // 0x68 + uint32_t volatile DSM; // 0x68 uint32_t volatile RTC_CALIB; // 0x6c uint32_t volatile RTC_CALIB_RESULT; // 0x70 }; @@ -117,9 +117,9 @@ _Static_assert(sizeof(struct GPIO_REGS) == 0x74, "GPIO_REGS is the wrong size"); * GPIO_CONF_OPEN_DRAIN does not appear to work on all pins. * * - * GPIO_CONF_SOURCE_PWM (boolean) - * When set, GPIO pin output will be connected to the sigma-delta PWM - * generator (controlled by the GPIO.PWM register). When cleared, pin + * GPIO_CONF_SOURCE_DSM (boolean) + * When set, GPIO pin output will be connected to the sigma-delta + * generator (controlled by the GPIO.DSM register). When cleared, pin * output will function as a normal GPIO output (controlled by the * GPIO.OUT* registers). */ @@ -130,7 +130,7 @@ _Static_assert(sizeof(struct GPIO_REGS) == 0x74, "GPIO_REGS is the wrong size"); #define GPIO_CONF_INTTYPE_M 0x00000007 #define GPIO_CONF_INTTYPE_S 7 #define GPIO_CONF_OPEN_DRAIN BIT(2) -#define GPIO_CONF_SOURCE_PWM BIT(0) +#define GPIO_CONF_SOURCE_DSM BIT(0) /* Valid values for the GPIO_CONF_INTTYPE field */ typedef enum { @@ -142,13 +142,13 @@ typedef enum { GPIO_INTTYPE_LEVEL_HIGH = 5, } gpio_inttype_t; -/* Details for PWM register */ +/* Details for DSM register */ -#define GPIO_PWM_ENABLE BIT(16) -#define GPIO_PWM_PRESCALER_M 0x000000ff -#define GPIO_PWM_PRESCALER_S 8 -#define GPIO_PWM_TARGET_M 0x000000ff -#define GPIO_PWM_TARGET_S 0 +#define GPIO_DSM_ENABLE BIT(16) +#define GPIO_DSM_PRESCALER_M 0x000000ff +#define GPIO_DSM_PRESCALER_S 8 +#define GPIO_DSM_TARGET_M 0x000000ff +#define GPIO_DSM_TARGET_S 0 /* Details for RTC_CALIB register */ diff --git a/examples/dsm_test/Makefile b/examples/dsm_test/Makefile new file mode 100644 index 0000000..8438f41 --- /dev/null +++ b/examples/dsm_test/Makefile @@ -0,0 +1,4 @@ +# Simple makefile for simple example +PROGRAM=dsm_test +EXTRA_COMPONENTS = extras/dsm +include ../../common.mk diff --git a/examples/dsm_test/dsm_test.c b/examples/dsm_test/dsm_test.c new file mode 100644 index 0000000..234a66b --- /dev/null +++ b/examples/dsm_test/dsm_test.c @@ -0,0 +1,67 @@ +/* Very basic example to test the dsm library + * Led intensity from module will change over time. + * + * Part of esp-open-rtos + * Copyright (C) 2018 zaltora (https://github.com/Zaltora) + * BSD Licensed as described in the file LICENSE + */ +#include "espressif/esp_common.h" +#include "esp/uart.h" +#include "FreeRTOS.h" +#include "task.h" +#include "dsm.h" + +#define TEST_WITH_160MHZ (0) +#define DSM_PIN (2) + +void task1(void *pvParameters) +{ + uint32_t const init_count = 0; + uint32_t count = init_count; + while(1) + { + vTaskDelay(100/portTICK_PERIOD_MS); + printf("Target set to %3u, ", count); + //Freq = (80,000,000/prescale) * (target / 256) HZ (0 < target < 128) + //Freq = (80,000,000/prescale) * ((256 - target) / 256) HZ (128 < target < 256) + if (count < 128) + { + printf("Freqency: %.1f Hz\r\n", (80000000.0/255.0 * (count/ 256.0))); + } + else + { + printf("Freqency: %.1f Hz\r\n", 80000000.0/255.0 * ((256.0-count)/ 256.0)); + } + dsm_set_target(count); + count++; + if (count > UINT8_MAX) + count = init_count; + } +} + +void user_init(void) +{ + uint8_t pins[1]; + uart_set_baud(0, 115200); + +#if (TEST_WITH_160MHZ) + sdk_system_update_cpu_freq(160); +#endif + + printf("SDK version:%s\r\n", sdk_system_get_sdk_version()); + + pins[0] = DSM_PIN; + + /* register pin to use with DSM */ + dsm_init(1, pins); + /* Set prescale to FF to get a proper signal */ + dsm_set_prescale(0xFF); + /* Target initial */ + dsm_set_target(0); + /* start dsm to pin */ + dsm_start(); + + printf("dsm start\r\n"); + + xTaskCreate(task1, "tsk1", 256, NULL, 2, NULL); +} diff --git a/extras/dsm/component.mk b/extras/dsm/component.mk new file mode 100644 index 0000000..06e56b1 --- /dev/null +++ b/extras/dsm/component.mk @@ -0,0 +1,9 @@ +# Component makefile for extras/dsm + +INC_DIRS += $(ROOT)extras/dsm + +# args for passing into compile rule generation +extras/dsm_INC_DIR = $(ROOT)extras/dsm +extras/dsm_SRC_DIR = $(ROOT)extras/dsm + +$(eval $(call component_compile_rules,extras/dsm)) diff --git a/extras/dsm/dsm.c b/extras/dsm/dsm.c new file mode 100644 index 0000000..dd54fc4 --- /dev/null +++ b/extras/dsm/dsm.c @@ -0,0 +1,111 @@ +/* Implementation of Delta-Sigma modulator support. + * + * Part of esp-open-rtos + * Copyright (C) 2018 ourairquality (https://github.com/ourairquality) + * Copyright (C) 2018 Zaltora (https://github.com/Zaltora) + * BSD Licensed as described in the file LICENSE + */ +#include "dsm.h" + +#include +#include + + +#if (DSM_DEBUG) +#define debug(fmt, ...) printf("%s: " fmt "\n", "DSM", ## __VA_ARGS__) +#else +#define debug(fmt, ...) +#endif + +typedef struct dsmInfoDefinition +{ + uint8_t running; + uint8_t preScale; + uint8_t target; + bool output; + + /* private */ + uint8_t usedPins; + uint8_t pins[8]; +} DSMInfo; + +static DSMInfo dsmInfo; + +void dsm_init(uint8_t npins, const uint8_t* pins) +{ + /* Assert number of pins is correct */ + if (npins > MAX_DSM_PINS) + { + debug("Incorrect number of DSM pins (%d)\n", npins); + return; + } + + /* Save pins information */ + dsmInfo.usedPins = npins; + + for (uint8_t i = 0 ; i < npins; ++i) + { + dsmInfo.pins[i] = pins[i]; + /* configure GPIOs */ + gpio_enable(pins[i], GPIO_OUTPUT); + } + + /* Set output to LOW */ + dsm_stop(); + + /* Flag not running */ + dsmInfo.running = 0; +} + +void dsm_set_prescale(uint8_t prescale) +{ + //TODO: Add a freq/prescale converter + dsmInfo.preScale = prescale; + debug("Set Prescale: %u",dsmInfo.preScale); +} + +void dsm_set_target(uint8_t target) +{ + dsmInfo.target = target; + if (target == 0 || target == UINT8_MAX) + { + dsmInfo.output = (target == UINT8_MAX); + } + debug("Duty set at %u",dsmInfo.target); + if (dsmInfo.running) + { + dsm_start(); + } +} + +void dsm_start() +{ + if (dsmInfo.target > 0 && dsmInfo.target < UINT8_MAX) + { + for (uint8_t i = 0; i < dsmInfo.usedPins; ++i) + { + SET_MASK_BITS(GPIO.CONF[dsmInfo.pins[i]], GPIO_CONF_SOURCE_DSM); + } + GPIO.DSM = GPIO_DSM_ENABLE | (dsmInfo.preScale << 8) | dsmInfo.target; + } + else + { + for (uint8_t i = 0; i < dsmInfo.usedPins; ++i) + { + gpio_write(dsmInfo.pins[i], dsmInfo.output ); + } + } + debug("start"); + dsmInfo.running = 1; +} + +void dsm_stop() +{ + for (uint8_t i = 0; i < dsmInfo.usedPins; ++i) + { + CLEAR_MASK_BITS(GPIO.CONF[dsmInfo.pins[i]], GPIO_CONF_SOURCE_DSM); + gpio_write(dsmInfo.pins[i], false); + } + debug("stop"); + dsmInfo.running = 0; +} diff --git a/extras/dsm/dsm.h b/extras/dsm/dsm.h new file mode 100644 index 0000000..8190f7e --- /dev/null +++ b/extras/dsm/dsm.h @@ -0,0 +1,36 @@ +/* Implementation of Delta-Sigma modulator support. + * + * Part of esp-open-rtos + * Copyright (C) 2018 ourairquality (https://github.com/ourairquality) + * Copyright (C) 2018 Zaltora (https://github.com/Zaltora) + * BSD Licensed as described in the file LICENSE + */ +#ifndef EXTRAS_DSM_H_ +#define EXTRAS_DSM_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define MAX_DSM_PINS (8) +#define DSM_DEBUG (0) + +/* + * Freq = (80,000,000/prescale) * (target / 256) HZ (0 < target < 128) + * Freq = (80,000,000/prescale) * ((256 - target) / 256) HZ (128 < target < 256) + */ + +void dsm_init(uint8_t npins, const uint8_t* pins); +void dsm_set_prescale(uint8_t prescale); +void dsm_set_target(uint8_t target); + +void dsm_start(); +void dsm_stop(); + +#ifdef __cplusplus +} +#endif + +#endif /* EXTRAS_DSM_H_ */ From 090db8da5e087171766cf53fef71e4f8eb9d5482 Mon Sep 17 00:00:00 2001 From: Our Air Quality Date: Tue, 5 Jun 2018 22:21:35 +1000 Subject: [PATCH 6/8] sysparam: always create the semaphore on init. Otherwise when initialization was not successful it may fail with an assertion in FreeRTOS rather than returning SYSPARAM_ERR_NOINIT. --- core/sysparam.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/sysparam.c b/core/sysparam.c index 27471a0..19e5ada 100644 --- a/core/sysparam.c +++ b/core/sysparam.c @@ -505,6 +505,8 @@ sysparam_status_t sysparam_init(uint32_t base_addr, uint32_t top_addr) { struct sysparam_context ctx; uint16_t num_sectors; + _sysparam_info.sem = xSemaphoreCreateMutex(); + // Make sure we're starting at the beginning of the sector base_addr -= (base_addr % sdk_flashchip.sector_size); @@ -584,8 +586,6 @@ sysparam_status_t sysparam_init(uint32_t base_addr, uint32_t top_addr) { _sysparam_info.end_addr = ctx.addr; } - _sysparam_info.sem = xSemaphoreCreateMutex(); - return SYSPARAM_OK; } From c3b7a0189196c39a92e2efa14e6ce107cd4fe6eb Mon Sep 17 00:00:00 2001 From: Alex Demenchuk Date: Tue, 5 Jun 2018 16:17:26 -0400 Subject: [PATCH 7/8] Add SPI3 SUPPORT preprocessor macro to CFLAGS --- extras/ssd1306/component.mk | 4 +++- extras/ssd1306/ssd1306.c | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/extras/ssd1306/component.mk b/extras/ssd1306/component.mk index f12a292..2cfb14d 100644 --- a/extras/ssd1306/component.mk +++ b/extras/ssd1306/component.mk @@ -7,11 +7,13 @@ INC_DIRS += $(ssd1306_ROOT).. SSD1306_I2C_SUPPORT ?= 1 # SPI4 support is on by default SSD1306_SPI4_SUPPORT ?= 1 +# SPI3 support is on by default +SSD1306_SPI3_SUPPORT ?= 1 # args for passing into compile rule generation ssd1306_SRC_DIR = $(ssd1306_ROOT) -ssd1306_CFLAGS = -DSSD1306_I2C_SUPPORT=${SSD1306_I2C_SUPPORT} -DSSD1306_SPI4_SUPPORT=${SSD1306_SPI4_SUPPORT} $(CFLAGS) +ssd1306_CFLAGS = -DSSD1306_I2C_SUPPORT=${SSD1306_I2C_SUPPORT} -DSSD1306_SPI4_SUPPORT=${SSD1306_SPI4_SUPPORT} -DSSD1306_SPI3_SUPPORT=${SSD1306_SPI3_SUPPORT} $(CFLAGS) $(eval $(call component_compile_rules,ssd1306)) diff --git a/extras/ssd1306/ssd1306.c b/extras/ssd1306/ssd1306.c index 6ce2c74..df188c5 100644 --- a/extras/ssd1306/ssd1306.c +++ b/extras/ssd1306/ssd1306.c @@ -236,7 +236,9 @@ static int sh1106_go_coordinate(const ssd1306_t *dev, uint8_t x, uint8_t y) int ssd1306_load_frame_buffer(const ssd1306_t *dev, uint8_t buf[]) { uint16_t i; +#if (SSD1306_SPI3_SUPPORT) uint8_t j; +#endif #if (SSD1306_I2C_SUPPORT) uint8_t tab[16] = { 0 }; #endif From b4271792b919e1d178ccea87807a3069cbc86d28 Mon Sep 17 00:00:00 2001 From: Our Air Quality Date: Fri, 8 Jun 2018 11:06:35 +1000 Subject: [PATCH 8/8] i2c: include stdio.h for debugging. --- extras/i2c/i2c.c | 1 + 1 file changed, 1 insertion(+) diff --git a/extras/i2c/i2c.c b/extras/i2c/i2c.c index 204bc98..527b3ac 100644 --- a/extras/i2c/i2c.c +++ b/extras/i2c/i2c.c @@ -32,6 +32,7 @@ //#define I2C_DEBUG true #ifdef I2C_DEBUG +#include #define debug(fmt, ...) printf("%s: " fmt "\n", "I2C", ## __VA_ARGS__) #else #define debug(fmt, ...)