Compare commits

...

3 Commits

  1. 274
      applications/VK_Client.c
  2. 50
      applications/VK_Com.c
  3. 3
      applications/VK_Com.h
  4. 549
      applications/drv_ec800k.c
  5. 70
      applications/drv_ec800k.h
  6. 2711
      docs/Quectel_LTE_StandardA_AT命令手册.md
  7. 1263
      docs/Quectel_LTE_StandardA系列_TCPIP_应用指导_V1.6.md

274
applications/VK_Client.c

@ -31,6 +31,12 @@
static char cmd_cmd[128] = {0}; static char cmd_cmd[128] = {0};
static uint8_t socket_tx_buffer[LTE_SOCKET_TX_CHUNK_SIZE];
static uint8_t socket_rx_buffer[LTE_SOCKET_RX_CHUNK_SIZE];
static rt_size_t socket_tx_pending = 0;
static rt_tick_t last_ack_query_tick = 0;
static void lte_diag_finish_disconnect(void);
no_carrier_match_t _no_carrier_t = {0}; no_carrier_match_t _no_carrier_t = {0};
@ -39,6 +45,14 @@ void client_tcp_close(Cclient_t *client) {
char close_cmd[24]; char close_cmd[24];
client->connect_sta = false; client->connect_sta = false;
BSP_LTE_SetDataTxPaused(true);
if (lte_diag.disconnect_report_pending) {
BSP_LTE_CollectNetworkSnapshot();
lte_diag_finish_disconnect();
}
BSP_LTE_ClearSocketEvents();
fmu_net_queue_reset();
socket_tx_pending = 0;
rt_snprintf(close_cmd, sizeof(close_cmd), AT_QICLOSE, client->connect_ID); rt_snprintf(close_cmd, sizeof(close_cmd), AT_QICLOSE, client->connect_ID);
BSP_LTE_SendCmd(close_cmd, DEFAULT_EXPECT, DEFAULT_ERROR, BSP_LTE_SendCmd(close_cmd, DEFAULT_EXPECT, DEFAULT_ERROR,
LTE_CMD_WAIT_QICLOSE); LTE_CMD_WAIT_QICLOSE);
@ -149,6 +163,8 @@ static const char *disconnect_reason_name(lte_disconnect_reason_t reason) {
case LTE_DISC_AT_TIMEOUT: return "AT_TIMEOUT"; case LTE_DISC_AT_TIMEOUT: return "AT_TIMEOUT";
case LTE_DISC_QIOPEN_FAILED: return "QIOPEN_FAILED"; case LTE_DISC_QIOPEN_FAILED: return "QIOPEN_FAILED";
case LTE_DISC_MODULE_RESET: return "MODULE_RESET"; case LTE_DISC_MODULE_RESET: return "MODULE_RESET";
case LTE_DISC_SERVER_SILENCE: return "SERVER_SILENCE";
case LTE_DISC_SOCKET_SEND: return "SOCKET_SEND";
default: return "UNKNOWN"; default: return "UNKNOWN";
} }
} }
@ -167,6 +183,7 @@ void lte_diag_disconnect(lte_disconnect_reason_t reason) {
lte_diag.disconnect_count++; lte_diag.disconnect_count++;
lte_diag.last_disconnect_reason = reason; lte_diag.last_disconnect_reason = reason;
lte_diag.last_disconnect_tick = now; lte_diag.last_disconnect_tick = now;
lte_diag.disconnect_report_pending = true;
LOG_I("[DISC] reason=%s count=%u connected_ticks=%u", LOG_I("[DISC] reason=%s count=%u connected_ticks=%u",
disconnect_reason_name(reason), lte_diag.disconnect_count, disconnect_reason_name(reason), lte_diag.disconnect_count,
@ -176,10 +193,24 @@ void lte_diag_disconnect(lte_disconnect_reason_t reason) {
lte_diag.uart2_rx_events, lte_diag.uart2_write_failures, lte_diag.uart2_rx_events, lte_diag.uart2_write_failures,
lte_diag.uart2_error_count, lte_diag.uart3_error_count, lte_diag.uart2_error_count, lte_diag.uart3_error_count,
lte_diag.last_uart_error_code); lte_diag.last_uart_error_code);
LOG_I("[DISC] fmu_rx=%u fmu_tx=%u server_rx=%u read_events=%u silence_timeout=%u",
lte_diag.fmu_rx_bytes, lte_diag.fmu_tx_bytes,
lte_diag.server_rx_bytes, lte_diag.server_rx_read_events,
lte_diag.server_silence_timeout_count);
LOG_I("[CONN] fmu_rx=%u fmu_tx=%u fmu_hb=%u server_rx=%u server_hb=%u events=%u",
lte_diag.fmu_rx_bytes - lte_diag.conn_fmu_rx_base,
lte_diag.fmu_tx_bytes - lte_diag.conn_fmu_tx_base,
lte_diag.fmu_heartbeats - lte_diag.conn_fmu_heartbeat_base,
lte_diag.server_rx_bytes - lte_diag.conn_server_rx_base,
lte_diag.server_heartbeats - lte_diag.conn_server_heartbeat_base,
lte_diag.server_rx_read_events - lte_diag.conn_server_events_base);
LOG_I("[CONN] socket_tx=%u send_ok=%u send_fail=%u prompt_timeout=%u read_errors=%u",
lte_diag.socket_tx_bytes - lte_diag.conn_socket_tx_base,
lte_diag.socket_send_ok - lte_diag.conn_send_ok_base,
lte_diag.socket_send_fail - lte_diag.conn_send_fail_base,
lte_diag.socket_prompt_timeouts,
lte_diag.socket_read_errors);
LOG_I("[DISC] acked=%u unacked=%u ack_queries=%u ack_errors=%u",
lte_diag.socket_acked_bytes, lte_diag.socket_unacked_bytes,
lte_diag.socket_ack_queries, lte_diag.socket_ack_errors);
LOG_I("[DISC] tx_queue_high=%u drops=%u",
lte_diag.tx_queue_high_water, lte_diag.tx_queue_drops);
LOG_I("[DISC] age_uart2_rx=%u age_uart2_tx=%u age_fmu_rx=%u age_server_rx=%u", LOG_I("[DISC] age_uart2_rx=%u age_uart2_tx=%u age_fmu_rx=%u age_server_rx=%u",
diag_age(now, lte_diag.last_uart2_rx_tick), diag_age(now, lte_diag.last_uart2_rx_tick),
diag_age(now, lte_diag.last_uart2_tx_tick), diag_age(now, lte_diag.last_uart2_tx_tick),
@ -191,13 +222,91 @@ void lte_diag_disconnect(lte_disconnect_reason_t reason) {
LOG_I("[DISC] attempts=%u reconnects=%u qioopen_fail=%u resets=%u", LOG_I("[DISC] attempts=%u reconnects=%u qioopen_fail=%u resets=%u",
lte_diag.connect_attempts, lte_diag.reconnect_count, lte_diag.connect_attempts, lte_diag.reconnect_count,
lte_diag.qioopen_failures, lte_diag.reset_count); lte_diag.qioopen_failures, lte_diag.reset_count);
LOG_I("[DISC] csq=%d cereg=%u pdp=%u heap=%u/%u min_free=%u",
lte_dev.csq, lte_dev.eps_sta, lte_dev.reset_flag == DTU_CF_NO_NEED_RESET,
heap_used, heap_total, heap_total - heap_max);
LOG_I("[DISC] heap=%u/%u min_free=%u", heap_used, heap_total,
heap_total - heap_max);
if (reason == LTE_DISC_AT_TIMEOUT || reason == LTE_DISC_QIOPEN_FAILED ||
reason == LTE_DISC_MODULE_RESET) {
const char *classification = reason == LTE_DISC_QIOPEN_FAILED
? "SOCKET_OPEN"
: "MODEM_OR_DEVICE";
LOG_I("[CLASS] class=%s confidence=MEDIUM net_snapshot=unavailable",
classification);
lte_diag.disconnect_report_pending = false;
}
lte_dev.client1->connect_sta = false; lte_dev.client1->connect_sta = false;
} }
static const char *diag_text_or_unknown(const char *text) {
return text[0] == '\0' ? "?" : text;
}
static void lte_diag_finish_disconnect(void) {
const lte_network_snapshot_t *network = &lte_diag.network;
rt_tick_t now = lte_diag.last_disconnect_tick;
rt_uint32_t connected_ms = now - lte_diag.connect_tick;
rt_uint32_t fmu_hb =
lte_diag.fmu_heartbeats - lte_diag.conn_fmu_heartbeat_base;
rt_uint32_t server_hb =
lte_diag.server_heartbeats - lte_diag.conn_server_heartbeat_base;
rt_uint32_t ack_queries =
lte_diag.socket_ack_queries - lte_diag.conn_ack_queries_base;
const char *classification = "UNKNOWN";
const char *confidence = "LOW";
const char *evidence = "insufficient";
bool registration_bad = network->cereg >= 0 && network->cereg != 1 &&
network->cereg != 5;
LOG_I("[NET] oper=%s rat=%s band=%s channel=%u tac=%s cell=%s",
diag_text_or_unknown(network->oper),
diag_text_or_unknown(network->rat),
diag_text_or_unknown(network->band), network->channel,
diag_text_or_unknown(network->tac),
diag_text_or_unknown(network->cell));
LOG_I("[NET] cereg=%d cgatt=%d pdp=%d csq=%d pdpdeact=%u",
network->cereg, network->cgatt, network->pdp, network->csq,
lte_dev.socket_pdpdeact_pending ? 1 : 0);
LOG_I("[PATH] acked=%u unacked=%u ack_queries=%u last_ack_age_ms=%u queue_drops=%u",
lte_diag.socket_acked_bytes, lte_diag.socket_unacked_bytes,
ack_queries, diag_age(now, lte_diag.last_socket_ack_tick),
lte_diag.tx_queue_drops - lte_diag.conn_queue_drops_base);
if (lte_dev.socket_pdpdeact_pending || registration_bad ||
network->cgatt == 0 || network->pdp == 0) {
classification = "CELLULAR";
confidence = "HIGH";
evidence = lte_dev.socket_pdpdeact_pending ? "pdpdeact" : "registration";
} else if (connected_ms >= 25000 && connected_ms <= 40000 &&
fmu_hb == 0 && server_hb >= 5 &&
lte_diag.socket_unacked_bytes == 0) {
classification = "SERVER_POLICY";
confidence = "HIGH";
evidence = "no_fmu_hb_30s";
} else if (lte_diag.socket_unacked_bytes > 0) {
classification = "IP_PATH";
confidence = "MEDIUM";
evidence = "tcp_unacked";
} else if (lte_diag.last_disconnect_reason == LTE_DISC_SERVER_SILENCE) {
classification = "SERVER_OR_DOWNLINK";
confidence = "MEDIUM";
evidence = "server_silence";
} else if (lte_diag.last_disconnect_reason == LTE_DISC_SOCKET_SEND) {
classification = "MODEM_OR_SOCKET";
confidence = "MEDIUM";
evidence = "socket_send_fail";
} else if (ack_queries > 0 && lte_diag.socket_unacked_bytes == 0 &&
diag_age(now, lte_diag.last_server_rx_tick) <= 5000) {
classification = "REMOTE_CLOSE";
confidence = "MEDIUM";
evidence = "recent_rx_all_acked";
}
LOG_I("[CLASS] class=%s confidence=%s evidence=%s", classification,
confidence, evidence);
lte_diag.disconnect_report_pending = false;
}
/*将EC800K软件复位*/ /*将EC800K软件复位*/
int16_t EC800K_Reset(void) { int16_t EC800K_Reset(void) {
@ -211,11 +320,7 @@ int16_t EC800K_Reset(void) {
lte_dev.client1->connect_sta = false; lte_dev.client1->connect_sta = false;
//lte_dev.client2->connect_sta = false; //lte_dev.client2->connect_sta = false;
rt_thread_mdelay(3000);
BSP_LTE_SendData((uint8_t *)"+++", 3);
rt_thread_mdelay(2000);
BSP_LTE_SendData((uint8_t *)"+++", 3);
rt_thread_mdelay(2000);
rt_thread_mdelay(1000);
uint8_t try_count = 5; uint8_t try_count = 5;
@ -261,9 +366,9 @@ int16_t client_tcp_connect(Cclient_t *client) {
BSP_LTE_InitLogClock(); BSP_LTE_InitLogClock();
// //
BSP_LTE_SendCmd(AT_CFG_TRANS_SIZE, DEFAULT_EXPECT, DEFAULT_ERROR,
BSP_LTE_SendCmd(AT_CFG_RECV_IND, DEFAULT_EXPECT, DEFAULT_ERROR,
LTE_CMD_WAIT_NORMAL); LTE_CMD_WAIT_NORMAL);
BSP_LTE_SendCmd(AT_CFG_TRANS_WAITTM, DEFAULT_EXPECT, DEFAULT_ERROR,
BSP_LTE_SendCmd(AT_QISDE0, DEFAULT_EXPECT, DEFAULT_ERROR,
LTE_CMD_WAIT_NORMAL); LTE_CMD_WAIT_NORMAL);
BSP_LTE_SendCmd(AT_CFG_PASSIVE_CLOSED, DEFAULT_EXPECT, DEFAULT_ERROR, BSP_LTE_SendCmd(AT_CFG_PASSIVE_CLOSED, DEFAULT_EXPECT, DEFAULT_ERROR,
LTE_CMD_WAIT_NORMAL); LTE_CMD_WAIT_NORMAL);
@ -276,7 +381,7 @@ int16_t client_tcp_connect(Cclient_t *client) {
// 2, 打开链接 // 2, 打开链接
memset(cmd_cmd, 0, sizeof(cmd_cmd)); memset(cmd_cmd, 0, sizeof(cmd_cmd));
cmd_len = rt_snprintf(cmd_cmd, sizeof(cmd_cmd), AT_QIOPEN_TRANS,
cmd_len = rt_snprintf(cmd_cmd, sizeof(cmd_cmd), AT_QIOPEN_BUFFER,
client->connect_ID, client->mode, client->ip, client->connect_ID, client->mode, client->ip,
client->port); client->port);
if (cmd_len < 0 || cmd_len >= (int)sizeof(cmd_cmd)) { if (cmd_len < 0 || cmd_len >= (int)sizeof(cmd_cmd)) {
@ -285,8 +390,7 @@ int16_t client_tcp_connect(Cclient_t *client) {
return -1; return -1;
} }
/* 透传模式成功返回 CONNECT;一次尝试只发送一次 QIOPEN。 */ /* 透传模式成功返回 CONNECT;一次尝试只发送一次 QIOPEN。 */
while (0 != BSP_LTE_SendCmd(cmd_cmd, CONNECTE_OK, DEFAULT_ERROR,
LTE_CMD_WAIT_QIOPEN)) {
while (0 != BSP_LTE_OpenSocket(cmd_cmd, client->connect_ID)) {
lte_diag.qioopen_failures++; lte_diag.qioopen_failures++;
client_tcp_close(client); client_tcp_close(client);
#ifdef debug_mode #ifdef debug_mode
@ -305,8 +409,12 @@ int16_t client_tcp_connect(Cclient_t *client) {
#endif #endif
} }
client->connect_sta = true; client->connect_sta = true;
BSP_LTE_ClearSocketEvents();
fmu_net_queue_reset();
socket_tx_pending = 0;
BSP_LTE_SetDataTxPaused(false); BSP_LTE_SetDataTxPaused(false);
lte_diag_connect_success(); lte_diag_connect_success();
last_ack_query_tick = lte_diag.connect_tick;
client->error_cnt = 0; client->error_cnt = 0;
lte_dev.reset_flag = DTU_CF_NO_NEED_RESET; lte_dev.reset_flag = DTU_CF_NO_NEED_RESET;
@ -323,7 +431,7 @@ int16_t client_tcp_connect(Cclient_t *client) {
mav_len = mavlink_msg_to_send_buffer(mav_buf, &msg); mav_len = mavlink_msg_to_send_buffer(mav_buf, &msg);
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
BSP_LTE_SendData(mav_buf, mav_len);
BSP_LTE_SendSocketData(client->connect_ID, mav_buf, mav_len);
} }
rt_device_t fmu_com = fmu_com_get(); rt_device_t fmu_com = fmu_com_get();
if (fmu_com != RT_NULL) { if (fmu_com != RT_NULL) {
@ -334,11 +442,11 @@ int16_t client_tcp_connect(Cclient_t *client) {
rt_sprintf(buf, "{\"sn\":\"%s\",\"client_id\":\"%s\",\"csq\":\"%d\"}\r\n", rt_sprintf(buf, "{\"sn\":\"%s\",\"client_id\":\"%s\",\"csq\":\"%d\"}\r\n",
lte_dev.iccid, lte_dev.imei, lte_dev.csq); lte_dev.iccid, lte_dev.imei, lte_dev.csq);
BSP_LTE_SendData((uint8_t *)buf, sizeof(buf));
BSP_LTE_SendSocketData(client->connect_ID, (uint8_t *)buf, sizeof(buf));
BSP_LTE_SendData((uint8_t *)buf, sizeof(buf));
BSP_LTE_SendSocketData(client->connect_ID, (uint8_t *)buf, sizeof(buf));
BSP_LTE_SendData((uint8_t *)buf, sizeof(buf));
BSP_LTE_SendSocketData(client->connect_ID, (uint8_t *)buf, sizeof(buf));
//hw_printf(buf); //hw_printf(buf);
#endif #endif
@ -350,37 +458,7 @@ int16_t client_tcp_connect(Cclient_t *client) {
static rt_tick_t last_rx_tick = 0; static rt_tick_t last_rx_tick = 0;
#endif #endif
/* Leave transparent mode only after the UART has been quiet for the
* required guard time. The caller keeps data_tx_paused asserted until the
* next successful QIOPEN. */
static bool client_exit_transparent_mode(CLte_dev_t *pLte_dev) {
rt_tick_t deadline;
rt_ssize_t len;
BSP_LTE_SetDataTxPaused(true);
rt_thread_mdelay(1000);
BSP_LTE_SendData((uint8_t *)"+++", 3);
rt_thread_mdelay(1000);
deadline = rt_tick_get() + 2000;
while ((rt_int32_t)(rt_tick_get() - deadline) < 0) {
if (pLte_dev->com_dev_rx_sem != RT_NULL) {
rt_sem_take(pLte_dev->com_dev_rx_sem, 100);
}
rt_memset(pLte_dev->at_buf, 0, sizeof(pLte_dev->at_buf));
len = rt_device_read(pLte_dev->com_dev, 0, pLte_dev->at_buf,
sizeof(pLte_dev->at_buf) - 1);
if (len > 0) {
lte_diag_uart2_rx((rt_size_t)len);
pLte_dev->at_buf[len] = '\0';
if (rt_strstr((const char *)pLte_dev->at_buf, DEFAULT_EXPECT) != RT_NULL) {
return true;
}
}
}
return false;
}
#if 0
void client_yield(CLte_dev_t *pLte_dev) { void client_yield(CLte_dev_t *pLte_dev) {
while (1) { while (1) {
if (pLte_dev->client1->connect_sta == true) { if (pLte_dev->client1->connect_sta == true) {
@ -437,9 +515,7 @@ void client_yield(CLte_dev_t *pLte_dev) {
} }
rt_device_t fmu_com = fmu_com_get(); rt_device_t fmu_com = fmu_com_get();
lte_diag.server_rx_bytes += len;
lte_diag.server_rx_read_events++;
lte_diag.last_server_rx_tick = rt_tick_get();
lte_diag_server_data(pLte_dev->at_buf, len);
if (fmu_com) { if (fmu_com) {
rt_ssize_t written = rt_device_write(fmu_com, 0, rt_ssize_t written = rt_device_write(fmu_com, 0,
pLte_dev->at_buf, len); pLte_dev->at_buf, len);
@ -468,6 +544,94 @@ void client_yield(CLte_dev_t *pLte_dev) {
} }
} }
#endif
void client_yield(CLte_dev_t *pLte_dev) {
while (1) {
if (pLte_dev->client1->connect_sta == true) {
int16_t socket_result;
BSP_LTE_PollSocketUrc(20);
if (pLte_dev->socket_closed_pending) {
LOG_W("[URC] socket closed received");
lte_diag_disconnect(LTE_DISC_CLOSED);
client_tcp_close(pLte_dev->client1);
continue;
}
while (pLte_dev->socket_recv_pending &&
pLte_dev->client1->connect_sta) {
rt_device_t fmu_com;
int16_t read_length = BSP_LTE_ReadSocketData(
pLte_dev->client1->connect_ID, socket_rx_buffer,
sizeof(socket_rx_buffer));
if (read_length < 0) {
lte_diag_disconnect(pLte_dev->socket_closed_pending
? LTE_DISC_CLOSED
: LTE_DISC_AT_TIMEOUT);
client_tcp_close(pLte_dev->client1);
break;
}
if (read_length == 0) break;
lte_diag_server_data(socket_rx_buffer, read_length);
#if LTE_SERVER_SILENCE_TIMEOUT_SEC > 0
last_rx_tick = lte_diag.last_server_rx_tick;
#endif
fmu_com = fmu_com_get();
if (fmu_com != RT_NULL) {
rt_ssize_t written = rt_device_write(fmu_com, 0, socket_rx_buffer,
read_length);
if (written > 0) lte_diag_fmu_tx((rt_size_t)written);
}
if (read_length == sizeof(socket_rx_buffer))
pLte_dev->socket_recv_pending = true;
}
if (!pLte_dev->client1->connect_sta) continue;
if (socket_tx_pending == 0) {
socket_tx_pending = fmu_net_queue_get(socket_tx_buffer,
sizeof(socket_tx_buffer));
}
if (socket_tx_pending > 0) {
socket_result = BSP_LTE_SendSocketData(
pLte_dev->client1->connect_ID, socket_tx_buffer,
(uint16_t)socket_tx_pending);
if (socket_result == 0) {
socket_tx_pending = 0;
} else if (socket_result < 0) {
lte_diag_disconnect(LTE_DISC_SOCKET_SEND);
client_tcp_close(pLte_dev->client1);
continue;
} else {
rt_thread_mdelay(50);
}
}
if (rt_tick_get() - last_ack_query_tick >= RT_TICK_PER_SECOND * 5) {
last_ack_query_tick = rt_tick_get();
BSP_LTE_QuerySocketSendStatus(pLte_dev->client1->connect_ID);
}
#if LTE_SERVER_SILENCE_TIMEOUT_SEC > 0
if (rt_tick_get() - last_rx_tick >
RT_TICK_PER_SECOND * LTE_SERVER_SILENCE_TIMEOUT_SEC) {
lte_diag.server_silence_timeout_count++;
LOG_W("server silence timeout, reconnect\n");
lte_diag_disconnect(LTE_DISC_SERVER_SILENCE);
client_tcp_close(pLte_dev->client1);
continue;
}
#endif
} else {
if (pLte_dev->reset_flag == DTU_CF_NEED_RESET) BSP_LTE_Config();
client_tcp_connect(pLte_dev->client1);
#if LTE_SERVER_SILENCE_TIMEOUT_SEC > 0
last_rx_tick = rt_tick_get();
#endif
}
}
}
void client_task(void) { void client_task(void) {
client_yield(&lte_dev); client_yield(&lte_dev);

50
applications/VK_Com.c

@ -3,6 +3,7 @@
#include "drv_ec800k.h" #include "drv_ec800k.h"
#include "rtdef.h" #include "rtdef.h"
#include "rtthread.h" #include "rtthread.h"
#include <ipc/ringbuffer.h>
#define ENABLE_MEMORY_USAGE_LOG 0 #define ENABLE_MEMORY_USAGE_LOG 0
@ -15,6 +16,12 @@
rt_device_t fmu_com = RT_NULL; rt_device_t fmu_com = RT_NULL;
rt_sem_t fmu_com_rx_sem = RT_NULL; rt_sem_t fmu_com_rx_sem = RT_NULL;
#define FMU_NET_QUEUE_SIZE 512
static struct rt_ringbuffer fmu_net_queue;
static struct rt_mutex fmu_net_queue_lock;
static uint8_t fmu_net_queue_pool[FMU_NET_QUEUE_SIZE];
static bool fmu_net_queue_ready = false;
#if ENABLE_MEMORY_USAGE_LOG #if ENABLE_MEMORY_USAGE_LOG
static rt_size_t thread_stack_used(rt_thread_t thread) { static rt_size_t thread_stack_used(rt_thread_t thread) {
rt_uint8_t *stack; rt_uint8_t *stack;
@ -69,9 +76,48 @@ int fmu_com_register(rt_device_t com_dev) {
rt_device_set_rx_indicate(fmu_com, fmu_com_rx_cb); rt_device_set_rx_indicate(fmu_com, fmu_com_rx_cb);
if (!fmu_net_queue_ready) {
rt_ringbuffer_init(&fmu_net_queue, fmu_net_queue_pool,
sizeof(fmu_net_queue_pool));
rt_mutex_init(&fmu_net_queue_lock, "fmuNet", RT_IPC_FLAG_PRIO);
fmu_net_queue_ready = true;
}
return 0; return 0;
} }
rt_size_t fmu_net_queue_put(const uint8_t *data, rt_size_t length) {
rt_size_t queued;
rt_size_t used;
if (!fmu_net_queue_ready || data == RT_NULL || length == 0) return 0;
rt_mutex_take(&fmu_net_queue_lock, RT_WAITING_FOREVER);
queued = rt_ringbuffer_put(&fmu_net_queue, data, length);
used = rt_ringbuffer_data_len(&fmu_net_queue);
rt_mutex_release(&fmu_net_queue_lock);
if (queued < length) lte_diag.tx_queue_drops += length - queued;
if (used > lte_diag.tx_queue_high_water) lte_diag.tx_queue_high_water = used;
return queued;
}
rt_size_t fmu_net_queue_get(uint8_t *data, rt_size_t length) {
rt_size_t read;
if (!fmu_net_queue_ready || data == RT_NULL || length == 0) return 0;
rt_mutex_take(&fmu_net_queue_lock, RT_WAITING_FOREVER);
read = rt_ringbuffer_get(&fmu_net_queue, data, length);
rt_mutex_release(&fmu_net_queue_lock);
return read;
}
void fmu_net_queue_reset(void) {
if (!fmu_net_queue_ready) return;
rt_mutex_take(&fmu_net_queue_lock, RT_WAITING_FOREVER);
rt_ringbuffer_reset(&fmu_net_queue);
rt_mutex_release(&fmu_net_queue_lock);
}
/*接收到串口的数据,并将数据转发到网络端*/ /*接收到串口的数据,并将数据转发到网络端*/
void com_task(void) { void com_task(void) {
static uint8_t buff[128]; static uint8_t buff[128];
@ -86,11 +132,11 @@ void com_task(void) {
while (1) { while (1) {
len = rt_device_read(fmu_com, 0, buff, sizeof(buff)); len = rt_device_read(fmu_com, 0, buff, sizeof(buff));
if (len > 0) { if (len > 0) {
lte_diag_fmu_rx(len);
lte_diag_fmu_data(buff, len);
if (lte_dev.client1->connect_sta == true && if (lte_dev.client1->connect_sta == true &&
lte_dev.data_tx_paused == false) { lte_dev.data_tx_paused == false) {
/* 仅在客户端2连接时转发 */ /* 仅在客户端2连接时转发 */
BSP_LTE_SendData(buff, len);
fmu_net_queue_put(buff, len);
} }
} else { } else {
break; break;

3
applications/VK_Com.h

@ -15,6 +15,9 @@ void com_task(void);
rt_device_t fmu_com_get(void); rt_device_t fmu_com_get(void);
int fmu_com_register(rt_device_t com_dev); int fmu_com_register(rt_device_t com_dev);
rt_size_t fmu_net_queue_put(const uint8_t *data, rt_size_t length);
rt_size_t fmu_net_queue_get(uint8_t *data, rt_size_t length);
void fmu_net_queue_reset(void);
#ifdef __cplusplus #ifdef __cplusplus
} }

549
applications/drv_ec800k.c

@ -38,6 +38,247 @@ CLte_dev_t lte_dev = {
lte_diag_t lte_diag = {0}; lte_diag_t lte_diag = {0};
static bool lte_log_clock_query_done = false; static bool lte_log_clock_query_done = false;
static char socket_urc_line[80];
static rt_size_t socket_urc_line_len = 0;
static volatile bool socket_open_seen = false;
static volatile int16_t socket_open_result = -1;
typedef struct {
rt_uint16_t remaining;
rt_uint16_t checksum;
rt_uint16_t received_checksum;
rt_uint8_t magic;
rt_uint8_t phase;
rt_uint8_t position;
rt_uint8_t payload_length;
rt_uint8_t incompat_flags;
bool heartbeat;
} mavlink_diag_parser_t;
static mavlink_diag_parser_t fmu_mavlink_parser;
static mavlink_diag_parser_t server_mavlink_parser;
static int parse_decimal(const char **text) {
int value = 0;
bool found = false;
const char *p = *text;
while (*p == ' ') p++;
while (*p >= '0' && *p <= '9') {
found = true;
value = value * 10 + (*p++ - '0');
}
*text = p;
return found ? value : -1;
}
static void copy_csv_token(const char **text, char *output, rt_size_t capacity) {
const char *p = *text;
rt_size_t used = 0;
char terminator = ',';
if (capacity == 0) return;
while (*p == ' ' || *p == ',') p++;
if (*p == '"') {
terminator = '"';
p++;
}
while (*p != '\0' && *p != '\r' && *p != '\n' && *p != terminator) {
if (used + 1 < capacity) output[used++] = *p;
p++;
}
while (used > 0 && output[used - 1] == ' ') used--;
output[used] = '\0';
if (*p == terminator) p++;
*text = p;
}
static void mavlink_crc_accumulate(uint8_t data, rt_uint16_t *checksum) {
uint8_t tmp = data ^ (uint8_t)(*checksum & 0xff);
tmp ^= tmp << 4;
*checksum = (*checksum >> 8) ^ ((rt_uint16_t)tmp << 8) ^
((rt_uint16_t)tmp << 3) ^ ((rt_uint16_t)tmp >> 4);
}
static void mavlink_diag_start(mavlink_diag_parser_t *parser, uint8_t magic) {
parser->magic = magic;
parser->phase = 1;
parser->position = 0;
parser->remaining = 0;
parser->checksum = 0xffff;
parser->received_checksum = 0;
parser->payload_length = 0;
parser->incompat_flags = 0;
parser->heartbeat = false;
}
static void mavlink_diag_feed(mavlink_diag_parser_t *parser,
const uint8_t *data, rt_size_t size,
rt_uint32_t *heartbeat_count) {
rt_size_t i;
for (i = 0; i < size; i++) {
uint8_t ch = data[i];
if (parser->phase == 0) {
if (ch == 0xFE || ch == 0xFD) {
mavlink_diag_start(parser, ch);
}
continue;
}
if (parser->phase == 5) {
parser->remaining--;
if (parser->remaining == 0) parser->phase = 0;
continue;
}
if (parser->phase == 2) {
mavlink_crc_accumulate(ch, &parser->checksum);
parser->remaining--;
if (parser->remaining == 0) parser->phase = 3;
continue;
}
if (parser->phase == 3) {
parser->received_checksum = ch;
parser->phase = 4;
continue;
}
if (parser->phase == 4) {
parser->received_checksum |= (rt_uint16_t)ch << 8;
mavlink_crc_accumulate(50, &parser->checksum);
if (parser->heartbeat &&
parser->checksum == parser->received_checksum) {
(*heartbeat_count)++;
}
if (parser->magic == 0xFD &&
(parser->incompat_flags & 0x01) != 0) {
parser->phase = 5;
parser->remaining = 13;
} else {
parser->phase = 0;
}
continue;
}
mavlink_crc_accumulate(ch, &parser->checksum);
if (parser->position == 0) parser->payload_length = ch;
if (parser->magic == 0xFE && parser->position == 4) {
parser->heartbeat = parser->payload_length == 9 && ch == 0;
parser->remaining = parser->payload_length;
parser->phase = parser->remaining > 0 ? 2 : 3;
} else if (parser->magic == 0xFD) {
if (parser->position == 1) parser->incompat_flags = ch;
if (parser->position == 6) parser->heartbeat = ch == 0;
if (parser->position == 7)
parser->heartbeat = parser->heartbeat && ch == 0;
if (parser->position == 8) {
parser->heartbeat = parser->payload_length == 9 &&
parser->heartbeat && ch == 0;
parser->remaining = parser->payload_length;
parser->phase = parser->remaining > 0 ? 2 : 3;
}
}
parser->position++;
}
}
static void lte_process_urc_line(const char *line) {
const char *p;
if (rt_strstr(line, "+QIURC:") != RT_NULL) {
if (rt_strstr(line, "\"recv\"") != RT_NULL) {
lte_dev.socket_recv_pending = true;
} else if (rt_strstr(line, "\"closed\"") != RT_NULL) {
lte_dev.socket_closed_pending = true;
} else if (rt_strstr(line, "\"pdpdeact\"") != RT_NULL) {
lte_dev.socket_pdpdeact_pending = true;
lte_diag.pdpdeact_count++;
}
}
p = rt_strstr(line, "+QIOPEN:");
if (p != RT_NULL) {
int connect_id;
int error;
p += rt_strlen("+QIOPEN:");
connect_id = parse_decimal(&p);
if (*p == ',') p++;
error = parse_decimal(&p);
if (connect_id == lte_dev.client1->connect_ID && error >= 0) {
socket_open_result = (int16_t)error;
socket_open_seen = true;
}
}
}
static void lte_process_text(const uint8_t *data, rt_size_t length) {
rt_size_t i;
for (i = 0; i < length; i++) {
uint8_t ch = data[i];
if (ch == '\r') continue;
if (ch == '\n') {
if (socket_urc_line_len > 0) {
socket_urc_line[socket_urc_line_len] = '\0';
lte_process_urc_line(socket_urc_line);
socket_urc_line_len = 0;
}
} else if (ch >= 0x20 && ch <= 0x7e) {
if (socket_urc_line_len < sizeof(socket_urc_line) - 1) {
socket_urc_line[socket_urc_line_len++] = (char)ch;
} else {
socket_urc_line_len = 0;
}
}
}
}
static rt_ssize_t lte_read_available(uint8_t *buffer, rt_size_t capacity) {
rt_ssize_t length = rt_device_read(lte_dev.com_dev, 0, buffer, capacity);
if (length > 0) lte_diag_uart2_rx((rt_size_t)length);
return length;
}
static void lte_drain_socket_input(void) {
rt_ssize_t length;
do {
length = lte_read_available(lte_dev.at_buf, sizeof(lte_dev.at_buf));
if (length > 0) lte_process_text(lte_dev.at_buf, (rt_size_t)length);
} while (length > 0);
while (rt_sem_take(lte_dev.com_dev_rx_sem, 0) == RT_EOK) { }
}
static int lte_wait_text(const char *success, const char *failure,
rt_tick_t timeout) {
rt_tick_t deadline = rt_tick_get() + timeout;
rt_size_t used = 0;
rt_memset(lte_dev.at_buf, 0, sizeof(lte_dev.at_buf));
while ((rt_int32_t)(rt_tick_get() - deadline) < 0) {
rt_ssize_t length;
rt_sem_take(lte_dev.com_dev_rx_sem, 50);
length = lte_read_available(lte_dev.at_buf + used,
sizeof(lte_dev.at_buf) - 1 - used);
if (length <= 0) continue;
lte_process_text(lte_dev.at_buf + used, (rt_size_t)length);
used += (rt_size_t)length;
lte_dev.at_buf[used] = '\0';
if (lte_dev.socket_closed_pending) return 1;
if (success != RT_NULL && rt_strstr((char *)lte_dev.at_buf, success)) return 0;
if ((failure != RT_NULL && rt_strstr((char *)lte_dev.at_buf, failure)) ||
rt_strstr((char *)lte_dev.at_buf, DEFAULT_ERROR)) return 1;
if (used >= sizeof(lte_dev.at_buf) - 1) {
rt_memcpy(lte_dev.at_buf, lte_dev.at_buf + used - 32, 32);
used = 32;
lte_dev.at_buf[used] = '\0';
}
}
return -1;
}
void lte_diag_at_begin(const char *cmd) { void lte_diag_at_begin(const char *cmd) {
rt_size_t i; rt_size_t i;
@ -86,6 +327,21 @@ void lte_diag_fmu_rx(rt_size_t size) {
lte_diag.last_fmu_rx_tick = rt_tick_get(); lte_diag.last_fmu_rx_tick = rt_tick_get();
} }
void lte_diag_fmu_data(const uint8_t *data, rt_size_t size) {
if (data == RT_NULL || size == 0) return;
lte_diag_fmu_rx(size);
mavlink_diag_feed(&fmu_mavlink_parser, data, size, &lte_diag.fmu_heartbeats);
}
void lte_diag_server_data(const uint8_t *data, rt_size_t size) {
if (data == RT_NULL || size == 0) return;
lte_diag.server_rx_bytes += size;
lte_diag.server_rx_read_events++;
lte_diag.last_server_rx_tick = rt_tick_get();
mavlink_diag_feed(&server_mavlink_parser, data, size,
&lte_diag.server_heartbeats);
}
void lte_diag_fmu_tx(rt_size_t size) { void lte_diag_fmu_tx(rt_size_t size) {
lte_diag.fmu_tx_bytes += size; lte_diag.fmu_tx_bytes += size;
lte_diag.last_fmu_tx_tick = rt_tick_get(); lte_diag.last_fmu_tx_tick = rt_tick_get();
@ -101,6 +357,26 @@ void lte_diag_connect_attempt(void) {
void lte_diag_connect_success(void) { void lte_diag_connect_success(void) {
lte_diag.connect_tick = rt_tick_get(); lte_diag.connect_tick = rt_tick_get();
lte_diag.last_server_rx_tick = lte_diag.connect_tick; lte_diag.last_server_rx_tick = lte_diag.connect_tick;
lte_diag.last_socket_ack_tick = 0;
lte_diag.socket_acked_bytes = 0;
lte_diag.socket_unacked_bytes = 0;
lte_diag.socket_prompt_timeouts = 0;
lte_diag.socket_read_errors = 0;
lte_diag.socket_ack_errors = 0;
lte_diag.tx_queue_high_water = 0;
lte_diag.conn_fmu_rx_base = lte_diag.fmu_rx_bytes;
lte_diag.conn_fmu_tx_base = lte_diag.fmu_tx_bytes;
lte_diag.conn_server_rx_base = lte_diag.server_rx_bytes;
lte_diag.conn_server_events_base = lte_diag.server_rx_read_events;
lte_diag.conn_socket_tx_base = lte_diag.socket_tx_bytes;
lte_diag.conn_send_ok_base = lte_diag.socket_send_ok;
lte_diag.conn_send_fail_base = lte_diag.socket_send_fail;
lte_diag.conn_ack_queries_base = lte_diag.socket_ack_queries;
lte_diag.conn_queue_drops_base = lte_diag.tx_queue_drops;
lte_diag.conn_fmu_heartbeat_base = lte_diag.fmu_heartbeats;
lte_diag.conn_server_heartbeat_base = lte_diag.server_heartbeats;
rt_memset(&fmu_mavlink_parser, 0, sizeof(fmu_mavlink_parser));
rt_memset(&server_mavlink_parser, 0, sizeof(server_mavlink_parser));
} }
void lte_diag_module_reset(void) { void lte_diag_module_reset(void) {
@ -135,6 +411,180 @@ void BSP_LTE_SetDataTxPaused(bool paused) {
} }
} }
void BSP_LTE_ClearSocketEvents(void) {
lte_dev.socket_recv_pending = false;
lte_dev.socket_closed_pending = false;
lte_dev.socket_pdpdeact_pending = false;
socket_open_seen = false;
socket_open_result = -1;
socket_urc_line_len = 0;
}
int16_t BSP_LTE_OpenSocket(const char *cmd, uint8_t connect_id) {
rt_tick_t deadline;
(void)connect_id;
lte_drain_socket_input();
socket_open_seen = false;
socket_open_result = -1;
lte_diag_at_begin(cmd);
LOG_I("%s", cmd);
BSP_LTE_SendData((uint8_t *)cmd, rt_strlen(cmd));
deadline = rt_tick_get() + LTE_CMD_WAIT_QIOPEN;
while ((rt_int32_t)(rt_tick_get() - deadline) < 0) {
rt_ssize_t length;
rt_sem_take(lte_dev.com_dev_rx_sem, 100);
length = lte_read_available(lte_dev.at_buf, sizeof(lte_dev.at_buf) - 1);
if (length > 0) {
lte_dev.at_buf[length] = '\0';
lte_process_text(lte_dev.at_buf, (rt_size_t)length);
if (rt_strstr((char *)lte_dev.at_buf, DEFAULT_ERROR)) {
lte_diag_at_end(1);
return 1;
}
}
if (socket_open_seen) {
LOG_I("[SOCKET] open result=%d", socket_open_result);
lte_diag_at_end(socket_open_result == 0 ? 0 : 1);
return socket_open_result == 0 ? 0 : 1;
}
}
lte_diag_at_end(-1);
return -1;
}
int16_t BSP_LTE_SendSocketData(uint8_t connect_id, const uint8_t *data,
uint16_t length) {
char command[32];
int result;
if (data == RT_NULL || length == 0 || length > 1460) return -1;
lte_drain_socket_input();
rt_snprintf(command, sizeof(command), AT_QISEND, connect_id, length);
BSP_LTE_SendData((uint8_t *)command, rt_strlen(command));
result = lte_wait_text(TPOK, DEFAULT_ERROR, LTE_CMD_WAIT_PROMPT);
if (result != 0) {
if (result < 0) lte_diag.socket_prompt_timeouts++;
lte_diag.socket_send_fail++;
return result < 0 ? -1 : 1;
}
BSP_LTE_SendData((uint8_t *)data, length);
result = lte_wait_text(QI_SEND_OK, QI_SEND_FAIL, LTE_CMD_WAIT_SEND);
if (result == 0) {
lte_diag.socket_tx_bytes += length;
lte_diag.socket_send_ok++;
return 0;
}
lte_diag.socket_send_fail++;
return result < 0 ? -1 : 1;
}
int16_t BSP_LTE_QuerySocketSendStatus(uint8_t connect_id) {
char command[24];
const char *p;
int total;
int acked;
int unacked;
lte_drain_socket_input();
rt_snprintf(command, sizeof(command), AT_QISEND, connect_id, 0);
BSP_LTE_SendData((uint8_t *)command, rt_strlen(command));
if (lte_wait_text("\r\nOK\r\n", DEFAULT_ERROR, LTE_CMD_WAIT_SEND) != 0) {
lte_diag.socket_ack_errors++;
return -1;
}
p = rt_strstr((char *)lte_dev.at_buf, "+QISEND:");
if (p == RT_NULL) {
lte_diag.socket_ack_errors++;
return -1;
}
p += rt_strlen("+QISEND:");
total = parse_decimal(&p);
if (*p == ',') p++;
acked = parse_decimal(&p);
if (*p == ',') p++;
unacked = parse_decimal(&p);
if (total < 0 || acked < 0 || unacked < 0) {
lte_diag.socket_ack_errors++;
return -1;
}
(void)total;
lte_diag.socket_acked_bytes = (rt_uint32_t)acked;
lte_diag.socket_unacked_bytes = (rt_uint32_t)unacked;
lte_diag.socket_ack_queries++;
lte_diag.last_socket_ack_tick = rt_tick_get();
return 0;
}
int16_t BSP_LTE_ReadSocketData(uint8_t connect_id, uint8_t *data,
uint16_t capacity) {
char command[32];
rt_tick_t deadline;
rt_size_t used = 0;
if (data == RT_NULL || capacity == 0 || capacity > LTE_SOCKET_RX_CHUNK_SIZE)
return -1;
lte_drain_socket_input();
lte_dev.socket_recv_pending = false;
rt_snprintf(command, sizeof(command), "AT+QIRD=%u,%u\r\n",
connect_id, capacity);
BSP_LTE_SendData((uint8_t *)command, rt_strlen(command));
rt_memset(lte_dev.at_buf, 0, sizeof(lte_dev.at_buf));
deadline = rt_tick_get() + LTE_CMD_WAIT_SEND;
while ((rt_int32_t)(rt_tick_get() - deadline) < 0) {
rt_ssize_t length;
char *header;
char *payload;
const char *number;
int payload_length;
rt_sem_take(lte_dev.com_dev_rx_sem, 50);
length = lte_read_available(lte_dev.at_buf + used,
sizeof(lte_dev.at_buf) - 1 - used);
if (length <= 0) continue;
used += (rt_size_t)length;
lte_dev.at_buf[used] = '\0';
header = rt_strstr((char *)lte_dev.at_buf, "+QIRD:");
if (header == RT_NULL) {
if (rt_strstr((char *)lte_dev.at_buf, "\"closed\"") != RT_NULL) {
lte_dev.socket_closed_pending = true;
return -1;
}
continue;
}
number = header + rt_strlen("+QIRD:");
payload_length = parse_decimal(&number);
payload = rt_strstr((char *)number, "\r\n");
if (payload_length < 0 || payload == RT_NULL) continue;
payload += 2;
if ((rt_size_t)(payload - (char *)lte_dev.at_buf) + payload_length + 6 > used)
continue;
if (payload_length > capacity) {
lte_diag.socket_read_errors++;
return -1;
}
if (header > (char *)lte_dev.at_buf)
lte_process_text(lte_dev.at_buf, (rt_size_t)(header - (char *)lte_dev.at_buf));
if (payload_length > 0) rt_memcpy(data, payload, payload_length);
lte_process_text((uint8_t *)payload + payload_length, 6);
return (int16_t)payload_length;
}
lte_diag.socket_read_errors++;
return -1;
}
void BSP_LTE_PollSocketUrc(uint32_t waittime) {
rt_ssize_t length;
if (rt_sem_take(lte_dev.com_dev_rx_sem, waittime) != RT_EOK) return;
do {
length = lte_read_available(lte_dev.at_buf, sizeof(lte_dev.at_buf));
if (length > 0) lte_process_text(lte_dev.at_buf, (rt_size_t)length);
} while (length > 0);
}
void BSP_LTE_InitLogClock(void) { void BSP_LTE_InitLogClock(void) {
if (lte_log_clock_query_done) { if (lte_log_clock_query_done) {
return; return;
@ -151,6 +601,104 @@ void BSP_LTE_InitLogClock(void) {
} }
} }
static void parse_cereg_snapshot(const char *response) {
const char *p = rt_strstr(response, "+CEREG:");
int value;
if (p == RT_NULL) return;
p += rt_strlen("+CEREG:");
value = parse_decimal(&p);
if (value < 0 || *p != ',') return;
p++;
value = parse_decimal(&p);
if (value < 0) return;
lte_diag.network.cereg = (int8_t)value;
if (*p == ',') {
copy_csv_token(&p, lte_diag.network.tac,
sizeof(lte_diag.network.tac));
copy_csv_token(&p, lte_diag.network.cell,
sizeof(lte_diag.network.cell));
}
}
static void parse_cgatt_snapshot(const char *response) {
const char *p = rt_strstr(response, "+CGATT:");
int value;
if (p == RT_NULL) return;
p += rt_strlen("+CGATT:");
value = parse_decimal(&p);
if (value >= 0) lte_diag.network.cgatt = (int8_t)value;
}
static void parse_qiact_snapshot(const char *response) {
const char *p = rt_strstr(response, "+QIACT:");
int context;
int state;
if (p == RT_NULL) {
lte_diag.network.pdp = 0;
return;
}
p += rt_strlen("+QIACT:");
context = parse_decimal(&p);
if (context < 0 || *p != ',') return;
p++;
state = parse_decimal(&p);
if (context == 1 && state >= 0) lte_diag.network.pdp = (int8_t)state;
}
static void parse_qnwinfo_snapshot(const char *response) {
const char *p = rt_strstr(response, "+QNWINFO:");
char channel[12];
if (p == RT_NULL) return;
p += rt_strlen("+QNWINFO:");
copy_csv_token(&p, lte_diag.network.rat, sizeof(lte_diag.network.rat));
copy_csv_token(&p, lte_diag.network.oper, sizeof(lte_diag.network.oper));
copy_csv_token(&p, lte_diag.network.band, sizeof(lte_diag.network.band));
copy_csv_token(&p, channel, sizeof(channel));
p = channel;
{
int value = parse_decimal(&p);
if (value >= 0) lte_diag.network.channel = (rt_uint32_t)value;
}
}
void BSP_LTE_CollectNetworkSnapshot(void) {
lte_network_snapshot_t *network = &lte_diag.network;
rt_memset(network, 0, sizeof(*network));
network->cereg = -1;
network->cgatt = -1;
network->pdp = -1;
network->csq = -1;
BSP_LTE_SendCmd(AT_CEREG2, DEFAULT_EXPECT, DEFAULT_ERROR,
LTE_CMD_WAIT_NORMAL);
if (BSP_LTE_SendCmd(AT_CEREG, DEFAULT_EXPECT, DEFAULT_ERROR,
LTE_CMD_WAIT_NORMAL) == 0) {
parse_cereg_snapshot((const char *)lte_dev.at_buf);
}
BSP_LTE_SendCmd(AT_CEREG0, DEFAULT_EXPECT, DEFAULT_ERROR,
LTE_CMD_WAIT_NORMAL);
if (BSP_LTE_SendCmd(AT_CGATT, DEFAULT_EXPECT, DEFAULT_ERROR,
LTE_CMD_WAIT_NORMAL) == 0) {
parse_cgatt_snapshot((const char *)lte_dev.at_buf);
}
if (BSP_LTE_SendCmd(AT_QIACT, DEFAULT_EXPECT, DEFAULT_ERROR,
LTE_CMD_WAIT_NORMAL) == 0) {
parse_qiact_snapshot((const char *)lte_dev.at_buf);
}
if (BSP_LTE_SendCmd(AT_QNWINFO, DEFAULT_EXPECT, DEFAULT_ERROR,
LTE_CMD_WAIT_NORMAL) == 0) {
parse_qnwinfo_snapshot((const char *)lte_dev.at_buf);
}
network->csq = BSP_LTE_GetCSQ();
if (network->csq >= 0) lte_dev.csq = network->csq;
}
int16_t BSP_LTE_SendCmd(const char *cmd, const char *expect, const char *error, int16_t BSP_LTE_SendCmd(const char *cmd, const char *expect, const char *error,
uint32_t waittime) { uint32_t waittime) {
lte_diag_at_begin(cmd); lte_diag_at_begin(cmd);
@ -167,6 +715,7 @@ int16_t BSP_LTE_SendCmd(const char *cmd, const char *expect, const char *error,
sizeof(lte_dev.at_buf)); sizeof(lte_dev.at_buf));
if (read_len > 0) { if (read_len > 0) {
lte_diag_uart2_rx((rt_size_t)read_len); lte_diag_uart2_rx((rt_size_t)read_len);
lte_process_text(lte_dev.at_buf, (rt_size_t)read_len);
} }
LOG_I("%s\n", lte_dev.at_buf); LOG_I("%s\n", lte_dev.at_buf);

70
applications/drv_ec800k.h

@ -66,7 +66,9 @@ extern "C" {
#define AT_CGREG "AT+CGREG?\r\n" // GPRS REG 2G #define AT_CGREG "AT+CGREG?\r\n" // GPRS REG 2G
#define AT_CEREG "AT+CEREG?\r\n" // EPS REG 4G #define AT_CEREG "AT+CEREG?\r\n" // EPS REG 4G
#define AT_CEREG0 "AT+CEREG=0\r\n" #define AT_CEREG0 "AT+CEREG=0\r\n"
#define AT_CEREG2 "AT+CEREG=2\r\n"
#define AT_CSQ "AT+CSQ\r\n" #define AT_CSQ "AT+CSQ\r\n"
#define AT_QNWINFO "AT+QNWINFO\r\n"
#define AT_CPSI "AT+CPSI?\r\n" #define AT_CPSI "AT+CPSI?\r\n"
#define AT_CIPMODE "AT+CIPMODE=1\r\n" #define AT_CIPMODE "AT+CIPMODE=1\r\n"
@ -88,6 +90,7 @@ extern "C" {
#define AT_TPCLOSE "+++\r\n" #define AT_TPCLOSE "+++\r\n"
#define AT_CIPSEND "AT+CIPSEND=%d,%d\r\n" #define AT_CIPSEND "AT+CIPSEND=%d,%d\r\n"
#define AT_QISEND "AT+QISEND=%d,%d\r\n" #define AT_QISEND "AT+QISEND=%d,%d\r\n"
#define AT_QISDE0 "AT+QISDE=0\r\n"
#define QI_SEND_OK "\r\nSEND OK\r\n" #define QI_SEND_OK "\r\nSEND OK\r\n"
#define QI_SEND_FAIL "\r\nSEND FAIL\r\n" #define QI_SEND_FAIL "\r\nSEND FAIL\r\n"
#define AT_CGMR "AT+CGMR\r\n" #define AT_CGMR "AT+CGMR\r\n"
@ -98,6 +101,8 @@ extern "C" {
#define AT_QIOPEN_TRANS \ #define AT_QIOPEN_TRANS \
"AT+QIOPEN=1,%d,\"%s\",\"%s\",%s,0,2\r\n" // transparent Mode "AT+QIOPEN=1,%d,\"%s\",\"%s\",%s,0,2\r\n" // transparent Mode
#define AT_QIOPEN_BUFFER \
"AT+QIOPEN=1,%d,\"%s\",\"%s\",%s,0,0\r\n" // buffer Mode
#define AT_QIOPEN_FORW \ #define AT_QIOPEN_FORW \
"AT+QIOPEN=1,%d,\"%s\",\"%s\",%s,0,1\r\n" // Immediate Forwarding Mode "AT+QIOPEN=1,%d,\"%s\",\"%s\",%s,0,1\r\n" // Immediate Forwarding Mode
@ -199,6 +204,7 @@ extern "C" {
//AT CFG //AT CFG
#define AT_CFG_TRANS_SIZE "AT+QICFG=\"transpktsize\",512\r\n" #define AT_CFG_TRANS_SIZE "AT+QICFG=\"transpktsize\",512\r\n"
#define AT_CFG_TRANS_WAITTM "AT+QICFG=\"transwaittm\",0\r\n" #define AT_CFG_TRANS_WAITTM "AT+QICFG=\"transwaittm\",0\r\n"
#define AT_CFG_RECV_IND "AT+QICFG=\"recvind\",1\r\n"
#define AT_CFG_PASSIVE_CLOSED "AT+QICFG=\"passiveclosed\",1\r\n" #define AT_CFG_PASSIVE_CLOSED "AT+QICFG=\"passiveclosed\",1\r\n"
#define AT_CFG_TCP_KEEPALIVE "AT+QICFG=\"tcp/keepalive\",1,30,25,3\r\n" #define AT_CFG_TCP_KEEPALIVE "AT+QICFG=\"tcp/keepalive\",1,30,25,3\r\n"
@ -206,9 +212,12 @@ extern "C" {
#define LTE_CMD_WAIT_QICLOSE (10000) #define LTE_CMD_WAIT_QICLOSE (10000)
#define LTE_CMD_WAIT_QIACT (150000) #define LTE_CMD_WAIT_QIACT (150000)
#define LTE_CMD_WAIT_QIDEACT (40000) #define LTE_CMD_WAIT_QIDEACT (40000)
#define LTE_CMD_WAIT_PROMPT (3000)
#define LTE_CMD_WAIT_SEND (10000)
#define LTE_SOCKET_RX_CHUNK_SIZE (128)
#define LTE_SOCKET_TX_CHUNK_SIZE (256)
/* Set after confirming the server MAVLink heartbeat period. 0 disables the
* application-level silence recovery and leaves NO CARRIER/keepalive active. */
/* Set after confirming the server MAVLink heartbeat period. */
#define LTE_SERVER_SILENCE_TIMEOUT_SEC (15) #define LTE_SERVER_SILENCE_TIMEOUT_SEC (15)
typedef struct { typedef struct {
@ -227,8 +236,23 @@ typedef enum {
LTE_DISC_AT_TIMEOUT, LTE_DISC_AT_TIMEOUT,
LTE_DISC_QIOPEN_FAILED, LTE_DISC_QIOPEN_FAILED,
LTE_DISC_MODULE_RESET, LTE_DISC_MODULE_RESET,
LTE_DISC_SERVER_SILENCE,
LTE_DISC_SOCKET_SEND,
} lte_disconnect_reason_t; } lte_disconnect_reason_t;
typedef struct {
int8_t cereg;
int8_t cgatt;
int8_t pdp;
int8_t csq;
char rat[12];
char oper[16];
char band[16];
char tac[9];
char cell[12];
rt_uint32_t channel;
} lte_network_snapshot_t;
typedef struct { typedef struct {
rt_uint32_t uart2_rx_bytes; rt_uint32_t uart2_rx_bytes;
rt_uint32_t uart2_tx_bytes; rt_uint32_t uart2_tx_bytes;
@ -250,17 +274,45 @@ typedef struct {
rt_uint32_t server_rx_bytes; rt_uint32_t server_rx_bytes;
rt_uint32_t server_rx_read_events; rt_uint32_t server_rx_read_events;
rt_uint32_t server_silence_timeout_count; rt_uint32_t server_silence_timeout_count;
rt_uint32_t socket_tx_bytes;
rt_uint32_t socket_send_ok;
rt_uint32_t socket_send_fail;
rt_uint32_t socket_prompt_timeouts;
rt_uint32_t socket_read_errors;
rt_uint32_t socket_acked_bytes;
rt_uint32_t socket_unacked_bytes;
rt_uint32_t socket_ack_queries;
rt_uint32_t socket_ack_errors;
rt_uint32_t tx_queue_drops;
rt_uint32_t tx_queue_high_water;
rt_uint32_t fmu_heartbeats;
rt_uint32_t server_heartbeats;
rt_uint32_t pdpdeact_count;
rt_uint32_t conn_fmu_rx_base;
rt_uint32_t conn_fmu_tx_base;
rt_uint32_t conn_server_rx_base;
rt_uint32_t conn_server_events_base;
rt_uint32_t conn_socket_tx_base;
rt_uint32_t conn_send_ok_base;
rt_uint32_t conn_send_fail_base;
rt_uint32_t conn_ack_queries_base;
rt_uint32_t conn_queue_drops_base;
rt_uint32_t conn_fmu_heartbeat_base;
rt_uint32_t conn_server_heartbeat_base;
rt_tick_t last_uart2_rx_tick; rt_tick_t last_uart2_rx_tick;
rt_tick_t last_uart2_tx_tick; rt_tick_t last_uart2_tx_tick;
rt_tick_t last_fmu_rx_tick; rt_tick_t last_fmu_rx_tick;
rt_tick_t last_fmu_tx_tick; rt_tick_t last_fmu_tx_tick;
rt_tick_t last_server_rx_tick; rt_tick_t last_server_rx_tick;
rt_tick_t last_socket_ack_tick;
rt_tick_t connect_tick; rt_tick_t connect_tick;
rt_tick_t last_disconnect_tick; rt_tick_t last_disconnect_tick;
rt_tick_t last_at_elapsed; rt_tick_t last_at_elapsed;
rt_int32_t last_at_result; rt_int32_t last_at_result;
char last_at_cmd[20]; char last_at_cmd[20];
lte_disconnect_reason_t last_disconnect_reason; lte_disconnect_reason_t last_disconnect_reason;
lte_network_snapshot_t network;
bool disconnect_report_pending;
} lte_diag_t; } lte_diag_t;
extern lte_diag_t lte_diag; extern lte_diag_t lte_diag;
@ -272,6 +324,8 @@ void lte_diag_uart2_tx(rt_size_t size);
void lte_diag_uart_error(const char *name, rt_uint32_t error_code); void lte_diag_uart_error(const char *name, rt_uint32_t error_code);
void lte_diag_fmu_rx(rt_size_t size); void lte_diag_fmu_rx(rt_size_t size);
void lte_diag_fmu_tx(rt_size_t size); void lte_diag_fmu_tx(rt_size_t size);
void lte_diag_fmu_data(const uint8_t *data, rt_size_t size);
void lte_diag_server_data(const uint8_t *data, rt_size_t size);
void lte_diag_connect_attempt(void); void lte_diag_connect_attempt(void);
void lte_diag_connect_success(void); void lte_diag_connect_success(void);
void lte_diag_disconnect(lte_disconnect_reason_t reason); void lte_diag_disconnect(lte_disconnect_reason_t reason);
@ -299,6 +353,9 @@ typedef struct {
bool reset_flag; bool reset_flag;
bool dev_init_flag; bool dev_init_flag;
volatile bool data_tx_paused; volatile bool data_tx_paused;
volatile bool socket_recv_pending;
volatile bool socket_closed_pending;
volatile bool socket_pdpdeact_pending;
} CLte_dev_t; } CLte_dev_t;
extern CLte_dev_t lte_dev; extern CLte_dev_t lte_dev;
@ -320,6 +377,15 @@ void BSP_LTE_SetDataTxPaused(bool paused);
void BSP_LTE_Config(void); void BSP_LTE_Config(void);
void BSP_LTE_InitLogClock(void); void BSP_LTE_InitLogClock(void);
int16_t BSP_LTE_OpenSocket(const char *cmd, uint8_t connect_id);
int16_t BSP_LTE_SendSocketData(uint8_t connect_id, const uint8_t *data,
uint16_t length);
int16_t BSP_LTE_ReadSocketData(uint8_t connect_id, uint8_t *data,
uint16_t capacity);
int16_t BSP_LTE_QuerySocketSendStatus(uint8_t connect_id);
void BSP_LTE_PollSocketUrc(uint32_t waittime);
void BSP_LTE_ClearSocketEvents(void);
void BSP_LTE_CollectNetworkSnapshot(void);
int BSP_LTE_GetICCID(char *pICCID); int BSP_LTE_GetICCID(char *pICCID);

2711
docs/Quectel_LTE_StandardA_AT命令手册.md

File diff suppressed because it is too large

1263
docs/Quectel_LTE_StandardA系列_TCPIP_应用指导_V1.6.md

File diff suppressed because it is too large
Loading…
Cancel
Save