初始提交

This commit is contained in:
2024-09-28 14:24:04 +08:00
commit c756587541
5564 changed files with 2413077 additions and 0 deletions

41
driver/extern/gsm/inc/c20_gsm_driver.h vendored Normal file
View File

@@ -0,0 +1,41 @@
/****************************************************************************
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
be copied by any method or incorporated into another program without
the express written consent of Aerospace C.Power. This Information or any portion
thereof remains the property of Aerospace C.Power. The Information contained herein
is believed to be accurate and Aerospace C.Power assumes no responsibility or
liability for its use in any way and conveys no license or title under
any patent or copyright and makes no representation or warranty that this
Information is free from patent or copyright infringement.
****************************************************************************/
#ifndef C20_GSM_DRIVER_H
#define C20_GSM_DRIVER_H
#ifdef __cplusplus
extern "C" {
#endif
/* @brief c20_gps_report_cb() - report gps information.
* @iot_gps_rpt_info_t see - iot_gps_rpt_info_t.
*/
typedef void (*c20_gps_report_cb)(const iot_gps_rpt_info_t *gps_rpt_info);
/* @brief c20_gsm_init() - init c20 gsm device.
* @c20_gps_report_cb: callback function , see - c20_gps_report_cb.
* @retval: ERR_OK - init successfully, otherwise - error code
*/
uint32_t c20_gsm_init(c20_gps_report_cb location_cb);
/* @brief c20_gsm_deinit() - deinit c20 gsm device.
*/
void c20_gsm_deinit();
#ifdef __cplusplus
}
#endif
#endif /* C20_GSM_DRIVER_H */

541
driver/extern/gsm/src/c20_gsm_driver.c vendored Normal file
View File

@@ -0,0 +1,541 @@
/****************************************************************************
*
* Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
*
* This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
* be copied by any method or incorporated into another program without
* the express written consent of Aerospace C.Power. This Information or any portion
* thereof remains the property of Aerospace C.Power. The Information contained herein
* is believed to be accurate and Aerospace C.Power assumes no responsibility or
* liability for its use in any way and conveys no license or title under
* any patent or copyright and makes no representation or warranty that this
* Information is free from patent or copyright infringement.
*
* ****************************************************************************/
/* os_shim header files */
#include "os_types_api.h"
#include "os_utils_api.h"
#include "os_timer_api.h"
/* iot common header files */
#include "iot_io_api.h"
#include "iot_errno_api.h"
#include "iot_uart_h.h"
#include "iot_uart_api.h"
#include "iot_string.h"
#include "iot_utils_api.h"
#include "iot_board.h"
#include "iot_task_api.h"
#include "iot_gpio_api.h"
#include "iot_gsm_ext_api.h"
#include "c20_gsm_driver.h"
#define C20_GSM_TASK_PRIO 7
#define C20_GSM_TASK_STACK_SIZE 512
#define C20_GSM_TASK_MSG_COUNT 32
/* message to rise init action. */
#define C20_GSM_MSG_TYPE_DO_INIT 0
#define C20_GSM_MSG_TYPE_DO_UART 1
/* max retry count */
#define C20_GSM_CMD_MAX_RETRY_CNT 3
/* device status */
#define C20_STATE_POWER_OFF 0
#define C20_STATE_POWER_ON 1
#define C20_STATE_GPS_SETTING 2
#define C20_STATE_GET_LOCATION 3
/* cmd timout unit: ms */
#define C20_CMD_TIMEOUT 3000
/* gps data monitor timeout time unit: ms */
#define C20_GPS_DATA_MONITOR_TMOUT 60000
/* c20 device reset wait time unit: ms */
#define C20_GPS_RETSET_WAITTM 3000
typedef struct _c20_gsm_msg_type_t {
iot_task_msg_t msg; /* The main entity of message. */
void *data; /* The user data inside this message. */
} c20_gsm_msg_t;
typedef struct {
/* gps uart handle */
iot_uart_h uart_h;
/* task handle */
iot_task_h task_h;
/* refresh timer */
timer_id_t refresh_timer;
/* device status */
uint8_t state;
/* send cmd step */
uint8_t cmd_step;
/* cmd retry cnt */
uint8_t cmd_retry;
/* control gpio */
uint8_t ctrl_pin;
/* report data to loader from callback */
c20_gps_report_cb local_cb;
} c20_gsm_handle;
static c20_gsm_handle *gsm_handle = NULL;
#if IOT_GSM_DRIVER_DEBUG
#define iot_gsm_dbg_print(fmt, ...) iot_printf(fmt, ##__VA_ARGS__)
#else
#define iot_gsm_dbg_print(fmt, ...)
#endif
static void c20_gsm_changed_state(uint32_t state)
{
if (gsm_handle->state != (uint8_t)state) {
gsm_handle->state = (uint8_t)state;
gsm_handle->cmd_retry = 0;
gsm_handle->cmd_step = 0;
}
}
static int c20_gsm_get_reset_active_level()
{
uint32_t ver = iot_board_hw_version_hex();
if (ver == HW_VERSION_BRMT_I3C_V1) {
return 1;
}
return 0;
}
/* post message to task */
static void c20_gsm_post_msg(uint16_t msg_type, uint16_t msg_id, void *data)
{
iot_task_msg_t *msg;
c20_gsm_msg_t *task_msg;
msg = iot_task_alloc_msg_with_reserved(gsm_handle->task_h, 0);
if (NULL == msg) {
IOT_ASSERT(0);
}
task_msg = (c20_gsm_msg_t *)msg;
task_msg->msg.type = msg_type;
task_msg->msg.id = msg_id;
task_msg->data = data;
iot_task_queue_msg(gsm_handle->task_h, &task_msg->msg, 0);
return;
}
static void c20_gsm_cmd_send(const char *cmd, uint32_t timeout)
{
iot_pkt_t *pkt;
uint32_t len = iot_strlen(cmd);
iot_printf("gps send : %s \n", cmd);
pkt = iot_pkt_alloc(len, IOT_DRIVER_MID);
if (!pkt) {
IOT_ASSERT(0);
}
os_mem_cpy(iot_pkt_data(pkt), cmd, len);
iot_pkt_put(pkt, len);
iot_uart_send(gsm_handle->uart_h, pkt, NULL);
os_start_timer(gsm_handle->refresh_timer, timeout);
}
static void c20_gsm_reset(void)
{
/* Just post msg to reset gsm chip */
c20_gsm_post_msg(C20_GSM_MSG_TYPE_DO_INIT, 0, 0);
}
static void c20_gsm_get_dms(char *ddmm_mm, gps_location *location)
{
char *ptr;
uint32_t part1;
uint32_t dec_len = 0;
char decimal[5];
ptr = iot_strchr(ddmm_mm, '.');
if (ptr) {
*ptr = 0;
ptr++;
os_mem_set(decimal, '0', sizeof(decimal));
dec_len = iot_strlen(ptr);
os_mem_cpy(decimal, ptr, dec_len > 4 ? 4 : dec_len);
decimal[4] = 0;
part1 = (uint32_t)iot_atoi(decimal);
part1 *= 60;
location->sec = part1 / 100;
}
part1 = (uint32_t)iot_atoi(ddmm_mm);
location->min = part1 % 100;
location->degree = (part1 / 100);
}
static uint32_t c20_gsm_parse_location(char *src, uint32_t len,
iot_gps_rpt_info_t *gps_rpt_info)
{
char *pre_ptr = src;
char *tail_ptr;
char *tmp_ptr;
uint8_t parase_index = 0;
uint32_t utc_value;
tail_ptr = iot_strstr(pre_ptr, ",");
while (tail_ptr) {
*tail_ptr = 0;
iot_gsm_dbg_print("parase gps %s\n", pre_ptr);
switch (parase_index) {
case 1:
utc_value = iot_atoi(pre_ptr);
gps_rpt_info->utc_tm.hour = utc_value / 10000 % 24;
gps_rpt_info->utc_tm.minu = utc_value % 10000 / 100 % 60;
gps_rpt_info->utc_tm.sec = utc_value % 100 % 60;
tmp_ptr = iot_strstr(pre_ptr, ".");
if (tmp_ptr) {
gps_rpt_info->utc_tm.mill_sec = (uint16_t)iot_atoi(++tmp_ptr);
}
break;
case 2:
if (*pre_ptr == 'A') {
gps_rpt_info->gps_valid = 1;
}
break;
case 3:
c20_gsm_get_dms(pre_ptr, &(gps_rpt_info->latitude));
break;
case 4:
if (*pre_ptr == 'N') {
gps_rpt_info->latitude.single = 0;
} else {
gps_rpt_info->latitude.single = 1;
}
break;
case 5:
c20_gsm_get_dms(pre_ptr, &(gps_rpt_info->longtitude));
break;
case 6:
if (*pre_ptr == 'E') {
gps_rpt_info->longtitude.single = 0;
} else {
gps_rpt_info->longtitude.single = 1;
}
break;
case 9:
utc_value = iot_atoi(pre_ptr);
gps_rpt_info->utc_tm.day = utc_value / 10000 % 100 % 32;
gps_rpt_info->utc_tm.month = utc_value % 10000 / 100 % 13;
gps_rpt_info->utc_tm.year = utc_value % 100;
return ERR_OK;
break;
default:
break;
}
if (len < (uint8_t )(iot_strlen((const char *)pre_ptr) +
iot_strlen(","))) {
break;
} else {
len -= (iot_strlen((const char *)pre_ptr) + iot_strlen(","));
}
tail_ptr++;
parase_index++;
pre_ptr = tail_ptr;
tail_ptr = iot_strstr(pre_ptr, ",");
}
return ERR_AGAIN;
}
static void c20_gsm_uart_recv(uint8_t* buffer, uint32_t buffer_len,
bool_t is_full_frame, uint32_t invalid_data_len)
{
iot_pkt_t *pkt;
(void)invalid_data_len;
(void)is_full_frame;
iot_gsm_dbg_print("gsm uart recv len %d : %s \n", buffer_len, buffer);
pkt = iot_pkt_alloc(buffer_len, IOT_DRIVER_MID);
if (pkt) {
os_mem_cpy(iot_pkt_put(pkt, buffer_len), buffer, buffer_len);
c20_gsm_post_msg(C20_GSM_MSG_TYPE_DO_UART, 0, pkt);
}
}
static void c20_gsm_recv_handle(iot_pkt_t *pkt)
{
char *buffer = NULL;
char *ptr = NULL;
uint32_t buffer_len = 0;
uint32_t ret;
iot_gps_rpt_info_t gps_rpt_info = { 0 };
if (pkt) {
buffer = (char *)iot_pkt_data(pkt);
buffer_len = iot_pkt_data_len(pkt);
}
switch (gsm_handle->state) {
case C20_STATE_POWER_OFF:
{
if (buffer) {
break;
}
if (!gsm_handle->cmd_step) {
iot_gpio_value_set(gsm_handle->ctrl_pin,
c20_gsm_get_reset_active_level());
os_start_timer(gsm_handle->refresh_timer, C20_GPS_RETSET_WAITTM);
gsm_handle->cmd_step++;
} else if (1 == gsm_handle->cmd_step) {
iot_gpio_value_set(gsm_handle->ctrl_pin,
!c20_gsm_get_reset_active_level());
os_start_timer(gsm_handle->refresh_timer, C20_GPS_RETSET_WAITTM);
gsm_handle->cmd_step++;
} else {
c20_gsm_changed_state(C20_STATE_POWER_ON);
c20_gsm_cmd_send("AT\r\n", C20_CMD_TIMEOUT);
}
break;
}
case C20_STATE_POWER_ON:
{
if (!buffer) {
if (++gsm_handle->cmd_retry >= C20_GSM_CMD_MAX_RETRY_CNT) {
c20_gsm_reset();
} else {
c20_gsm_cmd_send("AT\r\n", C20_CMD_TIMEOUT);
}
break;
}
if (iot_strstr(buffer, "AT")) {
c20_gsm_changed_state(C20_STATE_GPS_SETTING);
c20_gsm_cmd_send("AT+QGNSSC=1\r\n", C20_CMD_TIMEOUT);
}
break;
}
case C20_STATE_GPS_SETTING:
{
if (!buffer) {
if (++gsm_handle->cmd_retry >= C20_GSM_CMD_MAX_RETRY_CNT) {
c20_gsm_reset();
break;
}
}
if (0 == gsm_handle->cmd_step) {
if (!buffer) {
c20_gsm_cmd_send("AT+QGNSSC=1\r\n", C20_CMD_TIMEOUT);
} else if (buffer && iot_strstr(buffer, "OK")) {
c20_gsm_cmd_send("AT+QGNSSC?\r\n", C20_CMD_TIMEOUT);
gsm_handle->cmd_step++;
gsm_handle->cmd_retry = 0;
}
} else if (1 == gsm_handle->cmd_step) {
if (!buffer) {
c20_gsm_cmd_send("AT+QGNSSC?\r\n", C20_CMD_TIMEOUT);
} else if (iot_strstr(buffer, "QGNSSC: 1")) {
c20_gsm_cmd_send(
"AT+QGNSSCMD=0,\"$PMTK353,1,1,1,0,0*2A\"\r\n",
C20_CMD_TIMEOUT);
gsm_handle->cmd_step++;
gsm_handle->cmd_retry = 0;
} else if (iot_strstr(buffer, "QGNSSC: 0")) {
c20_gsm_cmd_send("AT+QGNSSC=1\r\n", C20_CMD_TIMEOUT);
gsm_handle->cmd_step = 0;
gsm_handle->cmd_retry = 0;
}
} else {
if (!buffer) {
c20_gsm_cmd_send(
"AT+QGNSSCMD=0,\"$PMTK353,1,1,1,0,0*2A\"\r\n",
C20_CMD_TIMEOUT);
} else if (iot_strstr(buffer, "OK")){
c20_gsm_changed_state(C20_STATE_GET_LOCATION);
os_start_timer(gsm_handle->refresh_timer,
C20_GPS_DATA_MONITOR_TMOUT);
}
}
break;
}
case C20_STATE_GET_LOCATION:
{
if (!buffer) {
c20_gsm_reset();
break;
}
ptr = iot_strstr(buffer, "RMC,");
if (ptr) {
buffer_len -= (ptr - buffer);
ret = c20_gsm_parse_location(ptr, buffer_len, &gps_rpt_info);
if (ERR_OK == ret) {
if (gsm_handle->local_cb) {
gsm_handle->local_cb(&gps_rpt_info);
}
}
os_start_timer(gsm_handle->refresh_timer,
C20_GPS_DATA_MONITOR_TMOUT);
gsm_handle->cmd_retry = 0;
}
break;
}
default:
break;
}
if (pkt) {
iot_pkt_free(pkt);
}
}
/* init gsm chip */
static uint32_t c20_gsm_init_chip(void)
{
c20_gsm_changed_state(C20_STATE_POWER_OFF);
os_start_timer(gsm_handle->refresh_timer, 1);
return ERR_OK;
}
static void c20_gsm_msg_handle(iot_task_h task_h, iot_task_msg_t *msg)
{
c20_gsm_msg_t *gsm_msg = (c20_gsm_msg_t *)msg;
switch (gsm_msg->msg.type) {
case C20_GSM_MSG_TYPE_DO_INIT:
c20_gsm_init_chip();
break;
case C20_GSM_MSG_TYPE_DO_UART:
c20_gsm_recv_handle((iot_pkt_t *)gsm_msg->data);
break;
default:
iot_printf("gsm module Unknown MSG-TYPE %d!\n", gsm_msg->msg.type);
break;
}
iot_task_free_msg(task_h, &(gsm_msg->msg));
return;
}
static void c20_gsm_msg_cancel(iot_task_h task_h, iot_task_msg_t *msg)
{
c20_gsm_msg_t *gsm_msg = (c20_gsm_msg_t *)msg;
if ((gsm_msg->msg.type == C20_GSM_MSG_TYPE_DO_UART) && gsm_msg->data) {
iot_pkt_free((iot_pkt_t *)gsm_msg->data);
}
iot_task_free_msg(task_h, &(gsm_msg->msg));
return;
}
static void c20_gsm_refresh(timer_id_t timer_id, void *arg)
{
(void)timer_id;
(void)arg;
/* wait device timeout */
c20_gsm_post_msg(C20_GSM_MSG_TYPE_DO_UART, 0, NULL);
}
uint32_t c20_gsm_init(c20_gps_report_cb location_cb)
{
uint32_t ret = ERR_OK;
iot_task_config_t t_cfg;
iot_frame_fmt fmt = { 0 };
if (!location_cb) {
return ERR_INVAL;
}
if (gsm_handle) {
return ret;
}
gsm_handle = os_mem_malloc(IOT_DRIVER_MID, sizeof(*gsm_handle));
if (gsm_handle == NULL) {
ret = ERR_NOMEM;
return ret;
}
/* init task */
t_cfg.stack_size = C20_GSM_TASK_STACK_SIZE;
t_cfg.task_prio = C20_GSM_TASK_PRIO;
t_cfg.msg_size = sizeof(c20_gsm_msg_t);
t_cfg.msg_cnt = C20_GSM_TASK_MSG_COUNT;
t_cfg.queue_cnt = 1;
t_cfg.queue_cfg[0].quota = 0;
t_cfg.task_event_func = NULL;
t_cfg.msg_exe_func = c20_gsm_msg_handle;
t_cfg.msg_cancel_func = c20_gsm_msg_cancel;
gsm_handle->task_h = iot_task_create(IOT_DRIVER_MID, &t_cfg);
if (NULL == gsm_handle->task_h) {
iot_printf("gsm module Init task failed!\n", __LINE__);
goto task_error;
}
gsm_handle->refresh_timer = os_create_timer(IOT_DRIVER_MID, false,
c20_gsm_refresh, NULL);
if (gsm_handle->refresh_timer == 0) {
goto create_timer_failed;
}
gsm_handle->ctrl_pin = iot_board_get_gpio(GPIO_GPS_RST_CTRL);
if (gsm_handle->ctrl_pin == 0xff) {
goto gpio_err;
}
if ( -1 == iot_gpio_open_as_output(gsm_handle->ctrl_pin)) {
goto gpio_err;
}
iot_gpio_value_set(gsm_handle->ctrl_pin,
c20_gsm_get_reset_active_level());
/* open gsm serial port */
fmt.preamble_code[0] = 0;
fmt.preamble_codelen = 0;
fmt.datalen_offset = 0;
fmt.datalen_size = 0;
fmt.backcode_offset = 1;
fmt.backcode_len = 2;
fmt.datalen_fix = 0;
fmt.backcode[0] = 0x0d;
fmt.backcode[1] = 0x0a;
fmt.frame_timeout = 20;
fmt.timeout_mode = TIMEOUT_PERDATA;
if (iot_board_get_uart(UART_EXT_GPS_PORT) >= IOT_UART_PORT_SUPP_MAX) {
goto uart_error;
}
gsm_handle->uart_h = iot_uart_open(iot_board_get_uart(UART_EXT_GPS_PORT),
c20_gsm_uart_recv, 1024, &fmt);
if (gsm_handle->uart_h == NULL) {
goto uart_error;
}
gsm_handle->local_cb = location_cb;
c20_gsm_reset();
return ret;
uart_error:
iot_gpio_close(gsm_handle->ctrl_pin);
gpio_err:
os_delete_timer(gsm_handle->refresh_timer);
create_timer_failed:
iot_task_delete(gsm_handle->task_h);
gsm_handle->task_h = NULL;
task_error:
os_mem_free(gsm_handle);
gsm_handle = NULL;
ret = ERR_NOMEM;
return ret;
}
void c20_gsm_deinit()
{
if (!gsm_handle) {
return;
}
if (gsm_handle->uart_h) {
iot_uart_close(gsm_handle->uart_h);
gsm_handle->uart_h = NULL;
}
iot_gpio_value_set(gsm_handle->ctrl_pin,
c20_gsm_get_reset_active_level());
iot_gpio_close(gsm_handle->ctrl_pin);
os_delete_timer(gsm_handle->refresh_timer);
iot_task_delete(gsm_handle->task_h);
os_mem_free(gsm_handle);
gsm_handle = NULL;
}

126
driver/extern/gsm/src/iot_gsm_ext.c vendored Normal file
View File

@@ -0,0 +1,126 @@
/****************************************************************************
*
* Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
*
* This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
* be copied by any method or incorporated into another program without
* the express written consent of Aerospace C.Power. This Information or any portion
* thereof remains the property of Aerospace C.Power. The Information contained herein
* is believed to be accurate and Aerospace C.Power assumes no responsibility or
* liability for its use in any way and conveys no license or title under
* any patent or copyright and makes no representation or warranty that this
* Information is free from patent or copyright infringement.
*
* ****************************************************************************/
#include "os_types.h"
#include "os_mem_api.h"
#include "iot_config.h"
#include "iot_errno_api.h"
#include "iot_io_api.h"
#include "iot_config_api.h"
#include "iot_gsm_ext_api.h"
#if IOT_GSM_EXT_ENABLE
#define IOT_GSM_EXT_MODULE_ID IOT_GSM_EXT_MODULE_C20
#if (IOT_GSM_EXT_MODULE_ID == IOT_GSM_EXT_MODULE_C20)
#include "c20_gsm_driver.h"
#endif
/* gsm extern module information context */
typedef struct _iot_gsm_ext_ctxt {
/* gps info report callback */
iot_gsm_gps_report_cb gps_rpt_cb;
} iot_gsm_ext_ctxt_t;
static iot_gsm_ext_ctxt_t *g_gsm_ext_ctxt = NULL;
#if (IOT_GSM_EXT_MODULE_ID == IOT_GSM_EXT_MODULE_C20)
static void c20_gps_report_callback(const iot_gps_rpt_info_t *gps_rpt_info)
{
g_gsm_ext_ctxt->gps_rpt_cb(gps_rpt_info);
}
#endif
uint32_t iot_gsm_ext_module_open(iot_gsm_gps_report_cb gps_rpt_cb)
{
uint32_t reason = 0;
if (!gps_rpt_cb) {
return ERR_INVAL;
}
if (g_gsm_ext_ctxt) {
iot_printf("gsm_ext:exist\n");
return ERR_OK;
}
do {
/* alloc gsm extern module ctxt */
if (NULL == (g_gsm_ext_ctxt = os_mem_malloc(IOT_DRIVER_MID,
sizeof(*g_gsm_ext_ctxt)))) {
reason = (uint32_t)__LINE__;
break;
}
os_mem_set(g_gsm_ext_ctxt, 0, sizeof(*g_gsm_ext_ctxt));
#if (IOT_GSM_EXT_MODULE_ID == IOT_GSM_EXT_MODULE_C20)
/* init module id */
if (ERR_OK != c20_gsm_init(c20_gps_report_callback)) {
reason = (uint32_t)__LINE__;
break;
}
#else
reason = (uint32_t)__LINE__;
break;
#endif
} while(0);
iot_printf("gsm_ext:open.reason-%d\n", reason);
if (reason) {
#if (IOT_GSM_EXT_MODULE_ID == IOT_GSM_EXT_MODULE_C20)
c20_gsm_deinit();
#endif
if (g_gsm_ext_ctxt) {
os_mem_free(g_gsm_ext_ctxt);
g_gsm_ext_ctxt = NULL;
}
return ERR_FAIL;
} else {
g_gsm_ext_ctxt->gps_rpt_cb = gps_rpt_cb;
return ERR_OK;
}
}
uint32_t iot_gsm_ext_module_close(void)
{
if (NULL == g_gsm_ext_ctxt) {
return ERR_INVAL;
}
/* deinit hw */
#if (IOT_GSM_EXT_MODULE_ID == IOT_GSM_EXT_MODULE_C20)
c20_gsm_deinit();
#endif
/* free ctxt memory */
os_mem_free(g_gsm_ext_ctxt);
g_gsm_ext_ctxt = NULL;
iot_printf("gsm_ext:closed\n");
return ERR_OK;
}
#else /* IOT_GSM_EXT_ENABLE */
uint32_t iot_gsm_ext_module_open(iot_gsm_gps_report_cb gps_rpt_cb)
{
(void)gps_rpt_cb;
return ERR_NOSUPP;
}
uint32_t iot_gsm_ext_module_close(void)
{
return ERR_OK;
}
#endif /* IOT_GSM_EXT_ENABLE */