/** * @brief Send data and wait for prompt from DCE * * @param dte Modem DTE object * @param data data buffer * @param length length of data to send * @param prompt pointer of specific prompt * @param timeout timeout value (unit: ms) * @return esp_err_t * ESP_OK on success * ESP_FAIL on error */ static esp_err_t esp_modem_dte_send_wait(modem_dte_t *dte, const char *data, uint32_t length, const char *prompt, uint32_t timeout) { MODEM_CHECK(data, "data is NULL", err_param); MODEM_CHECK(prompt, "prompt is NULL", err_param); esp_modem_dte_t *esp_dte = __containerof(dte, esp_modem_dte_t, parent); // We'd better disable pattern detection here for a moment in case prompt string contains the pattern character uart_disable_pattern_det_intr(esp_dte->uart_port); // uart_disable_rx_intr(esp_dte->uart_port); MODEM_CHECK(uart_write_bytes(esp_dte->uart_port, data, length) >= 0, "uart write bytes failed", err_write); uint32_t len = strlen(prompt); uint8_t *buffer = calloc(len + 1, sizeof(uint8_t)); int res = uart_read_bytes(esp_dte->uart_port, buffer, len, pdMS_TO_TICKS(timeout)); MODEM_CHECK(res >= len, "wait prompt [%s] timeout", err, prompt); MODEM_CHECK(!strncmp(prompt, (const char *)buffer, len), "get wrong prompt: %s", err, buffer); free(buffer); uart_enable_pattern_det_intr(esp_dte->uart_port, '\n', 1, MIN_PATTERN_INTERVAL, MIN_POST_IDLE, MIN_PRE_IDLE); return ESP_OK; err: free(buffer); err_write: uart_enable_pattern_det_intr(esp_dte->uart_port, '\n', 1, MIN_PATTERN_INTERVAL, MIN_POST_IDLE, MIN_PRE_IDLE); err_param: return ESP_FAIL; }
/** * @brief Change Modem's working mode * * @param dte Modem DTE object * @param new_mode new working mode * @return esp_err_t * - ESP_OK on success * - ESP_FAIL on error */ static esp_err_t esp_modem_dte_change_mode(modem_dte_t *dte, modem_mode_t new_mode) { modem_dce_t *dce = dte->dce; MODEM_CHECK(dce, "DTE has not yet bind with DCE", err); esp_modem_dte_t *esp_dte = __containerof(dte, esp_modem_dte_t, parent); MODEM_CHECK(dce->mode != new_mode, "already in mode: %d", err, new_mode); switch (new_mode) { case MODEM_PPP_MODE: MODEM_CHECK(dce->set_working_mode(dce, new_mode) == ESP_OK, "set new working mode:%d failed", err, new_mode); uart_disable_pattern_det_intr(esp_dte->uart_port); uart_enable_rx_intr(esp_dte->uart_port); break; case MODEM_COMMAND_MODE: uart_disable_rx_intr(esp_dte->uart_port); uart_flush(esp_dte->uart_port); uart_enable_pattern_det_intr(esp_dte->uart_port, '\n', 1, MIN_PATTERN_INTERVAL, MIN_POST_IDLE, MIN_PRE_IDLE); uart_pattern_queue_reset(esp_dte->uart_port, CONFIG_UART_PATTERN_QUEUE_SIZE); MODEM_CHECK(dce->set_working_mode(dce, new_mode) == ESP_OK, "set new working mode:%d failed", err, new_mode); break; default: break; } return ESP_OK; err: return ESP_FAIL; }
static void uart_evt_task(void *pvParameters) { int uart_num = UART_NUM_0; uart_config_t uart_config = { .baud_rate = 115200, .data_bits = UART_DATA_8_BITS, .parity = UART_PARITY_DISABLE, .stop_bits = UART_STOP_BITS_1, .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, .rx_flow_ctrl_thresh = 122, }; //Set UART parameters uart_param_config(uart_num, &uart_config); //Set UART log level esp_log_level_set(TAG, ESP_LOG_INFO); //Install UART driver, and get the queue. uart_driver_install(uart_num, BUF_SIZE * 2, BUF_SIZE * 2, 10, &uart0_queue, 0); //Set UART pins,(-1: default pin, no change.) //For UART0, we can just use the default pins. //uart_set_pin(uart_num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); //Set uart pattern detect function. uart_enable_pattern_det_intr(uart_num, '+', 3, 10000, 10, 10); //Create a task to handler UART event from ISR xTaskCreate(uart_task, "uart_task", UART_TASK_STACK_SIZE, NULL, UART_TASK_PRIO, NULL); //process data uint8_t* data = (uint8_t*) malloc(BUF_SIZE); do { int len = uart_read_bytes(uart_num, data, BUF_SIZE, 100 / portTICK_RATE_MS); if(len > 0) { //ESP_LOGI(TAG, "uart read : %d", len); //uart_write_bytes(uart_num, (const char*)data, len); uart_input_handler((const char*)data, len); } } while(1); } void uart_init(void) { memset(&rcvMsg, 0, sizeof(rcvMsg)); rcvMsg.RcvBuffSize = RECV_BUF_SIZE; rcvMsg.pRcvMsgBuff = NULL; rcvMsg.pRcvMsgBuff = (uint8_t *) malloc(RECV_BUF_SIZE); if (rcvMsg.pRcvMsgBuff == NULL) { ESP_LOGE(TAG, "receive buffer alloc failed"); return; } rcvMsg.pReadPos = rcvMsg.pRcvMsgBuff; rcvMsg.pWritePos = rcvMsg.pRcvMsgBuff; xTaskCreate(uart_evt_task, "uart_evt_task", UART_EVT_TASK_STACK_SIZE, NULL, UART_EVT_TASK_PRIO, NULL); }
modem_dte_t *esp_modem_dte_init(const esp_modem_dte_config_t *config) { esp_err_t res; /* malloc memory for esp_dte object */ esp_modem_dte_t *esp_dte = calloc(1, sizeof(esp_modem_dte_t)); MODEM_CHECK(esp_dte, "calloc esp_dte failed", err_dte_mem); /* malloc memory to storing lines from modem dce */ esp_dte->buffer = calloc(1, ESP_MODEM_LINE_BUFFER_SIZE); MODEM_CHECK(esp_dte->buffer, "calloc line memory failed", err_line_mem); /* Set attributes */ esp_dte->uart_port = config->port_num; esp_dte->parent.flow_ctrl = config->flow_control; /* Bind methods */ esp_dte->parent.send_cmd = esp_modem_dte_send_cmd; esp_dte->parent.send_data = esp_modem_dte_send_data; esp_dte->parent.send_wait = esp_modem_dte_send_wait; esp_dte->parent.change_mode = esp_modem_dte_change_mode; esp_dte->parent.process_cmd_done = esp_modem_dte_process_cmd_done; esp_dte->parent.deinit = esp_modem_dte_deinit; /* Config UART */ uart_config_t uart_config = { .baud_rate = config->baud_rate, .data_bits = config->data_bits, .parity = config->parity, .stop_bits = config->stop_bits, .flow_ctrl = (config->flow_control == MODEM_FLOW_CONTROL_HW) ? UART_HW_FLOWCTRL_CTS_RTS : UART_HW_FLOWCTRL_DISABLE }; MODEM_CHECK(uart_param_config(esp_dte->uart_port, &uart_config) == ESP_OK, "config uart parameter failed", err_uart_config); if (config->flow_control == MODEM_FLOW_CONTROL_HW) { res = uart_set_pin(esp_dte->uart_port, CONFIG_MODEM_TX_PIN, CONFIG_MODEM_RX_PIN, CONFIG_MODEM_RTS_PIN, CONFIG_MODEM_CTS_PIN); } else { res = uart_set_pin(esp_dte->uart_port, CONFIG_MODEM_TX_PIN, CONFIG_MODEM_RX_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); } MODEM_CHECK(res == ESP_OK, "config uart gpio failed", err_uart_config); /* Set flow control threshold */ if (config->flow_control == MODEM_FLOW_CONTROL_HW) { res = uart_set_hw_flow_ctrl(esp_dte->uart_port, UART_HW_FLOWCTRL_CTS_RTS, UART_FIFO_LEN - 8); } else if (config->flow_control == MODEM_FLOW_CONTROL_SW) { res = uart_set_sw_flow_ctrl(esp_dte->uart_port, true, 8, UART_FIFO_LEN - 8); } MODEM_CHECK(res == ESP_OK, "config uart flow control failed", err_uart_config); /* Install UART driver and get event queue used inside driver */ res = uart_driver_install(esp_dte->uart_port, CONFIG_UART_RX_BUFFER_SIZE, CONFIG_UART_TX_BUFFER_SIZE, CONFIG_UART_EVENT_QUEUE_SIZE, &(esp_dte->event_queue), 0); MODEM_CHECK(res == ESP_OK, "install uart driver failed", err_uart_config); /* Set pattern interrupt, used to detect the end of a line. */ res = uart_enable_pattern_det_intr(esp_dte->uart_port, '\n', 1, MIN_PATTERN_INTERVAL, MIN_POST_IDLE, MIN_PRE_IDLE); /* Set pattern queue size */ res |= uart_pattern_queue_reset(esp_dte->uart_port, CONFIG_UART_PATTERN_QUEUE_SIZE); MODEM_CHECK(res == ESP_OK, "config uart pattern failed", err_uart_pattern); /* Create Event loop */ esp_event_loop_args_t loop_args = { .queue_size = ESP_MODEM_EVENT_QUEUE_SIZE, .task_name = NULL }; MODEM_CHECK(esp_event_loop_create(&loop_args, &esp_dte->event_loop_hdl) == ESP_OK, "create event loop failed", err_eloop); /* Create semaphore */ esp_dte->process_sem = xSemaphoreCreateBinary(); MODEM_CHECK(esp_dte->process_sem, "create process semaphore failed", err_sem); /* Create UART Event task */ BaseType_t ret = xTaskCreate(uart_event_task_entry, //Task Entry "uart_event", //Task Name CONFIG_UART_EVENT_TASK_STACK_SIZE, //Task Stack Size(Bytes) esp_dte, //Task Parameter CONFIG_UART_EVENT_TASK_PRIORITY, //Task Priority & (esp_dte->uart_event_task_hdl) //Task Handler ); MODEM_CHECK(ret == pdTRUE, "create uart event task failed", err_tsk_create); return &(esp_dte->parent); /* Error handling */ err_tsk_create: vSemaphoreDelete(esp_dte->process_sem); err_sem: esp_event_loop_delete(esp_dte->event_loop_hdl); err_eloop: uart_disable_pattern_det_intr(esp_dte->uart_port); err_uart_pattern: uart_driver_delete(esp_dte->uart_port); err_uart_config: free(esp_dte->buffer); err_line_mem: free(esp_dte); err_dte_mem: return NULL; } esp_err_t esp_modem_add_event_handler(modem_dte_t *dte, esp_event_handler_t handler, void *handler_args) { esp_modem_dte_t *esp_dte = __containerof(dte, esp_modem_dte_t, parent); return esp_event_handler_register_with(esp_dte->event_loop_hdl, ESP_MODEM_EVENT, ESP_EVENT_ANY_ID, handler, handler_args); }