Files
banban/ql-kernel/threadx/quec/gps_channel.c
T

556 lines
16 KiB
C

/*============================================================================================
Copyright(c) 2018 Quectel Wierless Solution,Co.,Ltd. All Rights Reserved.
Quectel Wireless Solution Proprietary and Confidential.
============================================================================*/
#include "gps_channel.h"
#include "quec_rtos.h"
#include "UART.h"
#include "quec_uart.h"
#include "gps_debug.h"
#include "cgpio.h"
#include "pmic_rtc.h"
#include "quec_rtc.h"
#include "quec_net_app.h"
#include "sockets.h"
#include "netdb.h"
#include "quec_sockets.h"
#include "gps_app.h"
#include "quec_mfpr_api.h"
#define GPS_VIA_UART
char g_gps_data_buf[4096] = {0};
g_gps_channel_t g_gps_channel;
GPS_CHANNEL_TYPE g_gps_channel_type = CHANNEL_TYPE_UART;
static quec_mutex_t gps_uart_mutexref;
static quec_mutex_t gps_uart_mutexref_tx;
quec_gps_gpio_struct_t gps_gpio_pin;
extern int get_ntp_time_type(void);
extern int GetNTPStatus(void);
extern void get_ntp_time_internal(void);
extern int quec_boardcfg_gnss_pin_init(quec_gps_gpio_struct_t *gpio_pin);
static void quec_uart_callback(char port, void *para)
{
if(g_gps_channel.m_event_callback != NULL)
{
g_gps_channel.m_event_callback(para);
}
}
void gps_event_register_cb(gnss_event_callback cb)
{
g_gps_channel.m_event_callback = cb;
}
void gps_delay_ms(unsigned int ms)
{
if(ms<5)
ms = 5;
quec_rtos_task_sleep_ms(ms);
}
char gps_uart_init()
{
quec_uart_config_t dcb;
quec_uart_register_cb(UART_PORT_BTUART, quec_uart_callback);
quec_uart_open(UART_PORT_BTUART, QUEC_UART_BAUD_921600,QUEC_FC_NONE);
dcb.baudrate = QUEC_UART_BAUD_921600;
dcb.parity_bit=QUEC_UART_PARITY_NONE;
dcb.stop_bit=QUEC_UART_STOP_1;
dcb.data_bit=QUEC_UART_DATABIT_8;
quec_uart_set_dcbconfig(UART_PORT_BTUART, &dcb);
return TRUE;
}
//将uart配置成输入下拉模式防止朝GNSS漏电
static void quec_gnss_gpio_set_pulldown(int pin)
{
GPIOConfiguration gpio_config_data = {
.pinDir = GPIO_IN_PIN,
.pinPull = GPIO_PULLDN_ENABLE,
.initLv = 0,
.pinEd = GPIO_NO_EDGE,
.isr = NULL,
.wu = NULL,
};
GpioInitConfiguration(pin, gpio_config_data);
*(volatile unsigned long *)(GPIO_MFPR_ADDR(pin)) = MFP_AF0;
//初始化时增加设置gpio上下拉操作,修复gpio设置为输入时,上下拉不生效
GpioSetPullControl(pin, GPIO_PULLDN_ENABLE);
}
//rest 默认输入浮空,quectel不在控制,和芯内部弱上拉
static void quec_gnss_rest_gpio_set_float(int pin)
{
GPIOConfiguration gpio_config_data = {
.pinDir = GPIO_IN_PIN,
.pinPull = GPIO_PULL_DISABLE,
.initLv = 0,
.pinEd = GPIO_NO_EDGE,
.isr = NULL,
.wu = NULL,
};
GpioInitConfiguration(pin, gpio_config_data);
*(volatile unsigned long *)(GPIO_MFPR_ADDR(pin)) = MFP_AF0;
GpioSetPullControl(pin, GPIO_PULL_DISABLE);
}
//将uart配置成输入下拉模式防止朝GNSS漏电
static void quec_gnss_uart_low_power(void)
{
#if defined(QUEC_HX_GNSS_SUPPORT)
/*初始化gnss引脚*/
quec_boardcfg_gnss_pin_init(&gps_gpio_pin);
quec_gnss_gpio_set_pulldown(gps_gpio_pin.rx);
quec_gnss_gpio_set_pulldown(gps_gpio_pin.tx);
quec_gnss_rest_gpio_set_float(gps_gpio_pin.rst);
if(gps_gpio_pin.pwr_en)
{
/*默认需配置输入上拉,防止漏电*/
#if defined (__QUECTEL_PROJECT_EG915NLA_GK__)
*(volatile unsigned long *)(GPIO_MFPR_ADDR(gps_gpio_pin.pwr_en)) = MFP_AF0;
#else
*(volatile unsigned long *)(GPIO_MFPR_ADDR(gps_gpio_pin.pwr_en)) = MFP_AF1;
#endif
GpioSetDirection(gps_gpio_pin.pwr_en, GPIO_IN_PIN);
GpioSetPullControl(gps_gpio_pin.pwr_en, GPIO_PULLUP_ENABLE);
}
#endif
}
char gps_uart_deinit()
{
int ret=0;
ret=quec_uart_close(UART_PORT_BTUART);
#if defined(QUEC_HX_GNSS_SUPPORT)
quec_gnss_uart_low_power();
#endif
return (ret == 0);
}
unsigned int gps_uart_get_byte_status(void)
{
unsigned int len = 0;
len = quec_uart_get_rxrb_data_len(UART_PORT_BTUART);
//GPS_LOGI("%d",len);
return len;
}
unsigned int gps_uart_get_byte_buffer(char *buf, unsigned int len)
{
int rck=0;
int read_len=0;
quec_rtos_mutex_lock(gps_uart_mutexref, QUEC_WAIT_FOREVER);
read_len = quec_uart_read(UART_PORT_BTUART, (unsigned char*)buf, len);
quec_rtos_mutex_unlock(gps_uart_mutexref);
if (read_len <= 0)
{
rck=FALSE;
}
else
{
rck=(unsigned int)read_len;
}
//quec_rtos_mutex_unlock(gps_uart_mutexref);
GPS_LOGI(" length=%d received_len=%d", len, rck);
return rck;
}
unsigned int gps_uart_put_byte_buffer(char *buf, unsigned int length)
{
int len = 0;
unsigned int ret = 0;
quec_rtos_mutex_lock(gps_uart_mutexref_tx, QUEC_WAIT_FOREVER);
quec_uart_write_sync(UART_PORT_BTUART,(unsigned char*)buf,length);
quec_rtos_mutex_unlock(gps_uart_mutexref_tx);
return length;
}
void gps_uart_purge_fifo()
{
quec_uart_flush_fifo(UART_PORT_BTUART);
GPS_LOGI(" clear fifo...");
}
void gps_uart_set_baudrate(int baud_rate)
{
quec_uart_config_t dcb;
dcb.baudrate = (QUEC_UART_BAUD_E)baud_rate;
dcb.parity_bit=QUEC_UART_PARITY_NONE;
dcb.stop_bit=QUEC_UART_STOP_1;
dcb.data_bit=QUEC_UART_DATABIT_8;
quec_uart_set_dcbconfig(UART_PORT_BTUART, &dcb);
GPS_LOGI("baud_rate=%d", baud_rate);
}
void gps_gpio_set_level(unsigned int pin_num,unsigned int level)
{
*(volatile unsigned long *)(GPIO_MFPR_ADDR(pin_num)) = 0x00;
GPIOConfiguration gpio_config_data = {
.pinDir = GPIO_OUT_PIN,
.pinPull = GPIO_PULLDN_ENABLE,
.initLv = level,
.pinEd = GPIO_NO_EDGE,
.isr = NULL,
.wu = NULL,
};
GpioInitConfiguration(pin_num, gpio_config_data);
}
extern int GetTimeZone(void);
unsigned int gps_get_rtc_time(void)
{
unsigned int rtc_cnt = 0;
rtc_cnt = PMIC_RTC_GetTime_Count(SYS_OFFSET)-(GetTimeZone()*60);
return rtc_cnt;
}
typedef struct
{
int cid;
char * url; // dup from user setting
char * host; //
char * path; //
char * name;
char * password;
unsigned short int port;
int auth_type;
int https;
char * auth_value;
struct sockaddr_in ip;
struct sockaddr_in6 ip6;
int use_ip6;
int url_is_ip6_address;
int fd;
}QL_NTP_SERVSER;
typedef struct
{
struct in_addr gps_ip4_addr;
int pdp_cid;
quec_task_t gps_nw_task;
char nw_status;
char rtc_status;
} gps_nw_t;
char ntp_hostname[32];
gps_nw_t gps_nw_ctx_ptr ;
struct in_addr quec_get_gps_ip4_addr(void)
{
return gps_nw_ctx_ptr.gps_ip4_addr;
}
char *get_ntp_server_ip(void)
{
return &ntp_hostname[0];
}
int ntp_server_setting(char *ntp_svr_ip, int size ){
if(ntp_svr_ip == NULL)
return -1;
memset(ntp_hostname,0,sizeof(ntp_hostname));
memcpy(ntp_hostname, ntp_svr_ip, size);
return 0;
}
static int quec_is_valid_ip46_address(char *ip_string)
{
int a,b,c,d;
char* temp;
int flag=0;
if((sscanf(ip_string,"%d.%d.%d.%d",&a,&b,&c,&d)==4)
&& a>=0&&a<=255
&& b>=0&&b<=255
&& c>=0&&c<=255
&& d>=0&&d<=255)
{
return 1;
}else{
temp=ip_string;
while(*temp!='\0')
{
if(*temp==':')
{
flag++;
temp++;
continue;
}else{
if(*temp=='0'
||(*temp>='1'&&*temp<='9')
||(*temp>='a'&&*temp<='f')
||(*temp>='A'&&*temp<='F')){
temp++;
}else{
return 0;
}
}
}
return 2;
}
}
int quec_gps_ntp_set_server(char *ntp_svr)
{
int ret;
QL_NTP_SERVSER ntp_server;
struct addrinfo * pres = NULL;
struct sockaddr_in * ip4_svr_addr;
char ntp_svr_ip[32]={0};
if(ntp_svr == NULL){
printf("ql_ntp_set_svr with error parameter !!\n");
return -4;
}
ntp_server.host = ntp_svr;
int valid_ip_flag=0;
ret= quec_is_valid_ip46_address(ntp_svr);
if(ret){
valid_ip_flag=1;
// memcpy(ntp_svr_ip, ntp_svr, sizeof(ntp_svr_ip));
if(ret==1)
{
struct sockaddr_in adr_inet;
unsigned int temp;
ntp_server.use_ip6 = 0;
inet_aton(ntp_server.host, &adr_inet.sin_addr);
ntp_server.ip.sin_addr = adr_inet.sin_addr;
ntp_server.ip.sin_family = AF_INET;
ntp_server.ip.sin_port = htons(ntp_server.port);
temp = (unsigned int)ntp_server.ip.sin_addr.s_addr;
}
else
{
struct sockaddr_in6 sa;
inet6_aton(ntp_server.host, &sa.sin6_addr);
ntp_server.ip6.sin6_addr=sa.sin6_addr;
ntp_server.use_ip6 = 1;
ntp_server.ip6.sin6_family = AF_INET6;
ntp_server.ip6.sin6_port = htons(ntp_server.port);
ntp_server.ip6.sin6_len = sizeof(struct sockaddr_in6);
}
inet_ntop(AF_INET, &ntp_server.ip.sin_addr, ntp_svr_ip, sizeof(ntp_svr_ip));
}
else
{
ret = getaddrinfo_with_pcid(ntp_server.host, "123", NULL, &pres,gps_nw_ctx_ptr.pdp_cid);
if (ret < 0)
{
GPS_LOGE("DNS getaddrinfo failed(%d)!\n",ret);
return -1;
}
if (pres == NULL)
{
GPS_LOGE("DNS getaddrinfo faield?!\n");
return -2;
}
if (pres->ai_addrlen == sizeof(struct sockaddr_in))
{
ntp_server.use_ip6 = 0;
unsigned int temp;
struct sockaddr_in * sin_res = (struct sockaddr_in *)pres->ai_addr;
ntp_server.ip.sin_addr = sin_res->sin_addr;
ntp_server.ip.sin_family = AF_INET;
ntp_server.ip.sin_port = htons(ntp_server.port);
temp = (unsigned int)ntp_server.ip.sin_addr.s_addr;
}
else
{
ntp_server.use_ip6 = 1;
ntp_server.ip6.sin6_family = AF_INET6;
ntp_server.ip6.sin6_port = htons(ntp_server.port);
ntp_server.ip6.sin6_len = sizeof(struct sockaddr_in6);
memcpy(&ntp_server.ip6.sin6_addr, pres->ai_addr->sa_data, 16);
}
ip4_svr_addr = (struct sockaddr_in *)pres->ai_addr;
inet_ntop(AF_INET, &ip4_svr_addr->sin_addr, ntp_svr_ip, 16);
freeaddrinfo(pres);
}
ret = ntp_server_setting(ntp_svr_ip,sizeof(ntp_svr_ip));
if(ret)
{
GPS_LOGE("ntp_server_setting failed(%d)!!!\n",ret);
return -3;
}
return 0;
}
/*获取第几路pdp被激活*/
static int quec_gps_get_cid_act(void)
{
int i = 0;
int pdp_status = 0;
int netif_status = 0;
for(i=1;i<QUEC_PDP_MAX_NUM;i++)
{
pdp_status = quec_pdp_get_act_status(i);
netif_status=quec_netif_get_bind_status(i);
if(pdp_status && netif_status){
return i;
}
}
return -1;
}
/*网络状态监控线程,此task会1s执行一次*/
/*历史问题:gps侧默认激活pdp,对于应用侧重复激活pdp会存在影响,内部讨论最终决定去除之前打开gps时默认激活pdp操作*/
/*修改方案:创建一个网络监控线程,去监控用户是否激活pdp和绑定网卡,如果有,会将此路cid配置成gps网络业务cid*/
char ntp_dns_gain = 0;
char ntp_sync_cnt = 0;
void quec_gps_nw_status_monitor(void * argv)
{
int cid_num = 0;
struct sockaddr sockaddr = {0};
while(1)
{
cid_num = quec_gps_get_cid_act();
t_rtc tm;
if(cid_num>0)
{
quec_gps_handle * quec_gps_cfg = quec_gnss_config_para_get();
gps_nw_ctx_ptr.pdp_cid = cid_num;
gps_nw_ctx_ptr.nw_status = 1;
/*获取本地网卡ip地址*/
quec_soc_get_ipv4v6_local_addr(cid_num, AF_INET, &sockaddr);
memcpy(&gps_nw_ctx_ptr.gps_ip4_addr, &(((struct sockaddr_in *)&sockaddr)->sin_addr), sizeof(struct in_addr));
quec_rtos_task_sleep_s(2);
if(!ntp_dns_gain){
quec_gps_ntp_set_server(quec_gps_cfg->ntp_url);
ntp_dns_gain++;
}
/*限制成功激活pdp后ntp的同步次数*/
if((gps_nw_ctx_ptr.rtc_status !=1)&&(ntp_sync_cnt < 10))
{
get_ntp_time_internal();
ntp_sync_cnt++;
GPS_LOGD("Ntp sync cnt:%d!!!",ntp_sync_cnt);
}
PMIC_RTC_GetTime((t_rtc *)&tm, SYS_OFFSET);
GPS_LOGD("Found an active pdp %d:%d:%d:%d:%d:%d!!!",tm.tm_year,tm.tm_mon,tm.tm_mday,tm.tm_hour,tm.tm_min,tm.tm_sec);
}
else
{
gps_nw_ctx_ptr.pdp_cid = 0;
gps_nw_ctx_ptr.nw_status = 0;
memset((void*)&gps_nw_ctx_ptr.gps_ip4_addr,0,sizeof(gps_nw_ctx_ptr.gps_ip4_addr));
quec_rtos_task_sleep_s(2);
}
if(get_ntp_time_type()==1 || GetNTPStatus()==1) /*检查nitz和ntp是否同步成功*/
{
gps_nw_ctx_ptr.rtc_status = 1;
}
//RTI_LOG("Found an active pdp %d:%d:%d:%d:%d:%d!!!",tm.tm_year,tm.tm_mon,tm.tm_mday,tm.tm_hour,tm.tm_min,tm.tm_sec);
}
}
int quec_get_rtc_status(void)
{
return gps_nw_ctx_ptr.rtc_status;
}
/*获取网卡状态,如果已经激活则返回pdpnum*/
int quec_get_nw_status(void)
{
if(gps_nw_ctx_ptr.nw_status)
return gps_nw_ctx_ptr.pdp_cid;
else
return gps_nw_ctx_ptr.nw_status;
}
int gps_nw_active(void)
{
int cid_num = 0;
cid_num = quec_gps_get_cid_act();
struct sockaddr sockaddr = {0};
if(cid_num>0)
{
quec_gps_handle * quec_gps_cfg = quec_gnss_config_para_get();
gps_nw_ctx_ptr.pdp_cid = cid_num;
gps_nw_ctx_ptr.nw_status = 1;
/*获取本地网卡ip地址*/
quec_soc_get_ipv4v6_local_addr(cid_num, AF_INET, &sockaddr);
memcpy(&gps_nw_ctx_ptr.gps_ip4_addr, &(((struct sockaddr_in *)&sockaddr)->sin_addr), sizeof(struct in_addr));
if(!ntp_dns_gain){
quec_gps_ntp_set_server(quec_gps_cfg->ntp_url);
ntp_dns_gain++;
}
GPS_LOGI("Found an active pdp!!!");
}
else
{
gps_nw_ctx_ptr.pdp_cid = 0;
gps_nw_ctx_ptr.nw_status = 0;
memset(&gps_nw_ctx_ptr.gps_ip4_addr,0,sizeof(gps_nw_ctx_ptr.gps_ip4_addr));
}
if(gps_nw_ctx_ptr.gps_nw_task == NULL){
quec_rtos_task_create(&gps_nw_ctx_ptr.gps_nw_task, 1024*2, 100,"gps_nw", quec_gps_nw_status_monitor,NULL);
}
return 0;
}
int gps_nw_deactive(void)
{
if(gps_nw_ctx_ptr.gps_nw_task){
quec_rtos_task_delete(gps_nw_ctx_ptr.gps_nw_task);
gps_nw_ctx_ptr.gps_nw_task = NULL;
}
return 0;
}
char gps_channel_init(void)
{
char success = TRUE;
#ifdef GPS_VIA_UART
g_gps_channel_type = CHANNEL_TYPE_UART;
g_gps_channel.m_com_init = gps_uart_init;
g_gps_channel.m_com_get_byte_status = gps_uart_get_byte_status;
g_gps_channel.m_com_get_byte_buffer = gps_uart_get_byte_buffer;
g_gps_channel.m_com_put_byte_buffer = gps_uart_put_byte_buffer;
g_gps_channel.m_com_purge_fifo = gps_uart_purge_fifo;
g_gps_channel.m_com_set_baudrate = gps_uart_set_baudrate;
g_gps_channel.m_com_deinit = gps_uart_deinit;
g_gps_channel.m_com_event_register_cb = gps_event_register_cb;
g_gps_channel.m_get_rtc_time = gps_get_rtc_time;
g_gps_channel.m_nw_act = gps_nw_active;
g_gps_channel.m_get_rtc_status = quec_get_rtc_status;
g_gps_channel.m_get_netif_status = quec_get_nw_status;
g_gps_channel.m_nw_deact = gps_nw_deactive;
#elif defined(GPS_VIA_SPI)
g_gps_channel_type = CHANNEL_TYPE_SPI;
#elif defined(GPS_VIA_I2C)
g_gps_channel_type = CHANNEL_TYPE_I2C;
#else
#error "No Define GPS_VIA_UART/SPI/I2C"
#endif
g_gps_channel.m_gpio_set_level = gps_gpio_set_level;
if(gps_uart_mutexref==NULL){
quec_rtos_mutex_create(&gps_uart_mutexref);
}
if(gps_uart_mutexref_tx==NULL){
quec_rtos_mutex_create(&gps_uart_mutexref_tx);
}
//20240313初始化gnss相关pin脚
quec_gnss_uart_low_power();
GPS_LOGI("gps_channel_type=%d", g_gps_channel_type);
return success;
}
char gps_get_channel_type(void)
{
return g_gps_channel_type;
}