diff options
Diffstat (limited to 'fw/esp32/components/eos')
31 files changed, 1978 insertions, 1501 deletions
diff --git a/fw/esp32/components/eos/CMakeLists.txt b/fw/esp32/components/eos/CMakeLists.txt new file mode 100644 index 0000000..8750f85 --- /dev/null +++ b/fw/esp32/components/eos/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS "app_main.c" "msgq.c" "unicode.c" "power.c" "net.c" "app.c" "rng.c" "wifi.c" "sock.c" "tun.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" + 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..ab04c2c 100644 --- a/fw/esp32/components/eos/app.c +++ b/fw/esp32/components/eos/app.c @@ -15,209 +15,168 @@ #include "eos.h" #include "msgq.h" +#include "power.h" +#include "net.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_RTS 47 +#define SPI_GPIO_CTS 9 +#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_HDR 3 +#define SPI_HOST SPI2_HOST + +#define APP_SIZE_BUFQ 16 +#define APP_SIZE_SNDQ 16 static EOSBufQ app_buf_q; -static unsigned char *app_bufq_array[EOS_APP_SIZE_BUFQ]; +static unsigned char *app_bufq_array[APP_SIZE_BUFQ]; static EOSMsgQ app_send_q; -static EOSMsgItem app_sndq_array[EOS_APP_SIZE_SNDQ]; +static EOSMsgItem app_sndq_array[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 eos_app_fptr_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 void bad_handler(unsigned char mtype, unsigned char *buffer, uint16_t len) { - ESP_LOGE(TAG, "bad handler: %d len: %d", mtype, len); -} +static const char *TAG = "EOS APP"; -// 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 bad_handler(unsigned char mtype, EOSMessage *msg, uint16_t len) { + ESP_LOGE(TAG, "BAD HANDLER: 0x%.2X LEN: %d", mtype, len); } -// 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 IRAM_ATTR app_bridge(unsigned char mtype, EOSMessage *msg, uint16_t len) { + EOSMessage _msg; + int rv; + + eos_net_alloc(&_msg); + if (len > _msg.size) { + eos_net_free(&_msg); + return; + } + memcpy(_msg.buffer, msg->buffer, len); + rv = eos_net_send(mtype & EOS_NET_MTYPE_MASK, &_msg, len); + if (rv) ESP_LOGE(TAG, "BRIDGE ERR: %d", rv); } -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); - } +static void IRAM_ATTR app_msg_handler(unsigned char mtype, EOSMessage *msg, uint16_t len) { + uint8_t idx; + + idx = mtype & EOS_NET_MTYPE_FLAG_BRIDGE ? EOS_NET_MTYPE_BRIDGE : mtype & EOS_NET_MTYPE_MASK; + if ((idx < EOS_APP_MAX_MTYPE) && (len <= msg->size)) { + app_handler[idx](mtype, msg, len); + } else { + bad_handler(mtype, msg, 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)); + eos_msgq_init(&app_send_q, app_sndq_array, APP_SIZE_SNDQ); + eos_bufq_init(&app_buf_q, app_bufq_array, APP_SIZE_BUFQ); + for (i=0; i<APP_SIZE_BUFQ; i++) { + unsigned char *buffer; + + buffer = malloc(EOS_NET_MTU); + 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(APP_SIZE_BUFQ, 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 = esp_reset_reason() == ESP_RST_DEEPSLEEP ? 1 : 0; + app_config.sleep_req = 0; + app_config.present = 1; + app_config.dev = NET_DEV_APP; + 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.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.handler = app_msg_handler; + + /* Configuration for the SPI bus */ + app_spi_bus_cfg.mosi_io_num = SPI_GPIO_MOSI; + app_spi_bus_cfg.miso_io_num = SPI_GPIO_MISO; + app_spi_bus_cfg.sclk_io_num = SPI_GPIO_SCLK; + app_spi_bus_cfg.intr_flags = ESP_INTR_FLAG_IRAM; + + /* Configuration for the SPI slave interface */ + app_spi_iface_cfg.mode = 0; + app_spi_iface_cfg.spics_io_num = SPI_GPIO_CS; + app_spi_iface_cfg.queue_size = 2; + app_spi_iface_cfg.flags = 0; + + _eos_net_init_gpio(&app_config); + eos_app_set_handler(EOS_NET_MTYPE_BRIDGE, app_bridge); + 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); +void eos_app_alloc(EOSMessage *msg) { + _eos_net_alloc(&app_config, msg); } -int eos_app_send(unsigned char mtype, unsigned char *buffer, uint16_t len) { - int rv = EOS_OK; +void eos_app_free(EOSMessage *msg) { + _eos_net_free(&app_config, msg); +} - 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, EOSMessage *msg, uint16_t len) { + return _eos_net_send(&app_config, mtype, msg, len); +} - if (rv) eos_app_free(buffer); +void eos_app_sleep_req(void) { + _eos_net_sleep_req(&app_config); +} + +void eos_app_wake(void) { + _eos_net_wake(&app_config); +} + +void eos_app_deep_sleep(void) { + _eos_net_deep_sleep(&app_config); +} - return rv; +void eos_app_deep_wake(void) { + _eos_net_deep_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; + if (mtype < EOS_APP_MAX_MTYPE) app_handler[mtype] = 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..885f9c8 --- /dev/null +++ b/fw/esp32/components/eos/app_main.c @@ -0,0 +1,60 @@ +#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 "power.h" +#include "net.h" +#include "app.h" +#include "rng.h" +#include "wifi.h" +#include "sock.h" +#include "tun.h" +#include "cell.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); + + /* first one */ + 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_net_run(); + eos_app_run(); + eos_modem_run(); + eos_cell_run(); + eos_wifi_run(); + eos_sock_run(); + + /* last one */ + eos_power_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..7dc4a32 100644 --- a/fw/esp32/components/eos/cell.c +++ b/fw/esp32/components/eos/cell.c @@ -17,55 +17,70 @@ 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]; static SemaphoreHandle_t mutex; static QueueHandle_t cell_queue; -static void _cell_handler(unsigned char _mtype, unsigned char *buffer, uint16_t buf_len) { - uint8_t mtype; +static void _cell_handler(unsigned char _mtype, EOSMessage *msg, uint16_t len) { + unsigned char mtype; + unsigned char *buffer = msg->buffer; + int rv; - if (buf_len < 1) return; + if (len < 1) return; mtype = buffer[0]; switch (mtype & EOS_CELL_MTYPE_MASK) { case EOS_CELL_MTYPE_DEV: { switch (mtype & ~EOS_CELL_MTYPE_MASK) { case EOS_CELL_MTYPE_STATUS: { - size_t rv; + size_t _rv; + + if (!(eos_msg_flags(msg) & EOS_MSG_FLAG_RPLY_REQ)) break; + if (msg->size < 3) break; - rv = eos_modem_get_status(buffer + 1); - eos_net_reply(EOS_NET_MTYPE_CELL, buffer, rv + 1); + _rv = eos_modem_get_status(buffer + 1); + eos_net_reply(EOS_NET_MTYPE_CELL, msg, _rv + 1); break; } case EOS_CELL_MTYPE_RESET: { + 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; - - 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); + 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, len - 1); + } break; } } @@ -73,33 +88,35 @@ static void _cell_handler(unsigned char _mtype, unsigned char *buffer, uint16_t } case EOS_CELL_MTYPE_VOICE: { - eos_cell_voice_handler(mtype & ~EOS_CELL_MTYPE_MASK, buffer, buf_len); + eos_cell_voice_handler(_mtype, msg, len); break; } case EOS_CELL_MTYPE_SMS: { - eos_cell_sms_handler(mtype & ~EOS_CELL_MTYPE_MASK, buffer, buf_len); + eos_cell_sms_handler(_mtype, msg, len); break; } case EOS_CELL_MTYPE_USSD: { - eos_cell_ussd_handler(mtype & ~EOS_CELL_MTYPE_MASK, buffer, buf_len); + eos_cell_ussd_handler(_mtype, msg, len); break; } case EOS_CELL_MTYPE_PDP: { - eos_cell_pdp_handler(mtype & ~EOS_CELL_MTYPE_MASK, buffer, buf_len); + eos_cell_pdp_handler(_mtype, msg, len); break; } } } static void cell_handler_task(void *pvParameters) { + EOSMessage msg; EOSMsgItem mi; while (1) { if (xQueueReceive(cell_queue, &mi, portMAX_DELAY)) { - _cell_handler(mi.type, mi.buffer, mi.len); + eos_msg_init(&msg, mi.buffer, mi.size); + _cell_handler(mi.type, &msg, mi.len); xSemaphoreTake(mutex, portMAX_DELAY); eos_bufq_push(&cell_buf_q, mi.buffer); xSemaphoreGive(mutex); @@ -108,22 +125,31 @@ 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, EOSMessage *msg, uint16_t len) { EOSMsgItem mi; - unsigned char *buf; + unsigned char *buffer; + + if (len < 1) return; + if (len > EOS_CELL_MTU) return; + + if (eos_msg_flags(msg) & EOS_MSG_FLAG_RPLY_REQ) { + _cell_handler(type, msg, 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", msg->buffer[0]); return; } - memcpy(buf, buffer, len); mi.type = type; - mi.buffer = buf; + mi.buffer = buffer; + mi.size = EOS_CELL_MTU; + memcpy(mi.buffer, msg->buffer, len); mi.len = len; xQueueSend(cell_queue, &mi, portMAX_DELAY); } @@ -133,13 +159,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_CELL_MTU); + 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..9a024ae 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); @@ -142,16 +152,22 @@ static void uart_data_read(uint8_t mode) { } case EOS_CELL_UART_MODE_RELAY: { - unsigned char *buf; - rd = 0; + EOSMessage msg; + 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); + eos_net_alloc(&msg); + if (msg.size < 1) { + eos_net_free(&msg); + break; + } + msg.buffer[0] = EOS_CELL_MTYPE_DEV | EOS_CELL_MTYPE_UART_DATA; + _rd = eos_modem_read(msg.buffer + 1, MIN(bsize - rd, msg.size - 1), 100); + rv = eos_net_send(EOS_NET_MTYPE_CELL, &msg, _rd + 1); + if (rv) ESP_LOGE(TAG, "NET SEND ERR:%d", rv); rd += _rd; } while (rd != bsize); break; @@ -160,36 +176,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 +198,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 +246,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 +291,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 +306,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 +322,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"); @@ -349,12 +334,19 @@ static void modem_event_task(void *pvParameters) { } case MODEM_ETYPE_STATUS: { - unsigned char *buf; + EOSMessage msg; + 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); + eos_net_alloc(&msg); + if (msg.size < 3) { + eos_net_free(&msg); + break; + } + + msg.buffer[0] = EOS_CELL_MTYPE_DEV | EOS_CELL_MTYPE_STATUS; + memcpy(msg.buffer + 1, evt.param, evt.param_len); + rv = eos_net_send(EOS_NET_MTYPE_CELL, &msg, evt.param_len + 1); + if (rv) ESP_LOGE(TAG, "NET SEND ERR:%d", rv); break; } @@ -365,7 +357,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 +391,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 +404,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 +478,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 +608,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) { @@ -635,7 +642,21 @@ static int ppp_setup(void) { return EOS_OK; } +static void modem_init_ri(void) { + gpio_config_t io_conf = { + .pin_bit_mask = BIT64(UART_GPIO_RI), + .mode = GPIO_MODE_INPUT, + .intr_type = GPIO_INTR_NEGEDGE, + .pull_up_en = 1, + .pull_down_en = 0, + }; + + gpio_config(&io_conf); + gpio_isr_handler_add(UART_GPIO_RI, uart_ring_handler, NULL); +} + 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 +664,89 @@ 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; - modem_present = 0; - modem_initialized = 0; - modem_init_gpio(); - } + 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); mutex = xSemaphoreCreateBinary(); - xSemaphoreGive(mutex); + assert(mutex != NULL); + if (esp_reset_reason() != ESP_RST_DEEPSLEEP) { + xSemaphoreGive(mutex); + } uart_mutex = xSemaphoreCreateBinary(); - xSemaphoreGive(uart_mutex); + assert(uart_mutex != NULL); + if (esp_reset_reason() != ESP_RST_DEEPSLEEP) { + 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); + + // 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, esp_reset_reason() == ESP_RST_DEEPSLEEP ? 1 : 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); + + if (esp_reset_reason() != ESP_RST_DEEPSLEEP) { + modem_init_ri(); + } 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; + + if (esp_reset_reason() == ESP_RST_DEEPSLEEP) { + eos_modem_deep_wake(); + } else { + uart_mode = EOS_CELL_UART_MODE_NONE; + modem_present = 0; + modem_initialized = 0; + } + + 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 +779,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 +868,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 +919,6 @@ int eos_modem_set_mode(uint8_t mode) { } if (!rv) { uart_mode = mode; - modem_send_status(); } } } @@ -876,70 +962,39 @@ 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); -} + 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); -void eos_modem_deep_sleep(void) { - gpio_hold_en(UART_GPIO_DTR); + 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; - - evt.type = MODEM_ETYPE_RING; - xQueueSend(modem_queue, &evt, portMAX_DELAY); - } - - 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); - - uart_change_mode(uart_mode); - xSemaphoreGive(uart_mutex); - xSemaphoreGive(mutex); - - break; - } - - case EOS_PWR_SMODE_DEEP: { - gpio_hold_dis(UART_GPIO_DTR); - modem_init_gpio(); +void eos_modem_wake(void) { + modem_init_ri(); + uart_change_mode(uart_mode); + xSemaphoreGive(uart_mutex); + xSemaphoreGive(mutex); - break; - } - } + gpio_set_level(UART_GPIO_DTR, 0); } -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); +void eos_modem_deep_sleep(void) { + gpio_hold_en(UART_GPIO_DTR); + gpio_hold_en(MODEM_GPIO_USB_EN); + gpio_hold_en(MODEM_GPIO_USB_S); +} - return EOS_OK; +void eos_modem_deep_wake(void) { + gpio_hold_dis(UART_GPIO_DTR); + gpio_hold_dis(MODEM_GPIO_USB_EN); + gpio_hold_dis(MODEM_GPIO_USB_S); } void eos_ppp_get_apn(char *apn) { diff --git a/fw/esp32/components/eos/cell_pcm.c b/fw/esp32/components/eos/cell_pcm.c index b993021..67a3a08 100644 --- a/fw/esp32/components/eos/cell_pcm.c +++ b/fw/esp32/components/eos/cell_pcm.c @@ -1,309 +1,141 @@ +#include <stdint.h> #include <stdlib.h> -#include <string.h> #include <freertos/FreeRTOS.h> -#include <freertos/semphr.h> #include <freertos/task.h> -#include <freertos/queue.h> -#include <driver/i2s.h> -#include <driver/gpio.h> +#include <driver/i2s_tdm.h> #include <esp_log.h> #include "eos.h" #include "net.h" -#include "msgq.h" #include "cell.h" -#define PCM_MIC_WM 128 -#define PCM_HOLD_CNT_TX 3 -#define PCM_HOLD_CNT_RX 3 -#define PCM_SIZE_BUFQ 4 -#define PCM_SIZE_BUF (PCM_MIC_WM * 4) +#define PCM_GPIO_BCK 1 +#define PCM_GPIO_WS 41 +#define PCM_GPIO_DIN 2 +#define PCM_GPIO_DOUT 42 -#define PCM_GPIO_BCK 33 -#define PCM_GPIO_WS 4 -#define PCM_GPIO_DIN 34 -#define PCM_GPIO_DOUT 2 +#define PCM_RX_WM 256 /* receive watermark, must be less than NET_SIZE_MTU */ -#define PCM_ETYPE_WRITE 1 +static i2s_chan_handle_t tx_chan; +static i2s_chan_handle_t rx_chan; -static EOSBufQ pcm_buf_q; -static unsigned char *pcm_bufq_array[PCM_SIZE_BUFQ]; +static const char *TAG = "EOS CELL PCM"; -static EOSMsgQ pcm_evt_q; -static EOSMsgItem pcm_evtq_array[PCM_SIZE_BUFQ]; -static char pcm_hold_tx; -static char pcm_active = 0; - -static i2s_dev_t* I2S[I2S_NUM_MAX] = {&I2S0, &I2S1}; - -static QueueHandle_t i2s_queue; -static SemaphoreHandle_t mutex; - -static const char *TAG = "EOS PCM"; - -static void i2s_event_task(void *pvParameters) { - i2s_event_t event; - ssize_t hold_bytes_r = 0; - unsigned char *hold_buf = NULL; - char hold_cnt = 0; - - while (1) { - // Waiting for I2S event. - if (xQueueReceive(i2s_queue, &event, portMAX_DELAY)) { - switch (event.type) { - case I2S_EVENT_RX_DONE: { - ssize_t bytes_r; - size_t bytes_w; - uint16_t bytes_e; - unsigned char _type; - unsigned char *buf; - - if (!pcm_active) { - if (hold_buf) { - eos_net_free(hold_buf); - hold_buf = NULL; - } - break; - } - - // Event of I2S receiving data - if (!hold_cnt) { - buf = eos_net_alloc(); - buf[0] = EOS_CELL_MTYPE_VOICE | EOS_CELL_MTYPE_VOICE_PCM; - bytes_r = eos_cell_pcm_read(buf + 1, PCM_MIC_WM); - if (bytes_r < 0) { - ESP_LOGE(TAG, "*** I2S READ ERROR ***"); - eos_net_free(buf); - break; - } - eos_net_send(EOS_NET_MTYPE_CELL, buf, bytes_r + 1); - } else { - if (hold_buf == NULL) { - hold_buf = eos_net_alloc(); - hold_buf[0] = EOS_CELL_MTYPE_VOICE | EOS_CELL_MTYPE_VOICE_PCM; - hold_bytes_r = 0; - } - if (1 + hold_bytes_r + PCM_MIC_WM <= EOS_NET_SIZE_BUF) { - bytes_r = eos_cell_pcm_read(hold_buf + 1 + hold_bytes_r, PCM_MIC_WM); - if (bytes_r < 0) { - ESP_LOGE(TAG, "*** I2S READ ERROR ***"); - break; - } - hold_bytes_r += bytes_r; - } - hold_cnt--; - if (hold_cnt == 0) { - eos_net_send(EOS_NET_MTYPE_CELL, hold_buf, hold_bytes_r + 1); - hold_buf = NULL; - } - } - - buf = NULL; - xSemaphoreTake(mutex, portMAX_DELAY); - if (pcm_hold_tx && (eos_msgq_len(&pcm_evt_q) == PCM_HOLD_CNT_TX)) pcm_hold_tx = 0; - if (!pcm_hold_tx) eos_msgq_pop(&pcm_evt_q, &_type, &buf, &bytes_e); - xSemaphoreGive(mutex); - - if (buf) { - esp_err_t ret; - - ret = i2s_write(I2S_NUM_0, (const void *)buf, bytes_e, &bytes_w, 1000 / portTICK_RATE_MS); - xSemaphoreTake(mutex, portMAX_DELAY); - eos_bufq_push(&pcm_buf_q, buf); - xSemaphoreGive(mutex); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "*** I2S WRITE ERROR ***"); - break; - } - } - break; - } +static void pcm_rcvr_task(void *pvParameters) { + EOSMessage msg; + size_t size_r; + esp_err_t ret; + int done = 0; + int rv; - case I2S_EVENT_DMA_ERROR: { - ESP_LOGE(TAG, "*** I2S DMA ERROR ***"); - break; - } + while (!done) { + eos_net_alloc(&msg); + if (msg.size < PCM_RX_WM + 1) { + eos_net_free(&msg); + return; + } + msg.buffer[0] = EOS_CELL_MTYPE_VOICE | EOS_CELL_MTYPE_VOICE_PCM; + ret = i2s_channel_read(rx_chan, msg.buffer + 1, PCM_RX_WM, &size_r, 1000); + switch (ret) { + case ESP_OK: { + assert(size_r == PCM_RX_WM); + break; + } - case I2S_EVENT_MAX: { - hold_cnt = PCM_HOLD_CNT_RX; - break; - } + case ESP_ERR_INVALID_STATE: { + done = 1; + break; + } - default: - 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, &msg, size_r + 1); + if (rv) ESP_LOGE(TAG, "NET SEND ERR:%d", rv); + } else { + eos_net_free(&msg); + } } vTaskDelete(NULL); } -void eos_cell_pcm_init(void) { - int i; - - i2s_config_t i2s_config = { - .mode = I2S_MODE_SLAVE | I2S_MODE_TX | I2S_MODE_RX, - .sample_rate = 32000, - .bits_per_sample = 32, - .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT, - .communication_format = I2S_COMM_FORMAT_STAND_I2S, - .dma_buf_count = 4, - .dma_buf_len = PCM_MIC_WM, - .use_apll = true, - .fixed_mclk = 2048000 * 8, - .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1 - }; - - i2s_pin_config_t pin_config = { - .bck_io_num = PCM_GPIO_BCK, - .ws_io_num = PCM_GPIO_WS, - .data_in_num = PCM_GPIO_DIN, - .data_out_num = PCM_GPIO_DOUT - }; - i2s_driver_install(I2S_NUM_0, &i2s_config, 10, &i2s_queue); //install and start i2s driver - i2s_stop(I2S_NUM_0); - i2s_set_pin(I2S_NUM_0, &pin_config); - gpio_matrix_in(pin_config.ws_io_num, I2S0I_WS_IN_IDX, 1); - gpio_matrix_in(pin_config.bck_io_num, I2S0I_BCK_IN_IDX, 1); - ESP_LOGI(TAG, "TX FIFO:%d TX CHAN:%d RX FIFO:%d RX CHAN:%d", I2S[I2S_NUM_0]->fifo_conf.tx_fifo_mod, I2S[I2S_NUM_0]->conf_chan.tx_chan_mod, I2S[I2S_NUM_0]->fifo_conf.rx_fifo_mod, I2S[I2S_NUM_0]->conf_chan.rx_chan_mod); - - I2S[I2S_NUM_0]->fifo_conf.tx_fifo_mod = 2; - I2S[I2S_NUM_0]->conf_chan.tx_chan_mod = 0; - - I2S[I2S_NUM_0]->fifo_conf.rx_fifo_mod = 3; - I2S[I2S_NUM_0]->conf_chan.rx_chan_mod = 1; - // I2S[I2S_NUM_0]->conf.tx_mono = 1; - I2S[I2S_NUM_0]->conf.rx_mono = 1; - // I2S[I2S_NUM_0]->timing.tx_dsync_sw = 1 - // I2S[I2S_NUM_0]->timing.rx_dsync_sw = 1 - // I2S[I2S_NUM_0]->conf.sig_loopback = 0; - - // I2S[I2S_NUM_0]->timing.tx_bck_in_inv = 1; - - eos_msgq_init(&pcm_evt_q, pcm_evtq_array, PCM_SIZE_BUFQ); - eos_bufq_init(&pcm_buf_q, pcm_bufq_array, PCM_SIZE_BUFQ); - for (i=0; i<PCM_SIZE_BUFQ; i++) { - eos_bufq_push(&pcm_buf_q, malloc(PCM_SIZE_BUF)); - } - - mutex = xSemaphoreCreateBinary(); - xSemaphoreGive(mutex); - - // Create a task to handle i2s event from ISR - xTaskCreate(i2s_event_task, "i2s_event", EOS_TASK_SSIZE_I2S, NULL, EOS_TASK_PRIORITY_I2S, NULL); - ESP_LOGI(TAG, "INIT"); -} - -ssize_t eos_cell_pcm_read(unsigned char *data, size_t size) { - static unsigned char buf[PCM_SIZE_BUF]; - size_t bytes_r; +void eos_cell_pcm_start(void) { + BaseType_t rv; esp_err_t ret; - int i; - if (size > PCM_MIC_WM) return EOS_ERR; - - ret = i2s_read(I2S_NUM_0, (void *)buf, size * 4, &bytes_r, 1000 / portTICK_RATE_MS); - if (ret != ESP_OK) return EOS_ERR; + ret = i2s_channel_enable(tx_chan); + if (ret) { + ESP_LOGE(TAG, "TX CHAN ENABLE ERR:%d", ret); + return; + } - for (i=0; i<size/2; i++) { - data[i * 2] = buf[i * 8 + 3]; - data[i * 2 + 1] = buf[i * 8 + 2]; + ret = i2s_channel_enable(rx_chan); + if (ret) { + ESP_LOGE(TAG, "RX CHAN ENABLE ERR:%d", ret); + return; } - return bytes_r / 4; + rv = xTaskCreate(&pcm_rcvr_task, "pcm_rcvr", EOS_TASK_SSIZE_PCM, NULL, EOS_TASK_PRIORITY_PCM, NULL); + assert(rv == pdPASS); } -static ssize_t pcm_expand(unsigned char *buf, unsigned char *data, size_t size) { - int i; - - if (size > PCM_MIC_WM) return EOS_ERR; +void eos_cell_pcm_stop(void) { + esp_err_t ret; - memset(buf, 0, PCM_SIZE_BUF); - for (i=0; i<size/2; i++) { - buf[i * 8 + 3] = data[i * 2]; - buf[i * 8 + 2] = data[i * 2 + 1]; - } + ret = i2s_channel_disable(tx_chan); + if (ret) ESP_LOGE(TAG, "TX CHAN DISABLE ERR:%d", ret); - return size * 4; + ret = i2s_channel_disable(rx_chan); + if (ret) ESP_LOGE(TAG, "RX CHAN DISABLE ERR:%d", ret); } -int eos_cell_pcm_push(unsigned char *data, size_t size) { - unsigned char *buf = NULL; - ssize_t esize; - int rv; - - if (size > PCM_MIC_WM) return EOS_ERR; - - xSemaphoreTake(mutex, portMAX_DELAY); - if (!pcm_active) { - xSemaphoreGive(mutex); - return EOS_ERR; - } - if (pcm_hold_tx && (eos_msgq_len(&pcm_evt_q) == PCM_HOLD_CNT_TX)) { - unsigned char _type; - uint16_t _len; +void eos_cell_pcm_push(unsigned char *data, size_t size) { + esp_err_t ret; + size_t size_w; - eos_msgq_pop(&pcm_evt_q, &_type, &buf, &_len); + ret = i2s_channel_write(tx_chan, data, size, &size_w, 1000); + if (ret == ESP_OK) { + assert(size_w == size); } else { - buf = eos_bufq_pop(&pcm_buf_q); - } - xSemaphoreGive(mutex); - - if (buf == NULL) return EOS_ERR_EMPTY; - - esize = pcm_expand(buf, data, size); - if (esize < 0) { - xSemaphoreTake(mutex, portMAX_DELAY); - eos_bufq_push(&pcm_buf_q, buf); - xSemaphoreGive(mutex); - return esize; + ESP_LOGE(TAG, "CHAN WRITE ERR:%d", ret); } - - xSemaphoreTake(mutex, portMAX_DELAY); - rv = eos_msgq_push(&pcm_evt_q, PCM_ETYPE_WRITE, buf, esize); - if (rv) eos_bufq_push(&pcm_buf_q, buf); - xSemaphoreGive(mutex); - - return rv; } -void eos_cell_pcm_start(void) { - i2s_event_t evt; - - xSemaphoreTake(mutex, portMAX_DELAY); - if (pcm_active) { - xSemaphoreGive(mutex); - return; - } - while (1) { - unsigned char _type; - unsigned char *buf; - uint16_t len; - - eos_msgq_pop(&pcm_evt_q, &_type, &buf, &len); - if (buf) { - eos_bufq_push(&pcm_buf_q, buf); - } else { - break; - } - } - pcm_active = 1; - pcm_hold_tx = 1; - xSemaphoreGive(mutex); +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; - evt.type = I2S_EVENT_MAX; /* my type */ - xQueueSend(i2s_queue, &evt, portMAX_DELAY); - i2s_zero_dma_buffer(I2S_NUM_0); - i2s_start(I2S_NUM_0); -} + tdm_cfg.slot_cfg.total_slot = 16; + ret = i2s_new_channel(&chan_cfg, &tx_chan, &rx_chan); + assert(ret == ESP_OK); -void eos_cell_pcm_stop(void) { - char active; + ret = i2s_channel_init_tdm_mode(tx_chan, &tdm_cfg); + assert(ret == ESP_OK); - xSemaphoreTake(mutex, portMAX_DELAY); - active = pcm_active; - pcm_active = 0; - xSemaphoreGive(mutex); + ret = i2s_channel_init_tdm_mode(rx_chan, &tdm_cfg); + assert(ret == ESP_OK); - if (active) i2s_stop(I2S_NUM_0); + ESP_LOGI(TAG, "INIT"); } diff --git a/fw/esp32/components/eos/cell_pdp.c b/fw/esp32/components/eos/cell_pdp.c index d04b66b..9ff3ed7 100644 --- a/fw/esp32/components/eos/cell_pdp.c +++ b/fw/esp32/components/eos/cell_pdp.c @@ -7,20 +7,28 @@ #include "net.h" #include "cell.h" -void eos_cell_pdp_handler(unsigned char mtype, unsigned char *buffer, uint16_t buf_len) { +void eos_cell_pdp_handler(unsigned char _mtype, EOSMessage *msg, uint16_t len) { + unsigned char mtype; + unsigned char *buffer = msg->buffer; + + if (len < 1) return; + + mtype = buffer[0] & ~EOS_CELL_MTYPE_MASK; + switch (mtype) { case EOS_CELL_MTYPE_PDP_SET_APN: case EOS_CELL_MTYPE_PDP_SET_USR: case EOS_CELL_MTYPE_PDP_SET_PWD: { - char *arg; + char arg[EOS_CELL_PDP_SIZE_ARG + 1]; buffer++; - buf_len--; + len--; - arg = (char *)buffer; - if (buf_len > EOS_CELL_PDP_SIZE_ARG) break; + if (len > EOS_CELL_PDP_SIZE_ARG) break; + + memcpy(arg, buffer, len); + arg[len] = '\0'; - buffer[buf_len] = '\0'; switch (mtype) { case EOS_CELL_MTYPE_PDP_SET_APN: { eos_ppp_set_apn(arg); @@ -43,10 +51,12 @@ void eos_cell_pdp_handler(unsigned char mtype, unsigned char *buffer, uint16_t b case EOS_CELL_MTYPE_PDP_GET_APN: case EOS_CELL_MTYPE_PDP_GET_USR: case EOS_CELL_MTYPE_PDP_GET_PWD: { - char *arg; + char arg[EOS_CELL_PDP_SIZE_ARG + 1]; + + if (!(eos_msg_flags(msg) & EOS_MSG_FLAG_RPLY_REQ)) break; + if (msg->size < EOS_CELL_PDP_SIZE_ARG + 1) break; buffer[0] = EOS_CELL_MTYPE_PDP | mtype; - arg = (char *)(buffer + 1); switch (mtype) { case EOS_CELL_MTYPE_PDP_GET_APN: { eos_ppp_get_apn(arg); @@ -63,8 +73,9 @@ void eos_cell_pdp_handler(unsigned char mtype, unsigned char *buffer, uint16_t b break; } } + memcpy(buffer + 1, arg, strlen(arg)); - eos_net_reply(EOS_NET_MTYPE_CELL, buffer, strlen(arg) + 1); + eos_net_reply(EOS_NET_MTYPE_CELL, msg, strlen(arg) + 1); break; } diff --git a/fw/esp32/components/eos/cell_sms.c b/fw/esp32/components/eos/cell_sms.c index 5145cd7..c162d4d 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]; @@ -224,26 +224,30 @@ static ssize_t sms_decode(char *pdu, size_t pdu_len, unsigned char *buf, uint16_ return buf_len; } -void eos_cell_sms_handler(unsigned char mtype, unsigned char *buffer, uint16_t buf_len) { +void eos_cell_sms_handler(unsigned char _mtype, EOSMessage *msg, uint16_t len) { + unsigned char mtype; + unsigned char *buffer = msg->buffer; int rv; + if (len < 1) return; + + mtype = buffer[0] & ~EOS_CELL_MTYPE_MASK; buffer++; - buf_len--; + len--; + switch (mtype) { case EOS_CELL_MTYPE_SMS_LIST: { - if (buf_len < 1) return; + if (len < 1) break; rv = snprintf(at_cmd_buf, AT_SIZE_CMD_BUF, "AT+CMGL=%d\r", buffer[0]); - if ((rv < 0) || (rv >= AT_SIZE_CMD_BUF)) return; + if ((rv < 0) || (rv >= AT_SIZE_CMD_BUF)) break; rv = eos_modem_take(1000); - if (rv) return; + if (rv) break; at_cmd(at_cmd_buf); do { - unsigned char *buf; - uint16_t buf_len; - + EOSMessage _msg; char *pdu = _pdu_in; size_t pdu_size = sizeof(_pdu_in); size_t pdu_len; @@ -257,16 +261,20 @@ void eos_cell_sms_handler(unsigned char mtype, unsigned char *buffer, uint16_t b pdu_len = strlen(pdu); - buf = eos_net_alloc(); - buf[0] = EOS_CELL_MTYPE_SMS | EOS_CELL_MTYPE_SMS_LIST_ITEM; - _rv = sms_decode(pdu, pdu_len, buf + 1, EOS_NET_SIZE_BUF - 1); + eos_net_alloc(&_msg); + if (_msg.size < 1) { + eos_net_free(&_msg); + continue; + } + _msg.buffer[0] = EOS_CELL_MTYPE_SMS | EOS_CELL_MTYPE_SMS_LIST_ITEM; + _rv = sms_decode(pdu, pdu_len, _msg.buffer + 1, _msg.size - 1); if (_rv < 0) { - eos_net_free(buf); + eos_net_free(&_msg); continue; } - buf_len = _rv; - eos_net_send(EOS_NET_MTYPE_CELL, buf, buf_len + 1); + rv = eos_net_send(EOS_NET_MTYPE_CELL, &_msg, _rv + 1); + if (rv) ESP_LOGE(TAG, "NET SEND ERR:%d", rv); } while (1); eos_modem_give(); @@ -281,19 +289,19 @@ void eos_cell_sms_handler(unsigned char mtype, unsigned char *buffer, uint16_t b size_t pdu_len; ssize_t _rv; - _rv = sms_encode(buffer, buf_len, pdu, pdu_size); - if (_rv < 0) return; + _rv = sms_encode(buffer, len, pdu, pdu_size); + if (_rv < 0) break; pdu_len = _rv; - if (pdu_size < pdu_len + 2) return; + if (pdu_size < pdu_len + 2) break; pdu[pdu_len] = CTRL_Z; pdu[pdu_len + 1] = '\0'; rv = snprintf(at_cmd_buf, AT_SIZE_CMD_BUF, "AT+CMGS=%d\r", pdu_len / 2); - if ((rv < 0) || (rv >= AT_SIZE_CMD_BUF)) return; + if ((rv < 0) || (rv >= AT_SIZE_CMD_BUF)) break; rv = eos_modem_take(1000); - if (rv) return; + if (rv) break; at_cmd(at_cmd_buf); // wait for: '> ' (0d 0a 3e 20) @@ -309,15 +317,13 @@ void eos_cell_sms_handler(unsigned char mtype, unsigned char *buffer, uint16_t b } static void sms_received_handler(char *urc, regmatch_t m[]) { + EOSMessage msg; char cmd[32]; - unsigned char *buf; - uint16_t buf_len; - int ref, rv; - char *pdu = _pdu_out; size_t pdu_size = sizeof(_pdu_out); size_t pdu_len; ssize_t _rv; + int ref, rv; sscanf(urc + m[1].rm_so, "%d", &ref); @@ -336,18 +342,25 @@ static void sms_received_handler(char *urc, regmatch_t m[]) { rv = at_expect("^OK", NULL, 1000); - buf = eos_net_alloc(); - buf[0] = EOS_CELL_MTYPE_SMS | EOS_CELL_MTYPE_SMS_MSG; - _rv = sms_decode(pdu, pdu_len, buf + 1, EOS_NET_SIZE_BUF - 1); + eos_net_alloc(&msg); + if (msg.size < 1) { + eos_net_free(&msg); + return; + } + msg.buffer[0] = EOS_CELL_MTYPE_SMS | EOS_CELL_MTYPE_SMS_MSG; + _rv = sms_decode(pdu, pdu_len, msg.buffer + 1, msg.size - 1); if (_rv < 0) { - eos_net_free(buf); + eos_net_free(&msg); return; } - buf_len = _rv; - eos_net_send(EOS_NET_MTYPE_CELL, buf, buf_len + 1); + rv = eos_net_send(EOS_NET_MTYPE_CELL, &msg, _rv + 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..002391e 100644 --- a/fw/esp32/components/eos/cell_ussd.c +++ b/fw/esp32/components/eos/cell_ussd.c @@ -9,25 +9,30 @@ #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; -void eos_cell_ussd_handler(unsigned char mtype, unsigned char *buffer, uint16_t buf_len) { +void eos_cell_ussd_handler(unsigned char _mtype, EOSMessage *msg, uint16_t len) { + unsigned char mtype; + unsigned char *buffer = msg->buffer; int rv; + if (len < 1) return; + + mtype = buffer[0] & ~EOS_CELL_MTYPE_MASK; buffer++; - buf_len--; + len--; + switch (mtype) { case EOS_CELL_MTYPE_USSD_REQUEST: { - if (buf_len > EOS_CELL_USSD_SIZE_REQ) return; + if (len > EOS_CELL_USSD_SIZE_REQ) break; - buffer[buf_len] = '\0'; - rv = snprintf(at_cmd_buf, AT_SIZE_CMD_BUF, "AT+CUSD=1,\"%s\",15\r", buffer); - if ((rv < 0) || (rv >= AT_SIZE_CMD_BUF)) return; + rv = snprintf(at_cmd_buf, AT_SIZE_CMD_BUF, "AT+CUSD=1,\"%.*s\",15\r", len, buffer); + if ((rv < 0) || (rv >= AT_SIZE_CMD_BUF)) break; rv = eos_modem_take(1000); - if (rv) return; + if (rv) break; at_cmd(at_cmd_buf); rv = at_expect("^OK", "^ERROR", 1000); @@ -38,7 +43,7 @@ void eos_cell_ussd_handler(unsigned char mtype, unsigned char *buffer, uint16_t case EOS_CELL_MTYPE_USSD_CANCEL: { rv = eos_modem_take(1000); - if (rv) return; + if (rv) break; at_cmd("AT+CUSD=2\r"); rv = at_expect("^OK", "^ERROR", 1000); @@ -50,60 +55,69 @@ void eos_cell_ussd_handler(unsigned char mtype, unsigned char *buffer, uint16_t } static void ussd_reply_handler(char *urc, regmatch_t m[]) { - int rep, rv; - unsigned char *buf; + EOSMessage msg; uint16_t len; - char *_buf; - size_t _len; + char *rbuf; + size_t rlen; + int rep, rv; sscanf(urc + m[1].rm_so, "%1d", &rep); - buf = eos_net_alloc(); - buf[0] = EOS_CELL_MTYPE_USSD | EOS_CELL_MTYPE_USSD_REPLY; - buf[1] = rep; + eos_net_alloc(&msg); + if (msg.size < 2) { + eos_net_free(&msg); + return; + } + msg.buffer[0] = EOS_CELL_MTYPE_USSD | EOS_CELL_MTYPE_USSD_REPLY; + msg.buffer[1] = rep; 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, &msg, len); + if (rv) ESP_LOGE(TAG, "NET SEND ERR:%d", rv); return; } - _buf = (char *)buf + len; - _len = m[2].rm_eo - m[2].rm_so - 2; - if (_len > EOS_NET_SIZE_BUF - len) { - eos_net_free(buf); + rbuf = (char *)msg.buffer + len; + rlen = m[2].rm_eo - m[2].rm_so - 2; + if (msg.size < rlen + len + 1) { + eos_net_free(&msg); return; } - memcpy(_buf, urc + m[2].rm_so + 2, _len); - len += _len; + memcpy(rbuf, urc + m[2].rm_so + 2, rlen); + rbuf[rlen] = '\0'; rv = EOS_OK; do { char *end; - end = strchr(_buf, '"'); + end = strchr(rbuf, '"'); if (end) { - len += end - _buf; + len += end - rbuf; break; } else { - _len = strlen(_buf); - _buf[_len] = '\n'; - _buf += _len + 1; - len += _len + 1; + rlen = strlen(rbuf); + rbuf[rlen] = '\n'; + rbuf += rlen + 1; + len += rlen + 1; } - rv = eos_modem_readln(_buf, EOS_NET_SIZE_BUF - len, 1000); + rv = eos_modem_readln(rbuf, msg.size - len, 1000); if (rv) break; } while (1); if (rv) { - ESP_LOGE(TAG, "error"); - eos_net_free(buf); + ESP_LOGE(TAG, "ERROR"); + eos_net_free(&msg); return; } - eos_net_send(EOS_NET_MTYPE_CELL, buf, len); + rv = eos_net_send(EOS_NET_MTYPE_CELL, &msg, 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..0ec543b 100644 --- a/fw/esp32/components/eos/cell_voice.c +++ b/fw/esp32/components/eos/cell_voice.c @@ -13,23 +13,30 @@ #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) { +void eos_cell_voice_handler(unsigned char _mtype, EOSMessage *msg, uint16_t len) { + unsigned char mtype; + unsigned char *buffer = msg->buffer; int rv; + if (len < 1) return; + + mtype = buffer[0] & ~EOS_CELL_MTYPE_MASK; buffer++; - buf_len--; + len--; + switch (mtype) { case EOS_CELL_MTYPE_VOICE_DIAL: { - if (buf_len > EOS_CELL_SIZE_PHNUM) return; + if (len > EOS_CELL_SIZE_PHNUM) break; - buffer[buf_len] = '\0'; - rv = snprintf(at_cmd_buf, AT_SIZE_CMD_BUF, "ATD%s;\r", buffer); - if ((rv < 0) || (rv >= AT_SIZE_CMD_BUF)) return; + rv = snprintf(at_cmd_buf, AT_SIZE_CMD_BUF, "ATD%.*s;\r", len, buffer); + if ((rv < 0) || (rv >= AT_SIZE_CMD_BUF)) break; rv = eos_modem_take(1000); - if (rv) return; + if (rv) break; at_cmd(at_cmd_buf); rv = at_expect("^OK", "^(ERROR|\\+CME ERROR: [0-9]+)", 1000); @@ -41,7 +48,7 @@ void eos_cell_voice_handler(unsigned char mtype, unsigned char *buffer, uint16_t case EOS_CELL_MTYPE_VOICE_ANSWER: { rv = eos_modem_take(1000); - if (rv) return; + if (rv) break; at_cmd("ATA\r"); // Response will be picked up by urc handler @@ -55,7 +62,7 @@ void eos_cell_voice_handler(unsigned char mtype, unsigned char *buffer, uint16_t eos_cell_pcm_stop(); rv = eos_modem_take(1000); - if (rv) return; + if (rv) break; at_cmd("AT+CHUP\r"); // Response will be picked up by urc handler @@ -65,63 +72,83 @@ void eos_cell_voice_handler(unsigned char mtype, unsigned char *buffer, uint16_t } case EOS_CELL_MTYPE_VOICE_PCM: { - eos_cell_pcm_push(buffer, buf_len); + eos_cell_pcm_push(buffer, len); break; } } } static void ring_handler(char *urc, regmatch_t m[]) { - unsigned char *buf; - char *ring_buf; + EOSMessage msg; uint16_t len; + char *buffer; regmatch_t match[2]; int rv = EOS_OK; - buf = eos_net_alloc(); - buf[0] = EOS_CELL_MTYPE_VOICE | EOS_CELL_MTYPE_VOICE_RING; + eos_net_alloc(&msg); + if (msg.size < EOS_CELL_SIZE_PHNUM + 1) { + eos_net_free(&msg); + return; + } + msg.buffer[0] = EOS_CELL_MTYPE_VOICE | EOS_CELL_MTYPE_VOICE_RING; len = 1; - rv = at_expect_match("^\\+CLIP: \"(\\+?[0-9]+)\"", NULL, &ring_buf, match, 2, REG_EXTENDED, 1000); + rv = at_expect_match("^\\+CLIP: \"(\\+?[0-9]+)\"", NULL, &buffer, match, 2, REG_EXTENDED, 1000); if (!rv) { regoff_t num_len; num_len = match[1].rm_eo - match[1].rm_so; if (num_len > EOS_CELL_SIZE_PHNUM) { - eos_net_free(buf); + eos_net_free(&msg); return; } - memcpy(buf + 1, ring_buf + match[1].rm_so, num_len); + memcpy(msg.buffer + 1, buffer + 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, &msg, 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; + EOSMessage msg; + 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); + eos_net_alloc(&msg); + if (msg.size < 1) { + eos_net_free(&msg); + return; + } + msg.buffer[0] = EOS_CELL_MTYPE_VOICE | EOS_CELL_MTYPE_VOICE_BUSY; + rv = eos_net_send(EOS_NET_MTYPE_CELL, &msg, 1); + 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; + EOSMessage msg; + 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); + eos_net_alloc(&msg); + if (msg.size < 1) { + eos_net_free(&msg); + return; + } + msg.buffer[0] = EOS_CELL_MTYPE_VOICE | EOS_CELL_MTYPE_VOICE_MISS; + rv = eos_net_send(EOS_NET_MTYPE_CELL, &msg, 1); + if (rv) ESP_LOGE(TAG, "NET SEND ERR:%d", rv); } static void call_begin_handler(char *urc, regmatch_t m[]) { - unsigned char *buf; + EOSMessage msg; + int rv; + + eos_net_alloc(&msg); + if (msg.size < 1) { + eos_net_free(&msg); + return; + } vTaskDelay(100 / portTICK_PERIOD_MS); at_cmd("AT+CECH=0x0000\r"); @@ -140,32 +167,53 @@ static void call_begin_handler(char *urc, regmatch_t m[]) { at_expect("^OK", "^ERROR", 1000); */ - buf = eos_net_alloc(); - buf[0] = EOS_CELL_MTYPE_VOICE | EOS_CELL_MTYPE_VOICE_BEGIN; - eos_net_send(EOS_NET_MTYPE_CELL, buf, 1); + msg.buffer[0] = EOS_CELL_MTYPE_VOICE | EOS_CELL_MTYPE_VOICE_BEGIN; + rv = eos_net_send(EOS_NET_MTYPE_CELL, &msg, 1); + if (rv) ESP_LOGE(TAG, "NET SEND ERR:%d", rv); } static void call_end_handler(char *urc, regmatch_t m[]) { - unsigned char *buf; + EOSMessage msg; int duration = 0; + int rv; eos_cell_pcm_stop(); + eos_net_alloc(&msg); + if (msg.size < 5) { + eos_net_free(&msg); + return; + } + sscanf(urc + m[1].rm_so, "%6d", &duration); - buf = eos_net_alloc(); - buf[0] = EOS_CELL_MTYPE_VOICE | EOS_CELL_MTYPE_VOICE_END; - buf[1] = duration >> 24; - buf[2] = duration >> 16; - buf[3] = duration >> 8; - buf[4] = duration; - eos_net_send(EOS_NET_MTYPE_CELL, buf, 5); + msg.buffer[0] = EOS_CELL_MTYPE_VOICE | EOS_CELL_MTYPE_VOICE_END; + msg.buffer[1] = duration >> 24; + msg.buffer[2] = duration >> 16; + msg.buffer[3] = duration >> 8; + msg.buffer[4] = duration; + rv = eos_net_send(EOS_NET_MTYPE_CELL, &msg, 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/i2c.c b/fw/esp32/components/eos/i2c.c deleted file mode 100644 index 828e4cd..0000000 --- a/fw/esp32/components/eos/i2c.c +++ /dev/null @@ -1,82 +0,0 @@ -#include <stdlib.h> - -#include <esp_log.h> -#include <driver/i2c.h> - -#include "eos.h" - -static const char *TAG = "EOS I2C"; - -#define I2C_MASTER_NUM I2C_NUM_0 -#define I2C_MASTER_FREQ_HZ 100000 -#define I2C_MASTER_GPIO_SCL 25 -#define I2C_MASTER_GPIO_SDA 26 - -#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */ -#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */ -#define ACK_CHECK_EN 0x1 /*!< I2C master will check ack from slave*/ -#define ACK_CHECK_DIS 0x0 /*!< I2C master will not check ack from slave */ -#define ACK_VAL 0x0 /*!< I2C ack value */ -#define NCK_VAL 0x1 /*!< I2C nack value */ - -void eos_i2c_init(void) { - i2c_config_t conf; - conf.mode = I2C_MODE_MASTER; - conf.sda_io_num = I2C_MASTER_GPIO_SDA; - conf.sda_pullup_en = GPIO_PULLUP_ENABLE; - conf.scl_io_num = I2C_MASTER_GPIO_SCL; - conf.scl_pullup_en = GPIO_PULLUP_ENABLE; - conf.master.clk_speed = I2C_MASTER_FREQ_HZ; - i2c_param_config(I2C_MASTER_NUM, &conf); - i2c_driver_install(I2C_MASTER_NUM, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0); - ESP_LOGI(TAG, "INIT"); -} - -int eos_i2c_read(uint8_t addr, uint8_t reg, uint8_t *data, size_t len) { - int i, ret; - i2c_cmd_handle_t cmd = i2c_cmd_link_create(); - i2c_master_start(cmd); - i2c_master_write_byte(cmd, addr << 1 | I2C_MASTER_WRITE, ACK_CHECK_EN); - i2c_master_write_byte(cmd, reg, ACK_CHECK_EN); - i2c_master_start(cmd); - i2c_master_write_byte(cmd, addr << 1 | I2C_MASTER_READ, ACK_CHECK_EN); - for (i=0; i < len - 1; i++) { - i2c_master_read_byte(cmd, data+i, ACK_VAL); - } - i2c_master_read_byte(cmd, data+i, NCK_VAL); - i2c_master_stop(cmd); - - ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_RATE_MS); - i2c_cmd_link_delete(cmd); - if (ret != ESP_OK) { - return EOS_ERR; - } - return EOS_OK; -} - -int eos_i2c_write(uint8_t addr, uint8_t reg, uint8_t *data, size_t len) { - int i, ret; - i2c_cmd_handle_t cmd = i2c_cmd_link_create(); - i2c_master_start(cmd); - i2c_master_write_byte(cmd, addr << 1 | I2C_MASTER_WRITE, ACK_CHECK_EN); - i2c_master_write_byte(cmd, reg, ACK_CHECK_EN); - for (i=0; i < len; i++) { - i2c_master_write_byte(cmd, *(data+i), ACK_CHECK_EN); - } - i2c_master_stop(cmd); - - ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_RATE_MS); - i2c_cmd_link_delete(cmd); - if (ret != ESP_OK) { - return EOS_ERR; - } - return EOS_OK; -} - -int eos_i2c_read8(uint8_t addr, uint8_t reg, uint8_t *data) { - return eos_i2c_read(addr, reg, data, 1); -} - -int eos_i2c_write8(uint8_t addr, uint8_t reg, uint8_t data) { - return eos_i2c_write(addr, reg, &data, 1); -} diff --git a/fw/esp32/components/eos/include/_net.h b/fw/esp32/components/eos/include/_net.h deleted file mode 100644 index 35b5308..0000000 --- a/fw/esp32/components/eos/include/_net.h +++ /dev/null @@ -1 +0,0 @@ -#include "net.h"
\ No newline at end of file diff --git a/fw/esp32/components/eos/include/app.h b/fw/esp32/components/eos/include/app.h index 2033b2b..38fba1a 100644 --- a/fw/esp32/components/eos/include/app.h +++ b/fw/esp32/components/eos/include/app.h @@ -1,23 +1,21 @@ #include <stdint.h> -/* common */ -#define EOS_APP_MTU 1500 -#define EOS_APP_SIZE_BUF EOS_APP_MTU +#include "net.h" #define EOS_APP_MTYPE_TUN 1 #define EOS_APP_MAX_MTYPE 8 -#define EOS_APP_MTYPE_FLAG_MASK 0xc0 +void eos_app_init(void); +void eos_app_run(void); -/* esp32 specific */ -#define EOS_APP_SIZE_BUFQ 4 -#define EOS_APP_SIZE_SNDQ 4 +void eos_app_alloc(EOSMessage *msg); +void eos_app_free(EOSMessage *msg); -typedef void (*eos_app_fptr_t) (unsigned char, unsigned char *, uint16_t); +int eos_app_send(unsigned char mtype, EOSMessage *msg, uint16_t len); -void eos_app_init(void); +void eos_app_sleep_req(void); +void eos_app_wake(void); +void eos_app_deep_sleep(void); +void eos_app_deep_wake(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); +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..30347c1 100644 --- a/fw/esp32/components/eos/include/cell.h +++ b/fw/esp32/components/eos/include/cell.h @@ -1,6 +1,10 @@ #include <sys/types.h> #include <stdint.h> +#include "net.h" + +#define EOS_CELL_MTU EOS_NET_MTU + #define EOS_CELL_MTYPE_DEV 0x10 #define EOS_CELL_MTYPE_VOICE 0x20 #define EOS_CELL_MTYPE_SMS 0x30 @@ -27,7 +31,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 +79,28 @@ #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_sleep_req(void); +void eos_modem_wake(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_deep_wake(void); void eos_ppp_get_apn(char *apn); void eos_ppp_set_apn(char *apn); @@ -105,15 +112,14 @@ 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); -void eos_cell_voice_handler(unsigned char mtype, unsigned char *buffer, uint16_t buf_len); -void eos_cell_sms_handler(unsigned char mtype, unsigned char *buffer, uint16_t buf_len); -void eos_cell_ussd_handler(unsigned char mtype, unsigned char *buffer, uint16_t buf_len); -void eos_cell_pdp_handler(unsigned char mtype, unsigned char *buffer, uint16_t buf_len); +void eos_cell_voice_handler(unsigned char mtype, EOSMessage *msg, uint16_t len); +void eos_cell_sms_handler(unsigned char mtype, EOSMessage *msg, uint16_t len); +void eos_cell_ussd_handler(unsigned char mtype, EOSMessage *msg, uint16_t len); +void eos_cell_pdp_handler(unsigned char mtype, EOSMessage *msg, uint16_t len); void eos_cell_voice_init(void); void eos_cell_sms_init(void); diff --git a/fw/esp32/components/eos/include/eos.h b/fw/esp32/components/eos/include/eos.h index bc9dc51..3f9755d 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_UART 1 -#define EOS_TASK_PRIORITY_MODEM 1 -#define EOS_TASK_PRIORITY_I2S 1 -#define EOS_TASK_PRIORITY_CELL 1 -#define EOS_TASK_PRIORITY_PWR 1 +#define EOS_TASK_PRIORITY_NET 16 +#define EOS_TASK_PRIORITY_APP 17 +#define EOS_TASK_PRIORITY_SOCK 10 +#define EOS_TASK_PRIORITY_UART 10 +#define EOS_TASK_PRIORITY_MODEM 10 +#define EOS_TASK_PRIORITY_PCM 10 +#define EOS_TASK_PRIORITY_CELL 10 +#define EOS_TASK_PRIORITY_PWR 10 -#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/i2c.h b/fw/esp32/components/eos/include/i2c.h deleted file mode 100644 index f014141..0000000 --- a/fw/esp32/components/eos/include/i2c.h +++ /dev/null @@ -1,9 +0,0 @@ -#include <sys/types.h> -#include <stdint.h> - -void eos_i2c_init(void); - -int eos_i2c_read(uint8_t addr, uint8_t reg, uint8_t *data, size_t len); -int eos_i2c_write(uint8_t addr, uint8_t reg, uint8_t *data, size_t len); -int eos_i2c_read8(uint8_t addr, uint8_t reg, uint8_t *data); -int eos_i2c_write8(uint8_t addr, uint8_t reg, uint8_t data); diff --git a/fw/esp32/components/eos/include/msgq.h b/fw/esp32/components/eos/include/msgq.h index bbfe041..2b216d1 100644 --- a/fw/esp32/components/eos/include/msgq.h +++ b/fw/esp32/components/eos/include/msgq.h @@ -1,8 +1,27 @@ #include <stdint.h> +#ifndef _EOS_MSGQ_H_ +#define _EOS_MSGQ_H_ + +#define EOS_MSG_FLAG_WAKE 0x01 +#define EOS_MSG_FLAG_RPLY_REQ 0x02 +#define EOS_MSG_FLAG_RPLY_REP 0x04 + +typedef struct EOSMessage { + unsigned char *buffer; + uint16_t size; + uint8_t flags; +} EOSMessage; + +void eos_msg_init(EOSMessage *msg, unsigned char *buffer, uint16_t size); +void eos_msg_set_flags(EOSMessage *msg, uint8_t flags); +void eos_msg_clear_flags(EOSMessage *msg, uint8_t flags); +uint8_t eos_msg_flags(EOSMessage *msg); + typedef struct EOSMsgItem { unsigned char type; unsigned char *buffer; + uint16_t size; uint16_t len; } EOSMsgItem; @@ -14,9 +33,9 @@ typedef struct EOSMsgQ { } EOSMsgQ; void eos_msgq_init(EOSMsgQ *msgq, EOSMsgItem *array, uint8_t size); -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); +int eos_msgq_push(EOSMsgQ *msgq, unsigned char type, EOSMessage *msg, uint16_t len); +void eos_msgq_pop(EOSMsgQ *msgq, unsigned char *type, EOSMessage *msg, uint16_t *len); typedef struct EOSBufQ { uint8_t idx_r; @@ -26,6 +45,8 @@ 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); + +#endif /* _EOS_MSGQ_H_ */ diff --git a/fw/esp32/components/eos/include/net.h b/fw/esp32/components/eos/include/net.h index 3e9e625..edf1a58 100644 --- a/fw/esp32/components/eos/include/net.h +++ b/fw/esp32/components/eos/include/net.h @@ -1,36 +1,40 @@ #include <stdint.h> -/* common */ +#include "msgq.h" + #define EOS_NET_MTU 1500 -#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_BRIDGE 0 /* handler only */ +#define EOS_NET_MTYPE_WIFI 1 +#define EOS_NET_MTYPE_CELL 2 +#define EOS_NET_MTYPE_SOCK 3 +#define EOS_NET_MTYPE_RNG 4 -#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 0x20 /* 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_FLAG_ONEW 0x80 +#define EOS_NET_MTYPE_FLAG_REPL 0x40 +#define EOS_NET_MTYPE_FLAG_BRIDGE 0x08 -/* esp32 specific */ -#define EOS_NET_SIZE_BUFQ 4 -#define EOS_NET_SIZE_SNDQ 4 +#define EOS_NET_MTYPE_MASK 0x0F -typedef void (*eos_net_fptr_t) (unsigned char, unsigned char *, uint16_t); +typedef void (*eos_net_handler_t) (unsigned char, EOSMessage *msg, uint16_t); +void eos_net_xchg_task(void *param); void eos_net_init(void); +void eos_net_run(void); + +void eos_net_alloc(EOSMessage *msg); +void eos_net_free(EOSMessage *msg); + +int eos_net_send(unsigned char mtype, EOSMessage *msg, uint16_t len); +void eos_net_reply(unsigned char mtype, EOSMessage *msg, uint16_t len); + +void eos_net_sleep_req(void); +void eos_net_wake(void); +void eos_net_deep_sleep(void); +void eos_net_deep_wake(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); +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..5627e12 --- /dev/null +++ b/fw/esp32/components/eos/include/net_priv.h @@ -0,0 +1,30 @@ +#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_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; + 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 handler; +} NETConfig; + +void _eos_net_init_gpio(NETConfig *config); +void _eos_net_alloc(NETConfig *config, EOSMessage *msg); +void _eos_net_free(NETConfig *config, EOSMessage *msg); +int _eos_net_send(NETConfig *config, unsigned char mtype, EOSMessage *msg, uint16_t len); +void _eos_net_sleep_req(NETConfig *config); +void _eos_net_wake(NETConfig *config); +void _eos_net_deep_sleep(NETConfig *config); +void _eos_net_deep_wake(NETConfig *config); diff --git a/fw/esp32/components/eos/include/power.h b/fw/esp32/components/eos/include/power.h index 2215907..c7d184c 100644 --- a/fw/esp32/components/eos/include/power.h +++ b/fw/esp32/components/eos/include/power.h @@ -1,22 +1,26 @@ #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_set_mode(uint8_t mode); +void eos_power_sleep_req(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/tun.h b/fw/esp32/components/eos/include/tun.h index 3acb2a6..ab1e0f4 100644 --- a/fw/esp32/components/eos/include/tun.h +++ b/fw/esp32/components/eos/include/tun.h @@ -1 +1,5 @@ +#include <stdint.h> + +void eos_tun_portmap_add(uint32_t ext_addr); +void eos_tun_portmap_remove(void); void eos_tun_init(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..0aae73a 100644 --- a/fw/esp32/components/eos/include/wifi.h +++ b/fw/esp32/components/eos/include/wifi.h @@ -1,3 +1,5 @@ +#include <sys/types.h> + #define EOS_WIFI_MTYPE_STATUS 0 #define EOS_WIFI_MTYPE_SCAN 1 #define EOS_WIFI_MTYPE_START 2 @@ -13,12 +15,13 @@ #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); int eos_wifi_connect(void); int eos_wifi_disconnect(void); -ssize_t eos_wifi_get_status(unsigned char *buffer); +ssize_t eos_wifi_get_status(unsigned char *buffer, size_t size); 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..50dbd3e 100644 --- a/fw/esp32/components/eos/msgq.c +++ b/fw/esp32/components/eos/msgq.c @@ -5,6 +5,24 @@ #define IDX_MASK(IDX, SIZE) ((IDX) & ((SIZE) - 1)) +void eos_msg_init(EOSMessage *msg, unsigned char *buffer, uint16_t size) { + msg->buffer = buffer; + msg->size = size; + msg->flags = 0; +} + +void eos_msg_set_flags(EOSMessage *msg, uint8_t flags) { + msg->flags |= flags; +} + +void eos_msg_clear_flags(EOSMessage *msg, uint8_t flags) { + msg->flags &= ~flags; +} + +uint8_t eos_msg_flags(EOSMessage *msg) { + return msg->flags; +} + void eos_msgq_init(EOSMsgQ *msgq, EOSMsgItem *array, uint8_t size) { msgq->idx_r = 0; msgq->idx_w = 0; @@ -12,35 +30,46 @@ void eos_msgq_init(EOSMsgQ *msgq, EOSMsgItem *array, uint8_t size) { msgq->array = array; } -int eos_msgq_push(EOSMsgQ *msgq, unsigned char type, unsigned char *buffer, uint16_t len) { +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, EOSMessage *msg, uint16_t len) { + uint8_t idx; + if ((uint8_t)(msgq->idx_w - msgq->idx_r) == msgq->size) return EOS_ERR_FULL; - uint8_t idx = IDX_MASK(msgq->idx_w, msgq->size); + idx = IDX_MASK(msgq->idx_w, msgq->size); msgq->array[idx].type = type; - msgq->array[idx].buffer = buffer; - msgq->array[idx].len = len; + if (msg) { + msgq->array[idx].buffer = msg->buffer; + msgq->array[idx].size = msg->size; + msgq->array[idx].len = len; + } else { + msgq->array[idx].buffer = NULL; + msgq->array[idx].size = 0; + msgq->array[idx].len = 0; + } msgq->idx_w++; + return EOS_OK; } -void eos_msgq_pop(EOSMsgQ *msgq, unsigned char *type, unsigned char **buffer, uint16_t *len) { +void eos_msgq_pop(EOSMsgQ *msgq, unsigned char *type, EOSMessage *msg, uint16_t *len) { if (msgq->idx_r == msgq->idx_w) { *type = 0; - *buffer = NULL; + eos_msg_init(msg, NULL, 0); *len = 0; } else { uint8_t idx = IDX_MASK(msgq->idx_r, msgq->size); + *type = msgq->array[idx].type; - *buffer = msgq->array[idx].buffer; + eos_msg_init(msg, msgq->array[idx].buffer, msgq->array[idx].size); *len = msgq->array[idx].len; msgq->idx_r++; } } -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 +77,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 +93,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..dd3180a 100644 --- a/fw/esp32/components/eos/net.c +++ b/fw/esp32/components/eos/net.c @@ -16,283 +16,495 @@ #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 +#define SPI_HOST SPI3_HOST -static volatile int net_sleep = 0; -static volatile int net_wake = 0; +#define NET_SIZE_BUFQ 8 +#define NET_SIZE_SNDQ 8 + +#define NET_SIZE_HDR 3 +#define NET_SIZE_BUF (EOS_NET_MTU + 4) + +// #define EOS_DEBUG 1 static EOSBufQ net_buf_q; -static unsigned char *net_bufq_array[EOS_NET_SIZE_BUFQ]; +static unsigned char *net_bufq_array[NET_SIZE_BUFQ]; static EOSMsgQ net_send_q; -static EOSMsgItem net_sndq_array[EOS_NET_SIZE_SNDQ]; +static EOSMsgItem net_sndq_array[NET_SIZE_SNDQ]; + +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 SemaphoreHandle_t mutex; -static SemaphoreHandle_t semaph; -static TaskHandle_t net_xchg_task_handle; static const char *TAG = "EOS NET"; -static eos_net_fptr_t net_handler[EOS_NET_MAX_MTYPE]; +static void bad_handler(unsigned char mtype, EOSMessage *msg, uint16_t len) { + ESP_LOGE(TAG, "BAD HANDLER: 0x%.2X LEN: %d", mtype, len); +} + +static void IRAM_ATTR net_bridge(unsigned char mtype, EOSMessage *msg, uint16_t len) { + EOSMessage _msg; + int rv; + + eos_app_alloc(&_msg); + if (len > _msg.size) { + eos_app_free(&_msg); + return; + } + memcpy(_msg.buffer, msg->buffer, len); + rv = eos_app_send(mtype & EOS_NET_MTYPE_MASK, &_msg, len); + if (rv) ESP_LOGE(TAG, "BRIDGE ERR: %d", rv); +} + +static void IRAM_ATTR net_msg_handler(unsigned char mtype, EOSMessage *msg, uint16_t len) { + uint8_t idx; + + idx = mtype & EOS_NET_MTYPE_FLAG_BRIDGE ? EOS_NET_MTYPE_BRIDGE : mtype & EOS_NET_MTYPE_MASK; + if ((idx < EOS_NET_MAX_MTYPE) && (len <= msg->size)) { + net_handler[idx](mtype, msg, len); + } else { + bad_handler(mtype, msg, len); + } +} + +/* Called after a transaction is queued and ready for pickup by master */ +static void IRAM_ATTR _post_setup_cb(spi_slave_transaction_t *trans) { + NETConfig *config = trans->user; -static void bad_handler(unsigned char mtype, unsigned char *buffer, uint16_t len) { - ESP_LOGE(TAG, "bad handler: %d len: %d", mtype, len); + gpio_set_level(config->gpio_cts, 0); } -// 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); +/* Called after transaction is sent/received */ +static void IRAM_ATTR _post_trans_cb(spi_slave_transaction_t *trans) { + NETConfig *config = trans->user; + + gpio_set_level(config->gpio_cts, 1); } -// 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 net_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); + + eos_power_sleep_rdy(config->dev); +} + +static void net_wake(NETConfig *config) { + esp_err_t ret; + uint8_t msgq_len; + + 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 IRAM_ATTR eos_net_xchg_task(void *param) { + NETConfig *config = param; + int 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); + unsigned char *snd_buf; + unsigned char *rcv_buf; + EOSMessage msg; + uint16_t snd_buf_len, rcv_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, *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); + if (!config->present) { + vTaskDelete(NULL); + return; + } + + snd_buf = spi_bus_dma_memory_alloc(config->spi_host, NET_SIZE_BUF, MALLOC_CAP_DMA); + assert(snd_buf != NULL); + + rcv_buf = spi_bus_dma_memory_alloc(config->spi_host, NET_SIZE_BUF, MALLOC_CAP_DMA); + assert(rcv_buf != NULL); + + memset(&_spi_tr_cfg, 0, sizeof(_spi_tr_cfg)); + spi_tr_cfg = &_spi_tr_cfg; + + spi_iface_cfg->post_setup_cb = _post_setup_cb; + spi_iface_cfg->post_trans_cb = _post_trans_cb; - 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; + spi_tr_cfg->tx_buffer = snd_buf; + spi_tr_cfg->rx_buffer = rcv_buf; + spi_tr_cfg->length = NET_SIZE_BUF * 8; + spi_tr_cfg->user = config; - if (eos_power_wakeup_cause() != EOS_PWR_WAKE_RST) { - wake = 1; - skip_msg = 1; + if (esp_reset_reason() == ESP_RST_DEEPSLEEP) { + _eos_net_deep_wake(config); + vTaskSuspend(NULL); + net_wake(config); + } else { + ret = spi_slave_initialize(config->spi_host, spi_bus_cfg, spi_iface_cfg, SPI_DMA_CH_AUTO); + assert(ret == ESP_OK); } - eos_power_wait4init(); while (1) { if (!skip_msg) { - xSemaphoreTake(mutex, portMAX_DELAY); + int msg_free; - eos_msgq_pop(&net_send_q, &mtype, &buffer, &len); + xSemaphoreTake(config->mutex, portMAX_DELAY); + + msg_free = 0; + snd_buf_len = 0; + eos_msgq_pop(config->send_q, &mtype, &msg, &snd_buf_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(&net_buf_q, buffer); - xSemaphoreGive(semaph); +#ifdef EOS_DEBUG + ESP_LOGI(TAG, "SEND:0x%.2X DEV:0x%.8lX LEN:%d", mtype, config->dev, snd_buf_len); +#endif + snd_buf[0] = mtype; + snd_buf[1] = snd_buf_len >> 8; + snd_buf[2] = snd_buf_len & 0xFF; + if (msg.buffer) { + memcpy(snd_buf + NET_SIZE_HDR, msg.buffer, snd_buf_len); + msg_free = 1; } + } else if (!sleep_msg && config->sleep_req) { + snd_buf[0] = EOS_NET_MTYPE_SLEEP; + snd_buf[1] = 0; + snd_buf[2] = 0; + sleep_msg = 1; + config->sleep_req = 0; + config->sleep = 1; } else { - gpio_set_level(SPI_GPIO_RTS, 0); - buf_send[0] = 0; - buf_send[1] = 0; - buf_send[2] = 0; + gpio_set_level(config->gpio_rts, 1); + snd_buf[0] = 0; + snd_buf[1] = 0; + snd_buf[2] = 0; } - xSemaphoreGive(mutex); + xSemaphoreGive(config->mutex); + + if (msg_free) _eos_net_free(config, &msg); } 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]); + rcv_buf[0] = 0; + rcv_buf[1] = 0; + rcv_buf[2] = 0; + + ret = spi_slave_transmit(config->spi_host, spi_tr_cfg, portMAX_DELAY); + assert(ret == ESP_OK); - if (wake) { - eos_power_net_ready(); - wake = 0; + trans_len = spi_tr_cfg->trans_len / 8; + +#ifdef EOS_DEBUG + ESP_LOGI(TAG, "RECV:0x%.2X DEV:0x%.8lX LEN:%d", rcv_buf[0], config->dev, trans_len); +#endif + + if (sleep_msg) { + net_sleep(config); + vTaskSuspend(NULL); + net_wake(config); + sleep_msg = 0; + continue; } - if ((spi_tr.trans_len / 8) < SPI_SIZE_HDR) continue; - if (buf_recv[0] == 0x00) continue; + /* SPI reset */ + if (trans_len < NET_SIZE_HDR) { + if (snd_buf[0]) skip_msg = 1; + continue; + } - if (buf_recv[0] == 0xFF) { // Sleep req - if (buf_send[0] == 0) { - spi_slave_free(VSPI_HOST); - eos_power_sleep(); + mtype = rcv_buf[0] & EOS_NET_MTYPE_MASK; + mtype_flags = rcv_buf[0] & ~EOS_NET_MTYPE_MASK; + if (snd_buf[0] && (mtype_flags & EOS_NET_MTYPE_FLAG_ONEW)) { + skip_msg = 1; + } + rcv_buf_len = (uint16_t)rcv_buf[1] << 8; + rcv_buf_len |= (uint16_t)rcv_buf[2] & 0xFF; - xSemaphoreTake(mutex, portMAX_DELAY); - net_sleep = 1; - if (eos_msgq_len(&net_send_q)) net_wake = 1; - xSemaphoreGive(mutex); + if (snd_buf[0] && (trans_len < snd_buf_len + NET_SIZE_HDR) && !skip_msg) { + spi_tr_cfg->tx_buffer = snd_buf + trans_len; + spi_tr_cfg->rx_buffer = rcv_buf + trans_len; + spi_tr_cfg->length = (NET_SIZE_BUF - trans_len) * 8; - if (net_wake) eos_power_wake(EOS_PWR_WAKE_NETQ); - vTaskSuspend(NULL); + ret = spi_slave_transmit(config->spi_host, spi_tr_cfg, portMAX_DELAY); + assert(ret == ESP_OK); - xSemaphoreTake(mutex, portMAX_DELAY); - net_sleep = 0; - net_wake = 0; - xSemaphoreGive(mutex); + trans_len += spi_tr_cfg->trans_len / 8; + spi_tr_cfg->tx_buffer = snd_buf; + spi_tr_cfg->rx_buffer = rcv_buf; + spi_tr_cfg->length = NET_SIZE_BUF * 8; + } - spi_slave_initialize(VSPI_HOST, &spi_bus_cfg, &spi_slave_cfg, 1); - wake = 1; - skip_msg = 1; - } + if (rcv_buf[0] == EOS_NET_MTYPE_SLEEP) { + eos_power_sleep_req(config->dev); 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 (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; + if (mtype == 0) continue; + + eos_msg_init(&msg, rcv_buf + NET_SIZE_HDR, EOS_NET_MTU); + if (mtype_flags & EOS_NET_MTYPE_FLAG_REPL) eos_msg_set_flags(&msg, EOS_MSG_FLAG_RPLY_REQ); + config->handler(rcv_buf[0], &msg, rcv_buf_len); + + if (eos_msg_flags(&msg) & EOS_MSG_FLAG_RPLY_REQ) { + if (!(eos_msg_flags(&msg) & EOS_MSG_FLAG_RPLY_REP)) { + // eos_net_reply(EOS_MTYPE_ERR, msg, 0); + } + spi_tr_cfg->tx_buffer = rcv_buf; + 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 = snd_buf; + spi_tr_cfg->rx_buffer = rcv_buf; } } + 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, NET_SIZE_SNDQ); + eos_bufq_init(&net_buf_q, net_bufq_array, NET_SIZE_BUFQ); + for (i=0; i<NET_SIZE_BUFQ; i++) { + unsigned char *buffer; - 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)); + buffer = malloc(EOS_NET_MTU); + 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(NET_SIZE_BUFQ, 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 = esp_reset_reason() == ESP_RST_DEEPSLEEP ? 1 : 0; + net_config.sleep_req = 0; + net_config.present = 1; + net_config.dev = NET_DEV_NET; + 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.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.handler = net_msg_handler; + + /* Configuration for the SPI bus */ + net_spi_bus_cfg.mosi_io_num = SPI_GPIO_MOSI; + net_spi_bus_cfg.miso_io_num = SPI_GPIO_MISO; + net_spi_bus_cfg.sclk_io_num = SPI_GPIO_SCLK; + net_spi_bus_cfg.intr_flags = ESP_INTR_FLAG_IRAM; + + /* Configuration for the SPI slave interface */ + net_spi_iface_cfg.mode = 0; + net_spi_iface_cfg.spics_io_num = SPI_GPIO_CS; + net_spi_iface_cfg.queue_size = 2; + net_spi_iface_cfg.flags = 0; + + _eos_net_init_gpio(&net_config); + eos_net_set_handler(EOS_NET_MTYPE_BRIDGE, net_bridge); + ESP_LOGI(TAG, "INIT"); } -unsigned char *eos_net_alloc(void) { - unsigned char *ret; +void eos_net_run(void) { + BaseType_t rv; - xSemaphoreTake(semaph, portMAX_DELAY); - xSemaphoreTake(mutex, portMAX_DELAY); - ret = eos_bufq_pop(&net_buf_q); - xSemaphoreGive(mutex); + 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); - return ret; + ESP_LOGI(TAG, "RUN"); } -void eos_net_free(unsigned char *buf) { - xSemaphoreTake(mutex, portMAX_DELAY); - eos_bufq_push(&net_buf_q, buf); - xSemaphoreGive(semaph); - xSemaphoreGive(mutex); +void _eos_net_alloc(NETConfig *config, EOSMessage *msg) { + xSemaphoreTake(config->bufq_semaph, portMAX_DELAY); + xSemaphoreTake(config->bufq_mutex, portMAX_DELAY); + msg->buffer = eos_bufq_pop(config->buf_q); + msg->size = EOS_NET_MTU; + xSemaphoreGive(config->bufq_mutex); } -int eos_net_send(unsigned char mtype, unsigned char *buffer, uint16_t len) { - int rv = EOS_OK; - int sleep; +void _eos_net_free(NETConfig *config, EOSMessage *msg) { + xSemaphoreTake(config->bufq_mutex, portMAX_DELAY); + eos_bufq_push(config->buf_q, msg->buffer); + xSemaphoreGive(config->bufq_semaph); + xSemaphoreGive(config->bufq_mutex); +} - 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); +void eos_net_alloc(EOSMessage *msg) { + _eos_net_alloc(&net_config, msg); +} + +void eos_net_free(EOSMessage *msg) { + _eos_net_free(&net_config, msg); +} + +int _eos_net_send(NETConfig *config, unsigned char mtype, EOSMessage *msg, uint16_t len) { + int wake, rv; + + wake = eos_msg_flags(msg) & EOS_MSG_FLAG_WAKE; + rv = EOS_OK; + + xSemaphoreTake(config->mutex, portMAX_DELAY); + + if (!config->present) rv = EOS_ERR_NOTFOUND; + if (rv) goto net_send_fin; + + if (!wake && (config->sleep || config->sleep_req)) rv = EOS_ERR_BUSY; + if (rv) goto net_send_fin; - if (rv) eos_net_free(buffer); + rv = eos_msgq_push(config->send_q, mtype, msg, len); + if (rv) goto net_send_fin; - if (sleep) eos_power_wake(EOS_PWR_WAKE_NETQ); + /* we can't wake app module by pulling rts low */ + gpio_set_level(config->gpio_rts, 0); + +net_send_fin: + xSemaphoreGive(config->mutex); + + if (rv) _eos_net_free(config, msg); return rv; } -void eos_net_reply(unsigned char mtype, unsigned char *buffer, uint16_t len) { - buffer -= SPI_SIZE_HDR; +int eos_net_send(unsigned char mtype, EOSMessage *msg, uint16_t len) { + return _eos_net_send(&net_config, mtype, msg, len); +} + +void eos_net_reply(unsigned char mtype, EOSMessage *msg, uint16_t len) { + unsigned char *buffer = msg->buffer - NET_SIZE_HDR; + + if (!(eos_msg_flags(msg) & EOS_MSG_FLAG_RPLY_REQ)) return; + if (eos_msg_flags(msg) & EOS_MSG_FLAG_RPLY_REP) return; buffer[0] = mtype; buffer[1] = len >> 8; buffer[2] = len & 0xFF; + eos_msg_set_flags(msg, EOS_MSG_FLAG_RPLY_REP); } -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; -void eos_net_sleep(void) { - gpio_set_level(SPI_GPIO_CTS, 1); - vTaskDelay(200 / portTICK_PERIOD_MS); - gpio_set_level(SPI_GPIO_CTS, 0); + 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); + + 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_deep_sleep(NETConfig *config) { + gpio_hold_en(config->gpio_cts); +} + +void _eos_net_deep_wake(NETConfig *config) { + gpio_hold_dis(config->gpio_cts); +} + +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_deep_sleep(void) { + _eos_net_deep_sleep(&net_config); +} + +void eos_net_deep_wake(void) { + _eos_net_deep_wake(&net_config); +} + +void eos_net_set_handler(unsigned char mtype, eos_net_handler_t handler) { + if (handler == NULL) handler = bad_handler; + if (mtype < EOS_NET_MAX_MTYPE) net_handler[mtype] = handler; +} diff --git a/fw/esp32/components/eos/power.c b/fw/esp32/components/eos/power.c index b98c0ec..1f58f77 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_SET_MODE 1 +#define PWR_ETYPE_SLEEP_REQ 2 +#define PWR_ETYPE_SLEEP_RDY 3 +#define PWR_ETYPE_WAKE 4 typedef struct { uint8_t type; - union { - uint8_t source; - uint8_t level; - }; + uint32_t param; } 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,154 @@ 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.param = 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.param = 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.param = 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); +static void power_sleep_req(uint32_t dev) { + if (dev & EOS_PWR_DEV_NET) { + eos_net_sleep_req(); } - - 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); + if (dev & EOS_PWR_DEV_APP) { + eos_app_sleep_req(); + } + if (dev & EOS_PWR_DEV_MODEM) { + eos_modem_sleep_req(); } - - 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"); +static void power_sleep_rdy(uint32_t dev) { + gpio_config_t io_conf = { + .mode = GPIO_MODE_INPUT, + .intr_type = GPIO_INTR_NEGEDGE, + .pull_up_en = 1, + .pull_down_en = 0, + }; - eos_modem_deep_sleep(); - esp_deep_sleep_start(); - break; - } + if (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); } -} - -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; + if (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); } - - 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); + if (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); } - - 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_wake(uint32_t dev) { + if (dev & EOS_PWR_DEV_NET) { + gpio_isr_handler_remove(EOS_PWR_GPIO_NET); + gpio_reset_pin(EOS_PWR_GPIO_NET); + eos_net_wake(); + } + if (dev & EOS_PWR_DEV_APP) { + gpio_isr_handler_remove(EOS_PWR_GPIO_APP); + gpio_reset_pin(EOS_PWR_GPIO_APP); + eos_app_wake(); + } + if (dev & EOS_PWR_DEV_MODEM) { + gpio_isr_handler_remove(EOS_PWR_GPIO_MODEM); + gpio_reset_pin(EOS_PWR_GPIO_MODEM); + eos_modem_wake(); + } } 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) { + sys_sleep = 0; + sleep_req = 0; + sleep_rdy = 0; + if (esp_reset_reason() == ESP_RST_DEEPSLEEP) { mode = EOS_PWR_SMODE_DEEP; - sleep1 = 1; - } else { - sleep1 = 0; + sys_sleep = 1; + sleep_rdy = EOS_PWR_DEV_ALL; + power_sleep_rdy(sleep_rdy); } - sleep2 = 0; - modem_wake_en = 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_SET_MODE: { + mode = evt.param; + if (sleep_rdy == EOS_PWR_DEV_ALL) { + eos_power_sleep_rdy(0); } break; } - case POWER_ETYPE_SLEEP2: { - if (sleep2) { - mode = EOS_PWR_SMODE_DEEP; - power_sleep_stage2(modem_wake_en, mode); - sleep2 = 0; - } + case PWR_ETYPE_SLEEP_REQ: { + evt.param &= ~sleep_req; + evt.param &= ~sleep_rdy; + + power_sleep_req(evt.param); + + sleep_req |= evt.param; break; } - case POWER_ETYPE_WAKE: { - if (sleep1) { - source = evt.source; - power_wake_stage1(source, mode); - if (sleep2) { - esp_timer_stop(timer); - sleep2 = 0; - } + case PWR_ETYPE_SLEEP_RDY: { + evt.param &= sleep_req; + evt.param &= ~sleep_rdy; + + power_sleep_rdy(evt.param); + + sleep_req &= ~evt.param; + sleep_rdy |= evt.param; + if (!sys_sleep && mode && (sleep_rdy == EOS_PWR_DEV_ALL)) { + sys_sleep = 1; + eos_power_sys_sleep(mode); } break; } - case POWER_ETYPE_NETRDY: { - power_wake_stage2(source, mode); - sleep1 = 0; - source = 0; - break; - } + case PWR_ETYPE_WAKE: { + evt.param &= ~sleep_req; + evt.param &= sleep_rdy; - case POWER_ETYPE_BTN: { - unsigned char *buf; + if (sys_sleep) { + eos_power_sys_wake(mode); + sys_sleep = 0; + mode = 0; + } - buf = eos_net_alloc(); - buf[0] = EOS_PWR_MTYPE_BUTTON; - buf[1] = evt.level; - eos_net_send(EOS_NET_MTYPE_POWER, buf, 2); - break; - } + power_wake(evt.param); - default: + sleep_rdy &= ~evt.param; break; + } } } } @@ -276,35 +191,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 +215,132 @@ 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); } - 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); + + if (esp_reset_reason() == ESP_RST_DEEPSLEEP) { + eos_power_wake(eos_power_wakeup_source()); + } -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) { + eos_net_deep_sleep(); + eos_app_deep_sleep(); + eos_modem_deep_sleep(); + + 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_set_mode(uint8_t mode) { power_event_t evt; - evt.type = POWER_ETYPE_SLEEP1; - evt.source = 0; + evt.type = PWR_ETYPE_SET_MODE; + evt.param = mode; xQueueSend(power_queue, &evt, portMAX_DELAY); } -void eos_power_wake(uint8_t source) { +void eos_power_sleep_req(uint32_t dev) { power_event_t evt; - evt.type = POWER_ETYPE_WAKE; - evt.source = source; - + evt.type = PWR_ETYPE_SLEEP_REQ; + evt.param = dev; xQueueSend(power_queue, &evt, portMAX_DELAY); } -void eos_power_net_ready(void) { +void eos_power_sleep_rdy(uint32_t dev) { power_event_t evt; - evt.type = POWER_ETYPE_NETRDY; - evt.source = 0; + evt.type = PWR_ETYPE_SLEEP_RDY; + evt.param = dev; + xQueueSend(power_queue, &evt, portMAX_DELAY); +} + +void eos_power_wake(uint32_t dev) { + power_event_t evt; + ESP_LOGI(TAG, "WAKE SENT"); + evt.type = PWR_ETYPE_WAKE; + evt.param = 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..6f53a0b 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> @@ -7,25 +7,24 @@ static const char *TAG = "EOS RNG"; -static void rng_handler(unsigned char _mtype, unsigned char *buffer, uint16_t buf_len) { +static void rng_handler(unsigned char _mtype, EOSMessage *msg, uint16_t len) { + unsigned char *buffer = msg->buffer; uint16_t rng_len = 0; - if (buf_len < sizeof(uint16_t)) goto rng_handler_fin; + if (!(eos_msg_flags(msg) & EOS_MSG_FLAG_RPLY_REQ)) return; + if (len < sizeof(uint16_t)) return; rng_len = (uint16_t)buffer[0] << 8; rng_len |= (uint16_t)buffer[1]; - if (rng_len > EOS_NET_SIZE_BUF) { - rng_len = 0; - goto rng_handler_fin; - } - esp_fill_random(buffer, rng_len); + if (rng_len > msg->size) return; -rng_handler_fin: - eos_net_reply(EOS_NET_MTYPE_RNG, buffer, rng_len); + esp_fill_random(buffer, rng_len); + eos_net_reply(EOS_NET_MTYPE_RNG, msg, rng_len); } 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..dcad8b2 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,105 +84,316 @@ static ssize_t t_recvfrom(int sock, void *msg, size_t msg_size, EOSNetAddr *addr return recvlen; } -static void udp_rcvr_task(void *pvParameters) { - uint8_t sock_i = (uint8_t)pvParameters; - int sock = _socks[sock_i-1]; +static void populate_fds(fd_set *fds, int *max_fd) { + int i; - 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; + *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]; + } } - _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); + } +} + +static void cmd_xchg(uint8_t *cmd) { + int rv; xSemaphoreTake(mutex, portMAX_DELAY); - _socks[sock_i-1] = 0; + + rv = write(cmd_fd, cmd, sizeof(uint64_t)); + assert(rv == sizeof(uint64_t)); + + do { + rv = read(rep_fd, cmd, sizeof(uint64_t)); + assert(rv == sizeof(uint64_t)); + } while (cmd[0] == 0); + xSemaphoreGive(mutex); +} + +static void udp_rcvr_task(void *pvParameters) { + EOSNetAddr addr; + EOSMessage msg; + unsigned char *buffer; + uint16_t 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; + + 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; + } + + for (i=0; i<EOS_SOCK_MAX_SOCK; i++) { + sock = _socks[i]; + if (sock && FD_ISSET(sock, &read_fds)) { + eos_net_alloc(&msg); + if (msg.size < EOS_SOCK_SIZE_UDP_HDR) { + eos_net_free(&msg); + continue; + } + _rv = t_recvfrom(sock, msg.buffer + EOS_SOCK_SIZE_UDP_HDR, msg.size - EOS_SOCK_SIZE_UDP_HDR, &addr); + if (_rv < 0) { + eos_net_free(&msg); + ESP_LOGE(TAG, "RECV ERR:%d", _rv); + continue; + } + buffer = msg.buffer; + buffer[0] = EOS_SOCK_MTYPE_PKT; + buffer[1] = i + 1; + buffer += 2; + memcpy(buffer, addr.host, sizeof(addr.host)); + buffer += sizeof(addr.host); + buffer[0] = addr.port >> 8; + buffer[1] = addr.port; + buffer += sizeof(addr.port); + rv = eos_net_send(EOS_NET_MTYPE_SOCK, &msg, _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); + } + } + 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; + sock = _socks[sock_i]; + if (sock) { + len = (uint16_t)cmd[2] << 8; + len |= (uint16_t)cmd[3]; + memcpy(&buffer, cmd + 4, sizeof(buffer)); + + memcpy(addr.host, buffer, sizeof(addr.host)); + buffer += sizeof(addr.host); + len -= sizeof(addr.host); + addr.port = (uint16_t)buffer[0] << 8; + addr.port |= (uint16_t)buffer[1]; + buffer += sizeof(addr.port); + len -= sizeof(addr.port); + _rv = t_sendto(sock, buffer, len, &addr); + } + + rv = write(rep_fd, cmd, sizeof(cmd)); + assert(rv == sizeof(cmd)); + + break; + } + + case CMD_REOPEN: { + for (i=0; i<EOS_SOCK_MAX_SOCK; i++) { + sock = _socks[i]; + if (sock) { + t_close(sock); + _socks[i] = -1; + } + } + + len = 0; + eos_msg_init(&msg, NULL, 0); + 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 (msg.buffer) { + if (msg.size == len) break; + msg.buffer[len] = i + 1; + len++; + } else { + eos_net_alloc(&msg); + if (msg.size < 2) break; + msg.buffer[0] = EOS_SOCK_MTYPE_CLOSE; + msg.buffer[1] = i + 1; + len = 2; + } + } + } + } + if (msg.buffer) { + rv = eos_net_send(EOS_NET_MTYPE_SOCK, &msg, 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) { +static void sock_handler(unsigned char _mtype, EOSMessage *msg, uint16_t len) { unsigned char mtype; + unsigned char *buffer = msg->buffer; uint8_t sock_i; - int sock, i; + uint8_t cmd[8]; + + if (len < 1) return; - 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; + uint16_t _len = len; + + if (len < EOS_SOCK_SIZE_UDP_HDR) break; + + sock_i = buffer[1]; + if ((sock_i == 0) || (sock_i > EOS_SOCK_MAX_SOCK)) break; - if (buf_len < EOS_SOCK_SIZE_UDP_HDR) return; + _buf += 2; + _len -= 2; + cmd[0] = CMD_SEND; + cmd[1] = sock_i; + cmd[2] = _len >> 8; + cmd[3] = _len; + memcpy(cmd + 4, &_buf, sizeof(_buf)); - sock_i = buffer[1]-1; - if (sock_i >= EOS_SOCK_MAX_SOCK) return; + cmd_xchg(cmd); - 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); + 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); + if (!(eos_msg_flags(msg) & EOS_MSG_FLAG_RPLY_REQ)) break; + if (msg->size < 2) break; + + cmd[0] = CMD_OPEN; + + cmd_xchg(cmd); + + 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); + + eos_net_reply(EOS_NET_MTYPE_SOCK, msg, 2); break; } case EOS_SOCK_MTYPE_CLOSE: { - if (buf_len < 2) return; + if (len < 2) break; + + sock_i = buffer[1]; + if ((sock_i == 0) || (sock_i > EOS_SOCK_MAX_SOCK)) break; + + cmd[0] = CMD_CLOSE; + cmd[1] = sock_i; - sock_i = buffer[1]-1; - if (sock_i >= EOS_SOCK_MAX_SOCK) return; + cmd_xchg(cmd); - sock = _socks[sock_i]; - t_close(sock); + 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]; + + cmd[0] = CMD_REOPEN; + + cmd_xchg(cmd); + + assert(cmd[0] == CMD_REOPEN); +} diff --git a/fw/esp32/components/eos/tun.c b/fw/esp32/components/eos/tun.c index a7181ee..cb1dde6 100644 --- a/fw/esp32/components/eos/tun.c +++ b/fw/esp32/components/eos/tun.c @@ -4,39 +4,49 @@ #include <lwip/pbuf.h> #include <lwip/netif.h> #include <lwip/tcpip.h> -#include <lwip/etharp.h> +#include <lwip/ip.h> +#include <lwip/lwip_napt.h> +#include <esp_log.h> + +#include "net.h" #include "app.h" #include "tun.h" +static const char *TAG = "EOS TUN"; + 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) { - unsigned char *buf; +static err_t IRAM_ATTR tun_output(struct netif *netif, struct pbuf *p, const struct ip4_addr *ipaddr) { + EOSMessage msg; struct pbuf *q; for (q = p; q != NULL; q = q->next) { - if (q->len > EOS_APP_MTU) continue; + eos_app_alloc(&msg); + if (q->len > msg.size) { + eos_app_free(&msg); + continue; + } - buf = eos_app_alloc(); - memcpy(buf, q->payload, q->len); - eos_app_send(EOS_APP_MTYPE_TUN, buf, q->len); + memcpy(msg.buffer, q->payload, q->len); + eos_app_send(EOS_APP_MTYPE_TUN, &msg, q->len); } 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, EOSMessage *msg, uint16_t len) { struct netif *netif = &netif_tun; struct pbuf *p; int rv; if (!netif_is_up(netif)) return; - p = pbuf_alloc(PBUF_RAW, len, PBUF_RAM); + p = pbuf_alloc(PBUF_LINK, len, PBUF_RAM); if (p == NULL) return; - memcpy(p->payload, buffer, len); + + memcpy(p->payload, msg->buffer, len); rv = netif->input(p, netif); if (rv != ERR_OK) { pbuf_free(p); @@ -54,12 +64,31 @@ static err_t tun_init(struct netif *netif) { return ERR_OK; } +void eos_tun_portmap_add(uint32_t ext_addr) { + ip4_addr_t app_addr; + + IP4_ADDR(&app_addr, 192,168,152,1); + ip_portmap_add(IP_PROTO_TCP, ext_addr, 22, app_addr.addr, 22); +} + +void eos_tun_portmap_remove(void) { + ip_portmap_remove(IP_PROTO_TCP, 22); +} + void eos_tun_init(void) { + struct netif *rv; + IP4_ADDR(&gw, 0,0,0,0); - IP4_ADDR(&ipaddr, 192,168,10,2); + IP4_ADDR(&ipaddr, 192,168,152,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); + ip_napt_enable_netif(&netif_tun, 1); eos_app_set_handler(EOS_APP_MTYPE_TUN, tun_input); -}
\ No newline at end of file + + ESP_LOGI(TAG, "INIT"); + ESP_LOGI(TAG, "addres: %x", (unsigned int)ipaddr.addr); +} diff --git a/fw/esp32/components/eos/wifi.c b/fw/esp32/components/eos/wifi.c index 2be169f..fe1b382 100755 --- a/fw/esp32/components/eos/wifi.c +++ b/fw/esp32/components/eos/wifi.c @@ -10,10 +10,10 @@ #include <esp_log.h> #include <esp_err.h> #include <esp_wifi.h> -#include <nvs_flash.h> #include "eos.h" #include "net.h" +#include "tun.h" #include "wifi.h" // XXX: WiFi fail due to no DHCP server @@ -53,9 +53,8 @@ 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(); + eos_tun_portmap_remove(); break; } if ((reconnect_cnt == 0) && (sta_disconnected->reason == WIFI_REASON_BEACON_TIMEOUT)) { @@ -67,6 +66,7 @@ static void wifi_event_handler(void *arg, esp_event_base_t event_base, int32_t e reconnect_cnt++; } else { eos_wifi_send_status(); + eos_tun_portmap_remove(); reconnect_cnt = 0; if (stop) { @@ -87,13 +87,17 @@ static void wifi_event_handler(void *arg, esp_event_base_t event_base, int32_t e got_ip = (ip_event_got_ip_t *)event_data; ESP_LOGI(TAG, "Event got IP - addres: " IPSTR, IP2STR(&got_ip->ip_info.ip)); + ESP_LOGI(TAG, "Event got IP - addres: %x", (unsigned int)got_ip->ip_info.ip.addr); eos_wifi_send_status(); + eos_tun_portmap_remove(); + eos_tun_portmap_add(got_ip->ip_info.ip.addr); /* if (got_ip->ip_changed) { recreate all sockets } */ + break; } @@ -104,35 +108,25 @@ static void wifi_event_handler(void *arg, esp_event_base_t event_base, int32_t e } -static void wifi_handler(unsigned char _mtype, unsigned char *buffer, uint16_t buf_len) { +static void wifi_handler(unsigned char _mtype, EOSMessage *msg, uint16_t len) { + unsigned char *buffer = msg->buffer; + uint16_t buf_size = msg->size; esp_err_t ret = ESP_OK; - uint8_t mtype; + unsigned char mtype; - if (buf_len < 1) return; + if (len < 1) return; mtype = buffer[0]; switch (mtype) { case EOS_WIFI_MTYPE_STATUS: { - int reply; ssize_t rv; - reply = _mtype & EOS_NET_MTYPE_FLAG_REPL; - - if (reply) { - rv = eos_wifi_get_status(buffer + 1); - if (rv < 0) break; - - eos_net_reply(EOS_NET_MTYPE_WIFI, buffer, rv + 1); - } else { - unsigned char *buf; + if (!(eos_msg_flags(msg) & EOS_MSG_FLAG_RPLY_REQ)) break; - buf = eos_net_alloc(); - buf[0] = EOS_WIFI_MTYPE_STATUS; - rv = eos_wifi_get_status(buf + 1); - if (rv < 0) break; + rv = eos_wifi_get_status(buffer + 1, buf_size - 1); + if (rv < 0) break; - eos_net_send(EOS_NET_MTYPE_WIFI, buf, rv + 1); - } + eos_net_reply(EOS_NET_MTYPE_WIFI, msg, rv + 1); break; } @@ -202,20 +196,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,14 +214,30 @@ void eos_wifi_init(void) { assert(ret == ESP_OK); eos_net_set_handler(EOS_NET_MTYPE_WIFI, wifi_handler); + ESP_LOGI(TAG, "INIT"); } -ssize_t eos_wifi_get_status(unsigned char *buffer) { +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, size_t size) { unsigned char *p; wifi_ap_record_t ap_info; esp_err_t ret; + /* 1 + sizeof(uint32_t) + sizeof(ap_info.ssid) - 1 */ + if (size < sizeof(uint32_t) + sizeof(ap_info.ssid)) return EOS_ERR_SIZE; + p = buffer; ret = esp_wifi_sta_get_ap_info(&ap_info); switch (ret) { @@ -292,27 +296,34 @@ ssize_t eos_wifi_get_status(unsigned char *buffer) { } void eos_wifi_send_status(void) { - unsigned char *rbuf; - ssize_t rv; - - rbuf = eos_net_alloc(); - rbuf[0] = EOS_WIFI_MTYPE_STATUS; - rv = eos_wifi_get_status(rbuf + 1); - if (rv < 0) { - eos_net_free(rbuf); + EOSMessage msg; + ssize_t _rv; + int rv; + + eos_net_alloc(&msg); + if (msg.size < 1) { + eos_net_free(&msg); + return; + } + msg.buffer[0] = EOS_WIFI_MTYPE_STATUS; + _rv = eos_wifi_get_status(msg.buffer + 1, msg.size - 1); + if (_rv < 0) { + eos_net_free(&msg); return; } - eos_net_send(EOS_NET_MTYPE_WIFI, rbuf, rv + 1); + rv = eos_net_send(EOS_NET_MTYPE_WIFI, &msg, _rv + 1); + if (rv) ESP_LOGE(TAG, "NET SEND ERR:%d", rv); } void eos_wifi_send_scan(void) { + EOSMessage msg; 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 *p; + int i, rv; scan_n = EOS_WIFI_MAX_SCAN_RECORDS; memset(scan_r, 0, sizeof(scan_r)); @@ -324,17 +335,23 @@ void eos_wifi_send_scan(void) { ESP_LOGI(TAG, "Scan done: %d", scan_n); - rbuf = eos_net_alloc(); - rbuf[0] = EOS_WIFI_MTYPE_SCAN; - p = rbuf + 1; + eos_net_alloc(&msg); + if (msg.size < 1) { + eos_net_free(&msg); + return; + } + msg.buffer[0] = EOS_WIFI_MTYPE_SCAN; + p = msg.buffer + 1; for (i=0; i<scan_n; i++) { len = strnlen((char *)scan_r[i].ssid, sizeof(scan_r[i].ssid)); if (len == sizeof(scan_r[i].ssid)) continue; - if (p - rbuf + len + 1 > EOS_NET_SIZE_BUF) break; + if (p - msg.buffer + len + 1 > msg.size) break; 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, &msg, p - msg.buffer); + if (rv) ESP_LOGE(TAG, "NET SEND ERR:%d", rv); } |
