diff --git a/components/base_nodemcu/include/nodemcu_esp_event.h b/components/base_nodemcu/include/nodemcu_esp_event.h new file mode 100644 index 00000000..8411f72e --- /dev/null +++ b/components/base_nodemcu/include/nodemcu_esp_event.h @@ -0,0 +1,75 @@ +/* + * Copyright 2016 Dius Computing Pty Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * - Neither the name of the copyright holders nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Johny Mattsson + */ + +#ifndef _NODEMCU_ESP_EVENT_H_ +#define _NODEMCU_ESP_EVENT_H_ + +#include "esp_event.h" +#include "module.h" + +/** + * Similarly to how a NodeMCU module is registered, a module can register + * to receive copies of ESP system events (e.g. WiFi stack notifications). + * These notifications will come in the form of callbacks within the main + * Lua thread context, making it possible to directly relay information + * through to Lua callbacks/globals. + * + * Registering is as simple as including this header file, then adding a + * line for each event the module wishes to be notified about, e.g.: + * + * NODEMCU_ESP_EVENT(SYSTEM_EVENT_STA_GOT_IP, do_stuff_when_got_ip); + * NODEMCU_ESP_EVENT(SYSTEM_EVENT_STA_DISCONNECTED, do_stuff_when_discon); + * + * These registrations are done at link-time, and consume no additional RAM. + * The event IDs are located in esp_event.h in the IDF. + */ + +// Event callback prototype +typedef void (*nodemcu_esp_event_cb) (const system_event_t *event); + +// System event queue getter (matching esp_event_loop.h's declaration) +QueueHandle_t esp_event_loop_get_queue (void); + +// Internal definitions +typedef struct { + system_event_id_t event_id; + nodemcu_esp_event_cb callback; +} nodemcu_esp_event_reg_t; + +extern nodemcu_esp_event_reg_t *esp_event_cb_table; + +#define NODEMCU_ESP_EVENT(evcode, func) \ + static const LOCK_IN_SECTION(".esp_event_cb_table") \ + nodemcu_esp_event_reg_t MODULE_PASTE_(func,evcode) = { evcode, func }; + +#endif diff --git a/components/base_nodemcu/ld/nodemcu_core.ld b/components/base_nodemcu/ld/nodemcu_core.ld index e0c936b9..2a5ed197 100644 --- a/components/base_nodemcu/ld/nodemcu_core.ld +++ b/components/base_nodemcu/ld/nodemcu_core.ld @@ -9,6 +9,9 @@ SECTIONS { lua_rotable = ABSOLUTE(.); KEEP(*(.lua_rotable)) LONG(0) LONG(0) /* Null-terminate the array */ + esp_event_cb_table = ABSOLUTE(.); + KEEP(*(.esp_event_cb_table)) + LONG(0) LONG(0) /* Null-terminate the array */ } } INSERT AFTER .flash.text diff --git a/components/base_nodemcu/user_main.c b/components/base_nodemcu/user_main.c index 02744439..c2b07c2c 100644 --- a/components/base_nodemcu/user_main.c +++ b/components/base_nodemcu/user_main.c @@ -15,19 +15,79 @@ #include "vfs.h" #include "sdkconfig.h" #include "esp_system.h" +#include "esp_event.h" +#include "nvs_flash.h" #include "flash_api.h" #include "driver/console.h" #include "task/task.h" #include "sections.h" +#include "nodemcu_esp_event.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" +#include "freertos/queue.h" #define SIG_LUA 0 #define SIG_UARTINPUT 1 +static task_handle_t esp_event_task; +static QueueHandle_t esp_event_queue; + +// We provide our own esp_event_send which hooks into the NodeMCU task +// task framework, and ensures all events are handled in the same context +// as the LVM, making life as easy as possible for us. +esp_err_t esp_event_send (system_event_t *event) +{ + if (!event) + return ESP_ERR_INVALID_ARG; + + if (!esp_event_task || !esp_event_queue) + return ESP_ERR_INVALID_STATE; // too early! + + portBASE_TYPE ret = xQueueSendToBack (esp_event_queue, event, 0); + if (ret != pdPASS) + { + NODE_ERR("failed to queue esp event %d", event->event_id); + return ESP_FAIL; + } + + // If the task_post() fails, it only means the event gets delayed, hence + // we claim OK regardless. + task_post_medium (esp_event_task, 0); + return ESP_OK; +} + + +QueueHandle_t esp_event_loop_get_queue (void) +{ + return esp_event_queue; +} + + +static void handle_esp_event (task_param_t param, task_prio_t prio) +{ + (void)param; + (void)prio; + + system_event_t evt; + while (xQueueReceive (esp_event_queue, &evt, 0) == pdPASS) + { + esp_err_t ret = esp_event_process_default (&evt); + if (ret != ESP_OK) + NODE_ERR("default event handler failed for %d", evt.event_id); + + nodemcu_esp_event_reg_t *evregs; + for (evregs = esp_event_cb_table; evregs->callback; ++evregs) + { + if (evregs->event_id == evt.event_id) + evregs->callback (&evt); + } + } +} + + // +================== New task interface ==================+ static void start_lua(task_param_t param, task_prio_t prio) { (void)param; @@ -93,29 +153,29 @@ void nodemcu_init(void) } -static void nodemcu_main (void *param) +void app_main (void) { - (void)param; + esp_event_queue = + xQueueCreate (CONFIG_SYSTEM_EVENT_QUEUE_SIZE, sizeof (system_event_t)); + esp_event_task = task_get_id (handle_esp_event); + + input_task = task_get_id (handle_input); + + ConsoleSetup_t cfg; + cfg.bit_rate = CONFIG_CONSOLE_BIT_RATE; + cfg.data_bits = CONSOLE_NUM_BITS_8; + cfg.parity = CONSOLE_PARITY_NONE; + cfg.stop_bits = CONSOLE_STOP_BITS_1; + cfg.auto_baud = CONFIG_CONSOLE_BIT_RATE_AUTO; + + console_init (&cfg, input_task); + nodemcu_init (); + nvs_flash_init (6, 3); + system_init (); + tcpip_adapter_init (); + task_pump_messages (); __builtin_unreachable (); } - - -void app_main (void) -{ - input_task = task_get_id (handle_input); - - ConsoleSetup_t cfg; - cfg.bit_rate = CONFIG_CONSOLE_BIT_RATE; - cfg.data_bits = CONSOLE_NUM_BITS_8; - cfg.parity = CONSOLE_PARITY_NONE; - cfg.stop_bits = CONSOLE_STOP_BITS_1; - cfg.auto_baud = CONFIG_CONSOLE_BIT_RATE_AUTO; - - console_init (&cfg, input_task); - - xTaskCreate ( - nodemcu_main, "nodemcu", 3072, 0, tskIDLE_PRIORITY +1, NULL); -} diff --git a/sdk/esp32-esp-idf b/sdk/esp32-esp-idf index 4480ab6c..e3ffcd22 160000 --- a/sdk/esp32-esp-idf +++ b/sdk/esp32-esp-idf @@ -1 +1 @@ -Subproject commit 4480ab6c8ce70778df4948e587e712540de237eb +Subproject commit e3ffcd22d533f30550c53023c2c680a1f234f014