diff --git a/Kconfig b/Kconfig new file mode 100644 index 00000000..37ad0dfa --- /dev/null +++ b/Kconfig @@ -0,0 +1,70 @@ +menu "Arduino Configuration" + +config AUTOSTART_ARDUINO + bool "Autostart Arduino setup and loop on boot" + default "n" + help + Enabling this option will implement app_main and start Arduino. + All you need to implement in your main.cpp is setup() and loop() + and include Arduino.h + If disabled, you can call initArduino() to run any preparations + required by the framework + +config DISABLE_HAL_LOCKS + bool "Disable mutex locks for HAL" + default "n" + help + Enabling this option will run all hardware abstraction without locks. + While communication with external hardware will be faster, you need to + make sure that there is no option to use the same bus from another thread + or interrupt at the same time. Option is best used with Arduino enabled + and code implemented only in setup/loop and Arduino callbacks + +menu "Debug Log Configuration" +choice ARDUHAL_LOG_DEFAULT_LEVEL + bool "Default log level" + default ARDUHAL_LOG_DEFAULT_LEVEL_ERROR + help + Specify how much output to see in logs by default. + +config ARDUHAL_LOG_DEFAULT_LEVEL_NONE + bool "No output" +config ARDUHAL_LOG_DEFAULT_LEVEL_ERROR + bool "Error" +config ARDUHAL_LOG_DEFAULT_LEVEL_WARN + bool "Warning" +config ARDUHAL_LOG_DEFAULT_LEVEL_INFO + bool "Info" +config ARDUHAL_LOG_DEFAULT_LEVEL_DEBUG + bool "Debug" +config ARDUHAL_LOG_DEFAULT_LEVEL_VERBOSE + bool "Verbose" +endchoice + +config ARDUHAL_LOG_DEFAULT_LEVEL + int + default 0 if ARDUHAL_LOG_DEFAULT_LEVEL_NONE + default 1 if ARDUHAL_LOG_DEFAULT_LEVEL_ERROR + default 2 if ARDUHAL_LOG_DEFAULT_LEVEL_WARN + default 3 if ARDUHAL_LOG_DEFAULT_LEVEL_INFO + default 4 if ARDUHAL_LOG_DEFAULT_LEVEL_DEBUG + default 5 if ARDUHAL_LOG_DEFAULT_LEVEL_VERBOSE + +config ARDUHAL_LOG_COLORS + bool "Use ANSI terminal colors in log output" + default "n" + help + Enable ANSI terminal color codes in bootloader output. + In order to view these, your terminal program must support ANSI color codes. + +endmenu + +config AUTOCONNECT_WIFI + bool "Autoconnect WiFi on boot" + default "n" + depends on AUTOSTART_ARDUINO + help + If enabled, WiFi will connect to the last used SSID (if station was enabled), + else connection will be started only after calling WiFi.begin(ssid, password) + +endmenu diff --git a/component.mk b/component.mk index 072fd3d3..0d8e061e 100644 --- a/component.mk +++ b/component.mk @@ -1,5 +1,4 @@ COMPONENT_ADD_INCLUDEDIRS := cores/esp32 variants/esp32 libraries/WiFi/src libraries/SPI/src libraries/Wire/src COMPONENT_PRIV_INCLUDEDIRS := cores/esp32/libb64 COMPONENT_SRCDIRS := cores/esp32/libb64 cores/esp32 variants/esp32 libraries/WiFi/src libraries/SPI/src libraries/Wire/src -include $(IDF_PATH)/make/component_common.mk CXXFLAGS += -fno-rtti diff --git a/cores/esp32/esp32-hal-i2c.c b/cores/esp32/esp32-hal-i2c.c index fefd761a..a803d287 100644 --- a/cores/esp32/esp32-hal-i2c.c +++ b/cores/esp32/esp32-hal-i2c.c @@ -30,7 +30,9 @@ struct i2c_struct_t { i2c_dev_t * dev; +#if !CONFIG_DISABLE_HAL_LOCKS xSemaphoreHandle lock; +#endif uint8_t num; }; @@ -42,6 +44,15 @@ enum { I2C_CMD_END }; +#if CONFIG_DISABLE_HAL_LOCKS +#define I2C_MUTEX_LOCK() +#define I2C_MUTEX_UNLOCK() + +static i2c_t _i2c_bus_array[2] = { + {(volatile i2c_dev_t *)(DR_REG_I2C_EXT_BASE), 0}, + {(volatile i2c_dev_t *)(DR_REG_I2C1_EXT_BASE), 1} +}; +#else #define I2C_MUTEX_LOCK() do {} while (xSemaphoreTake(i2c->lock, portMAX_DELAY) != pdPASS) #define I2C_MUTEX_UNLOCK() xSemaphoreGive(i2c->lock) @@ -49,6 +60,7 @@ static i2c_t _i2c_bus_array[2] = { {(volatile i2c_dev_t *)(DR_REG_I2C_EXT_BASE), NULL, 0}, {(volatile i2c_dev_t *)(DR_REG_I2C1_EXT_BASE), NULL, 1} }; +#endif i2c_err_t i2cAttachSCL(i2c_t * i2c, int8_t scl) { @@ -353,12 +365,14 @@ i2c_t * i2cInit(uint8_t i2c_num, uint16_t slave_addr, bool addr_10bit_en) i2c_t * i2c = &_i2c_bus_array[i2c_num]; +#if !CONFIG_DISABLE_HAL_LOCKS if(i2c->lock == NULL){ i2c->lock = xSemaphoreCreateMutex(); if(i2c->lock == NULL) { return NULL; } } +#endif if(i2c_num == 0) { SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG,DPORT_I2C_EXT0_CLK_EN); diff --git a/cores/esp32/esp32-hal-ledc.c b/cores/esp32/esp32-hal-ledc.c index 1df209ae..2fe70d6e 100644 --- a/cores/esp32/esp32-hal-ledc.c +++ b/cores/esp32/esp32-hal-ledc.c @@ -22,11 +22,14 @@ #include "soc/ledc_reg.h" #include "soc/ledc_struct.h" -xSemaphoreHandle _ledc_sys_lock; - - +#if CONFIG_DISABLE_HAL_LOCKS +#define LEDC_MUTEX_LOCK() +#define LEDC_MUTEX_UNLOCK() +#else #define LEDC_MUTEX_LOCK() do {} while (xSemaphoreTake(_ledc_sys_lock, portMAX_DELAY) != pdPASS) #define LEDC_MUTEX_UNLOCK() xSemaphoreGive(_ledc_sys_lock) +xSemaphoreHandle _ledc_sys_lock; +#endif /* * LEDC Chan to Group/Channel/Timer Mapping @@ -59,7 +62,9 @@ void ledcSetupTimer(uint8_t chan, uint32_t div_num, uint8_t bit_num, bool apb_cl SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_LEDC_CLK_EN); CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_LEDC_RST); ledc_dev->conf.apb_clk_sel = 1;//LS use apb clock +#if !CONFIG_DISABLE_HAL_LOCKS _ledc_sys_lock = xSemaphoreCreateMutex(); +#endif } LEDC_MUTEX_LOCK(); ledc_dev->timer_group[group].timer[timer].conf.div_num = div_num;//18 bit (10.8) This register is used to configure parameter for divider in timer the least significant eight bits represent the decimal part. diff --git a/cores/esp32/esp32-hal-misc.c b/cores/esp32/esp32-hal-misc.c index 07e2e27f..9cf2b800 100644 --- a/cores/esp32/esp32-hal-misc.c +++ b/cores/esp32/esp32-hal-misc.c @@ -47,6 +47,21 @@ void delayMicroseconds(uint32_t us) } } +void initVariant() __attribute__((weak)); +void initVariant() {} + +void init() __attribute__((weak)); +void init() {} + +void initWiFi() __attribute__((weak)); +void initWiFi() {} + +void initArduino(){ + init(); + initVariant(); + initWiFi(); +} + //used by hal log const char * IRAM_ATTR pathToFileName(const char * path){ size_t i = 0; diff --git a/cores/esp32/esp32-hal-sd.c b/cores/esp32/esp32-hal-sd.c index 8fdb83ad..6627f553 100644 --- a/cores/esp32/esp32-hal-sd.c +++ b/cores/esp32/esp32-hal-sd.c @@ -21,11 +21,15 @@ #include "soc/gpio_sd_reg.h" #include "soc/gpio_sd_struct.h" -xSemaphoreHandle _sd_sys_lock; +#if CONFIG_DISABLE_HAL_LOCKS +#define SD_MUTEX_LOCK() +#define SD_MUTEX_UNLOCK() +#else #define SD_MUTEX_LOCK() do {} while (xSemaphoreTake(_sd_sys_lock, portMAX_DELAY) != pdPASS) #define SD_MUTEX_UNLOCK() xSemaphoreGive(_sd_sys_lock) - +xSemaphoreHandle _sd_sys_lock; +#endif uint32_t sdSetup(uint8_t channel, uint32_t freq) //chan 0-7 freq 1220-312500 { @@ -35,7 +39,9 @@ uint32_t sdSetup(uint8_t channel, uint32_t freq) //chan 0-7 freq 1220-312500 static bool tHasStarted = false; if(!tHasStarted) { tHasStarted = true; +#if !CONFIG_DISABLE_HAL_LOCKS _sd_sys_lock = xSemaphoreCreateMutex(); +#endif } gpio_sd_dev_t * gpio_sd_dev = (volatile gpio_sd_dev_t *)(DR_REG_GPIO_SD_BASE); uint32_t prescale = (10000000/(freq*32)) - 1; diff --git a/cores/esp32/esp32-hal-spi.c b/cores/esp32/esp32-hal-spi.c index 39654453..09052c6c 100644 --- a/cores/esp32/esp32-hal-spi.c +++ b/cores/esp32/esp32-hal-spi.c @@ -41,10 +41,23 @@ struct spi_struct_t { spi_dev_t * dev; +#if !CONFIG_DISABLE_HAL_LOCKS xSemaphoreHandle lock; +#endif uint8_t num; }; +#if CONFIG_DISABLE_HAL_LOCKS +#define SPI_MUTEX_LOCK() +#define SPI_MUTEX_UNLOCK() + +static spi_t _spi_bus_array[4] = { + {(volatile spi_dev_t *)(DR_REG_SPI0_BASE), 0}, + {(volatile spi_dev_t *)(DR_REG_SPI1_BASE), 1}, + {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), 2}, + {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), 3} +}; +#else #define SPI_MUTEX_LOCK() do {} while (xSemaphoreTake(spi->lock, portMAX_DELAY) != pdPASS) #define SPI_MUTEX_UNLOCK() xSemaphoreGive(spi->lock) @@ -54,6 +67,7 @@ static spi_t _spi_bus_array[4] = { {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 2}, {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), NULL, 3} }; +#endif void spiAttachSCK(spi_t * spi, int8_t sck) { @@ -383,12 +397,14 @@ spi_t * spiStartBus(uint8_t spi_num, uint32_t clockDiv, uint8_t dataMode, uint8_ spi_t * spi = &_spi_bus_array[spi_num]; +#if !CONFIG_DISABLE_HAL_LOCKS if(spi->lock == NULL){ spi->lock = xSemaphoreCreateMutex(); if(spi->lock == NULL) { return NULL; } } +#endif if(spi_num == HSPI) { SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_CLK_EN_1); diff --git a/cores/esp32/esp32-hal-uart.c b/cores/esp32/esp32-hal-uart.c index 127a5881..a2194827 100644 --- a/cores/esp32/esp32-hal-uart.c +++ b/cores/esp32/esp32-hal-uart.c @@ -40,11 +40,23 @@ 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; }; +#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}, + {(volatile uart_dev_t *)(DR_REG_UART1_BASE), 1, NULL}, + {(volatile uart_dev_t *)(DR_REG_UART2_BASE), 2, NULL} +}; +#else #define UART_MUTEX_LOCK() do {} while (xSemaphoreTake(uart->lock, portMAX_DELAY) != pdPASS) #define UART_MUTEX_UNLOCK() xSemaphoreGive(uart->lock) @@ -53,6 +65,7 @@ static uart_t _uart_bus_array[3] = { {(volatile uart_dev_t *)(DR_REG_UART1_BASE), NULL, 1, NULL}, {(volatile uart_dev_t *)(DR_REG_UART2_BASE), NULL, 2, NULL} }; +#endif static void IRAM_ATTR _uart_isr(void *arg) { @@ -163,12 +176,14 @@ uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rx 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 @@ -379,6 +394,7 @@ int log_printf(const char *format, ...) } } 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); @@ -386,6 +402,9 @@ int log_printf(const char *format, ...) } else { ets_printf("%s", temp); } +#else + ets_printf("%s", temp); +#endif va_end(arg); if(len > 64){ free(temp); diff --git a/cores/esp32/esp32-hal.h b/cores/esp32/esp32-hal.h index 69d316f7..67b9ad3a 100644 --- a/cores/esp32/esp32-hal.h +++ b/cores/esp32/esp32-hal.h @@ -33,6 +33,14 @@ extern "C" { #include #include +#ifndef CONFIG_DISABLE_HAL_LOCKS +#define CONFIG_DISABLE_HAL_LOCKS 0 +#endif + +#ifndef CONFIG_AUTOSTART_ARDUINO +#define CONFIG_AUTOSTART_ARDUINO 1 +#endif + //forward declaration from freertos/portmacro.h void vPortYield( void ); #define yield() vPortYield() @@ -56,6 +64,10 @@ uint32_t millis(); void delay(uint32_t); void delayMicroseconds(uint32_t us); +#if !CONFIG_AUTOSTART_ARDUINO +void initArduino(); +#endif + #ifdef __cplusplus } #endif diff --git a/cores/esp32/main.cpp b/cores/esp32/main.cpp index 80fd075f..3889f4df 100644 --- a/cores/esp32/main.cpp +++ b/cores/esp32/main.cpp @@ -1,21 +1,16 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" +#include "esp32-hal.h" -void initVariant() __attribute__((weak)); -void initVariant() {} +#if CONFIG_AUTOSTART_ARDUINO -void init() __attribute__((weak)); -void init() {} +extern "C" void initArduino(); +extern void loop(); +extern void setup(); void startWiFi() __attribute__((weak)); void startWiFi() {} -void initWiFi() __attribute__((weak)); -void initWiFi() {} - -extern void loop(); -extern void setup(); - void loopTask(void *pvParameters) { bool setup_done = false; @@ -31,9 +26,8 @@ void loopTask(void *pvParameters) extern "C" void app_main() { - init(); - initVariant(); - initWiFi(); + initArduino(); xTaskCreatePinnedToCore(loopTask, "loopTask", 4096, NULL, 1, NULL, 1); } +#endif diff --git a/libraries/WiFi/src/WiFiGeneric.cpp b/libraries/WiFi/src/WiFiGeneric.cpp index d9a4efc4..adbc1d46 100644 --- a/libraries/WiFi/src/WiFiGeneric.cpp +++ b/libraries/WiFi/src/WiFiGeneric.cpp @@ -282,7 +282,7 @@ void wifi_dns_found_callback(const char *name, const ip_addr_t *ipaddr, void *ca * */ #include "nvs_flash.h" -void initWiFi() +extern "C" void initWiFi() { wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); nvs_flash_init(); @@ -294,14 +294,15 @@ void initWiFi() void startWiFi() { esp_err_t err; - wifi_mode_t mode = WIFI_MODE_NULL; - bool auto_connect = false; err = esp_wifi_start(); if (err != ESP_OK) { log_e("esp_wifi_start: %d", err); return; } +#if CONFIG_AUTOCONNECT_WIFI + wifi_mode_t mode = WIFI_MODE_NULL; + bool auto_connect = false; err = esp_wifi_get_mode(&mode); if (err != ESP_OK) { @@ -316,5 +317,6 @@ void startWiFi() log_e("esp_wifi_connect: %d", err); } } +#endif }