From 6a4b3ef0e72ee134b81a523ce41fd4c45f3b4429 Mon Sep 17 00:00:00 2001 From: Uros Majstorovic Date: Sun, 4 Sep 2022 18:43:50 +0200 Subject: fixed wifi and cell --- fw/esp32/components/eos/cell_modem.c | 546 ++++++++++++++++++++++------------- 1 file changed, 347 insertions(+), 199 deletions(-) (limited to 'fw/esp32/components/eos/cell_modem.c') diff --git a/fw/esp32/components/eos/cell_modem.c b/fw/esp32/components/eos/cell_modem.c index 09d65d9..029abe1 100644 --- a/fw/esp32/components/eos/cell_modem.c +++ b/fw/esp32/components/eos/cell_modem.c @@ -29,8 +29,9 @@ #define UART_GPIO_DTR 32 #define UART_GPIO_RI 35 -#define MODEM_ETYPE_INIT 1 -#define MODEM_ETYPE_RI 2 +#define MODEM_ETYPE_ATINIT 1 +#define MODEM_ETYPE_STATUS 2 +#define MODEM_ETYPE_RING 3 #define AT_CMD_INIT_SIZE 5 @@ -47,7 +48,6 @@ static char *at_cmd_init[AT_CMD_INIT_SIZE] = { "AT+CPMS=\"ME\",\"ME\",\"ME\"\r" }; -static char modem_initialized = 0; static SemaphoreHandle_t mutex; static QueueHandle_t modem_queue; @@ -58,16 +58,19 @@ static char uart_buf[EOS_CELL_UART_SIZE_BUF]; static size_t uart_buf_len; static char uart_buf_dirty = 0; -static uint8_t uart_mode = EOS_CELL_UART_MODE_ATCMD; -static uint8_t _uart_mode = EOS_CELL_UART_MODE_UNDEF; +static uint8_t RTC_NOINIT_ATTR modem_initialized; +static uint8_t RTC_NOINIT_ATTR uart_mode; +static uint8_t uart_mode_next = EOS_CELL_UART_MODE_NONE; static SemaphoreHandle_t uart_mutex; -static char ppp_apn[64]; -static char ppp_user[64]; -static char ppp_pass[64]; +static char ppp_apn[EOS_CELL_PDP_SIZE_APN]; +static char ppp_usr[EOS_CELL_PDP_SIZE_USR]; +static char ppp_pwd[EOS_CELL_PDP_SIZE_PWD]; static SemaphoreHandle_t ppp_mutex; static ppp_pcb *ppp_handle; +static int ppp_connected; +static ip_addr_t ppp_ipaddr; static struct netif ppp_netif; typedef enum { @@ -76,22 +79,57 @@ typedef enum { typedef struct { uint8_t type; + unsigned char param[2]; + size_t param_len; } modem_event_t; -static void modem_atcmd_read(size_t bsize); +static void modem_send_status(void); + +static void atcmd_read(size_t bsize) { + char *ln_end; + int rd = 0; + + do { + 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); + + rd += _rd; + uart_buf_len += _rd; + uart_buf[uart_buf_len] = '\0'; + while ((ln_end = strchr(uart_curr, '\n'))) { + char *_ln_end = ln_end; + + while ((_ln_end > uart_buf) && (*(_ln_end - 1) == '\r')) _ln_end--; + memcpy(urc_buf, uart_buf, _ln_end - uart_buf); + urc_buf[_ln_end - uart_buf] = '\0'; + + uart_buf_len -= ln_end - uart_buf + 1; + if (uart_buf_len) memmove(uart_buf, ln_end + 1, uart_buf_len); + if (!uart_buf_dirty) at_urc_process(urc_buf); + + uart_curr = uart_buf; + uart_buf[uart_buf_len] = '\0'; + uart_buf_dirty = 0; + } + if (uart_buf_len == sizeof(uart_buf) - 1) { + uart_buf_len = 0; + uart_buf_dirty = 1; + } + } while (rd != bsize); +} static void uart_data_read(uint8_t mode) { - unsigned char *buf; int rd; size_t bsize; uart_get_buffered_data_len(UART_NUM_2, &bsize); switch (mode) { - case EOS_CELL_UART_MODE_ATCMD: - modem_atcmd_read(bsize); + case EOS_CELL_UART_MODE_ATCMD: { + atcmd_read(bsize); break; + } - case EOS_CELL_UART_MODE_PPP: + case EOS_CELL_UART_MODE_PPP: { rd = 0; do { @@ -100,8 +138,10 @@ static void uart_data_read(uint8_t mode) { rd += _rd; } while (rd != bsize); break; + } - case EOS_CELL_UART_MODE_RELAY: + case EOS_CELL_UART_MODE_RELAY: { + unsigned char *buf; rd = 0; do { @@ -114,25 +154,45 @@ static void uart_data_read(uint8_t mode) { rd += _rd; } while (rd != bsize); break; - - default: - break; - + } } } static void uart_event_task(void *pvParameters) { - char mode = EOS_CELL_UART_MODE_ATCMD; - char _mode = EOS_CELL_UART_MODE_ATCMD; + char mode; + char _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) { + _mode = EOS_CELL_UART_MODE_NONE; + ESP_LOGE(TAG, "Modem init failed"); + } + } + } + + if (_mode == EOS_CELL_UART_MODE_NONE) xSemaphoreGive(uart_mutex); + mode = _mode; + xSemaphoreGive(mutex); + while (1) { /* Waiting for UART event. */ if (xQueueReceive(uart_queue, &event, portMAX_DELAY)) { switch (event.type) { - case UART_DATA: + case UART_DATA: { /* Event of UART receiving data */ if (mode != EOS_CELL_UART_MODE_NONE) uart_data_read(mode); @@ -141,8 +201,9 @@ static void uart_event_task(void *pvParameters) { mode = _mode; } break; + } - case UART_EEVT_MODE: + case UART_EEVT_MODE: { /* Mode change */ _mode = (char)event.size; @@ -155,6 +216,7 @@ static void uart_event_task(void *pvParameters) { mode = _mode; } break; + } default: break; @@ -164,14 +226,7 @@ static void uart_event_task(void *pvParameters) { vTaskDelete(NULL); } -static void IRAM_ATTR uart_ri_isr_handler(void *arg) { - modem_event_t evt; - - evt.type = MODEM_ETYPE_RI; - xQueueSendFromISR(modem_queue, &evt, NULL); -} - -static void modem_set_mode(uint8_t mode) { +static void uart_change_mode(uint8_t mode) { uart_event_t evt; evt.type = UART_EEVT_MODE; @@ -179,110 +234,97 @@ static void modem_set_mode(uint8_t mode) { xQueueSend(uart_queue, &evt, portMAX_DELAY); } -static int modem_atcmd_init(void) { - unsigned char *buf; - int echo_on = 0; - int tries = 3; - int i, r; +static void IRAM_ATTR uart_ring_handler(void *arg) { + modem_event_t evt; - xSemaphoreTake(mutex, portMAX_DELAY); - modem_set_mode(EOS_CELL_UART_MODE_NONE); - r = xSemaphoreTake(uart_mutex, 1000); - if (r == pdFALSE) { - modem_set_mode(uart_mode); - xSemaphoreGive(mutex); - return EOS_ERR_TIMEOUT; - } + evt.type = MODEM_ETYPE_RING; + xQueueSendFromISR(modem_queue, &evt, NULL); +} - do { - at_cmd("AT\r"); - r = at_expect("^AT", "^OK", 1000); - if (r >= 0) { - echo_on = r; - if (echo_on) { - r = at_expect("^OK", NULL, 1000); - } - break; - } - tries--; - } while (tries); +static void modem_init_gpio(void) { + // Configuration for the DTR/RI lines + gpio_config_t io_conf = {}; - if (tries == 0) { - modem_set_mode(uart_mode); - xSemaphoreGive(uart_mutex); - xSemaphoreGive(mutex); + 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); - return EOS_ERR_TIMEOUT; - } + 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); +} - if (echo_on) { - at_cmd("AT&F\r"); - r = at_expect("^AT&F", NULL, 1000); - r = at_expect("^OK", NULL, 1000); - } else { - at_cmd("AT&F\r"); - r = at_expect("^OK", NULL, 1000); - } - at_cmd("ATE0\r"); - r = at_expect("^ATE0", NULL, 1000); - r = at_expect("^OK", "^ERROR", 1000); +static size_t modem_get_status(unsigned char *buffer) { + size_t len; - for (i=0; i uart_buf) && (*(_ln_end - 1) == '\r')) _ln_end--; - memcpy(urc_buf, uart_buf, _ln_end - uart_buf); - urc_buf[_ln_end - uart_buf] = '\0'; + evt.type = MODEM_ETYPE_ATINIT; + xQueueSend(modem_queue, &evt, portMAX_DELAY); +} - uart_buf_len -= ln_end - uart_buf + 1; - if (uart_buf_len) memmove(uart_buf, ln_end + 1, uart_buf_len); - if (!uart_buf_dirty) at_urc_process(urc_buf); +static int modem_atinit(void) { + int r; - uart_curr = uart_buf; - uart_buf[uart_buf_len] = '\0'; - uart_buf_dirty = 0; - } - if (uart_buf_len == sizeof(uart_buf) - 1) { - uart_buf_len = 0; - uart_buf_dirty = 1; - } - } while (rd != bsize); -} + xSemaphoreTake(mutex, portMAX_DELAY); + uart_change_mode(EOS_CELL_UART_MODE_NONE); + r = xSemaphoreTake(uart_mutex, 1000); + if (r == pdFALSE) { + uart_change_mode(uart_mode); + xSemaphoreGive(mutex); + return EOS_ERR_TIMEOUT; + } -static void modem_urc_init_handler(char *urc, regmatch_t m[]) { - modem_event_t evt; + r = eos_modem_atinit(); + uart_change_mode(uart_mode); + xSemaphoreGive(uart_mutex); + xSemaphoreGive(mutex); - evt.type = MODEM_ETYPE_INIT; - xQueueSend(modem_queue, &evt, portMAX_DELAY); + return r; } static void modem_event_task(void *pvParameters) { @@ -291,16 +333,28 @@ static void modem_event_task(void *pvParameters) { while (1) { if (xQueueReceive(modem_queue, &evt, portMAX_DELAY)) { switch (evt.type) { - case MODEM_ETYPE_INIT: - modem_atcmd_init(); + case MODEM_ETYPE_ATINIT: { + int r; + + r = modem_atinit(); + if (r) ESP_LOGE(TAG, "Modem init failed"); break; + } - case MODEM_ETYPE_RI: - ESP_LOGI(TAG, "URC from RI"); + case MODEM_ETYPE_STATUS: { + unsigned char *buf; + + 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); break; + } - default: + case MODEM_ETYPE_RING: { + ESP_LOGI(TAG, "URC from RI"); break; + } } /* Obsolete uint64_t t_start = esp_timer_get_time(); @@ -350,21 +404,23 @@ 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) { - unsigned char *rbuf; struct netif *pppif = ppp_netif(pcb); LWIP_UNUSED_ARG(ctx); - switch(err_code) { + 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)); - rbuf = eos_net_alloc(); - rbuf[0] = EOS_CELL_MTYPE_PDP | EOS_CELL_MTYPE_PDP_CONNECT; - rbuf[1] = EOS_OK; - eos_net_send(EOS_NET_MTYPE_CELL, rbuf, 2); + + xSemaphoreTake(mutex, portMAX_DELAY); + ppp_connected = 1; + ip_addr_copy(ppp_ipaddr, pppif->ip_addr); + modem_send_status(); + xSemaphoreGive(mutex); + return; } case PPPERR_PARAM: { @@ -422,16 +478,20 @@ static void ppp_status_cb(ppp_pcb *pcb, int err_code, void *ctx) { } xSemaphoreTake(mutex, portMAX_DELAY); - - if (_uart_mode == EOS_CELL_UART_MODE_UNDEF) _uart_mode = EOS_CELL_UART_MODE_ATCMD; - uart_mode = _uart_mode; - _uart_mode = EOS_CELL_UART_MODE_UNDEF; - - modem_set_mode(EOS_CELL_UART_MODE_NONE); + 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; - modem_set_mode(uart_mode); + uart_change_mode(uart_mode); xSemaphoreGive(uart_mutex); xSemaphoreGive(mutex); @@ -450,7 +510,7 @@ static int ppp_pause(uint32_t timeout) { uint64_t t_start; uint32_t dt, _dt; - modem_set_mode(EOS_CELL_UART_MODE_NONE); + uart_change_mode(EOS_CELL_UART_MODE_NONE); t_start = esp_timer_get_time(); r = xSemaphoreTake(uart_mutex, timeout ? timeout / portTICK_PERIOD_MS : portMAX_DELAY); @@ -458,14 +518,14 @@ static int ppp_pause(uint32_t timeout) { if (timeout) { dt = ((esp_timer_get_time() - t_start) / 1000); if (dt >= timeout) { - modem_set_mode(EOS_CELL_UART_MODE_PPP); + uart_change_mode(EOS_CELL_UART_MODE_PPP); xSemaphoreGive(uart_mutex); return EOS_ERR_TIMEOUT; } } r = xSemaphoreTake(ppp_mutex, timeout ? (timeout - dt) / portTICK_PERIOD_MS : portMAX_DELAY); if (r == pdFALSE) { - modem_set_mode(EOS_CELL_UART_MODE_PPP); + uart_change_mode(EOS_CELL_UART_MODE_PPP); xSemaphoreGive(uart_mutex); return EOS_ERR_TIMEOUT; } @@ -500,7 +560,7 @@ static int ppp_pause(uint32_t timeout) { uart_buf_len = sizeof(uart_buf) / 2; } if (!done && timeout && (dt >= timeout)) { - modem_set_mode(EOS_CELL_UART_MODE_PPP); + uart_change_mode(EOS_CELL_UART_MODE_PPP); xSemaphoreGive(uart_mutex); xSemaphoreGive(ppp_mutex); return EOS_ERR_TIMEOUT; @@ -516,9 +576,9 @@ static int ppp_resume(void) { at_cmd("ATO\r"); r = at_expect("^CONNECT", "^(ERROR|NO CARRIER)", 1000); - if (r <= 0) rv = EOS_ERR; + if (r) rv = EOS_ERR; - modem_set_mode(EOS_CELL_UART_MODE_PPP); + uart_change_mode(EOS_CELL_UART_MODE_PPP); xSemaphoreGive(uart_mutex); xSemaphoreGive(ppp_mutex); @@ -533,25 +593,25 @@ static int ppp_setup(void) { cmd_len = snprintf(cmd, sizeof(cmd), "AT+CGDCONT=1,\"IP\",\"%s\"\r", ppp_apn); if ((cmd_len < 0) || (cmd_len >= sizeof(cmd))) return EOS_ERR; - modem_set_mode(EOS_CELL_UART_MODE_NONE); + uart_change_mode(EOS_CELL_UART_MODE_NONE); r = xSemaphoreTake(uart_mutex, 1000 / portTICK_PERIOD_MS); if (r == pdFALSE) { - modem_set_mode(uart_mode); + uart_change_mode(uart_mode); return EOS_ERR_TIMEOUT; } at_cmd(cmd); r = at_expect("^OK", "^ERROR", 1000); - if (r <= 0) { - modem_set_mode(uart_mode); + if (r) { + uart_change_mode(uart_mode); xSemaphoreGive(uart_mutex); return EOS_ERR; } at_cmd("AT+CGDATA=\"PPP\",1\r"); r = at_expect("^CONNECT", "^NO CARRIER", 1000); - if (r <= 0) { - modem_set_mode(uart_mode); + if (r) { + uart_change_mode(uart_mode); xSemaphoreGive(uart_mutex); return EOS_ERR; } @@ -559,18 +619,16 @@ static int ppp_setup(void) { ppp_handle = pppapi_pppos_create(&ppp_netif, ppp_output_cb, ppp_status_cb, NULL); ppp_set_usepeerdns(ppp_handle, 1); ppp_set_default(ppp_handle); - ppp_set_auth(ppp_handle, PPPAUTHTYPE_ANY, ppp_user, ppp_pass); + ppp_set_auth(ppp_handle, PPPAUTHTYPE_ANY, ppp_usr, ppp_pwd); ppp_connect(ppp_handle, 0); - modem_set_mode(EOS_CELL_UART_MODE_PPP); + uart_change_mode(EOS_CELL_UART_MODE_PPP); xSemaphoreGive(uart_mutex); return EOS_OK; } void eos_modem_init(void) { - /* Configure parameters of an UART driver, - * communication pins and install the driver */ uart_config_t uart_config = { .baud_rate = 115200, .data_bits = UART_DATA_8_BITS, @@ -582,23 +640,11 @@ void eos_modem_init(void) { 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); - // 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); + if (eos_power_wakeup_cause() == EOS_PWR_WAKE_RST) { + uart_mode = EOS_CELL_UART_MODE_ATCMD; + modem_initialized = 0; + modem_init_gpio(); + } mutex = xSemaphoreCreateBinary(); xSemaphoreGive(mutex); @@ -613,16 +659,59 @@ void eos_modem_init(void) { 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); - gpio_isr_handler_add(UART_GPIO_RI, uart_ri_isr_handler, NULL); - at_init(); - at_urc_insert("^PB DONE", modem_urc_init_handler, REG_EXTENDED); - eos_modem_set_mode(EOS_CELL_UART_MODE_ATCMD); + at_urc_insert("^PB DONE", modem_atinit_handler, REG_EXTENDED); + at_urc_insert("^\\+CME ERROR: SIM not inserted", modem_atinit_handler, REG_EXTENDED); + + ESP_LOGI(TAG, "INIT"); +} + +int eos_modem_atinit(void) { + int echo_on = 0; + int tries = 3; + int i, r; + + do { + at_cmd("AT\r"); + r = at_expect("^AT", "^OK", 1000); + if (r >= 0) { + echo_on = !r; + if (echo_on) { + r = at_expect("^OK", NULL, 1000); + } + break; + } + tries--; + } while (tries); + + if (tries == 0) return EOS_ERR_TIMEOUT; + + if (echo_on) { + at_cmd("AT&F\r"); + r = at_expect("^AT&F", NULL, 1000); + r = at_expect("^OK", NULL, 1000); + } else { + at_cmd("AT&F\r"); + r = at_expect("^OK", NULL, 1000); + } + at_cmd("ATE0\r"); + r = at_expect("^ATE0", NULL, 1000); + r = at_expect("^OK", "^ERROR", 1000); + + for (i=0; i