diff options
author | Uros Majstorovic <majstor@majstor.org> | 2025-07-28 23:37:45 +0200 |
---|---|---|
committer | Uros Majstorovic <majstor@majstor.org> | 2025-07-28 23:37:45 +0200 |
commit | fc70c6f78f43dbeda91d47b2d2071d4da4082121 (patch) | |
tree | c104744b62d3ea2c1a4a05eaab8283f368215300 /fw | |
parent | 58f41971b1e801ad2fbcea08e5152afa2b18ca73 (diff) |
upgrade to ESP-IDF v5; fixed SPI net and app protocoles; reimplemented power management;
Diffstat (limited to 'fw')
28 files changed, 1521 insertions, 956 deletions
diff --git a/fw/esp32/CMakeLists.txt b/fw/esp32/CMakeLists.txt new file mode 100644 index 0000000..c81db52 --- /dev/null +++ b/fw/esp32/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(eos_app) diff --git a/fw/esp32/components/eos/CMakeLists.txt b/fw/esp32/components/eos/CMakeLists.txt new file mode 100644 index 0000000..404b855 --- /dev/null +++ b/fw/esp32/components/eos/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS "app_main.c" "msgq.c" "unicode.c" "gsm.c" "gsm_cp.c" "at_cmd.c" "cell.c" "cell_modem.c" "cell_pcm.c" "cell_voice.c" "cell_ussd.c" "cell_sms.c" "cell_pdp.c" "wifi.c" "net.c" "power.c" "rng.c" "sock.c" "app.c" "tun.c" + INCLUDE_DIRS "include" + REQUIRES esp_driver_gpio esp_driver_spi esp_driver_uart esp_driver_i2s esp_event esp_netif esp_wifi esp_timer vfs) diff --git a/fw/esp32/components/eos/app.c b/fw/esp32/components/eos/app.c index 8396376..662da17 100644 --- a/fw/esp32/components/eos/app.c +++ b/fw/esp32/components/eos/app.c @@ -15,209 +15,142 @@ #include "eos.h" #include "msgq.h" +#include "power.h" #include "app.h" +#include "net_priv.h" -#define SPI_GPIO_CTS 26 -#define SPI_GPIO_RTS 27 -#define SPI_GPIO_MOSI 13 -#define SPI_GPIO_MISO 12 -#define SPI_GPIO_SCLK 14 -#define SPI_GPIO_CS 15 +#define SPI_GPIO_CTS 9 +#define SPI_GPIO_RTS 47 +#define SPI_GPIO_MOSI 11 +#define SPI_GPIO_MISO 13 +#define SPI_GPIO_SCLK 12 +#define SPI_GPIO_CS 10 -#define SPI_SIZE_BUF (EOS_APP_SIZE_BUF + 8) +#define SPI_SIZE_BUF (EOS_APP_SIZE_BUF + 4) #define SPI_SIZE_HDR 3 +#define SPI_HOST SPI2_HOST + static EOSBufQ app_buf_q; static unsigned char *app_bufq_array[EOS_APP_SIZE_BUFQ]; static EOSMsgQ app_send_q; static EOSMsgItem app_sndq_array[EOS_APP_SIZE_SNDQ]; -static SemaphoreHandle_t mutex; -static SemaphoreHandle_t semaph; -static TaskHandle_t app_xchg_task_handle; -static const char *TAG = "EOS APP"; +static NETConfig app_config; +static eos_net_handler_t app_handler[EOS_APP_MAX_MTYPE]; + +static spi_bus_config_t app_spi_bus_cfg; +static spi_slave_interface_config_t app_spi_iface_cfg; +static spi_slave_transaction_t app_spi_tr_cfg; -static eos_app_fptr_t app_handler[EOS_APP_MAX_MTYPE]; +static const char *TAG = "EOS APP"; static void bad_handler(unsigned char mtype, unsigned char *buffer, uint16_t len) { - ESP_LOGE(TAG, "bad handler: %d len: %d", mtype, len); + ESP_LOGE(TAG, "bad handler: 0x%.2X len: %d", mtype, len); } -// Called after a transaction is queued and ready for pickup by master. We use this to set the handshake line high. -static void _post_setup_cb(spi_slave_transaction_t *trans) { - gpio_set_level(SPI_GPIO_CTS, 1); -} +static void app_msg_handler(unsigned char mtype, unsigned char *buffer, uint16_t buf_len) { + uint8_t idx; -// Called after transaction is sent/received. We use this to set the handshake line low. -static void _post_trans_cb(spi_slave_transaction_t *trans) { - gpio_set_level(SPI_GPIO_CTS, 0); -} - -static void app_xchg_task(void *pvParameters) { - unsigned char mtype = 0; - unsigned char *buffer; - uint16_t len; - unsigned char *buf_send = heap_caps_malloc(SPI_SIZE_BUF, MALLOC_CAP_DMA); - unsigned char *buf_recv = heap_caps_malloc(SPI_SIZE_BUF, MALLOC_CAP_DMA); - esp_err_t ret; - size_t trans_len; - - static spi_slave_transaction_t spi_tr; - - //Configuration for the SPI bus - static spi_bus_config_t spi_bus_cfg = { - .mosi_io_num = SPI_GPIO_MOSI, - .miso_io_num = SPI_GPIO_MISO, - .sclk_io_num = SPI_GPIO_SCLK - }; - - //Configuration for the SPI slave interface - static spi_slave_interface_config_t spi_slave_cfg = { - .mode = 0, - .spics_io_num = SPI_GPIO_CS, - .queue_size = 2, - .flags = 0, - .post_setup_cb = _post_setup_cb, - .post_trans_cb = _post_trans_cb - }; - - //Initialize SPI slave interface - ret = spi_slave_initialize(HSPI_HOST, &spi_bus_cfg, &spi_slave_cfg, 1); - assert(ret == ESP_OK); - - memset(&spi_tr, 0, sizeof(spi_tr)); - spi_tr.tx_buffer = buf_send; - spi_tr.rx_buffer = buf_recv; - spi_tr.length = SPI_SIZE_BUF * 8; - - while (1) { - xSemaphoreTake(mutex, portMAX_DELAY); - - eos_msgq_pop(&app_send_q, &mtype, &buffer, &len); - if (mtype) { - buf_send[0] = mtype; - buf_send[1] = len >> 8; - buf_send[2] = len & 0xFF; - if (buffer) { - memcpy(buf_send + SPI_SIZE_HDR, buffer, len); - eos_bufq_push(&app_buf_q, buffer); - xSemaphoreGive(semaph); - } - } else { - gpio_set_level(SPI_GPIO_RTS, 0); - buf_send[0] = 0; - buf_send[1] = 0; - buf_send[2] = 0; - len = 0; - } - - xSemaphoreGive(mutex); - - buf_recv[0] = 0; - buf_recv[1] = 0; - buf_recv[2] = 0; - spi_slave_transmit(HSPI_HOST, &spi_tr, portMAX_DELAY); - - trans_len = spi_tr.trans_len / 8; - if (trans_len < SPI_SIZE_HDR) continue; - - if (len + SPI_SIZE_HDR > trans_len) { - spi_tr.tx_buffer = buf_send + trans_len; - spi_tr.rx_buffer = buf_recv + trans_len; - spi_tr.length = (SPI_SIZE_BUF - trans_len) * 8; - spi_slave_transmit(HSPI_HOST, &spi_tr, portMAX_DELAY); - spi_tr.tx_buffer = buf_send; - spi_tr.rx_buffer = buf_recv; - spi_tr.length = SPI_SIZE_BUF * 8; - } - mtype = buf_recv[0] & ~EOS_APP_MTYPE_FLAG_MASK; - len = (uint16_t)buf_recv[1] << 8; - len |= (uint16_t)buf_recv[2] & 0xFF; - buffer = buf_recv + 3; - - if (mtype == 0x00) continue; - - if ((mtype <= EOS_APP_MAX_MTYPE) && (len <= EOS_APP_MTU)) { - app_handler[mtype - 1](mtype, buffer, len); - } else { - bad_handler(mtype, buffer, len); - } + idx = mtype & EOS_NET_MTYPE_MASK; + if (idx && (idx <= EOS_APP_MAX_MTYPE) && (buf_len <= EOS_APP_MTU)) { + app_handler[idx - 1](mtype, buffer, buf_len); + } else { + bad_handler(mtype, buffer, buf_len); } - vTaskDelete(NULL); } void eos_app_init(void) { + SemaphoreHandle_t mutex; + SemaphoreHandle_t bufq_mutex; + SemaphoreHandle_t bufq_semaph; int i; - // Configuration for the handshake lines - gpio_config_t io_conf = {}; - - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.mode = GPIO_MODE_OUTPUT; - io_conf.pull_up_en = 0; - io_conf.pull_down_en = 0; - io_conf.pin_bit_mask = ((uint64_t)1 << SPI_GPIO_CTS); - gpio_config(&io_conf); - gpio_set_level(SPI_GPIO_CTS, 0); - - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.mode = GPIO_MODE_OUTPUT; - io_conf.pull_up_en = 0; - io_conf.pull_down_en = 0; - io_conf.pin_bit_mask = ((uint64_t)1 << SPI_GPIO_RTS); - gpio_config(&io_conf); - gpio_set_level(SPI_GPIO_RTS, 0); - eos_msgq_init(&app_send_q, app_sndq_array, EOS_APP_SIZE_SNDQ); eos_bufq_init(&app_buf_q, app_bufq_array, EOS_APP_SIZE_BUFQ); for (i=0; i<EOS_APP_SIZE_BUFQ; i++) { - eos_bufq_push(&app_buf_q, malloc(EOS_APP_SIZE_BUF)); + unsigned char *buffer; + + buffer = malloc(EOS_APP_SIZE_BUF); + assert(buffer != NULL); + eos_bufq_push(&app_buf_q, buffer); } for (i=0; i<EOS_APP_MAX_MTYPE; i++) { app_handler[i] = bad_handler; } - semaph = xSemaphoreCreateCounting(EOS_APP_SIZE_BUFQ, EOS_APP_SIZE_BUFQ); mutex = xSemaphoreCreateBinary(); + assert(mutex != NULL); + bufq_mutex = xSemaphoreCreateBinary(); + assert(bufq_mutex != NULL); + bufq_semaph = xSemaphoreCreateCounting(EOS_APP_SIZE_BUFQ, EOS_APP_SIZE_BUFQ); + assert(bufq_semaph != NULL); + xSemaphoreGive(mutex); - xTaskCreate(&app_xchg_task, "app_xchg", EOS_TASK_SSIZE_APP_XCHG, NULL, EOS_TASK_PRIORITY_APP_XCHG, &app_xchg_task_handle); + xSemaphoreGive(bufq_mutex); + + app_config.sleep = 0; + app_config.sleep_req = 0; + app_config.present = 0; + app_config.dev = NET_DEV_APP; + app_config.gpio_mosi = SPI_GPIO_MOSI; + app_config.gpio_miso = SPI_GPIO_MISO; + app_config.gpio_sclk = SPI_GPIO_SCLK; + app_config.gpio_cs = SPI_GPIO_CS; + app_config.gpio_rts = SPI_GPIO_RTS; + app_config.gpio_cts = SPI_GPIO_CTS; + app_config.spi_host = SPI_HOST; + app_config.spi_bus_cfg = &app_spi_bus_cfg; + app_config.spi_iface_cfg = &app_spi_iface_cfg; + app_config.spi_tr_cfg = &app_spi_tr_cfg; + app_config.mutex = mutex; + app_config.bufq_mutex = bufq_mutex; + app_config.bufq_semaph = bufq_semaph; + app_config.buf_q = &app_buf_q; + app_config.send_q = &app_send_q; + app_config.msg_handler = app_msg_handler; + + _eos_net_init_gpio(&app_config); + + if (esp_reset_reason() == ESP_RST_DEEPSLEEP) { + gpio_hold_dis(app_config.gpio_cts); + } + ESP_LOGI(TAG, "INIT"); } -unsigned char *eos_app_alloc(void) { - unsigned char *ret; +void eos_app_run(void) { + BaseType_t rv; - xSemaphoreTake(semaph, portMAX_DELAY); - xSemaphoreTake(mutex, portMAX_DELAY); - ret = eos_bufq_pop(&app_buf_q); - xSemaphoreGive(mutex); + rv = xTaskCreate(&eos_net_xchg_task, "app_xchg", EOS_TASK_SSIZE_APP, &app_config, EOS_TASK_PRIORITY_APP, &app_config.xchg_task_handle); + assert(rv == pdPASS); - return ret; + ESP_LOGI(TAG, "RUN"); } -void eos_app_free(unsigned char *buf) { - xSemaphoreTake(mutex, portMAX_DELAY); - eos_bufq_push(&app_buf_q, buf); - xSemaphoreGive(semaph); - xSemaphoreGive(mutex); +unsigned char *eos_app_alloc(void) { + return _eos_net_alloc(&app_config); } -int eos_app_send(unsigned char mtype, unsigned char *buffer, uint16_t len) { - int rv = EOS_OK; +void eos_app_free(unsigned char *buf) { + _eos_net_free(&app_config, buf); +} - xSemaphoreTake(mutex, portMAX_DELAY); - gpio_set_level(SPI_GPIO_RTS, 1); - rv = eos_msgq_push(&app_send_q, mtype, buffer, len); - xSemaphoreGive(mutex); +int eos_app_send(unsigned char mtype, unsigned char *buffer, uint16_t buf_len) { + return _eos_net_send(&app_config, mtype, buffer, buf_len); +} - if (rv) eos_app_free(buffer); +void eos_app_sleep_req(void) { + _eos_net_sleep_req(&app_config); +} - return rv; +void eos_app_wake(void) { + _eos_net_wake(&app_config); } -void eos_app_set_handler(unsigned char mtype, eos_app_fptr_t handler) { +void eos_app_set_handler(unsigned char mtype, eos_net_handler_t handler) { if (handler == NULL) handler = bad_handler; if (mtype && (mtype <= EOS_APP_MAX_MTYPE)) app_handler[mtype - 1] = handler; } diff --git a/fw/esp32/main/app_main.c b/fw/esp32/components/eos/app_main.c index 79f76ab..e096a23 100644 --- a/fw/esp32/main/app_main.c +++ b/fw/esp32/components/eos/app_main.c @@ -2,6 +2,8 @@ #include <freertos/task.h> #include <driver/gpio.h> +#include <esp_system.h> + #include <esp_event.h> #include <esp_netif.h> #include <esp_err.h> @@ -9,19 +11,17 @@ #include "i2c.h" #include "cell.h" -#include "_net.h" +#include "net.h" #include "wifi.h" #include "sock.h" #include "rng.h" -#ifdef EOS_WITH_APP #include "app.h" #include "tun.h" -#endif #include "power.h" #define ESP_INTR_FLAG_DEFAULT 0 -// Main application +/* main application */ void app_main() { esp_err_t ret; @@ -31,21 +31,28 @@ void app_main() { ret = esp_event_loop_create_default(); assert(ret == ESP_OK); - eos_net_init(); + ret = gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT); + assert(ret == ESP_OK); - eos_cell_pcm_init(); - gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT); + eos_power_init(); + + eos_net_init(); + eos_app_init(); + eos_tun_init(); eos_modem_init(); eos_cell_init(); + eos_cell_pcm_init(); eos_wifi_init(); eos_sock_init(); eos_rng_init(); -#ifdef EOS_WITH_APP - eos_app_init(); - eos_tun_init(); -#endif - eos_power_init(); + eos_power_run(); + eos_net_run(); + eos_app_run(); + eos_modem_run(); + eos_cell_run(); + eos_wifi_run(); + eos_sock_run(); } diff --git a/fw/esp32/components/eos/at_cmd.c b/fw/esp32/components/eos/at_cmd.c index a1c329e..d9ec228 100644 --- a/fw/esp32/components/eos/at_cmd.c +++ b/fw/esp32/components/eos/at_cmd.c @@ -36,6 +36,7 @@ void at_init(void) { memset(&urc_list, 0, sizeof(ATURCList)); mutex = xSemaphoreCreateBinary(); + assert(mutex != NULL); xSemaphoreGive(mutex); } diff --git a/fw/esp32/components/eos/cell.c b/fw/esp32/components/eos/cell.c index d34172e..8665616 100644 --- a/fw/esp32/components/eos/cell.c +++ b/fw/esp32/components/eos/cell.c @@ -17,8 +17,6 @@ static const char *TAG = "EOS CELL"; -static uint8_t cell_mode; - static EOSBufQ cell_buf_q; static unsigned char *cell_bufq_array[CELL_SIZE_QUEUE]; @@ -28,8 +26,6 @@ static QueueHandle_t cell_queue; static void _cell_handler(unsigned char _mtype, unsigned char *buffer, uint16_t buf_len) { uint8_t mtype; - if (buf_len < 1) return; - mtype = buffer[0]; switch (mtype & EOS_CELL_MTYPE_MASK) { case EOS_CELL_MTYPE_DEV: { @@ -43,29 +39,47 @@ static void _cell_handler(unsigned char _mtype, unsigned char *buffer, uint16_t } case EOS_CELL_MTYPE_RESET: { + int rv; + + rv = eos_modem_take(1000); + if (rv) { + ESP_LOGE(TAG, "Reset modem failed: %d", rv); + break; + } eos_modem_reset(); + eos_modem_give(); break; } case EOS_CELL_MTYPE_UART_TAKE: { - uint8_t mode; - - mode = eos_modem_get_mode(); - if (mode == EOS_CELL_UART_MODE_NONE) break; + int rv; - eos_modem_set_mode(EOS_CELL_UART_MODE_RELAY); - cell_mode = mode; + if (eos_modem_get_mode() == EOS_CELL_UART_MODE_ATCMD) { + rv = eos_modem_set_mode(EOS_CELL_UART_MODE_RELAY); + if (rv) ESP_LOGE(TAG, "Set RELAY mode failed: %d", rv); + } break; } case EOS_CELL_MTYPE_UART_GIVE: { - eos_modem_atinit(); - eos_modem_set_mode(cell_mode); + int rv; + + if (eos_modem_get_mode() == EOS_CELL_UART_MODE_RELAY) { + rv = eos_modem_take(1000); + if (!rv) { + eos_modem_atinit(); + eos_modem_give(); + } + rv = eos_modem_set_mode(EOS_CELL_UART_MODE_ATCMD); + if (rv) ESP_LOGE(TAG, "Set ATCMD mode failed: %d", rv); + } break; } case EOS_CELL_MTYPE_UART_DATA: { - if (eos_modem_get_mode() == EOS_CELL_UART_MODE_RELAY) eos_modem_write(buffer + 1, buf_len - 1); + if (eos_modem_get_mode() == EOS_CELL_UART_MODE_RELAY) { + eos_modem_write(buffer + 1, buf_len - 1); + } break; } } @@ -108,23 +122,30 @@ static void cell_handler_task(void *pvParameters) { vTaskDelete(NULL); } -static void cell_handler(unsigned char type, unsigned char *buffer, uint16_t len) { +static void cell_handler(unsigned char type, unsigned char *buffer, uint16_t buf_len) { EOSMsgItem mi; - unsigned char *buf; + unsigned char *_buffer; + + if (buf_len < 1) return; + + if (type & EOS_NET_MTYPE_FLAG_REPL) { + _cell_handler(type, buffer, buf_len); + return; + } xSemaphoreTake(mutex, portMAX_DELAY); - buf = eos_bufq_pop(&cell_buf_q); + _buffer = eos_bufq_pop(&cell_buf_q); xSemaphoreGive(mutex); - if (buf == NULL) { - if (len) ESP_LOGE(TAG, "Cell message NOT handled: %2x", buffer[0]); + if (_buffer == NULL) { + ESP_LOGE(TAG, "Cell message NOT handled: %2x", buffer[0]); return; } - memcpy(buf, buffer, len); + memcpy(_buffer, buffer, buf_len); mi.type = type; - mi.buffer = buf; - mi.len = len; + mi.buffer = _buffer; + mi.len = buf_len; xQueueSend(cell_queue, &mi, portMAX_DELAY); } @@ -133,13 +154,30 @@ void eos_cell_init(void) { eos_bufq_init(&cell_buf_q, cell_bufq_array, CELL_SIZE_QUEUE); for (i=0; i<CELL_SIZE_QUEUE; i++) { - eos_bufq_push(&cell_buf_q, malloc(EOS_NET_SIZE_BUF)); + unsigned char *buffer; + + buffer = malloc(EOS_NET_SIZE_BUF); + assert(buffer != NULL); + eos_bufq_push(&cell_buf_q, buffer); } mutex = xSemaphoreCreateBinary(); + assert(mutex != NULL); xSemaphoreGive(mutex); + cell_queue = xQueueCreate(CELL_SIZE_QUEUE, sizeof(EOSMsgItem)); - xTaskCreate(cell_handler_task, "cell_handler", EOS_TASK_SSIZE_CELL, NULL, EOS_TASK_PRIORITY_CELL, NULL); + assert(cell_queue != NULL); eos_net_set_handler(EOS_NET_MTYPE_CELL, cell_handler); + + ESP_LOGI(TAG, "INIT"); +} + +void eos_cell_run(void) { + BaseType_t rv; + + rv = xTaskCreate(cell_handler_task, "cell_handler", EOS_TASK_SSIZE_CELL, NULL, EOS_TASK_PRIORITY_CELL, NULL); + assert(rv == pdPASS); + + ESP_LOGI(TAG, "RUN"); } diff --git a/fw/esp32/components/eos/cell_modem.c b/fw/esp32/components/eos/cell_modem.c index b279db1..4f8efd1 100644 --- a/fw/esp32/components/eos/cell_modem.c +++ b/fw/esp32/components/eos/cell_modem.c @@ -5,12 +5,15 @@ #include <freertos/semphr.h> #include <freertos/task.h> #include <freertos/queue.h> + #include <netif/ppp/pppos.h> #include <netif/ppp/pppapi.h> + #include <driver/uart.h> #include <driver/gpio.h> + +#include <esp_system.h> #include <esp_timer.h> -#include <esp_sleep.h> #include <esp_log.h> #include "eos.h" @@ -24,30 +27,37 @@ #define UART_SIZE_IO_BUF 8192 -#define UART_GPIO_TXD 16 +// XXX: TXD and RXD switched for Quectel, fixed in new revision +#define UART_GPIO_TXD 18 #define UART_GPIO_RXD 17 -#define UART_GPIO_DTR 32 -#define UART_GPIO_RI 35 +#define UART_GPIO_DTR 15 +#define UART_GPIO_RI 16 +#define MODEM_GPIO_RST 6 +#define MODEM_GPIO_USB_EN 7 +#define MODEM_GPIO_USB_S 14 + +#define UART_PORT UART_NUM_1 #define MODEM_ETYPE_ATINIT 1 #define MODEM_ETYPE_STATUS 2 #define MODEM_ETYPE_RING 3 -#define AT_CMD_INIT_SIZE 5 - #define MIN(X, Y) (((X) < (Y)) ? (X) : (Y)) #define MAX(X, Y) (((X) > (Y)) ? (X) : (Y)) -static const char *TAG = "EOS MODEM"; - -static char *at_cmd_init[AT_CMD_INIT_SIZE] = { - "AT+CFGRI=1\r", - "AT+CSCLK=1\r", +static char *at_cmd_init[] = { + // "AT+CFGRI=1\r", + // "AT+CSCLK=1\r", + "AT+QSCLK=1\r", + "AT+QCFG=\"risignaltype\",\"physical\"\r", + "AT+QURCCFG=\"urcport\",\"uart1\"\r", "AT+CLIP=1\r", "AT+CMGF=0\r", "AT+CPMS=\"ME\",\"ME\",\"ME\"\r" }; +static const char *TAG = "EOS CELL MODEM"; + static SemaphoreHandle_t mutex; static QueueHandle_t modem_queue; @@ -84,8 +94,6 @@ typedef struct { size_t param_len; } modem_event_t; -static void modem_send_status(void); - static void atcmd_read(size_t bsize) { char *ln_end; int rd = 0; @@ -94,6 +102,9 @@ static void atcmd_read(size_t bsize) { char *uart_curr = uart_buf + uart_buf_len; int _rd = eos_modem_read(uart_curr, MIN(bsize - rd, sizeof(uart_buf) - uart_buf_len - 1), 100); + /* after sleep one 0xff character is emitted */ + if ((_rd == 1) && (*uart_curr == 0xff)) return; + rd += _rd; uart_buf_len += _rd; uart_buf[uart_buf_len] = '\0'; @@ -123,7 +134,7 @@ static void uart_data_read(uint8_t mode) { int rd; size_t bsize; - uart_get_buffered_data_len(UART_NUM_2, &bsize); + uart_get_buffered_data_len(UART_PORT, &bsize); switch (mode) { case EOS_CELL_UART_MODE_ATCMD: { atcmd_read(bsize); @@ -132,7 +143,6 @@ static void uart_data_read(uint8_t mode) { case EOS_CELL_UART_MODE_PPP: { rd = 0; - do { int _rd = eos_modem_read(uart_buf, MIN(bsize - rd, sizeof(uart_buf)), 100); if (ppp_handle) pppos_input_tcpip(ppp_handle, (uint8_t *)uart_buf, _rd); @@ -143,15 +153,17 @@ static void uart_data_read(uint8_t mode) { case EOS_CELL_UART_MODE_RELAY: { unsigned char *buf; - rd = 0; + int rv; + rd = 0; do { int _rd; buf = eos_net_alloc(); buf[0] = EOS_CELL_MTYPE_DEV | EOS_CELL_MTYPE_UART_DATA; _rd = eos_modem_read(buf + 1, MIN(bsize - rd, EOS_NET_SIZE_BUF - 1), 100); - eos_net_send(EOS_NET_MTYPE_CELL, buf, _rd + 1); + rv = eos_net_send(EOS_NET_MTYPE_CELL, buf, _rd + 1); + if (rv) ESP_LOGE(TAG, "NET SEND ERR:%d", rv); rd += _rd; } while (rd != bsize); break; @@ -160,36 +172,20 @@ static void uart_data_read(uint8_t mode) { } static void uart_event_task(void *pvParameters) { - char mode; - char _mode; + uint8_t mode, _mode; uart_event_t event; - eos_power_wait4wake(); - xSemaphoreTake(mutex, portMAX_DELAY); - _mode = uart_mode; - xSemaphoreTake(uart_mutex, portMAX_DELAY); - if (!modem_initialized) { - int r; - - at_cmd("\r\rAT\r"); - r = at_expect("^OK", NULL, 500); - if (!r) { - r = eos_modem_atinit(); - if (!r) { - modem_present = 1; - } else { - _mode = EOS_CELL_UART_MODE_NONE; - ESP_LOGE(TAG, "Modem init failed"); - } - } + eos_modem_reset(); } - - if (_mode == EOS_CELL_UART_MODE_NONE) xSemaphoreGive(uart_mutex); - mode = _mode; + mode = _mode = uart_mode; xSemaphoreGive(mutex); + if (mode != EOS_CELL_UART_MODE_NONE) { + xSemaphoreTake(uart_mutex, portMAX_DELAY); + } + while (1) { /* Waiting for UART event. */ @@ -198,6 +194,8 @@ static void uart_event_task(void *pvParameters) { case UART_DATA: { /* Event of UART receiving data */ + + ESP_LOGI(TAG, "UART DATA READ"); if (mode != EOS_CELL_UART_MODE_NONE) uart_data_read(mode); if ((mode != _mode) && (uart_buf_len == 0)) { if (_mode == EOS_CELL_UART_MODE_NONE) xSemaphoreGive(uart_mutex); @@ -244,27 +242,6 @@ static void IRAM_ATTR uart_ring_handler(void *arg) { xQueueSendFromISR(modem_queue, &evt, NULL); } -static void modem_init_gpio(void) { - // Configuration for the DTR/RI lines - gpio_config_t io_conf = {}; - - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.mode = GPIO_MODE_OUTPUT; - io_conf.pin_bit_mask = ((uint64_t)1 << UART_GPIO_DTR); - io_conf.pull_up_en = 0; - io_conf.pull_down_en = 0; - gpio_config(&io_conf); - gpio_set_level(UART_GPIO_DTR, 0); - - io_conf.intr_type = GPIO_INTR_NEGEDGE; - io_conf.mode = GPIO_MODE_INPUT; - io_conf.pin_bit_mask = ((uint64_t)1 << UART_GPIO_RI); - io_conf.pull_up_en = 0; - io_conf.pull_down_en = 0; - gpio_config(&io_conf); - gpio_isr_handler_add(UART_GPIO_RI, uart_ring_handler, NULL); -} - static size_t modem_get_status(unsigned char *buffer) { size_t len; @@ -310,12 +287,14 @@ static void modem_atinit_handler(char *urc, regmatch_t m[]) { xQueueSend(modem_queue, &evt, portMAX_DELAY); } -static int modem_atinit(void) { +static int modem_atinit_evt(void) { int r; + vTaskDelay(500 / portTICK_PERIOD_MS); + xSemaphoreTake(mutex, portMAX_DELAY); uart_change_mode(EOS_CELL_UART_MODE_NONE); - r = xSemaphoreTake(uart_mutex, 1000); + r = xSemaphoreTake(uart_mutex, 1000 / portTICK_PERIOD_MS); if (r == pdFALSE) { uart_change_mode(uart_mode); xSemaphoreGive(mutex); @@ -323,6 +302,8 @@ static int modem_atinit(void) { } r = eos_modem_atinit(); + modem_send_status(); + uart_change_mode(uart_mode); xSemaphoreGive(uart_mutex); xSemaphoreGive(mutex); @@ -337,10 +318,10 @@ static void modem_event_task(void *pvParameters) { if (xQueueReceive(modem_queue, &evt, portMAX_DELAY)) { switch (evt.type) { case MODEM_ETYPE_ATINIT: { - int r; + int rv; - r = modem_atinit(); - if (!r) { + rv = modem_atinit_evt(); + if (!rv) { modem_present = 1; } else { ESP_LOGE(TAG, "Modem init failed"); @@ -350,11 +331,13 @@ static void modem_event_task(void *pvParameters) { case MODEM_ETYPE_STATUS: { unsigned char *buf; + int rv; buf = eos_net_alloc(); buf[0] = EOS_CELL_MTYPE_DEV | EOS_CELL_MTYPE_STATUS; memcpy(buf + 1, evt.param, evt.param_len); - eos_net_send(EOS_NET_MTYPE_CELL, buf, evt.param_len + 1); + rv = eos_net_send(EOS_NET_MTYPE_CELL, buf, evt.param_len + 1); + if (rv) ESP_LOGE(TAG, "NET SEND ERR:%d", rv); break; } @@ -365,7 +348,7 @@ static void modem_event_task(void *pvParameters) { } /* Obsolete uint64_t t_start = esp_timer_get_time(); - if (xQueueReceive(modem_queue, &level, 200 / portTICK_RATE_MS) && (level == 1)) { + if (xQueueReceive(modem_queue, &level, 200 / portTICK_PERIOD_MS) && (level == 1)) { uint64_t t_end = esp_timer_get_time(); ESP_LOGI(TAG, "URC:%u", (uint32_t)(t_end - t_start)); } else { @@ -399,11 +382,11 @@ static char *memstr(char *mem, size_t size, char *str) { return NULL; } -static uint32_t ppp_output_cb(ppp_pcb *pcb, uint8_t *data, uint32_t len, void *ctx) { +static uint32_t ppp_output_cb(ppp_pcb *pcb, const void *data, uint32_t len, void *ctx) { size_t rv; xSemaphoreTake(ppp_mutex, portMAX_DELAY); - rv = eos_modem_write(data, len); + rv = eos_modem_write((uint8_t *)data, len); xSemaphoreGive(ppp_mutex); return rv; @@ -412,15 +395,16 @@ static uint32_t ppp_output_cb(ppp_pcb *pcb, uint8_t *data, uint32_t len, void *c /* PPP status callback */ static void ppp_status_cb(ppp_pcb *pcb, int err_code, void *ctx) { struct netif *pppif = ppp_netif(pcb); + int r; LWIP_UNUSED_ARG(ctx); switch (err_code) { case PPPERR_NONE: { ESP_LOGI(TAG, "status_cb: Connect"); - ESP_LOGI(TAG," our_ipaddr = %s\n", ipaddr_ntoa(&pppif->ip_addr)); - ESP_LOGI(TAG," his_ipaddr = %s\n", ipaddr_ntoa(&pppif->gw)); - ESP_LOGI(TAG," netmask = %s\n", ipaddr_ntoa(&pppif->netmask)); + ESP_LOGI(TAG," local ipaddr = %s\n", ipaddr_ntoa(&pppif->ip_addr)); + ESP_LOGI(TAG," remote ipaddr = %s\n", ipaddr_ntoa(&pppif->gw)); + ESP_LOGI(TAG," netmask = %s\n", ipaddr_ntoa(&pppif->netmask)); xSemaphoreTake(mutex, portMAX_DELAY); ppp_connected = 1; @@ -485,18 +469,26 @@ static void ppp_status_cb(ppp_pcb *pcb, int err_code, void *ctx) { } xSemaphoreTake(mutex, portMAX_DELAY); + ppp_connected = 0; + ip_addr_set_zero(&ppp_ipaddr); + modem_send_status(); + uart_change_mode(EOS_CELL_UART_MODE_NONE); + r = xSemaphoreTake(uart_mutex, 1000 / portTICK_PERIOD_MS); + if (r == pdFALSE) { + uart_mode = EOS_CELL_UART_MODE_NONE; + uart_mode_next = EOS_CELL_UART_MODE_NONE; + xSemaphoreGive(mutex); + ESP_LOGE(TAG, "status_cb: Obtaining UART mutex failed"); + + return; + } + if (uart_mode_next != EOS_CELL_UART_MODE_NONE) { uart_mode = uart_mode_next; uart_mode_next = EOS_CELL_UART_MODE_NONE; } else { uart_mode = EOS_CELL_UART_MODE_ATCMD; } - ppp_connected = 0; - ip_addr_set_zero(&ppp_ipaddr); - modem_send_status(); - uart_change_mode(EOS_CELL_UART_MODE_NONE); - xSemaphoreTake(uart_mutex, portMAX_DELAY); - ppp_handle = NULL; uart_change_mode(uart_mode); @@ -607,6 +599,12 @@ static int ppp_setup(void) { return EOS_ERR_TIMEOUT; } + if (ppp_handle) { + uart_change_mode(uart_mode); + xSemaphoreGive(uart_mutex); + return EOS_ERR; + } + at_cmd(cmd); r = at_expect("^OK", "^(ERROR|NO CARRIER)", 1000); if (r) { @@ -636,6 +634,7 @@ static int ppp_setup(void) { } void eos_modem_init(void) { + gpio_config_t io_conf = {}; uart_config_t uart_config = { .baud_rate = 115200, .data_bits = UART_DATA_8_BITS, @@ -643,37 +642,91 @@ void eos_modem_init(void) { .stop_bits = UART_STOP_BITS_1, .flow_ctrl = UART_HW_FLOWCTRL_DISABLE }; - uart_param_config(UART_NUM_2, &uart_config); - uart_set_pin(UART_NUM_2, UART_GPIO_TXD, UART_GPIO_RXD, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); - uart_driver_install(UART_NUM_2, UART_SIZE_IO_BUF, UART_SIZE_IO_BUF, 10, &uart_queue, 0); + esp_err_t ret; + int rv; - if (eos_power_wakeup_cause() == EOS_PWR_WAKE_RST) { - uart_mode = EOS_CELL_UART_MODE_ATCMD; + ret = uart_param_config(UART_PORT, &uart_config); + assert(ret == ESP_OK); + ret = uart_set_pin(UART_PORT, UART_GPIO_TXD, UART_GPIO_RXD, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); + assert(ret == ESP_OK); + ret = uart_driver_install(UART_PORT, UART_SIZE_IO_BUF, UART_SIZE_IO_BUF, 10, &uart_queue, 0); + assert(ret == ESP_OK); + + // Configuration for the RST/DTR/USB/RI lines + gpio_set_level(MODEM_GPIO_RST, 1); + io_conf.intr_type = GPIO_INTR_DISABLE; + io_conf.mode = GPIO_MODE_OUTPUT_OD; + io_conf.pin_bit_mask = BIT64(MODEM_GPIO_RST); + io_conf.pull_up_en = 0; + io_conf.pull_down_en = 0; + gpio_config(&io_conf); + + gpio_set_level(UART_GPIO_DTR, 0); + /* enable USB MUX and grab signals */ + gpio_set_level(MODEM_GPIO_USB_EN, 0); + gpio_set_level(MODEM_GPIO_USB_S, 1); + io_conf.intr_type = GPIO_INTR_DISABLE; + io_conf.mode = GPIO_MODE_OUTPUT; + io_conf.pin_bit_mask = BIT64(UART_GPIO_DTR) | BIT64(MODEM_GPIO_USB_EN) | BIT64(MODEM_GPIO_USB_S); + io_conf.pull_up_en = 0; + io_conf.pull_down_en = 0; + gpio_config(&io_conf); + + io_conf.intr_type = GPIO_INTR_NEGEDGE; + io_conf.mode = GPIO_MODE_INPUT; + io_conf.pin_bit_mask = BIT64(UART_GPIO_RI); + io_conf.pull_up_en = 1; + io_conf.pull_down_en = 0; + gpio_config(&io_conf); + + if (esp_reset_reason() == ESP_RST_DEEPSLEEP) { + gpio_hold_dis(UART_GPIO_DTR); + gpio_hold_dis(MODEM_GPIO_USB_EN); + gpio_hold_dis(MODEM_GPIO_USB_S); + } else { modem_present = 0; modem_initialized = 0; - modem_init_gpio(); } mutex = xSemaphoreCreateBinary(); + assert(mutex != NULL); xSemaphoreGive(mutex); uart_mutex = xSemaphoreCreateBinary(); + assert(uart_mutex != NULL); xSemaphoreGive(uart_mutex); ppp_mutex = xSemaphoreCreateBinary(); + assert(ppp_mutex != NULL); xSemaphoreGive(ppp_mutex); modem_queue = xQueueCreate(4, sizeof(modem_event_t)); - xTaskCreate(uart_event_task, "uart_event", EOS_TASK_SSIZE_UART, NULL, EOS_TASK_PRIORITY_UART, NULL); - xTaskCreate(modem_event_task, "modem_event", EOS_TASK_SSIZE_MODEM, NULL, EOS_TASK_PRIORITY_MODEM, NULL); + assert(modem_queue != NULL); at_init(); - at_urc_insert("^PB DONE", modem_atinit_handler, REG_EXTENDED); - at_urc_insert("^\\+CME ERROR: SIM not inserted", modem_atinit_handler, REG_EXTENDED); + rv = at_urc_insert("^RDY", modem_atinit_handler, REG_EXTENDED); + assert(rv == EOS_OK); + + eos_cell_sms_init(); + eos_cell_ussd_init(); + eos_cell_voice_init(); ESP_LOGI(TAG, "INIT"); } +void eos_modem_run(void) { + BaseType_t rv; + + gpio_isr_handler_add(UART_GPIO_RI, uart_ring_handler, NULL); + + rv = xTaskCreate(uart_event_task, "uart_event", EOS_TASK_SSIZE_UART, NULL, EOS_TASK_PRIORITY_UART, NULL); + assert(rv == pdPASS); + rv = xTaskCreate(modem_event_task, "modem_event", EOS_TASK_SSIZE_MODEM, NULL, EOS_TASK_PRIORITY_MODEM, NULL); + assert(rv == pdPASS); + + ESP_LOGI(TAG, "RUN"); +} + int eos_modem_atinit(void) { int echo_on = 0; int tries = 3; @@ -706,32 +759,36 @@ int eos_modem_atinit(void) { r = at_expect("^ATE0", NULL, 1000); r = at_expect("^OK", "^ERROR", 1000); - for (i=0; i<AT_CMD_INIT_SIZE; i++) { + for (i=0; i<sizeof(at_cmd_init)/sizeof(char *); i++) { at_cmd(at_cmd_init[i]); - r = at_expect("^OK", "^ERROR", 1000); + r = at_expect("^OK", "ERROR", 1000); } + modem_present = 1; modem_initialized = 1; - eos_cell_voice_init(); - eos_cell_sms_init(); - eos_cell_ussd_init(); + return EOS_OK; +} - modem_send_status(); +void eos_modem_reset(void) { + gpio_set_level(MODEM_GPIO_RST, 0); + vTaskDelay(500 / portTICK_PERIOD_MS); + gpio_set_level(MODEM_GPIO_RST, 1); - return EOS_OK; + modem_initialized = 0; + uart_mode = EOS_CELL_UART_MODE_ATCMD; } void eos_modem_flush(void){ - uart_wait_tx_done(UART_NUM_2, portMAX_DELAY); + uart_wait_tx_done(UART_PORT, portMAX_DELAY); } size_t eos_modem_write(void *data, size_t size) { - return uart_write_bytes(UART_NUM_2, (const char *)data, size); + return uart_write_bytes(UART_PORT, (const char *)data, size); } size_t eos_modem_read(void *data, size_t size, uint32_t timeout) { - return uart_read_bytes(UART_NUM_2, (uint8_t *)data, size, timeout / portTICK_RATE_MS); + return uart_read_bytes(UART_PORT, (uint8_t *)data, size, timeout / portTICK_PERIOD_MS); } int eos_modem_readln(char *buf, size_t buf_size, uint32_t timeout) { @@ -791,6 +848,16 @@ int eos_modem_present(void) { return rv; } +int eos_modem_initialized(void) { + int rv; + + xSemaphoreTake(mutex, portMAX_DELAY); + rv = modem_initialized; + xSemaphoreGive(mutex); + + return rv; +} + uint8_t eos_modem_get_mode(void) { uint8_t ret; @@ -832,7 +899,6 @@ int eos_modem_set_mode(uint8_t mode) { } if (!rv) { uart_mode = mode; - modem_send_status(); } } } @@ -876,71 +942,53 @@ void eos_modem_give(void) { xSemaphoreGive(mutex); } -void eos_modem_sleep(void) { - int r; +void eos_modem_sleep_req(void) { + int rv; + gpio_set_level(UART_GPIO_DTR, 1); xSemaphoreTake(mutex, portMAX_DELAY); uart_change_mode(EOS_CELL_UART_MODE_NONE); - r = xSemaphoreTake(uart_mutex, 1000 / portTICK_PERIOD_MS); - if (r == pdFALSE) { - ESP_LOGE(TAG, "Obtaining mutex before sleep failed"); - } - gpio_set_level(UART_GPIO_DTR, 1); -} - -void eos_modem_deep_sleep(void) { + rv = xSemaphoreTake(uart_mutex, 1000 / portTICK_PERIOD_MS); + if (rv == pdFALSE) ESP_LOGE(TAG, "Obtaining UART mutex before sleep failed"); + gpio_isr_handler_remove(UART_GPIO_RI); + gpio_reset_pin(UART_GPIO_RI); + /* for deep sleep */ gpio_hold_en(UART_GPIO_DTR); + gpio_hold_en(MODEM_GPIO_USB_EN); + gpio_hold_en(MODEM_GPIO_USB_S); + eos_power_sleep_rdy(EOS_PWR_DEV_MODEM); } -void eos_modem_wake(uint8_t source, uint8_t mode) { - if (source == EOS_PWR_WAKE_UART) { - modem_event_t evt; +void eos_modem_wake(void) { + gpio_config_t io_conf = { + .pin_bit_mask = BIT64(UART_GPIO_RI), + .mode = GPIO_MODE_INPUT, + .intr_type = GPIO_INTR_NEGEDGE, + }; + uint32_t dev; - evt.type = MODEM_ETYPE_RING; - xQueueSend(modem_queue, &evt, portMAX_DELAY); - } + gpio_hold_dis(UART_GPIO_DTR); + gpio_hold_dis(MODEM_GPIO_USB_EN); + gpio_hold_dis(MODEM_GPIO_USB_S); - switch (mode) { - case EOS_PWR_SMODE_LIGHT: { - gpio_set_intr_type(UART_GPIO_RI, GPIO_INTR_NEGEDGE); - gpio_isr_handler_add(UART_GPIO_RI, uart_ring_handler, NULL); - gpio_set_level(UART_GPIO_DTR, 0); + gpio_config(&io_conf); + gpio_isr_handler_add(UART_GPIO_RI, uart_ring_handler, NULL); - uart_change_mode(uart_mode); - xSemaphoreGive(uart_mutex); - xSemaphoreGive(mutex); + uart_change_mode(uart_mode); + xSemaphoreGive(uart_mutex); + xSemaphoreGive(mutex); - break; - } + gpio_set_level(UART_GPIO_DTR, 0); - case EOS_PWR_SMODE_DEEP: { - gpio_hold_dis(UART_GPIO_DTR); - modem_init_gpio(); + dev = eos_power_wakeup_source(); + if (dev == EOS_PWR_DEV_MODEM) { + modem_event_t evt; - break; - } + evt.type = MODEM_ETYPE_RING; + xQueueSend(modem_queue, &evt, portMAX_DELAY); } } -int eos_modem_reset(void) { - int rv; - - rv = eos_modem_take(1000); - if (rv) return rv; - - at_cmd("AT+CRESET\r"); - at_expect("^OK", NULL, 1000); - - uart_change_mode(EOS_CELL_UART_MODE_ATCMD); - xSemaphoreGive(uart_mutex); - - uart_mode = EOS_CELL_UART_MODE_ATCMD; - modem_initialized = 0; - modem_send_status(); - xSemaphoreGive(mutex); - - return EOS_OK; -} void eos_ppp_get_apn(char *apn) { xSemaphoreTake(mutex, portMAX_DELAY); diff --git a/fw/esp32/components/eos/cell_pcm.c b/fw/esp32/components/eos/cell_pcm.c new file mode 100644 index 0000000..3f5089d --- /dev/null +++ b/fw/esp32/components/eos/cell_pcm.c @@ -0,0 +1,137 @@ +#include <stdint.h> +#include <stdlib.h> + +#include <freertos/FreeRTOS.h> +#include <freertos/task.h> +#include <driver/i2s_tdm.h> +#include <esp_log.h> + +#include "eos.h" +#include "net.h" +#include "cell.h" + +#define PCM_GPIO_BCK 1 +#define PCM_GPIO_WS 41 +#define PCM_GPIO_DIN 2 +#define PCM_GPIO_DOUT 42 + +#define PCM_RX_WM 256 /* receive watermark, must be less than NET_SIZE_MTU */ + +static i2s_chan_handle_t tx_chan; +static i2s_chan_handle_t rx_chan; + +static const char *TAG = "EOS CELL PCM"; + +static void pcm_rcvr_task(void *pvParameters) { + unsigned char *buffer; + size_t size_r; + esp_err_t ret; + int done = 0; + int rv; + + while (!done) { + buffer = eos_net_alloc(); + buffer[0] = EOS_CELL_MTYPE_VOICE | EOS_CELL_MTYPE_VOICE_PCM; + ret = i2s_channel_read(rx_chan, buffer + 1, PCM_RX_WM, &size_r, 1000); + switch (ret) { + case ESP_OK: { + assert(size_r == PCM_RX_WM); + break; + } + + case ESP_ERR_INVALID_STATE: { + done = 1; + break; + } + + default: { + done = 1; + ESP_LOGE(TAG, "CHAN READ ERR:%d", ret); + break; + } + } + if (ret == ESP_OK) { + rv = eos_net_send(EOS_NET_MTYPE_CELL, buffer, size_r + 1); + if (rv) ESP_LOGE(TAG, "NET SEND ERR:%d", rv); + } else { + eos_net_free(buffer); + } + } + vTaskDelete(NULL); +} + +void eos_cell_pcm_start(void) { + BaseType_t rv; + esp_err_t ret; + + ret = i2s_channel_enable(tx_chan); + if (ret) { + ESP_LOGE(TAG, "TX CHAN ENABLE ERR:%d", ret); + return; + } + + ret = i2s_channel_enable(rx_chan); + if (ret) { + ESP_LOGE(TAG, "RX CHAN ENABLE ERR:%d", ret); + return; + } + + rv = xTaskCreate(&pcm_rcvr_task, "pcm_rcvr", EOS_TASK_SSIZE_PCM, NULL, EOS_TASK_PRIORITY_PCM, NULL); + assert(rv == pdPASS); +} + +void eos_cell_pcm_stop(void) { + esp_err_t ret; + + ret = i2s_channel_disable(tx_chan); + if (ret) ESP_LOGE(TAG, "TX CHAN DISABLE ERR:%d", ret); + + ret = i2s_channel_disable(rx_chan); + if (ret) ESP_LOGE(TAG, "RX CHAN DISABLE ERR:%d", ret); +} + +void eos_cell_pcm_push(unsigned char *data, size_t size) { + esp_err_t ret; + size_t size_w; + + ret = i2s_channel_write(tx_chan, data, size, &size_w, 1000); + if (ret == ESP_OK) { + assert(size_w == size); + } else { + ESP_LOGE(TAG, "CHAN WRITE ERR:%d", ret); + } +} + +void eos_cell_pcm_init(void) { + i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_AUTO, I2S_ROLE_SLAVE); + i2s_tdm_config_t tdm_cfg = { + .clk_cfg = I2S_TDM_CLK_DEFAULT_CONFIG(8000), + .slot_cfg = I2S_TDM_PCM_SHORT_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_MONO, + I2S_TDM_SLOT0), + .gpio_cfg = { + .mclk = I2S_GPIO_UNUSED, + .bclk = PCM_GPIO_BCK, + .ws = PCM_GPIO_WS, + .din = PCM_GPIO_DIN, + .dout = PCM_GPIO_DOUT, + .invert_flags = { + .mclk_inv = false, + .bclk_inv = false, + .ws_inv = false, + }, + }, + }; + esp_err_t ret; + + tdm_cfg.slot_cfg.total_slot = 16; + ret = i2s_new_channel(&chan_cfg, &tx_chan, &rx_chan); + assert(ret == ESP_OK); + + ret = i2s_channel_init_tdm_mode(tx_chan, &tdm_cfg); + assert(ret == ESP_OK); + + ret = i2s_channel_init_tdm_mode(rx_chan, &tdm_cfg); + assert(ret == ESP_OK); + + ESP_LOGI(TAG, "INIT"); +} diff --git a/fw/esp32/components/eos/cell_sms.c b/fw/esp32/components/eos/cell_sms.c index 5145cd7..1cd4cda 100644 --- a/fw/esp32/components/eos/cell_sms.c +++ b/fw/esp32/components/eos/cell_sms.c @@ -13,7 +13,7 @@ #define CTRL_Z 0x1a -static const char *TAG = "EOS SMS"; +static const char *TAG = "EOS CELL SMS"; static char _pdu_in[2048]; static char _pdu_out[2048]; @@ -266,7 +266,8 @@ void eos_cell_sms_handler(unsigned char mtype, unsigned char *buffer, uint16_t b } buf_len = _rv; - eos_net_send(EOS_NET_MTYPE_CELL, buf, buf_len + 1); + rv = eos_net_send(EOS_NET_MTYPE_CELL, buf, buf_len + 1); + if (rv) ESP_LOGE(TAG, "NET SEND ERR:%d", rv); } while (1); eos_modem_give(); @@ -345,9 +346,13 @@ static void sms_received_handler(char *urc, regmatch_t m[]) { } buf_len = _rv; - eos_net_send(EOS_NET_MTYPE_CELL, buf, buf_len + 1); + rv = eos_net_send(EOS_NET_MTYPE_CELL, buf, buf_len + 1); + if (rv) ESP_LOGE(TAG, "NET SEND ERR:%d", rv); } void eos_cell_sms_init(void) { - at_urc_insert("^\\+CMTI: .*,([0-9]+)$", sms_received_handler, REG_EXTENDED); + int rv; + + rv = at_urc_insert("^\\+CMTI: .*,([0-9]+)$", sms_received_handler, REG_EXTENDED); + assert(rv == EOS_OK); } diff --git a/fw/esp32/components/eos/cell_ussd.c b/fw/esp32/components/eos/cell_ussd.c index 375025f..fb77b67 100644 --- a/fw/esp32/components/eos/cell_ussd.c +++ b/fw/esp32/components/eos/cell_ussd.c @@ -9,7 +9,7 @@ #include "at_cmd.h" #include "cell.h" -static const char *TAG = "EOS USSD"; +static const char *TAG = "EOS CELL USSD"; extern char *at_cmd_buf; @@ -64,7 +64,8 @@ static void ussd_reply_handler(char *urc, regmatch_t m[]) { len = 2; if (m[2].rm_so == -1) { - eos_net_send(EOS_NET_MTYPE_CELL, buf, len); + rv = eos_net_send(EOS_NET_MTYPE_CELL, buf, len); + if (rv) ESP_LOGE(TAG, "NET SEND ERR:%d", rv); return; } @@ -101,9 +102,13 @@ static void ussd_reply_handler(char *urc, regmatch_t m[]) { return; } - eos_net_send(EOS_NET_MTYPE_CELL, buf, len); + rv = eos_net_send(EOS_NET_MTYPE_CELL, buf, len); + if (rv) ESP_LOGE(TAG, "NET SEND ERR:%d", rv); } void eos_cell_ussd_init(void) { - at_urc_insert("^\\+CUSD: ([0-9])(,\".*)?", ussd_reply_handler, REG_EXTENDED); + int rv; + + rv = at_urc_insert("^\\+CUSD: ([0-9])(,\".*)?", ussd_reply_handler, REG_EXTENDED); + assert(rv == EOS_OK); } diff --git a/fw/esp32/components/eos/cell_voice.c b/fw/esp32/components/eos/cell_voice.c index 2a7bb18..273b402 100644 --- a/fw/esp32/components/eos/cell_voice.c +++ b/fw/esp32/components/eos/cell_voice.c @@ -13,6 +13,8 @@ #include "at_cmd.h" #include "cell.h" +static const char *TAG = "EOS CELL VOICE"; + extern char *at_cmd_buf; void eos_cell_voice_handler(unsigned char mtype, unsigned char *buffer, uint16_t buf_len) { @@ -93,35 +95,41 @@ static void ring_handler(char *urc, regmatch_t m[]) { memcpy(buf + 1, ring_buf + match[1].rm_so, num_len); len += num_len; } - eos_net_send(EOS_NET_MTYPE_CELL, buf, len); + rv = eos_net_send(EOS_NET_MTYPE_CELL, buf, len); + if (rv) ESP_LOGE(TAG, "NET SEND ERR:%d", rv); } static void busy_handler(char *urc, regmatch_t m[]) { unsigned char *buf; uint16_t len; + int rv; eos_cell_pcm_stop(); buf = eos_net_alloc(); buf[0] = EOS_CELL_MTYPE_VOICE | EOS_CELL_MTYPE_VOICE_BUSY; len = 1; - eos_net_send(EOS_NET_MTYPE_CELL, buf, len); + rv = eos_net_send(EOS_NET_MTYPE_CELL, buf, len); + if (rv) ESP_LOGE(TAG, "NET SEND ERR:%d", rv); } static void miss_handler(char *urc, regmatch_t m[]) { unsigned char *buf; uint16_t len; + int rv; eos_cell_pcm_stop(); buf = eos_net_alloc(); buf[0] = EOS_CELL_MTYPE_VOICE | EOS_CELL_MTYPE_VOICE_MISS; len = 1; - eos_net_send(EOS_NET_MTYPE_CELL, buf, len); + rv = eos_net_send(EOS_NET_MTYPE_CELL, buf, len); + if (rv) ESP_LOGE(TAG, "NET SEND ERR:%d", rv); } static void call_begin_handler(char *urc, regmatch_t m[]) { unsigned char *buf; + int rv; vTaskDelay(100 / portTICK_PERIOD_MS); at_cmd("AT+CECH=0x0000\r"); @@ -142,12 +150,14 @@ static void call_begin_handler(char *urc, regmatch_t m[]) { buf = eos_net_alloc(); buf[0] = EOS_CELL_MTYPE_VOICE | EOS_CELL_MTYPE_VOICE_BEGIN; - eos_net_send(EOS_NET_MTYPE_CELL, buf, 1); + rv = eos_net_send(EOS_NET_MTYPE_CELL, buf, 1); + if (rv) ESP_LOGE(TAG, "NET SEND ERR:%d", rv); } static void call_end_handler(char *urc, regmatch_t m[]) { unsigned char *buf; int duration = 0; + int rv; eos_cell_pcm_stop(); @@ -158,14 +168,29 @@ static void call_end_handler(char *urc, regmatch_t m[]) { buf[2] = duration >> 16; buf[3] = duration >> 8; buf[4] = duration; - eos_net_send(EOS_NET_MTYPE_CELL, buf, 5); + rv = eos_net_send(EOS_NET_MTYPE_CELL, buf, 5); + if (rv) ESP_LOGE(TAG, "NET SEND ERR:%d", rv); } void eos_cell_voice_init(void) { - at_urc_insert("^RING", ring_handler, REG_EXTENDED); - at_urc_insert("^BUSY", busy_handler, REG_EXTENDED); - at_urc_insert("^NO CARRIER", miss_handler, REG_EXTENDED); - at_urc_insert("^MISSED.CALL: [^ ]+ (\\+?[0-9]+)$", miss_handler, REG_EXTENDED); - at_urc_insert("^VOICE CALL: BEGIN", call_begin_handler, REG_EXTENDED); - at_urc_insert("^VOICE CALL: END: ([0-9]{6}$)$", call_end_handler, REG_EXTENDED); -}
\ No newline at end of file + int rv; + + rv = at_urc_insert("^RING", ring_handler, REG_EXTENDED); + assert(rv == EOS_OK); + + rv = at_urc_insert("^BUSY", busy_handler, REG_EXTENDED); + assert(rv == EOS_OK); + + rv = at_urc_insert("^NO CARRIER", miss_handler, REG_EXTENDED); + assert(rv == EOS_OK); + + rv = at_urc_insert("^MISSED.CALL: [^ ]+ (\\+?[0-9]+)$", miss_handler, REG_EXTENDED); + assert(rv == EOS_OK); + + rv = at_urc_insert("^VOICE CALL: BEGIN", call_begin_handler, REG_EXTENDED); + assert(rv == EOS_OK); + + rv = at_urc_insert("^VOICE CALL: END: ([0-9]{6}$)$", call_end_handler, REG_EXTENDED); + assert(rv == EOS_OK); + +} diff --git a/fw/esp32/components/eos/include/app.h b/fw/esp32/components/eos/include/app.h index 2033b2b..b6dba99 100644 --- a/fw/esp32/components/eos/include/app.h +++ b/fw/esp32/components/eos/include/app.h @@ -1,5 +1,7 @@ #include <stdint.h> +#include "net.h" + /* common */ #define EOS_APP_MTU 1500 #define EOS_APP_SIZE_BUF EOS_APP_MTU @@ -7,17 +9,18 @@ #define EOS_APP_MTYPE_TUN 1 #define EOS_APP_MAX_MTYPE 8 -#define EOS_APP_MTYPE_FLAG_MASK 0xc0 - /* esp32 specific */ #define EOS_APP_SIZE_BUFQ 4 #define EOS_APP_SIZE_SNDQ 4 -typedef void (*eos_app_fptr_t) (unsigned char, unsigned char *, uint16_t); - void eos_app_init(void); +void eos_app_run(void); unsigned char *eos_app_alloc(void); void eos_app_free(unsigned char *buf); -int eos_app_send(unsigned char mtype, unsigned char *buffer, uint16_t len); -void eos_app_set_handler(unsigned char mtype, eos_app_fptr_t handler); + +int eos_app_send(unsigned char mtype, unsigned char *buffer, uint16_t buf_len); + +void eos_app_sleep_req(void); +void eos_app_wake(void); +void eos_app_set_handler(unsigned char mtype, eos_net_handler_t handler); diff --git a/fw/esp32/components/eos/include/cell.h b/fw/esp32/components/eos/include/cell.h index cb9f49c..c1e7545 100644 --- a/fw/esp32/components/eos/include/cell.h +++ b/fw/esp32/components/eos/include/cell.h @@ -27,7 +27,6 @@ #define EOS_CELL_MTYPE_VOICE_END 7 #define EOS_CELL_MTYPE_VOICE_MISS 8 #define EOS_CELL_MTYPE_VOICE_BUSY 9 -#define EOS_CELL_MTYPE_VOICE_ERR 10 #define EOS_CELL_MTYPE_SMS_MSG 1 #define EOS_CELL_MTYPE_SMS_LIST 2 @@ -76,24 +75,26 @@ #define EOS_CELL_UART_SIZE_BUF 1024 void eos_cell_init(void); +void eos_cell_run(void); void eos_modem_init(void); +void eos_modem_run(void); int eos_modem_atinit(void); +void eos_modem_reset(void); void eos_modem_flush(void); size_t eos_modem_write(void *data, size_t size); size_t eos_modem_read(void *data, size_t size, uint32_t timeout); int eos_modem_readln(char *buf, size_t buf_size, uint32_t timeout); -int eos_modem_resp(char *ok_str, char *err_str, uint32_t timeout); int eos_modem_present(void); +int eos_modem_initialized(void); uint8_t eos_modem_get_mode(void); size_t eos_modem_get_status(unsigned char *buffer); int eos_modem_set_mode(uint8_t mode); int eos_modem_take(uint32_t timeout); void eos_modem_give(void); -void eos_modem_sleep(void); -void eos_modem_deep_sleep(void); -void eos_modem_wake(uint8_t source, uint8_t mode); -int eos_modem_reset(void); + +void eos_modem_sleep_req(void); +void eos_modem_wake(void); void eos_ppp_get_apn(char *apn); void eos_ppp_set_apn(char *apn); @@ -105,8 +106,7 @@ int eos_ppp_connect(void); void eos_ppp_disconnect(void); void eos_cell_pcm_init(void); -ssize_t eos_cell_pcm_read(unsigned char *data, size_t size); -int eos_cell_pcm_push(unsigned char *data, size_t size); +void eos_cell_pcm_push(unsigned char *data, size_t size); void eos_cell_pcm_start(void); void eos_cell_pcm_stop(void); diff --git a/fw/esp32/components/eos/include/eos.h b/fw/esp32/components/eos/include/eos.h index bc9dc51..e772637 100644 --- a/fw/esp32/components/eos/include/eos.h +++ b/fw/esp32/components/eos/include/eos.h @@ -11,21 +11,21 @@ #define EOS_ERR_NOMEM -100 -#define EOS_TASK_PRIORITY_NET_XCHG 1 -#define EOS_TASK_PRIORITY_APP_XCHG 1 -#define EOS_TASK_PRIORITY_UDP_RCVR 1 +#define EOS_TASK_PRIORITY_NET 1 +#define EOS_TASK_PRIORITY_APP 1 +#define EOS_TASK_PRIORITY_SOCK 1 #define EOS_TASK_PRIORITY_UART 1 #define EOS_TASK_PRIORITY_MODEM 1 -#define EOS_TASK_PRIORITY_I2S 1 +#define EOS_TASK_PRIORITY_PCM 1 #define EOS_TASK_PRIORITY_CELL 1 #define EOS_TASK_PRIORITY_PWR 1 -#define EOS_TASK_SSIZE_NET_XCHG 8192 -#define EOS_TASK_SSIZE_APP_XCHG 8192 -#define EOS_TASK_SSIZE_UDP_RCVR 4096 +#define EOS_TASK_SSIZE_NET 8192 +#define EOS_TASK_SSIZE_APP 8192 +#define EOS_TASK_SSIZE_SOCK 4096 #define EOS_TASK_SSIZE_UART 4096 #define EOS_TASK_SSIZE_MODEM 4096 -#define EOS_TASK_SSIZE_I2S 4096 +#define EOS_TASK_SSIZE_PCM 4096 #define EOS_TASK_SSIZE_CELL 4096 #define EOS_TASK_SSIZE_PWR 4096 diff --git a/fw/esp32/components/eos/include/msgq.h b/fw/esp32/components/eos/include/msgq.h index bbfe041..b5ae9ac 100644 --- a/fw/esp32/components/eos/include/msgq.h +++ b/fw/esp32/components/eos/include/msgq.h @@ -14,9 +14,9 @@ typedef struct EOSMsgQ { } EOSMsgQ; void eos_msgq_init(EOSMsgQ *msgq, EOSMsgItem *array, uint8_t size); +uint8_t eos_msgq_len(EOSMsgQ *msgq); int eos_msgq_push(EOSMsgQ *msgq, unsigned char type, unsigned char *buffer, uint16_t len); void eos_msgq_pop(EOSMsgQ *msgq, unsigned char *type, unsigned char **buffer, uint16_t *len); -uint8_t eos_msgq_len(EOSMsgQ *msgq); typedef struct EOSBufQ { uint8_t idx_r; @@ -26,6 +26,6 @@ typedef struct EOSBufQ { } EOSBufQ; void eos_bufq_init(EOSBufQ *bufq, unsigned char **array, uint8_t size); +uint8_t eos_bufq_len(EOSBufQ *bufq); int eos_bufq_push(EOSBufQ *bufq, unsigned char *buffer); unsigned char *eos_bufq_pop(EOSBufQ *bufq); -uint8_t eos_bufq_len(EOSBufQ *bufq); diff --git a/fw/esp32/components/eos/include/net.h b/fw/esp32/components/eos/include/net.h index 3e9e625..b500e82 100644 --- a/fw/esp32/components/eos/include/net.h +++ b/fw/esp32/components/eos/include/net.h @@ -5,32 +5,36 @@ #define EOS_NET_SIZE_BUF EOS_NET_MTU #define EOS_NET_MTYPE_SOCK 1 -#define EOS_NET_MTYPE_RNG 3 -#define EOS_NET_MTYPE_POWER 4 +#define EOS_NET_MTYPE_WIFI 2 +#define EOS_NET_MTYPE_CELL 3 +#define EOS_NET_MTYPE_APP 4 +#define EOS_NET_MTYPE_RNG 5 -#define EOS_NET_MTYPE_WIFI 5 -#define EOS_NET_MTYPE_CELL 6 -#define EOS_NET_MTYPE_SIP 7 -#define EOS_NET_MTYPE_APP 8 +#define EOS_NET_MAX_MTYPE 5 -#define EOS_NET_MAX_MTYPE 8 +#define EOS_NET_MTYPE_SLEEP 0x10 /* does not have net handler */ #define EOS_NET_MTYPE_FLAG_ONEW 0x40 #define EOS_NET_MTYPE_FLAG_REPL 0x80 -#define EOS_NET_MTYPE_FLAG_MASK 0xc0 +#define EOS_NET_MTYPE_MASK 0x3F /* 0x0F if mtype is handled by evtq */ /* esp32 specific */ #define EOS_NET_SIZE_BUFQ 4 #define EOS_NET_SIZE_SNDQ 4 -typedef void (*eos_net_fptr_t) (unsigned char, unsigned char *, uint16_t); +typedef void (*eos_net_handler_t) (unsigned char, unsigned char *, uint16_t); +void eos_net_xchg_task(void *param); void eos_net_init(void); +void eos_net_run(void); unsigned char *eos_net_alloc(void); void eos_net_free(unsigned char *buf); -int eos_net_send(unsigned char mtype, unsigned char *buffer, uint16_t len); -void eos_net_reply(unsigned char mtype, unsigned char *buffer, uint16_t len); -void eos_net_set_handler(unsigned char mtype, eos_net_fptr_t handler); -void eos_net_sleep(void); -void eos_net_wake(uint8_t source, uint8_t mode); + +int eos_net_send(unsigned char mtype, unsigned char *buffer, uint16_t buf_len); +void eos_net_reply(unsigned char mtype, unsigned char *buffer, uint16_t buf_len); + +void eos_net_sleep_req(void); +void eos_net_wake(void); + +void eos_net_set_handler(unsigned char mtype, eos_net_handler_t handler); diff --git a/fw/esp32/components/eos/include/net_priv.h b/fw/esp32/components/eos/include/net_priv.h new file mode 100644 index 0000000..fa1de61 --- /dev/null +++ b/fw/esp32/components/eos/include/net_priv.h @@ -0,0 +1,33 @@ +#define NET_DEV_NET EOS_PWR_DEV_NET +#define NET_DEV_APP EOS_PWR_DEV_APP + +typedef struct NETConfig { + int sleep; + int sleep_req; + int present; + int gpio_mosi; + int gpio_miso; + int gpio_sclk; + int gpio_cs; + int gpio_rts; + int gpio_cts; + uint32_t dev; + spi_host_device_t spi_host; + spi_bus_config_t *spi_bus_cfg; + spi_slave_interface_config_t *spi_iface_cfg; + spi_slave_transaction_t *spi_tr_cfg; + TaskHandle_t xchg_task_handle; + SemaphoreHandle_t mutex; + SemaphoreHandle_t bufq_mutex; + SemaphoreHandle_t bufq_semaph; + EOSBufQ *buf_q; + EOSMsgQ *send_q; + eos_net_handler_t msg_handler; +} NETConfig; + +void _eos_net_init_gpio(NETConfig *config); +unsigned char *_eos_net_alloc(NETConfig *config); +void _eos_net_free(NETConfig *config, unsigned char *buf); +int _eos_net_send(NETConfig *config, unsigned char mtype, unsigned char *buffer, uint16_t buf_len); +void _eos_net_sleep_req(NETConfig *config); +void _eos_net_wake(NETConfig *config); diff --git a/fw/esp32/components/eos/include/power.h b/fw/esp32/components/eos/include/power.h index 2215907..2590b80 100644 --- a/fw/esp32/components/eos/include/power.h +++ b/fw/esp32/components/eos/include/power.h @@ -1,22 +1,25 @@ #include <stdint.h> -#define EOS_PWR_MTYPE_BUTTON 1 +#define EOS_PWR_GPIO_NET 8 +#define EOS_PWR_GPIO_APP 10 +#define EOS_PWR_GPIO_MODEM 16 -#define EOS_PWR_WAKE_RST 0 -#define EOS_PWR_WAKE_BTN 1 -#define EOS_PWR_WAKE_UART 2 -#define EOS_PWR_WAKE_NET 3 -#define EOS_PWR_WAKE_NETQ 4 -#define EOS_PWR_WAKE_UNDEF 5 +#define EOS_PWR_DEV_NONE 0 +#define EOS_PWR_DEV_NET ((uint32_t)1 << EOS_PWR_GPIO_NET) +#define EOS_PWR_DEV_APP ((uint32_t)1 << EOS_PWR_GPIO_APP) +#define EOS_PWR_DEV_MODEM ((uint32_t)1 << EOS_PWR_GPIO_MODEM) +#define EOS_PWR_DEV_ALL (EOS_PWR_DEV_NET | EOS_PWR_DEV_APP | EOS_PWR_DEV_MODEM) -#define EOS_PWR_SMODE_LIGHT 1 -#define EOS_PWR_SMODE_DEEP 2 +#define EOS_PWR_SMODE_TICKLESS 1 +#define EOS_PWR_SMODE_LIGHT 2 +#define EOS_PWR_SMODE_DEEP 3 void eos_power_init(void); +void eos_power_run(void); +void eos_power_sys_sleep(uint8_t mode); +void eos_power_sys_wake(uint8_t mode) ; +uint32_t eos_power_wakeup_source(void); -void eos_power_wait4init(void); -void eos_power_wait4wake(void); -uint8_t eos_power_wakeup_cause(void); -void eos_power_sleep(void); -void eos_power_wake(uint8_t source); -void eos_power_net_ready(void);
\ No newline at end of file +void eos_power_sleep_req(uint8_t mode, uint32_t dev); +void eos_power_sleep_rdy(uint32_t dev); +void eos_power_wake(uint32_t dev); diff --git a/fw/esp32/components/eos/include/sock.h b/fw/esp32/components/eos/include/sock.h index 7e937cb..f2cf0c4 100644 --- a/fw/esp32/components/eos/include/sock.h +++ b/fw/esp32/components/eos/include/sock.h @@ -15,4 +15,6 @@ typedef struct EOSNetAddr { uint16_t port; } EOSNetAddr; -void eos_sock_init(void);
\ No newline at end of file +void eos_sock_init(void); +void eos_sock_run(void); +void eos_sock_reopen(void);
\ No newline at end of file diff --git a/fw/esp32/components/eos/include/wifi.h b/fw/esp32/components/eos/include/wifi.h index c1819e7..d080e25 100644 --- a/fw/esp32/components/eos/include/wifi.h +++ b/fw/esp32/components/eos/include/wifi.h @@ -13,6 +13,7 @@ #define EOS_WIFI_MAX_SCAN_RECORDS 20 void eos_wifi_init(void); +void eos_wifi_run(void); int eos_wifi_scan(void); int eos_wifi_auth(char *ssid, char *pass); @@ -21,4 +22,4 @@ int eos_wifi_disconnect(void); ssize_t eos_wifi_get_status(unsigned char *buffer); void eos_wifi_send_status(void); -void eos_wifi_send_scan(void);
\ No newline at end of file +void eos_wifi_send_scan(void); diff --git a/fw/esp32/components/eos/msgq.c b/fw/esp32/components/eos/msgq.c index c200f7c..57fb669 100644 --- a/fw/esp32/components/eos/msgq.c +++ b/fw/esp32/components/eos/msgq.c @@ -12,6 +12,10 @@ void eos_msgq_init(EOSMsgQ *msgq, EOSMsgItem *array, uint8_t size) { msgq->array = array; } +uint8_t eos_msgq_len(EOSMsgQ *msgq) { + return (uint8_t)(msgq->idx_w - msgq->idx_r); +} + int eos_msgq_push(EOSMsgQ *msgq, unsigned char type, unsigned char *buffer, uint16_t len) { if ((uint8_t)(msgq->idx_w - msgq->idx_r) == msgq->size) return EOS_ERR_FULL; @@ -37,10 +41,6 @@ void eos_msgq_pop(EOSMsgQ *msgq, unsigned char *type, unsigned char **buffer, ui } } -uint8_t eos_msgq_len(EOSMsgQ *msgq) { - return (uint8_t)(msgq->idx_w - msgq->idx_r); -} - void eos_bufq_init(EOSBufQ *bufq, unsigned char **array, uint8_t size) { bufq->idx_r = 0; bufq->idx_w = 0; @@ -48,6 +48,10 @@ void eos_bufq_init(EOSBufQ *bufq, unsigned char **array, uint8_t size) { bufq->array = array; } +uint8_t eos_bufq_len(EOSBufQ *bufq) { + return (uint8_t)(bufq->idx_w - bufq->idx_r); +} + int eos_bufq_push(EOSBufQ *bufq, unsigned char *buffer) { if ((uint8_t)(bufq->idx_w - bufq->idx_r) == bufq->size) return EOS_ERR_FULL; @@ -60,7 +64,3 @@ unsigned char *eos_bufq_pop(EOSBufQ *bufq) { return bufq->array[IDX_MASK(bufq->idx_r++, bufq->size)]; } - -uint8_t eos_bufq_len(EOSBufQ *bufq) { - return (uint8_t)(bufq->idx_w - bufq->idx_r); -} diff --git a/fw/esp32/components/eos/net.c b/fw/esp32/components/eos/net.c index 56ec940..0ba2a2d 100644 --- a/fw/esp32/components/eos/net.c +++ b/fw/esp32/components/eos/net.c @@ -16,20 +16,21 @@ #include "eos.h" #include "msgq.h" #include "power.h" +#include "app.h" #include "net.h" +#include "net_priv.h" -#define SPI_GPIO_RTS 22 -#define SPI_GPIO_CTS 21 -#define SPI_GPIO_MOSI 23 -#define SPI_GPIO_MISO 19 -#define SPI_GPIO_SCLK 18 -#define SPI_GPIO_CS 5 +#define SPI_GPIO_RTS 35 +#define SPI_GPIO_CTS 3 +#define SPI_GPIO_MOSI 40 +#define SPI_GPIO_MISO 39 +#define SPI_GPIO_SCLK 38 +#define SPI_GPIO_CS 8 #define SPI_SIZE_BUF (EOS_NET_SIZE_BUF + 4) #define SPI_SIZE_HDR 3 -static volatile int net_sleep = 0; -static volatile int net_wake = 0; +#define SPI_HOST SPI3_HOST static EOSBufQ net_buf_q; static unsigned char *net_bufq_array[EOS_NET_SIZE_BUFQ]; @@ -37,262 +38,440 @@ static unsigned char *net_bufq_array[EOS_NET_SIZE_BUFQ]; static EOSMsgQ net_send_q; static EOSMsgItem net_sndq_array[EOS_NET_SIZE_SNDQ]; -static SemaphoreHandle_t mutex; -static SemaphoreHandle_t semaph; -static TaskHandle_t net_xchg_task_handle; +static NETConfig net_config; +static eos_net_handler_t net_handler[EOS_NET_MAX_MTYPE]; + +static spi_bus_config_t net_spi_bus_cfg; +static spi_slave_interface_config_t net_spi_iface_cfg; +static spi_slave_transaction_t net_spi_tr_cfg; + static const char *TAG = "EOS NET"; -static eos_net_fptr_t net_handler[EOS_NET_MAX_MTYPE]; +static void bad_handler(unsigned char mtype, unsigned char *buffer, uint16_t buf_len) { + ESP_LOGE(TAG, "bad handler: 0x%.2X len: %d", mtype, buf_len); +} + +static void net_msg_handler(unsigned char mtype, unsigned char *buffer, uint16_t buf_len) { + uint8_t idx; -static void bad_handler(unsigned char mtype, unsigned char *buffer, uint16_t len) { - ESP_LOGE(TAG, "bad handler: %d len: %d", mtype, len); + idx = mtype & EOS_NET_MTYPE_MASK; + if (idx && (idx <= EOS_NET_MAX_MTYPE) && (buf_len <= EOS_NET_MTU)) { + net_handler[idx - 1](mtype, buffer, buf_len); + } else { + bad_handler(mtype, buffer, buf_len); + } } -// Called after a transaction is queued and ready for pickup by master. We use this to set the handshake line high. +/* Called after a transaction is queued and ready for pickup by master */ static void _post_setup_cb(spi_slave_transaction_t *trans) { - gpio_set_level(SPI_GPIO_CTS, 1); + NETConfig *config = trans->user; + + gpio_set_level(config->gpio_cts, 0); } -// Called after transaction is sent/received. We use this to set the handshake line low. +/* Called after transaction is sent/received */ static void _post_trans_cb(spi_slave_transaction_t *trans) { - gpio_set_level(SPI_GPIO_CTS, 0); + NETConfig *config = trans->user; + + gpio_set_level(config->gpio_cts, 1); +} + +static void net_goto_sleep(NETConfig *config) { + esp_err_t ret; + uint8_t msgq_len; + + + xSemaphoreTake(config->mutex, portMAX_DELAY); + msgq_len = eos_msgq_len(config->send_q); + if (msgq_len) { + gpio_set_level(config->gpio_rts, 0); + } else { + gpio_set_level(config->gpio_rts, 1); + } + xSemaphoreGive(config->mutex); + + ret = spi_slave_free(config->spi_host); + assert(ret == ESP_OK); + + /* for deep sleep */ + gpio_hold_en(config->gpio_cts); + + eos_power_sleep_rdy(config->dev); + vTaskSuspend(NULL); + + gpio_hold_dis(config->gpio_cts); + + ret = spi_slave_initialize(config->spi_host, config->spi_bus_cfg, config->spi_iface_cfg, SPI_DMA_CH_AUTO); + assert(ret == ESP_OK); + + xSemaphoreTake(config->mutex, portMAX_DELAY); + config->sleep = 0; + msgq_len = eos_msgq_len(config->send_q); + if (msgq_len) { + gpio_set_level(config->gpio_rts, 0); + } else { + gpio_set_level(config->gpio_rts, 1); + } + xSemaphoreGive(config->mutex); } -static void net_xchg_task(void *pvParameters) { - int wake = 0; - int skip_msg = 0; +void eos_net_xchg_task(void *param) { + NETConfig *config = param; + int present, skip_msg = 0, sleep_msg = 0; unsigned char mtype = 0; unsigned char mtype_flags = 0; unsigned char *buffer; - uint16_t len; unsigned char *buf_send = heap_caps_malloc(SPI_SIZE_BUF, MALLOC_CAP_DMA); unsigned char *buf_recv = heap_caps_malloc(SPI_SIZE_BUF, MALLOC_CAP_DMA); + uint16_t buf_len; + size_t trans_len; + spi_bus_config_t *spi_bus_cfg = config->spi_bus_cfg; + spi_slave_interface_config_t *spi_iface_cfg = config->spi_iface_cfg; + spi_slave_transaction_t *spi_tr_cfg = config->spi_tr_cfg; esp_err_t ret; - static spi_slave_transaction_t spi_tr; - - //Configuration for the SPI bus - static spi_bus_config_t spi_bus_cfg = { - .mosi_io_num = SPI_GPIO_MOSI, - .miso_io_num = SPI_GPIO_MISO, - .sclk_io_num = SPI_GPIO_SCLK - }; - - //Configuration for the SPI slave interface - static spi_slave_interface_config_t spi_slave_cfg = { - .mode = 0, - .spics_io_num = SPI_GPIO_CS, - .queue_size = 2, - .flags = 0, - .post_setup_cb = _post_setup_cb, - .post_trans_cb = _post_trans_cb - }; - - //Initialize SPI slave interface - ret = spi_slave_initialize(VSPI_HOST, &spi_bus_cfg, &spi_slave_cfg, 2); - assert(ret == ESP_OK); - - memset(&spi_tr, 0, sizeof(spi_tr)); - spi_tr.tx_buffer = buf_send; - spi_tr.rx_buffer = buf_recv; - spi_tr.length = SPI_SIZE_BUF * 8; - - if (eos_power_wakeup_cause() != EOS_PWR_WAKE_RST) { - wake = 1; - skip_msg = 1; + assert(buf_send != NULL); + assert(buf_recv != NULL); + + /* Configuration for the SPI bus */ + spi_bus_cfg->mosi_io_num = config->gpio_mosi; + spi_bus_cfg->miso_io_num = config->gpio_miso; + spi_bus_cfg->sclk_io_num = config->gpio_sclk; + + /* Configuration for the SPI slave interface */ + spi_iface_cfg->mode = 0; + spi_iface_cfg->spics_io_num = config->gpio_cs; + spi_iface_cfg->queue_size = 2; + spi_iface_cfg->flags = 0; + spi_iface_cfg->post_setup_cb = _post_setup_cb; + spi_iface_cfg->post_trans_cb = _post_trans_cb; + + spi_tr_cfg->tx_buffer = buf_send; + spi_tr_cfg->rx_buffer = buf_recv; + spi_tr_cfg->length = SPI_SIZE_BUF * 8; + spi_tr_cfg->user = config; + + xSemaphoreTake(config->mutex, portMAX_DELAY); + present = config->present; + xSemaphoreGive(config->mutex); + if (!present) { + vTaskSuspend(NULL); } - eos_power_wait4init(); + /* Initialize SPI slave interface */ + ret = spi_slave_initialize(config->spi_host, spi_bus_cfg, spi_iface_cfg, SPI_DMA_CH_AUTO); + assert(ret == ESP_OK); + while (1) { if (!skip_msg) { - xSemaphoreTake(mutex, portMAX_DELAY); + xSemaphoreTake(config->mutex, portMAX_DELAY); - eos_msgq_pop(&net_send_q, &mtype, &buffer, &len); + eos_msgq_pop(config->send_q, &mtype, &buffer, &buf_len); if (mtype) { buf_send[0] = mtype; - buf_send[1] = len >> 8; - buf_send[2] = len & 0xFF; + buf_send[1] = buf_len >> 8; + buf_send[2] = buf_len & 0xFF; if (buffer) { - memcpy(buf_send + SPI_SIZE_HDR, buffer, len); - eos_bufq_push(&net_buf_q, buffer); - xSemaphoreGive(semaph); + memcpy(buf_send + SPI_SIZE_HDR, buffer, buf_len); + xSemaphoreTake(config->bufq_mutex, portMAX_DELAY); + eos_bufq_push(config->buf_q, buffer); + xSemaphoreGive(config->bufq_mutex); + xSemaphoreGive(config->bufq_semaph); } + } else if (!sleep_msg && config->sleep_req) { + buf_send[0] = EOS_NET_MTYPE_SLEEP; + buf_send[1] = 0; + buf_send[2] = 0; + sleep_msg = 1; + config->sleep_req = 0; + if (config->dev == NET_DEV_NET) config->sleep = 1; } else { - gpio_set_level(SPI_GPIO_RTS, 0); + gpio_set_level(config->gpio_rts, 1); buf_send[0] = 0; buf_send[1] = 0; buf_send[2] = 0; } - xSemaphoreGive(mutex); + xSemaphoreGive(config->mutex); } skip_msg = 0; buf_recv[0] = 0; buf_recv[1] = 0; buf_recv[2] = 0; - spi_slave_transmit(VSPI_HOST, &spi_tr, portMAX_DELAY); - // ESP_LOGI(TAG, "RECV:%d", buf_recv[0]); + ret = spi_slave_transmit(config->spi_host, spi_tr_cfg, portMAX_DELAY); + assert(ret == ESP_OK); + + trans_len = spi_tr_cfg->trans_len / 8; + + ESP_LOGI(TAG, "RECV:0x%.2X DEV:0x%.8lX LEN:%d", buf_recv[0], config->dev, trans_len); + + if (sleep_msg && (config->dev == NET_DEV_NET)) { + net_goto_sleep(config); + sleep_msg = 0; + continue; + } + + if (trans_len < 1) { + ESP_LOGE(TAG, "RECV LEN:%d", trans_len); + continue; + } - if (wake) { - eos_power_net_ready(); - wake = 0; + /* SPI reset */ + if ((trans_len == 1) && (buf_recv[0] == 0)) { + if (buf_send[0]) skip_msg = 1; + continue; } - if ((spi_tr.trans_len / 8) < SPI_SIZE_HDR) continue; - if (buf_recv[0] == 0x00) continue; + mtype = buf_recv[0] & EOS_NET_MTYPE_MASK; + mtype_flags = buf_recv[0] & ~EOS_NET_MTYPE_MASK; + if (buf_send[0] && (mtype_flags & EOS_NET_MTYPE_FLAG_ONEW)) { + skip_msg = 1; + } - if (buf_recv[0] == 0xFF) { // Sleep req - if (buf_send[0] == 0) { - spi_slave_free(VSPI_HOST); - eos_power_sleep(); + if (buf_send[0] && (trans_len < buf_len + SPI_SIZE_HDR) && !skip_msg) { + spi_tr_cfg->tx_buffer = buf_send + trans_len; + spi_tr_cfg->rx_buffer = buf_recv + trans_len; + spi_tr_cfg->length = (SPI_SIZE_BUF - trans_len) * 8; + ret = spi_slave_transmit(config->spi_host, spi_tr_cfg, portMAX_DELAY); + assert(ret == ESP_OK); + trans_len += spi_tr_cfg->trans_len / 8; + spi_tr_cfg->tx_buffer = buf_send; + spi_tr_cfg->rx_buffer = buf_recv; + spi_tr_cfg->length = SPI_SIZE_BUF * 8; + } - xSemaphoreTake(mutex, portMAX_DELAY); - net_sleep = 1; - if (eos_msgq_len(&net_send_q)) net_wake = 1; - xSemaphoreGive(mutex); + if (mtype == 0) continue; - if (net_wake) eos_power_wake(EOS_PWR_WAKE_NETQ); - vTaskSuspend(NULL); + if (mtype == EOS_NET_MTYPE_SLEEP) { + uint8_t mode; - xSemaphoreTake(mutex, portMAX_DELAY); - net_sleep = 0; - net_wake = 0; - xSemaphoreGive(mutex); + mode = EOS_PWR_SMODE_LIGHT; - spi_slave_initialize(VSPI_HOST, &spi_bus_cfg, &spi_slave_cfg, 1); - wake = 1; - skip_msg = 1; + switch (config->dev) { + case NET_DEV_NET: { + eos_power_sleep_req(mode, EOS_PWR_DEV_ALL); + break; + } + case NET_DEV_APP: { + uint8_t msgq_len; + + xSemaphoreTake(config->mutex, portMAX_DELAY); + msgq_len = eos_msgq_len(config->send_q); + if (msgq_len == 0) { + config->sleep = 1; + config->sleep_req = 0; + } + xSemaphoreGive(config->mutex); + if (msgq_len == 0) { + net_goto_sleep(config); + sleep_msg = 0; + } + break; + } } continue; } - mtype = buf_recv[0] & ~EOS_NET_MTYPE_FLAG_MASK; - mtype_flags = buf_recv[0] & EOS_NET_MTYPE_FLAG_MASK; - len = (uint16_t)buf_recv[1] << 8; - len |= (uint16_t)buf_recv[2] & 0xFF; - buffer = buf_recv + SPI_SIZE_HDR; - if ((mtype <= EOS_NET_MAX_MTYPE) && (len <= EOS_NET_MTU)) { - net_handler[mtype - 1](buf_recv[0], buffer, len); - } else { - bad_handler(buf_recv[0], buffer, len); - } - if ((mtype_flags & EOS_NET_MTYPE_FLAG_ONEW) && buf_send[0]) { - skip_msg = 1; + if (trans_len < SPI_SIZE_HDR) { + ESP_LOGE(TAG, "RECV LEN:%d", trans_len); + continue; } + buf_len = (uint16_t)buf_recv[1] << 8; + buf_len |= (uint16_t)buf_recv[2] & 0xFF; + buffer = buf_recv + SPI_SIZE_HDR; + config->msg_handler(buf_recv[0], buffer, buf_len); + if (mtype_flags & EOS_NET_MTYPE_FLAG_REPL) { - spi_tr.tx_buffer = buf_recv; - spi_tr.rx_buffer = NULL; - spi_slave_transmit(VSPI_HOST, &spi_tr, portMAX_DELAY); - spi_tr.tx_buffer = buf_send; - spi_tr.rx_buffer = buf_recv; + spi_tr_cfg->tx_buffer = buf_recv; + spi_tr_cfg->rx_buffer = NULL; + ret = spi_slave_transmit(config->spi_host, spi_tr_cfg, portMAX_DELAY); + assert(ret == ESP_OK); + spi_tr_cfg->tx_buffer = buf_send; + spi_tr_cfg->rx_buffer = buf_recv; } } + vTaskDelete(NULL); } -void eos_net_init(void) { - int i; - - // Configuration for the handshake lines +void _eos_net_init_gpio(NETConfig *config) { + /* Configuration for the handshake lines */ gpio_config_t io_conf = {}; + gpio_set_level(config->gpio_rts, 1); + gpio_set_level(config->gpio_cts, 1); io_conf.intr_type = GPIO_INTR_DISABLE; io_conf.mode = GPIO_MODE_OUTPUT; - io_conf.pull_up_en = 0; - io_conf.pull_down_en = 0; - io_conf.pin_bit_mask = ((uint64_t)1 << SPI_GPIO_CTS); + io_conf.pull_up_en = GPIO_PULLUP_DISABLE; + io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; + io_conf.pin_bit_mask = BIT64(config->gpio_rts) | BIT64(config->gpio_cts); gpio_config(&io_conf); - gpio_set_level(SPI_GPIO_CTS, 0); +} - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.mode = GPIO_MODE_OUTPUT; - io_conf.pull_up_en = 0; - io_conf.pull_down_en = 0; - io_conf.pin_bit_mask = ((uint64_t)1 << SPI_GPIO_RTS); - gpio_config(&io_conf); - gpio_set_level(SPI_GPIO_RTS, 0); +void eos_net_init(void) { + SemaphoreHandle_t mutex; + SemaphoreHandle_t bufq_mutex; + SemaphoreHandle_t bufq_semaph; + int i; eos_msgq_init(&net_send_q, net_sndq_array, EOS_NET_SIZE_SNDQ); eos_bufq_init(&net_buf_q, net_bufq_array, EOS_NET_SIZE_BUFQ); for (i=0; i<EOS_NET_SIZE_BUFQ; i++) { - eos_bufq_push(&net_buf_q, malloc(EOS_NET_SIZE_BUF)); + unsigned char *buffer; + + buffer = malloc(EOS_NET_SIZE_BUF); + assert(buffer != NULL); + eos_bufq_push(&net_buf_q, buffer); } for (i=0; i<EOS_NET_MAX_MTYPE; i++) { net_handler[i] = bad_handler; } - semaph = xSemaphoreCreateCounting(EOS_NET_SIZE_BUFQ, EOS_NET_SIZE_BUFQ); mutex = xSemaphoreCreateBinary(); + assert(mutex != NULL); + bufq_mutex = xSemaphoreCreateBinary(); + assert(bufq_mutex != NULL); + bufq_semaph = xSemaphoreCreateCounting(EOS_NET_SIZE_BUFQ, EOS_NET_SIZE_BUFQ); + assert(bufq_semaph != NULL); + xSemaphoreGive(mutex); - xTaskCreate(&net_xchg_task, "net_xchg", EOS_TASK_SSIZE_NET_XCHG, NULL, EOS_TASK_PRIORITY_NET_XCHG, &net_xchg_task_handle); + xSemaphoreGive(bufq_mutex); + + net_config.sleep = 0; + net_config.sleep_req = 0; + net_config.present = 1; + net_config.dev = NET_DEV_NET; + net_config.gpio_mosi = SPI_GPIO_MOSI; + net_config.gpio_miso = SPI_GPIO_MISO; + net_config.gpio_sclk = SPI_GPIO_SCLK; + net_config.gpio_cs = SPI_GPIO_CS; + net_config.gpio_rts = SPI_GPIO_RTS; + net_config.gpio_cts = SPI_GPIO_CTS; + net_config.spi_host = SPI_HOST; + net_config.spi_bus_cfg = &net_spi_bus_cfg; + net_config.spi_iface_cfg = &net_spi_iface_cfg; + net_config.spi_tr_cfg = &net_spi_tr_cfg; + net_config.mutex = mutex; + net_config.bufq_mutex = bufq_mutex; + net_config.bufq_semaph = bufq_semaph; + net_config.buf_q = &net_buf_q; + net_config.send_q = &net_send_q; + net_config.msg_handler = net_msg_handler; + + _eos_net_init_gpio(&net_config); + + if (esp_reset_reason() == ESP_RST_DEEPSLEEP) { + gpio_hold_dis(net_config.gpio_cts); + } + ESP_LOGI(TAG, "INIT"); } -unsigned char *eos_net_alloc(void) { +void eos_net_run(void) { + BaseType_t rv; + + rv = xTaskCreate(&eos_net_xchg_task, "net_xchg", EOS_TASK_SSIZE_NET, &net_config, EOS_TASK_PRIORITY_NET, &net_config.xchg_task_handle); + assert(rv == pdPASS); + + ESP_LOGI(TAG, "RUN"); +} + +unsigned char *_eos_net_alloc(NETConfig *config) { unsigned char *ret; - xSemaphoreTake(semaph, portMAX_DELAY); - xSemaphoreTake(mutex, portMAX_DELAY); - ret = eos_bufq_pop(&net_buf_q); - xSemaphoreGive(mutex); + xSemaphoreTake(config->bufq_semaph, portMAX_DELAY); + xSemaphoreTake(config->bufq_mutex, portMAX_DELAY); + ret = eos_bufq_pop(config->buf_q); + xSemaphoreGive(config->bufq_mutex); return ret; } +void _eos_net_free(NETConfig *config, unsigned char *buf) { + xSemaphoreTake(config->bufq_mutex, portMAX_DELAY); + eos_bufq_push(config->buf_q, buf); + xSemaphoreGive(config->bufq_semaph); + xSemaphoreGive(config->bufq_mutex); +} + +unsigned char *eos_net_alloc(void) { + return _eos_net_alloc(&net_config); +} + void eos_net_free(unsigned char *buf) { - xSemaphoreTake(mutex, portMAX_DELAY); - eos_bufq_push(&net_buf_q, buf); - xSemaphoreGive(semaph); - xSemaphoreGive(mutex); + _eos_net_free(&net_config, buf); } -int eos_net_send(unsigned char mtype, unsigned char *buffer, uint16_t len) { +int _eos_net_send(NETConfig *config, unsigned char mtype, unsigned char *buffer, uint16_t buf_len) { int rv = EOS_OK; int sleep; - xSemaphoreTake(mutex, portMAX_DELAY); - sleep = net_sleep && !net_wake; - gpio_set_level(SPI_GPIO_RTS, 1); - rv = eos_msgq_push(&net_send_q, mtype, buffer, len); - xSemaphoreGive(mutex); - - if (rv) eos_net_free(buffer); + xSemaphoreTake(config->mutex, portMAX_DELAY); + sleep = config->sleep; + rv = eos_msgq_push(config->send_q, mtype, buffer, buf_len); + if (!rv && !sleep) gpio_set_level(config->gpio_rts, 0); + xSemaphoreGive(config->mutex); - if (sleep) eos_power_wake(EOS_PWR_WAKE_NETQ); + if (!rv && sleep) eos_power_wake(config->dev); + if (rv) _eos_net_free(config, buffer); return rv; } -void eos_net_reply(unsigned char mtype, unsigned char *buffer, uint16_t len) { +int eos_net_send(unsigned char mtype, unsigned char *buffer, uint16_t buf_len) { + return _eos_net_send(&net_config, mtype, buffer, buf_len); +} + +void eos_net_reply(unsigned char mtype, unsigned char *buffer, uint16_t buf_len) { buffer -= SPI_SIZE_HDR; buffer[0] = mtype; - buffer[1] = len >> 8; - buffer[2] = len & 0xFF; + buffer[1] = buf_len >> 8; + buffer[2] = buf_len & 0xFF; } -void eos_net_set_handler(unsigned char mtype, eos_net_fptr_t handler) { - if (handler == NULL) handler = bad_handler; - if (mtype && (mtype <= EOS_NET_MAX_MTYPE)) net_handler[mtype - 1] = handler; -} +void _eos_net_sleep_req(NETConfig *config) { + int sleep, present; + + xSemaphoreTake(config->mutex, portMAX_DELAY); + sleep = config->sleep; + present = config->present; + if (!sleep && present) { + config->sleep_req = 1; + gpio_set_level(config->gpio_rts, 0); + } + xSemaphoreGive(config->mutex); -void eos_net_sleep(void) { - gpio_set_level(SPI_GPIO_CTS, 1); - vTaskDelay(200 / portTICK_PERIOD_MS); - gpio_set_level(SPI_GPIO_CTS, 0); + if (!present) eos_power_sleep_rdy(config->dev); } -void eos_net_wake(uint8_t source, uint8_t mode) { - int sleep; +void _eos_net_wake(NETConfig *config) { + int sleep, present; + + xSemaphoreTake(config->mutex, portMAX_DELAY); + present = config->present; + xSemaphoreGive(config->mutex); - if (mode == EOS_PWR_SMODE_DEEP) return; + if (!present) return; do { - vTaskResume(net_xchg_task_handle); + vTaskResume(config->xchg_task_handle); vTaskDelay(10 / portTICK_PERIOD_MS); - - xSemaphoreTake(mutex, portMAX_DELAY); - sleep = net_sleep; - xSemaphoreGive(mutex); + xSemaphoreTake(config->mutex, portMAX_DELAY); + sleep = config->sleep; + xSemaphoreGive(config->mutex); } while (sleep); } + +void eos_net_sleep_req(void) { + _eos_net_sleep_req(&net_config); +} + +void eos_net_wake(void) { + _eos_net_wake(&net_config); +} + +void eos_net_set_handler(unsigned char mtype, eos_net_handler_t handler) { + if (handler == NULL) handler = bad_handler; + if (mtype && (mtype <= EOS_NET_MAX_MTYPE)) net_handler[mtype - 1] = handler; +} diff --git a/fw/esp32/components/eos/power.c b/fw/esp32/components/eos/power.c index b98c0ec..27c44a5 100644 --- a/fw/esp32/components/eos/power.c +++ b/fw/esp32/components/eos/power.c @@ -4,37 +4,30 @@ #include <freertos/task.h> #include <freertos/queue.h> #include <driver/gpio.h> +#include <driver/rtc_io.h> +#include <driver/uart.h> + +#include <esp_system.h> #include <esp_sleep.h> -#include <esp_timer.h> #include <esp_pm.h> #include <esp_log.h> -#include <esp32/rom/rtc.h> #include "eos.h" #include "net.h" +#include "app.h" #include "cell.h" #include "power.h" -#define POWER_GPIO_BTN 0 -#define POWER_GPIO_NET 5 -#define POWER_GPIO_UART 35 - -#define POWER_ETYPE_BTN 1 -#define POWER_ETYPE_SLEEP1 2 -#define POWER_ETYPE_SLEEP2 3 -#define POWER_ETYPE_WAKE 4 -#define POWER_ETYPE_NETRDY 5 +#define PWR_ETYPE_SLEEP_REQ 1 +#define PWR_ETYPE_SLEEP_RDY 2 +#define PWR_ETYPE_WAKE 3 typedef struct { uint8_t type; - union { - uint8_t source; - uint8_t level; - }; + uint8_t mode; + uint32_t dev; } power_event_t; -static esp_timer_handle_t timer; - static esp_pm_lock_handle_t power_lock_cpu_freq; static esp_pm_lock_handle_t power_lock_apb_freq; static esp_pm_lock_handle_t power_lock_no_sleep; @@ -43,232 +36,119 @@ static const char *TAG = "EOS POWER"; static QueueHandle_t power_queue; -static volatile int init_done = 0; -static volatile int wake_done = 0; - -static void IRAM_ATTR btn_handler(void *arg) { - power_event_t evt; - - evt.type = POWER_ETYPE_BTN; - evt.level = gpio_get_level(POWER_GPIO_BTN); - xQueueSendFromISR(power_queue, &evt, NULL); -} - -static void IRAM_ATTR btn_wake_handler(void *arg) { - power_event_t evt; - - gpio_intr_disable(POWER_GPIO_BTN); - - evt.type = POWER_ETYPE_WAKE; - evt.source = EOS_PWR_WAKE_BTN; - xQueueSendFromISR(power_queue, &evt, NULL); - -} - static void IRAM_ATTR net_wake_handler(void *arg) { power_event_t evt; - gpio_intr_disable(POWER_GPIO_NET); - - evt.type = POWER_ETYPE_WAKE; - evt.source = EOS_PWR_WAKE_NET; + evt.type = PWR_ETYPE_WAKE; + evt.dev = EOS_PWR_DEV_NET; xQueueSendFromISR(power_queue, &evt, NULL); } -static void IRAM_ATTR uart_wake_handler(void *arg) { +static void IRAM_ATTR app_wake_handler(void *arg) { power_event_t evt; - gpio_intr_disable(POWER_GPIO_UART); - - evt.type = POWER_ETYPE_WAKE; - evt.source = EOS_PWR_WAKE_UART; + evt.type = PWR_ETYPE_WAKE; + evt.dev = EOS_PWR_DEV_APP; xQueueSendFromISR(power_queue, &evt, NULL); } -static void timer_handler(void *arg) { +static void IRAM_ATTR modem_wake_handler(void *arg) { power_event_t evt; - evt.type = POWER_ETYPE_SLEEP2; + evt.type = PWR_ETYPE_WAKE; + evt.dev = EOS_PWR_DEV_MODEM; xQueueSendFromISR(power_queue, &evt, NULL); } -static void power_sleep_stage1(int modem_wake_en) { - gpio_config_t io_conf = {}; - - eos_modem_sleep(); - eos_net_sleep(); - - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.mode = GPIO_MODE_INPUT; - io_conf.pin_bit_mask = ((uint64_t)1 << POWER_GPIO_NET); - io_conf.pull_up_en = 0; - io_conf.pull_down_en = 0; - gpio_config(&io_conf); - - gpio_isr_handler_add(POWER_GPIO_BTN, btn_wake_handler, NULL); - gpio_isr_handler_add(POWER_GPIO_NET, net_wake_handler, NULL); - if (modem_wake_en) { - gpio_isr_handler_add(POWER_GPIO_UART, uart_wake_handler, NULL); - } - - esp_sleep_enable_gpio_wakeup(); - gpio_wakeup_enable(POWER_GPIO_BTN, GPIO_INTR_LOW_LEVEL); - gpio_wakeup_enable(POWER_GPIO_NET, GPIO_INTR_LOW_LEVEL); - if (modem_wake_en) { - gpio_wakeup_enable(POWER_GPIO_UART, GPIO_INTR_LOW_LEVEL); - } - - esp_timer_start_once(timer, 10 * 1000000); - - esp_pm_lock_release(power_lock_cpu_freq); - esp_pm_lock_release(power_lock_apb_freq); - esp_pm_lock_release(power_lock_no_sleep); -} - -static void power_sleep_stage2(int modem_wake_en, uint8_t mode) { - switch (mode) { - case EOS_PWR_SMODE_LIGHT: { - ESP_LOGI(TAG, "LIGHT SLEEP"); - - esp_light_sleep_start(); - break; - } - - case EOS_PWR_SMODE_DEEP: { - esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL); - - gpio_deep_sleep_hold_en(); - esp_sleep_enable_ext0_wakeup(POWER_GPIO_BTN, 0); - if (modem_wake_en) { - esp_sleep_enable_ext1_wakeup((uint64_t)1 << POWER_GPIO_UART, ESP_EXT1_WAKEUP_ALL_LOW); - } - - ESP_LOGI(TAG, "DEEP SLEEP"); - - eos_modem_deep_sleep(); - esp_deep_sleep_start(); - break; - } - } -} - -static void power_wake_stage1(uint8_t source, uint8_t mode) { - if (mode == EOS_PWR_SMODE_LIGHT) { - gpio_config_t io_conf = {}; - - esp_pm_lock_acquire(power_lock_cpu_freq); - esp_pm_lock_acquire(power_lock_apb_freq); - esp_pm_lock_acquire(power_lock_no_sleep); - - gpio_wakeup_disable(POWER_GPIO_BTN); - gpio_wakeup_disable(POWER_GPIO_NET); - gpio_wakeup_disable(POWER_GPIO_UART); - esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL); - - gpio_isr_handler_remove(POWER_GPIO_NET); - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.mode = GPIO_MODE_DISABLE; - io_conf.pin_bit_mask = ((uint64_t)1 << POWER_GPIO_NET); - io_conf.pull_up_en = 0; - io_conf.pull_down_en = 0; - gpio_config(&io_conf); - } - - gpio_intr_disable(POWER_GPIO_BTN); - if ((source != EOS_PWR_WAKE_BTN) && (source != EOS_PWR_WAKE_NET)) { - gpio_set_level(POWER_GPIO_BTN, 0); - gpio_set_direction(POWER_GPIO_BTN, GPIO_MODE_OUTPUT); - vTaskDelay(200 / portTICK_PERIOD_MS); - gpio_set_direction(POWER_GPIO_BTN, GPIO_MODE_INPUT); - } - - eos_net_wake(source, mode); -} - -static void power_wake_stage2(uint8_t source, uint8_t mode) { - eos_modem_wake(source, mode); - - gpio_set_intr_type(POWER_GPIO_BTN, GPIO_INTR_ANYEDGE); - gpio_isr_handler_add(POWER_GPIO_BTN, btn_handler, NULL); - - ESP_LOGI(TAG, "WAKE"); - wake_done = 1; -} - static void power_event_task(void *pvParameters) { power_event_t evt; - uint8_t source; - uint8_t wakeup_cause; uint8_t mode; - int sleep1, sleep2; - int modem_wake_en; + uint32_t sleep_req, sleep_rdy; + int sys_sleep; mode = 0; - source = 0; - wakeup_cause = eos_power_wakeup_cause(); - if (wakeup_cause != EOS_PWR_WAKE_RST) { - mode = EOS_PWR_SMODE_DEEP; - sleep1 = 1; - } else { - sleep1 = 0; - } - sleep2 = 0; - modem_wake_en = 0; - + sys_sleep = 0; + sleep_req = 0; + sleep_rdy = 0; while (1) { if (xQueueReceive(power_queue, &evt, portMAX_DELAY)) { switch (evt.type) { - case POWER_ETYPE_SLEEP1: { - if (!sleep1) { - modem_wake_en = eos_modem_present(); - mode = EOS_PWR_SMODE_LIGHT; - power_sleep_stage1(modem_wake_en); - sleep1 = 1; - sleep2 = 1; + case PWR_ETYPE_SLEEP_REQ: { + if (evt.mode) mode = evt.mode; + if ((evt.dev & EOS_PWR_DEV_NET) && !(sleep_req & EOS_PWR_DEV_NET)) { + eos_net_sleep_req(); } - break; - } - - case POWER_ETYPE_SLEEP2: { - if (sleep2) { - mode = EOS_PWR_SMODE_DEEP; - power_sleep_stage2(modem_wake_en, mode); - sleep2 = 0; + if ((evt.dev & EOS_PWR_DEV_APP) && !(sleep_req & EOS_PWR_DEV_APP)) { + eos_app_sleep_req(); } - break; - } - - case POWER_ETYPE_WAKE: { - if (sleep1) { - source = evt.source; - power_wake_stage1(source, mode); - if (sleep2) { - esp_timer_stop(timer); - sleep2 = 0; - } + if ((evt.dev & EOS_PWR_DEV_MODEM) && !(sleep_req & EOS_PWR_DEV_MODEM)) { + eos_modem_sleep_req(); + } + sleep_req |= evt.dev; + if (sleep_rdy == EOS_PWR_DEV_ALL) { + eos_power_sleep_rdy(0); } break; } - case POWER_ETYPE_NETRDY: { - power_wake_stage2(source, mode); - sleep1 = 0; - source = 0; + case PWR_ETYPE_SLEEP_RDY: { + gpio_config_t io_conf = { + .mode = GPIO_MODE_INPUT, + .intr_type = GPIO_INTR_NEGEDGE, + .pull_up_en = 1, + .pull_down_en = 0, + }; + + if (evt.dev & EOS_PWR_DEV_NET) { + io_conf.pin_bit_mask = BIT64(EOS_PWR_GPIO_NET); + gpio_config(&io_conf); + gpio_isr_handler_add(EOS_PWR_GPIO_NET, net_wake_handler, NULL); + } + if (evt.dev & EOS_PWR_DEV_APP) { + io_conf.pin_bit_mask = BIT64(EOS_PWR_GPIO_APP); + gpio_config(&io_conf); + gpio_isr_handler_add(EOS_PWR_GPIO_APP, app_wake_handler, NULL); + } + if (evt.dev & EOS_PWR_DEV_MODEM) { + io_conf.pin_bit_mask = BIT64(EOS_PWR_GPIO_MODEM); + gpio_config(&io_conf); + gpio_isr_handler_add(EOS_PWR_GPIO_MODEM, modem_wake_handler, NULL); + } + sleep_rdy |= evt.dev; + if (!sys_sleep && mode && (sleep_rdy == EOS_PWR_DEV_ALL)) { + sys_sleep = 1; + eos_power_sys_sleep(mode); + } break; } - case POWER_ETYPE_BTN: { - unsigned char *buf; - - buf = eos_net_alloc(); - buf[0] = EOS_PWR_MTYPE_BUTTON; - buf[1] = evt.level; - eos_net_send(EOS_NET_MTYPE_POWER, buf, 2); + case PWR_ETYPE_WAKE: { + ESP_LOGI(TAG, "WAKE:0x%.8lX", evt.dev); + if (sys_sleep) { + eos_power_sys_wake(mode); + sys_sleep = 0; + mode = 0; + } + if ((evt.dev & EOS_PWR_DEV_NET) && (sleep_rdy & EOS_PWR_DEV_NET)) { + gpio_isr_handler_remove(EOS_PWR_GPIO_NET); + gpio_reset_pin(EOS_PWR_GPIO_NET); + eos_net_wake(); + } + if ((evt.dev & EOS_PWR_DEV_APP) && (sleep_rdy & EOS_PWR_DEV_APP)) { + gpio_isr_handler_remove(EOS_PWR_GPIO_APP); + gpio_reset_pin(EOS_PWR_GPIO_APP); + eos_app_wake(); + } + if ((evt.dev & EOS_PWR_DEV_MODEM) && (sleep_rdy & EOS_PWR_DEV_MODEM)) { + gpio_isr_handler_remove(EOS_PWR_GPIO_MODEM); + gpio_reset_pin(EOS_PWR_GPIO_MODEM); + eos_modem_wake(); + } + sleep_req &= ~evt.dev; + sleep_rdy &= ~evt.dev; + ESP_LOGI(TAG, "WAKE DONE:0x%.8lX", evt.dev); break; } - - default: - break; } } } @@ -276,35 +156,9 @@ static void power_event_task(void *pvParameters) { } void eos_power_init(void) { - esp_err_t ret; - gpio_config_t io_conf = {}; - esp_timer_create_args_t timer_args = {}; - esp_pm_config_esp32_t pwr_conf; - uint8_t wakeup_cause; - - io_conf.intr_type = GPIO_INTR_ANYEDGE; - io_conf.mode = GPIO_MODE_INPUT; - io_conf.pin_bit_mask = ((uint64_t)1 << POWER_GPIO_BTN); - io_conf.pull_up_en = 1; - io_conf.pull_down_en = 0; - gpio_config(&io_conf); - gpio_isr_handler_add(POWER_GPIO_BTN, btn_handler, NULL); - - timer_args.callback = timer_handler, - timer_args.arg = NULL; - timer_args.name = "sleep"; - - ret = esp_timer_create(&timer_args, &timer); - assert(ret == ESP_OK); - /* - ret = esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON); - assert(ret == ESP_OK); - ret = esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_FAST_MEM, ESP_PD_OPTION_ON); - assert(ret == ESP_OK); - ret = esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_SLOW_MEM, ESP_PD_OPTION_ON); - assert(ret == ESP_OK); - */ + esp_err_t ret; + esp_pm_config_t pwr_conf; ret = esp_pm_lock_create(ESP_PM_CPU_FREQ_MAX, 0, NULL, &power_lock_cpu_freq); assert(ret == ESP_OK); @@ -326,70 +180,118 @@ void eos_power_init(void) { ret = esp_pm_configure(&pwr_conf); assert(ret == ESP_OK); + */ - power_queue = xQueueCreate(4, sizeof(power_event_t)); - xTaskCreate(power_event_task, "power_event", EOS_TASK_SSIZE_PWR, NULL, EOS_TASK_PRIORITY_PWR, NULL); - - wakeup_cause = eos_power_wakeup_cause(); - if (wakeup_cause != EOS_PWR_WAKE_RST) { - eos_power_wake(wakeup_cause); + if (esp_reset_reason() == ESP_RST_DEEPSLEEP) { + rtc_gpio_deinit(EOS_PWR_GPIO_NET); + rtc_gpio_deinit(EOS_PWR_GPIO_APP); + rtc_gpio_deinit(EOS_PWR_GPIO_MODEM); + eos_power_sys_wake(EOS_PWR_SMODE_DEEP); } - init_done = 1; + power_queue = xQueueCreate(4, sizeof(power_event_t)); + assert(power_queue != NULL); + ESP_LOGI(TAG, "INIT"); } -void eos_power_wait4init(void) { - while (!init_done); -} +void eos_power_run(void) { + BaseType_t rv; -void eos_power_wait4wake(void) { - if (eos_power_wakeup_cause() == EOS_PWR_WAKE_RST) return; - while (!wake_done); -} + rv = xTaskCreate(power_event_task, "power_event", EOS_TASK_SSIZE_PWR, NULL, EOS_TASK_PRIORITY_PWR, NULL); + assert(rv == pdPASS); -uint8_t eos_power_wakeup_cause(void) { - esp_reset_reason_t reset_cause = esp_reset_reason(); - esp_sleep_wakeup_cause_t wakeup_cause = esp_sleep_get_wakeup_cause(); + ESP_LOGI(TAG, "RUN"); +} - if (reset_cause == ESP_RST_DEEPSLEEP) { - switch (wakeup_cause) { - case ESP_SLEEP_WAKEUP_EXT0: - return EOS_PWR_WAKE_BTN; +void eos_power_sys_sleep(uint8_t mode) { + switch (mode) { + case EOS_PWR_SMODE_TICKLESS: { + esp_pm_lock_release(power_lock_cpu_freq); + esp_pm_lock_release(power_lock_apb_freq); + esp_pm_lock_release(power_lock_no_sleep); + break; + } - case ESP_SLEEP_WAKEUP_EXT1: - return EOS_PWR_WAKE_UART; + case EOS_PWR_SMODE_LIGHT: + case EOS_PWR_SMODE_DEEP: { + esp_err_t ret; + + /* in case of missing modem */ + rtc_gpio_pullup_en(EOS_PWR_GPIO_MODEM); + esp_sleep_enable_ext1_wakeup_io(EOS_PWR_DEV_ALL, ESP_EXT1_WAKEUP_ANY_LOW); + if (mode == EOS_PWR_SMODE_DEEP) { + gpio_deep_sleep_hold_en(); + esp_deep_sleep_start(); + } else { + ESP_LOGI(TAG, "LIGHT SLEEP"); + uart_wait_tx_idle_polling(UART_NUM_0); + ret = esp_light_sleep_start(); + ESP_LOGI(TAG, "LIGHT WAKE: %d", ret); + eos_power_wake(eos_power_wakeup_source()); + } + break; + } + } +} - default: - return EOS_PWR_WAKE_UNDEF; +void eos_power_sys_wake(uint8_t mode) { + switch (mode) { + case EOS_PWR_SMODE_TICKLESS: { + esp_pm_lock_acquire(power_lock_cpu_freq); + esp_pm_lock_acquire(power_lock_apb_freq); + esp_pm_lock_acquire(power_lock_no_sleep); + break; + } + case EOS_PWR_SMODE_LIGHT: + case EOS_PWR_SMODE_DEEP: { + rtc_gpio_pullup_dis(EOS_PWR_GPIO_MODEM); + esp_sleep_disable_ext1_wakeup_io(0); + if (mode == EOS_PWR_SMODE_DEEP) { + gpio_deep_sleep_hold_dis(); + } + break; } + } +} + +uint32_t eos_power_wakeup_source(void) { + esp_sleep_wakeup_cause_t wakeup_cause; + uint32_t dev; + + dev = EOS_PWR_DEV_NONE; + wakeup_cause = esp_sleep_get_wakeup_cause(); + if (wakeup_cause == ESP_SLEEP_WAKEUP_EXT1) { + dev = esp_sleep_get_ext1_wakeup_status(); + return dev; } else { - return EOS_PWR_WAKE_RST; + ESP_LOGE(TAG, "BAD WAKEUP CAUSE"); } + return dev; } -void eos_power_sleep(void) { +void eos_power_sleep_req(uint8_t mode, uint32_t dev) { power_event_t evt; - evt.type = POWER_ETYPE_SLEEP1; - evt.source = 0; + evt.type = PWR_ETYPE_SLEEP_REQ; + evt.mode = mode; + evt.dev = dev; xQueueSend(power_queue, &evt, portMAX_DELAY); } -void eos_power_wake(uint8_t source) { +void eos_power_sleep_rdy(uint32_t dev) { power_event_t evt; - evt.type = POWER_ETYPE_WAKE; - evt.source = source; - + evt.type = PWR_ETYPE_SLEEP_RDY; + evt.dev = dev; xQueueSend(power_queue, &evt, portMAX_DELAY); } -void eos_power_net_ready(void) { +void eos_power_wake(uint32_t dev) { power_event_t evt; - evt.type = POWER_ETYPE_NETRDY; - evt.source = 0; - + ESP_LOGI(TAG, "WAKE SENT"); + evt.type = PWR_ETYPE_WAKE; + evt.dev = dev; xQueueSend(power_queue, &evt, portMAX_DELAY); } diff --git a/fw/esp32/components/eos/rng.c b/fw/esp32/components/eos/rng.c index 3927df1..675a79c 100644 --- a/fw/esp32/components/eos/rng.c +++ b/fw/esp32/components/eos/rng.c @@ -1,4 +1,4 @@ -#include <esp_system.h> +#include <esp_random.h> #include <esp_log.h> #include <esp_err.h> @@ -26,6 +26,7 @@ rng_handler_fin: void eos_rng_init(void) { eos_net_set_handler(EOS_NET_MTYPE_RNG, rng_handler); + ESP_LOGI(TAG, "INIT"); } diff --git a/fw/esp32/components/eos/sock.c b/fw/esp32/components/eos/sock.c index 08d95d5..b6ed3e9 100644 --- a/fw/esp32/components/eos/sock.c +++ b/fw/esp32/components/eos/sock.c @@ -1,6 +1,7 @@ #include <stdlib.h> #include <stdint.h> #include <string.h> +#include <sys/select.h> #include <freertos/FreeRTOS.h> #include <freertos/semphr.h> @@ -9,6 +10,9 @@ #include <esp_system.h> #include <esp_log.h> #include <esp_err.h> +#include <esp_vfs.h> +#include <esp_vfs_dev.h> +#include <esp_vfs_eventfd.h> #include <lwip/sockets.h> #include <lwip/err.h> @@ -23,8 +27,14 @@ static const char *TAG = "EOS SOCK"; static SemaphoreHandle_t mutex; +static int cmd_fd, rep_fd; static int _socks[EOS_SOCK_MAX_SOCK]; +#define CMD_OPEN 1 +#define CMD_CLOSE 2 +#define CMD_SEND 3 +#define CMD_REOPEN 4 + static int t_open_dgram(void) { struct sockaddr_in _myaddr; int sock; @@ -74,83 +84,246 @@ static ssize_t t_recvfrom(int sock, void *msg, size_t msg_size, EOSNetAddr *addr return recvlen; } +static void populate_fds(fd_set *fds, int *max_fd) { + int i; + + *max_fd = cmd_fd; + + FD_ZERO(fds); + FD_SET(cmd_fd, fds); + for (i=0; i<EOS_SOCK_MAX_SOCK; i++) { + if (_socks[i]) { + FD_SET(_socks[i], fds); + if (_socks[i] > *max_fd) { + *max_fd = _socks[i]; + } + } + } +} + static void udp_rcvr_task(void *pvParameters) { - uint8_t sock_i = (uint8_t)pvParameters; - int sock = _socks[sock_i-1]; - - do { - EOSNetAddr addr; - unsigned char *buf, *_buf; - ssize_t rv; - - buf = eos_net_alloc(); - rv = t_recvfrom(sock, buf + EOS_SOCK_SIZE_UDP_HDR, EOS_NET_SIZE_BUF - EOS_SOCK_SIZE_UDP_HDR, &addr); - if (rv < 0) { - eos_net_free(buf); - ESP_LOGE(TAG, "UDP RECV ERR:%d", rv); - break; + EOSNetAddr addr; + unsigned char *buffer; + uint16_t buf_len; + fd_set all_fds, read_fds; + uint8_t sock_i; + uint8_t cmd[8]; + ssize_t _rv; + int sock, max_fd, i; + int rv; + + assert(sizeof(buffer) == 4); + + populate_fds(&all_fds, &max_fd); + while (1) { + memcpy(&read_fds, &all_fds, sizeof(fd_set)); + rv = select(max_fd + 1, &read_fds, NULL, NULL, NULL); + if (rv <= 0) { + ESP_LOGE(TAG, "SELECT ERR:%d", rv); + continue; } - _buf = buf; - _buf[0] = EOS_SOCK_MTYPE_PKT; - _buf[1] = sock_i; - _buf += 2; - memcpy(_buf, addr.host, sizeof(addr.host)); - _buf += sizeof(addr.host); - _buf[0] = addr.port >> 8; - _buf[1] = addr.port; - _buf += sizeof(addr.port); - eos_net_send(EOS_NET_MTYPE_SOCK, buf, rv + EOS_SOCK_SIZE_UDP_HDR); - } while (1); - xSemaphoreTake(mutex, portMAX_DELAY); - _socks[sock_i-1] = 0; - xSemaphoreGive(mutex); + for (i=0; i<EOS_SOCK_MAX_SOCK; i++) { + sock = _socks[i]; + if (sock && FD_ISSET(sock, &read_fds)) { + unsigned char *_buf; + + buffer = eos_net_alloc(); + _rv = t_recvfrom(sock, buffer + EOS_SOCK_SIZE_UDP_HDR, EOS_NET_SIZE_BUF - EOS_SOCK_SIZE_UDP_HDR, &addr); + if (_rv < 0) { + eos_net_free(buffer); + ESP_LOGE(TAG, "RECV ERR:%d", _rv); + } + _buf = buffer; + _buf[0] = EOS_SOCK_MTYPE_PKT; + _buf[1] = i + 1; + _buf += 2; + memcpy(_buf, addr.host, sizeof(addr.host)); + _buf += sizeof(addr.host); + _buf[0] = addr.port >> 8; + _buf[1] = addr.port; + _buf += sizeof(addr.port); + rv = eos_net_send(EOS_NET_MTYPE_SOCK, buffer, _rv + EOS_SOCK_SIZE_UDP_HDR); + if (rv) ESP_LOGE(TAG, "NET SEND ERR:%d", rv); + } + } + if (FD_ISSET(cmd_fd, &read_fds)) { + rv = read(cmd_fd, cmd, sizeof(cmd)); + assert(rv == sizeof(cmd)); + + switch (cmd[0]) { + case CMD_OPEN: { + sock = t_open_dgram(); + sock_i = 0; + if (sock > 0) { + for (i=0; i<EOS_SOCK_MAX_SOCK; i++) { + if (_socks[i] == 0) { + sock_i = i + 1; + _socks[i] = sock; + break; + } + } + if (sock_i) { + populate_fds(&all_fds, &max_fd); + } + } + memset(cmd, 0, sizeof(cmd)); + cmd[1] = sock_i; + + rv = write(rep_fd, cmd, sizeof(cmd)); + assert(rv == sizeof(cmd)); + + break; + } + + case CMD_CLOSE: { + sock_i = cmd[1] - 1; + sock = _socks[sock_i]; + if (sock) { + t_close(sock); + _socks[sock_i] = 0; + populate_fds(&all_fds, &max_fd); + } + + rv = write(rep_fd, cmd, sizeof(cmd)); + assert(rv == sizeof(cmd)); + + break; + } + + case CMD_SEND: { + sock_i = cmd[1] - 1; + buf_len = (uint16_t)cmd[2] << 8; + buf_len |= (uint16_t)cmd[3]; + memcpy(&buffer, cmd + 4, sizeof(buffer)); + + sock = _socks[sock_i]; + memcpy(addr.host, buffer, sizeof(addr.host)); + buffer += sizeof(addr.host); + buf_len -= sizeof(addr.host); + addr.port = (uint16_t)buffer[0] << 8; + addr.port |= (uint16_t)buffer[1]; + buffer += sizeof(addr.port); + buf_len -= sizeof(addr.port); + _rv = t_sendto(sock, buffer, buf_len, &addr); + + memset(cmd, 0, sizeof(cmd)); + + rv = write(rep_fd, cmd, sizeof(cmd)); + assert(rv == sizeof(cmd)); + + break; + } + + case CMD_REOPEN: { + buffer = NULL; + buf_len = 0; + + for (i=0; i<EOS_SOCK_MAX_SOCK; i++) { + sock = _socks[i]; + if (sock) { + t_close(sock); + _socks[i] = -1; + } + } + for (i=0; i<EOS_SOCK_MAX_SOCK; i++) { + sock = _socks[i]; + if (sock) { + sock = t_open_dgram(); + if (sock > 0) { + _socks[i] = sock; + } else { + _socks[i] = 0; + if (buffer) { + buffer[buf_len] = i + 1; + buf_len++; + } else { + buffer = eos_net_alloc(); + buffer[0] = EOS_SOCK_MTYPE_CLOSE; + buffer[1] = i + 1; + buf_len = 2; + } + } + } + } + if (buffer) { + rv = eos_net_send(EOS_NET_MTYPE_SOCK, buffer, buf_len); + if (rv) ESP_LOGE(TAG, "NET SEND ERR:%d", rv); + } + + rv = write(rep_fd, cmd, sizeof(cmd)); + assert(rv == sizeof(cmd)); + + break; + } + + default: + ESP_LOGE(TAG, "BAD CMD:%d", cmd[0]); + break; + } + + } + } + vTaskDelete(NULL); } static void sock_handler(unsigned char _mtype, unsigned char *buffer, uint16_t buf_len) { unsigned char mtype; uint8_t sock_i; - int sock, i; + uint8_t cmd[8]; + int rv; if (buf_len < 1) return; + memset(cmd, 0, sizeof(cmd)); + mtype = buffer[0]; switch (mtype) { case EOS_SOCK_MTYPE_PKT: { - EOSNetAddr addr; + unsigned char *_buf = buffer; if (buf_len < EOS_SOCK_SIZE_UDP_HDR) return; - sock_i = buffer[1]-1; - if (sock_i >= EOS_SOCK_MAX_SOCK) return; - - sock = _socks[sock_i]; - buffer += 2; - memcpy(addr.host, buffer, sizeof(addr.host)); - buffer += sizeof(addr.host); - addr.port = (uint16_t)buffer[0] << 8; - addr.port |= (uint16_t)buffer[1]; - buffer += sizeof(addr.port); - t_sendto(sock, buffer, buf_len - EOS_SOCK_SIZE_UDP_HDR, &addr); + sock_i = buffer[1]; + if ((sock_i == 0) || (sock_i > EOS_SOCK_MAX_SOCK)) return; + + _buf += 2; + cmd[0] = CMD_SEND; + cmd[1] = sock_i; + cmd[2] = buf_len >> 8; + cmd[3] = buf_len; + memcpy(cmd + 4, &_buf, sizeof(_buf)); + + xSemaphoreTake(mutex, portMAX_DELAY); + + rv = write(cmd_fd, cmd, sizeof(cmd)); + assert(rv == sizeof(cmd)); + + rv = read(rep_fd, cmd, sizeof(cmd)); + assert(rv == sizeof(cmd)); + + xSemaphoreGive(mutex); + + assert(cmd[0] == CMD_SEND); break; } case EOS_SOCK_MTYPE_OPEN_DGRAM: { - sock = t_open_dgram(); - sock_i = 0; - if (sock > 0) { - xSemaphoreTake(mutex, portMAX_DELAY); - for (i=0; i<EOS_SOCK_MAX_SOCK; i++) { - if (_socks[i] == 0) { - sock_i = i+1; - _socks[i] = sock; - break; - } - } - xSemaphoreGive(mutex); - } - if (sock_i) xTaskCreate(&udp_rcvr_task, "udp_rcvr", EOS_TASK_SSIZE_UDP_RCVR, (void *)sock_i, EOS_TASK_PRIORITY_UDP_RCVR, NULL); + cmd[0] = CMD_OPEN; + + xSemaphoreTake(mutex, portMAX_DELAY); + + rv = write(cmd_fd, cmd, sizeof(cmd)); + assert(rv == sizeof(cmd)); + + rv = read(rep_fd, cmd, sizeof(cmd)); + assert(rv == sizeof(cmd)); + + xSemaphoreGive(mutex); + + assert(cmd[0] == CMD_OPEN); + sock_i = cmd[1]; buffer[0] = EOS_SOCK_MTYPE_OPEN_DGRAM; buffer[1] = sock_i; eos_net_reply(EOS_NET_MTYPE_SOCK, buffer, 2); @@ -160,19 +333,72 @@ static void sock_handler(unsigned char _mtype, unsigned char *buffer, uint16_t b case EOS_SOCK_MTYPE_CLOSE: { if (buf_len < 2) return; - sock_i = buffer[1]-1; - if (sock_i >= EOS_SOCK_MAX_SOCK) return; + sock_i = buffer[1]; + if ((sock_i == 0) || (sock_i > EOS_SOCK_MAX_SOCK)) return; + + cmd[0] = CMD_CLOSE; + cmd[1] = sock_i; + + xSemaphoreTake(mutex, portMAX_DELAY); - sock = _socks[sock_i]; - t_close(sock); + rv = write(cmd_fd, cmd, sizeof(cmd)); + assert(rv == sizeof(cmd)); + + rv = read(rep_fd, cmd, sizeof(cmd)); + assert(rv == sizeof(cmd)); + + xSemaphoreGive(mutex); + + assert(cmd[0] == CMD_CLOSE); break; } } } void eos_sock_init(void) { + esp_vfs_eventfd_config_t config = ESP_VFS_EVENTD_CONFIG_DEFAULT(); + esp_err_t ret; + + ret = esp_vfs_eventfd_register(&config); + assert(ret == ESP_OK); + + cmd_fd = eventfd(0, 0); + assert(cmd_fd > 0); + + rep_fd = eventfd(0, 0); + assert(rep_fd > 0); + mutex = xSemaphoreCreateBinary(); + assert(mutex != NULL); xSemaphoreGive(mutex); + eos_net_set_handler(EOS_NET_MTYPE_SOCK, sock_handler); + ESP_LOGI(TAG, "INIT"); } + +void eos_sock_run(void) { + BaseType_t rv; + + rv = xTaskCreate(&udp_rcvr_task, "udp_rcvr", EOS_TASK_SSIZE_SOCK, NULL, EOS_TASK_PRIORITY_SOCK, NULL); + assert(rv == pdPASS); + + ESP_LOGI(TAG, "RUN"); +} + +void eos_sock_reopen(void) { + uint8_t cmd[8]; + int rv; + + cmd[0] = CMD_REOPEN; + xSemaphoreTake(mutex, portMAX_DELAY); + + rv = write(cmd_fd, cmd, sizeof(cmd)); + assert(rv == sizeof(cmd)); + + rv = read(rep_fd, cmd, sizeof(cmd)); + assert(rv == sizeof(cmd)); + + xSemaphoreGive(mutex); + assert(cmd[0] == CMD_REOPEN); +} diff --git a/fw/esp32/components/eos/tun.c b/fw/esp32/components/eos/tun.c index a7181ee..f27fcfe 100644 --- a/fw/esp32/components/eos/tun.c +++ b/fw/esp32/components/eos/tun.c @@ -6,13 +6,14 @@ #include <lwip/tcpip.h> #include <lwip/etharp.h> +#include "net.h" #include "app.h" #include "tun.h" static ip4_addr_t ipaddr, netmask, gw; static struct netif netif_tun; -static err_t ESP_IRAM_ATTR tun_output(struct netif *netif, struct pbuf *p, const struct ip4_addr *ipaddr) { +static err_t IRAM_ATTR tun_output(struct netif *netif, struct pbuf *p, const struct ip4_addr *ipaddr) { unsigned char *buf; struct pbuf *q; @@ -27,7 +28,7 @@ static err_t ESP_IRAM_ATTR tun_output(struct netif *netif, struct pbuf *p, const return ERR_OK; } -static void ESP_IRAM_ATTR tun_input(unsigned char mtype, unsigned char *buffer, uint16_t len) { +static void IRAM_ATTR tun_input(unsigned char mtype, unsigned char *buffer, uint16_t len) { struct netif *netif = &netif_tun; struct pbuf *p; int rv; @@ -55,11 +56,15 @@ static err_t tun_init(struct netif *netif) { } void eos_tun_init(void) { + struct netif *rv; + IP4_ADDR(&gw, 0,0,0,0); IP4_ADDR(&ipaddr, 192,168,10,2); IP4_ADDR(&netmask, 255,255,255,0); - netif_add(&netif_tun, &ipaddr, &netmask, &gw, NULL, tun_init, tcpip_input); + rv = netif_add(&netif_tun, &ipaddr, &netmask, &gw, NULL, tun_init, tcpip_input); + assert(rv != NULL); + netif_set_up(&netif_tun); eos_app_set_handler(EOS_APP_MTYPE_TUN, tun_input); -}
\ No newline at end of file +} diff --git a/fw/esp32/components/eos/wifi.c b/fw/esp32/components/eos/wifi.c index 2be169f..77f9143 100755 --- a/fw/esp32/components/eos/wifi.c +++ b/fw/esp32/components/eos/wifi.c @@ -10,7 +10,6 @@ #include <esp_log.h> #include <esp_err.h> #include <esp_wifi.h> -#include <nvs_flash.h> #include "eos.h" #include "net.h" @@ -53,8 +52,6 @@ static void wifi_event_handler(void *arg, esp_event_base_t event_base, int32_t e ESP_LOGI(TAG, "Event disconnected - reason: %d", sta_disconnected->reason); if (sta_disconnected->reason == WIFI_REASON_ASSOC_LEAVE) { - stop = 0; - reconnect_cnt = 0; eos_wifi_send_status(); break; } @@ -113,25 +110,25 @@ static void wifi_handler(unsigned char _mtype, unsigned char *buffer, uint16_t b mtype = buffer[0]; switch (mtype) { case EOS_WIFI_MTYPE_STATUS: { - int reply; - ssize_t rv; + unsigned char *_buffer; + ssize_t _rv; + int reply, rv; reply = _mtype & EOS_NET_MTYPE_FLAG_REPL; if (reply) { - rv = eos_wifi_get_status(buffer + 1); - if (rv < 0) break; + _rv = eos_wifi_get_status(buffer + 1); + if (_rv < 0) break; - eos_net_reply(EOS_NET_MTYPE_WIFI, buffer, rv + 1); + eos_net_reply(EOS_NET_MTYPE_WIFI, buffer, _rv + 1); } else { - unsigned char *buf; - - buf = eos_net_alloc(); - buf[0] = EOS_WIFI_MTYPE_STATUS; - rv = eos_wifi_get_status(buf + 1); - if (rv < 0) break; + _buffer = eos_net_alloc(); + _buffer[0] = EOS_WIFI_MTYPE_STATUS; + _rv = eos_wifi_get_status(_buffer + 1); + if (_rv < 0) break; - eos_net_send(EOS_NET_MTYPE_WIFI, buf, rv + 1); + rv = eos_net_send(EOS_NET_MTYPE_WIFI, _buffer, _rv + 1); + if (rv) ESP_LOGE(TAG, "NET SEND ERR:%d", rv); } break; } @@ -202,20 +199,14 @@ static void wifi_handler(unsigned char _mtype, unsigned char *buffer, uint16_t b } void eos_wifi_init(void) { - esp_err_t ret; wifi_init_config_t wifi_config = WIFI_INIT_CONFIG_DEFAULT(); + esp_err_t ret; wifi_netif = esp_netif_create_default_wifi_sta(); ret = esp_wifi_init(&wifi_config); assert(ret == ESP_OK); - ret = esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL, NULL); - assert(ret == ESP_OK); - - ret = esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_event_handler, NULL, NULL); - assert(ret == ESP_OK); - ret = esp_wifi_set_storage(WIFI_STORAGE_RAM); assert(ret == ESP_OK); @@ -226,9 +217,22 @@ void eos_wifi_init(void) { assert(ret == ESP_OK); eos_net_set_handler(EOS_NET_MTYPE_WIFI, wifi_handler); + ESP_LOGI(TAG, "INIT"); } +void eos_wifi_run(void) { + esp_err_t ret; + + ret = esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL, NULL); + assert(ret == ESP_OK); + + ret = esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_event_handler, NULL, NULL); + assert(ret == ESP_OK); + + ESP_LOGI(TAG, "RUN"); +} + ssize_t eos_wifi_get_status(unsigned char *buffer) { unsigned char *p; wifi_ap_record_t ap_info; @@ -293,26 +297,28 @@ ssize_t eos_wifi_get_status(unsigned char *buffer) { void eos_wifi_send_status(void) { unsigned char *rbuf; - ssize_t rv; + ssize_t _rv; + int rv; rbuf = eos_net_alloc(); rbuf[0] = EOS_WIFI_MTYPE_STATUS; - rv = eos_wifi_get_status(rbuf + 1); - if (rv < 0) { + _rv = eos_wifi_get_status(rbuf + 1); + if (_rv < 0) { eos_net_free(rbuf); return; } - eos_net_send(EOS_NET_MTYPE_WIFI, rbuf, rv + 1); + rv = eos_net_send(EOS_NET_MTYPE_WIFI, rbuf, _rv + 1); + if (rv) ESP_LOGE(TAG, "NET SEND ERR:%d", rv); } void eos_wifi_send_scan(void) { static wifi_ap_record_t scan_r[EOS_WIFI_MAX_SCAN_RECORDS]; static uint16_t scan_n; - unsigned char *rbuf, *p; - int i; size_t len; esp_err_t ret; + unsigned char *rbuf, *p; + int i, rv; scan_n = EOS_WIFI_MAX_SCAN_RECORDS; memset(scan_r, 0, sizeof(scan_r)); @@ -336,5 +342,7 @@ void eos_wifi_send_scan(void) { strcpy((char *)p, (char *)scan_r[i].ssid); p += len + 1; } - eos_net_send(EOS_NET_MTYPE_WIFI, rbuf, p - rbuf); + + rv = eos_net_send(EOS_NET_MTYPE_WIFI, rbuf, p - rbuf); + if (rv) ESP_LOGE(TAG, "NET SEND ERR:%d", rv); } diff --git a/fw/esp32/main/component.mk b/fw/esp32/main/component.mk deleted file mode 100644 index 61f8990..0000000 --- a/fw/esp32/main/component.mk +++ /dev/null @@ -1,8 +0,0 @@ -# -# Main component makefile. -# -# This Makefile can be left empty. By default, it will take the sources in the -# src/ directory, compile them and link them into lib(subdirectory_name).a -# in the build directory. This behaviour is entirely configurable, -# please read the ESP-IDF documents if you need to do this. -# |