diff options
Diffstat (limited to 'fw/esp32/components')
26 files changed, 1556 insertions, 936 deletions
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/components/eos/app_main.c b/fw/esp32/components/eos/app_main.c new file mode 100644 index 0000000..e096a23 --- /dev/null +++ b/fw/esp32/components/eos/app_main.c @@ -0,0 +1,58 @@ +#include <freertos/FreeRTOS.h> +#include <freertos/task.h> + +#include <driver/gpio.h> +#include <esp_system.h> + +#include <esp_event.h> +#include <esp_netif.h> +#include <esp_err.h> +#include <esp_log.h> + +#include "i2c.h" +#include "cell.h" +#include "net.h" +#include "wifi.h" +#include "sock.h" +#include "rng.h" +#include "app.h" +#include "tun.h" +#include "power.h" + +#define ESP_INTR_FLAG_DEFAULT   0 + +/* main application */ +void app_main() { +    esp_err_t ret; + +    ret = esp_netif_init(); +    assert(ret == ESP_OK); + +    ret = esp_event_loop_create_default(); +    assert(ret == ESP_OK); + +    ret = gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT); +    assert(ret == ESP_OK); + +    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(); + +    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);  }  | 
