/*============================================================================================ 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;i0) { 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; }