|
@@ -0,0 +1,429 @@
|
|
|
+#include "ec800.h"
|
|
|
+#include "delay.h"
|
|
|
+#include "string.h"
|
|
|
+#include <stdlib.h>
|
|
|
+#include "fmc.h"
|
|
|
+#include "main.h"
|
|
|
+/*!
|
|
|
+ \brief configure EC800M pin
|
|
|
+ \param[out] none
|
|
|
+ \retval none
|
|
|
+*/
|
|
|
+#define RSP_READY "RDY"
|
|
|
+#define CMD_SET_PDP "AT+QICSGP=1,1,\"CTNET\",\"\",\"\",1\r\n"
|
|
|
+#define RSP_OK "OK"
|
|
|
+#define CMD_SET_ACTIVE "AT+QIACT=1\r\n"
|
|
|
+
|
|
|
+#define cmdOpenFile(cmd,filename) sprintf(cmd,"AT+QFOPEN=\"%s\",2\r\n",filename)
|
|
|
+#define cmdSetSeek(cmd,handle,offset) sprintf(cmd,"AT+QFSEEK=%d,%d,0\r\n",handle,offset)
|
|
|
+#define cmdReadFileData(cmd,handle) sprintf(cmd,"AT+QFREAD=%d,1024\r\n",handle)
|
|
|
+#define cmdLoadFile(cmd,filename) sprintf(cmd,"AT+QFDWL=%s\r\n",filename)
|
|
|
+
|
|
|
+uint8_t UART0_RX_BUF[UART0_RX_LEN];
|
|
|
+uint8_t UART0_RX_STAT;
|
|
|
+bool WaitResponse(char *expectStr, int timeout);
|
|
|
+void EC800MSendCmd(char *buf, uint16_t len);
|
|
|
+int get_file_handle(char *filename);
|
|
|
+static const char* my_memmem(const uint8_t* haystack, size_t hlen, const char* needle, size_t nlen);
|
|
|
+static void extract_data_from_buffer(const char *buffer, uint32_t *len_ptr, uint16_t *checkCode_ptr);
|
|
|
+static uint16_t checksum(const uint8_t *str, uint16_t len);
|
|
|
+
|
|
|
+void gd_EC800M_pin_init(void)
|
|
|
+{
|
|
|
+ /* enable the EC800M power pin clock */
|
|
|
+ rcu_periph_clock_enable(EC800M_PER_GPIO_CLK);
|
|
|
+ /* configure EC800M GPIO port */
|
|
|
+ gpio_init(EC800M_PER_GPIO_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, EC800M_PER_PIN);
|
|
|
+
|
|
|
+ GPIO_BC(EC800M_PER_GPIO_PORT) = EC800M_PER_PIN;
|
|
|
+
|
|
|
+ /* enable the EC800M reset pin clock */
|
|
|
+ rcu_periph_clock_enable(EC800M_RST_GPIO_CLK);
|
|
|
+ /* configure EC800M GPIO port */
|
|
|
+ gpio_init(EC800M_RST_GPIO_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, EC800M_RST_PIN);
|
|
|
+
|
|
|
+ GPIO_BC(EC800M_RST_GPIO_PORT) = EC800M_RST_PIN;
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+void gd_pull_EC800M_pwr_up(void)
|
|
|
+{
|
|
|
+ GPIO_BOP(EC800M_PER_GPIO_PORT) = EC800M_PER_PIN;
|
|
|
+}
|
|
|
+
|
|
|
+void gd_pull_EC800M_pwr_down(void)
|
|
|
+{
|
|
|
+ GPIO_BC(EC800M_PER_GPIO_PORT) = EC800M_PER_PIN;
|
|
|
+}
|
|
|
+
|
|
|
+void gd_pull_EC800M_rst_up(void)
|
|
|
+{
|
|
|
+ GPIO_BOP(EC800M_RST_GPIO_PORT) = EC800M_RST_PIN;
|
|
|
+}
|
|
|
+
|
|
|
+void gd_pull_EC800M_rst_down(void)
|
|
|
+{
|
|
|
+ GPIO_BC(EC800M_RST_GPIO_PORT) = EC800M_RST_PIN;
|
|
|
+}
|
|
|
+
|
|
|
+/*!
|
|
|
+ \brief configure COM port
|
|
|
+ \param[in] com: COM on the board
|
|
|
+ \arg COM_EC800: EC800
|
|
|
+ \arg COM_485: 485
|
|
|
+ \arg COM_232: 232
|
|
|
+ \param[out] none
|
|
|
+ \retval none
|
|
|
+*/
|
|
|
+void gd_com_init()
|
|
|
+{
|
|
|
+ nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2); // 设置抢占优先级和子优先级的位数为 2
|
|
|
+ nvic_irq_enable(USART0_IRQn, 0, 0);
|
|
|
+
|
|
|
+ /* enable GPIO clock */
|
|
|
+ rcu_periph_clock_enable(COM_EC800_GPIO_CLK);
|
|
|
+ /* enable USART clock */
|
|
|
+ rcu_periph_clock_enable(COM_EC800_CLK);
|
|
|
+ /* connect port to USARTx_Tx */
|
|
|
+ gpio_init(COM_EC800_GPIO_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, COM_EC800_TX_PIN);
|
|
|
+ /* connect port to USARTx_Rx */
|
|
|
+ gpio_init(COM_EC800_GPIO_PORT, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, COM_EC800_RX_PIN);
|
|
|
+
|
|
|
+ /* USART configure */
|
|
|
+ usart_deinit(COM_EC800);
|
|
|
+ usart_baudrate_set(COM_EC800, COM_EC800_BAUDRATE);
|
|
|
+ usart_word_length_set(COM_EC800, USART_WL_8BIT);
|
|
|
+ usart_stop_bit_set(COM_EC800, USART_STB_1BIT);
|
|
|
+ usart_parity_config(COM_EC800, USART_PM_NONE);
|
|
|
+ usart_hardware_flow_rts_config(COM_EC800, USART_RTS_DISABLE);
|
|
|
+ usart_hardware_flow_cts_config(COM_EC800, USART_CTS_DISABLE);
|
|
|
+ usart_receive_config(COM_EC800, USART_RECEIVE_ENABLE);
|
|
|
+ usart_transmit_config(COM_EC800, USART_TRANSMIT_ENABLE);
|
|
|
+ usart_enable(COM_EC800);
|
|
|
+ usart_interrupt_enable(COM_EC800, USART_INT_IDLE);
|
|
|
+
|
|
|
+}
|
|
|
+void dma_config(void)
|
|
|
+{
|
|
|
+ dma_parameter_struct dma_init_struct;
|
|
|
+
|
|
|
+ rcu_periph_clock_enable(RCU_DMA0);
|
|
|
+
|
|
|
+ dma_deinit(DMA0, DMA_CH4);
|
|
|
+ dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;
|
|
|
+ dma_init_struct.memory_addr = (uint32_t)UART0_RX_BUF;
|
|
|
+ dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
|
|
|
+ dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
|
|
|
+ dma_init_struct.number = UART0_RX_LEN;
|
|
|
+ dma_init_struct.periph_addr = (uint32_t)(&USART_DATA(USART0));// ((uint32_t)0x40013804);
|
|
|
+ dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
|
|
|
+ dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;
|
|
|
+ dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
|
|
|
+ dma_init(DMA0, DMA_CH4, &dma_init_struct);
|
|
|
+
|
|
|
+ dma_circulation_disable(DMA0, DMA_CH4);
|
|
|
+ dma_memory_to_memory_disable(DMA0, DMA_CH4);
|
|
|
+
|
|
|
+ usart_dma_transmit_config(USART0, USART_DENT_ENABLE|USART_DENR_ENABLE);
|
|
|
+ nvic_irq_enable(DMA0_Channel4_IRQn, 2, 1);
|
|
|
+
|
|
|
+ dma_interrupt_enable(DMA0, DMA_CH4, DMA_INT_FTF|DMA_INT_HTF|DMA_INT_ERR);
|
|
|
+ dma_channel_enable(DMA0, DMA_CH4);
|
|
|
+}
|
|
|
+
|
|
|
+// 4G模块
|
|
|
+void USART0_IRQHandler(void)
|
|
|
+{
|
|
|
+ if (RESET != usart_interrupt_flag_get(USART0, USART_INT_FLAG_IDLE)) // 空闲中断
|
|
|
+ {
|
|
|
+ usart_interrupt_flag_clear(USART0, USART_INT_FLAG_IDLE); /* 清除空闲中断标志位 */
|
|
|
+ usart_data_receive(USART0); /* 清除接收完成标志位 */
|
|
|
+ dma_channel_disable(DMA0, DMA_CH4); /* 关闭DMA传输 */
|
|
|
+ UART0_RX_STAT = 0x01; /* 接受状态 0x01:已接收到数据 */
|
|
|
+ dma_channel_enable(DMA0, DMA_CH4);
|
|
|
+
|
|
|
+ }
|
|
|
+}
|
|
|
+void DMA0_Channel4_IRQHandler(void)
|
|
|
+{
|
|
|
+ dma_interrupt_flag_clear(DMA0, DMA_CH4, DMA_INT_FLAG_G);
|
|
|
+}
|
|
|
+
|
|
|
+//清除dma buffer内数据
|
|
|
+void Clear_DMA_Buffer(void)
|
|
|
+{
|
|
|
+ memset(UART0_RX_BUF,0,UART0_RX_LEN);
|
|
|
+}
|
|
|
+void EC800MPwoerOn(void)
|
|
|
+{
|
|
|
+ rcu_periph_clock_enable(RCU_GPIOD);
|
|
|
+ gpio_init(GPIOD, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2);
|
|
|
+ gpio_bit_set(GPIOD,GPIO_PIN_2);
|
|
|
+ Delay_Ms(5000);
|
|
|
+ gd_pull_EC800M_pwr_up();
|
|
|
+ gd_pull_EC800M_rst_down();
|
|
|
+ Delay_Ms(50);
|
|
|
+ gd_pull_EC800M_pwr_down();
|
|
|
+ Delay_Ms(320);
|
|
|
+ gd_pull_EC800M_rst_up();
|
|
|
+ Delay_Ms(800);
|
|
|
+ gd_pull_EC800M_pwr_up();
|
|
|
+}
|
|
|
+
|
|
|
+void EC800MWaitReady()
|
|
|
+{
|
|
|
+ if(WaitResponse(RSP_READY, 5000)==FALSE) NVIC_SystemReset();
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * 函数名:bool WaitResponse(char *expectStr, int timeout)
|
|
|
+ * 输入参数:expectStr 需要匹配的关键字 timeout超时时间
|
|
|
+ * 输出参数:true flase
|
|
|
+ * 返回值:无
|
|
|
+ * 函数作用:从UART0_RX_BUF缓冲区中匹配有无对应关键字有关键字则返回true无返回false
|
|
|
+ */
|
|
|
+bool WaitResponse(char *expectStr, int timeout)
|
|
|
+{
|
|
|
+ bool timeoutFlag = FALSE;
|
|
|
+ if (timeout >= 0)
|
|
|
+ {
|
|
|
+ timeoutFlag = TRUE;
|
|
|
+ }
|
|
|
+ // gd_485_send((char *)&UART0_RX_BUF, strlen(UART0_RX_BUF)); 不清楚此处调用485意义
|
|
|
+
|
|
|
+ while (1)
|
|
|
+ {
|
|
|
+ Delay_Ms(50);
|
|
|
+ if (UART0_RX_STAT > 0)
|
|
|
+ {
|
|
|
+ UART0_RX_STAT = 0;
|
|
|
+ char *p = strstr((char *)&UART0_RX_BUF, expectStr);
|
|
|
+ if (p)
|
|
|
+ {
|
|
|
+ Clear_DMA_Buffer();
|
|
|
+ return TRUE;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ timeout -= 50;
|
|
|
+ if (timeoutFlag == TRUE && timeout <= 0)
|
|
|
+ {
|
|
|
+ Clear_DMA_Buffer();
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+ };
|
|
|
+}
|
|
|
+/*
|
|
|
+ * 函数名:bool WaitResponse(char *expectStr, int timeout)
|
|
|
+ * 输入参数:expectStr 需要匹配的关键字 timeout超时时间
|
|
|
+ * 输出参数:true flase
|
|
|
+ * 返回值:无
|
|
|
+ * 函数作用:从UART0_RX_BUF缓冲区中匹配有无对应关键字有关键字则返回true无返回false
|
|
|
+ */
|
|
|
+bool WaitResponseNotclear(char *expectStr, int timeout)
|
|
|
+{
|
|
|
+ bool timeoutFlag = FALSE;
|
|
|
+ if (timeout >= 0)
|
|
|
+ {
|
|
|
+ timeoutFlag = TRUE;
|
|
|
+ }
|
|
|
+ // gd_485_send((char *)&UART0_RX_BUF, strlen(UART0_RX_BUF)); 不清楚此处调用485意义
|
|
|
+
|
|
|
+ while (1)
|
|
|
+ {
|
|
|
+ Delay_Ms(50);
|
|
|
+ if (UART0_RX_STAT > 0)
|
|
|
+ {
|
|
|
+ UART0_RX_STAT = 0;
|
|
|
+ char *p = strstr((char *)&UART0_RX_BUF, expectStr);
|
|
|
+ if (p)
|
|
|
+ {
|
|
|
+ return TRUE;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ timeout -= 50;
|
|
|
+ if (timeoutFlag == TRUE && timeout <= 0)
|
|
|
+ {
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+ };
|
|
|
+}
|
|
|
+/*
|
|
|
+ * 函数名:void EC800MSetPDP()
|
|
|
+ * 输入参数:无
|
|
|
+ * 输出参数:无
|
|
|
+ * 返回值:无
|
|
|
+ * 函数作用:设置对应运营商和激活ip
|
|
|
+ */
|
|
|
+void EC800MSetPDP()
|
|
|
+{
|
|
|
+ Delay_Ms(200);
|
|
|
+ EC800MSendCmd(CMD_SET_PDP, strlen(CMD_SET_PDP));
|
|
|
+ WaitResponse(RSP_OK, 1000);
|
|
|
+ Delay_Ms(200);
|
|
|
+ EC800MSendCmd(CMD_SET_ACTIVE, strlen(CMD_SET_ACTIVE));
|
|
|
+ WaitResponse(RSP_OK, 1000);
|
|
|
+ Delay_Ms(2000);
|
|
|
+}
|
|
|
+
|
|
|
+void EC800MSendCmd(char *buf, uint16_t len)
|
|
|
+{
|
|
|
+ uint16_t i;
|
|
|
+ uint16_t data;
|
|
|
+ for (i = 0; i < len; i++)
|
|
|
+ {
|
|
|
+ data = buf[i];
|
|
|
+ usart_data_transmit(COM_EC800, data);
|
|
|
+ while (RESET == usart_flag_get(COM_EC800, USART_FLAG_TBE))
|
|
|
+ ;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+//读取bin文件内容
|
|
|
+int read_bin_txt()
|
|
|
+{
|
|
|
+ char *ptr;
|
|
|
+ uint32_t len;
|
|
|
+ uint16_t checkCode;
|
|
|
+ char sub_str[] = "\r\n+QFDWL:";
|
|
|
+ char cmd[50];
|
|
|
+ uint32_t BufferSize=40*1024;//最大获取的数据空间
|
|
|
+ uint8_t *dmabuffer=malloc(BufferSize);
|
|
|
+ dma_config_change(dmabuffer,BufferSize);
|
|
|
+ cmdLoadFile(cmd,"bin.txt");
|
|
|
+// Delay_Ms(1000);
|
|
|
+// EC800MSendCmd("AT+QFLST=\"*\"\r\n", strlen("AT+QFLST=\"*\"\r\n"));
|
|
|
+
|
|
|
+ Delay_Ms(1000);
|
|
|
+ EC800MSendCmd(cmd, strlen(cmd));
|
|
|
+ Delay_Ms(5000);
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ ptr = (char *)my_memmem(dmabuffer, BufferSize, sub_str, strlen(sub_str));
|
|
|
+ if(ptr==NULL){ free(dmabuffer);return 2;}
|
|
|
+ if(strstr(ptr,"ERROR"))
|
|
|
+ {
|
|
|
+ return 2;
|
|
|
+ }
|
|
|
+ extract_data_from_buffer(ptr,&len, &checkCode);
|
|
|
+ uint16_t code=checksum(dmabuffer,len);
|
|
|
+ if(checkCode==checksum(dmabuffer,len))
|
|
|
+ {
|
|
|
+ //校验成功数据正常,写入数据
|
|
|
+ GD32_EraseFlash(GD32_A_START_PAGE,GD32_A_PAGE_NUM);//擦除A区原有程序
|
|
|
+ GD32_WriteFlash(GD32_A_SADDR,(uint32_t *)dmabuffer,len);
|
|
|
+ free(dmabuffer);
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ dma_config();
|
|
|
+ free(dmabuffer);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+////获取文件句柄
|
|
|
+//int get_file_handle(char *filename)
|
|
|
+//{
|
|
|
+// int num;
|
|
|
+// char *ptr_start;
|
|
|
+// ptr_start=strstr((char *)&UART0_RX_BUF, filename);
|
|
|
+// if (ptr_start == NULL) {}
|
|
|
+// ptr_start = strchr(ptr_start, ':');
|
|
|
+// ptr_start++; // 跳过逗号
|
|
|
+// sscanf(ptr_start, "%d", &num);
|
|
|
+// return num;
|
|
|
+//}
|
|
|
+
|
|
|
+
|
|
|
+//手动控制dma搬运的数据地址和大小,在使用完成后需要恢复到默认的dma配置
|
|
|
+void dma_config_change(char *dmaBuffer,uint32_t bufferSize)
|
|
|
+{
|
|
|
+ dma_parameter_struct dma_init_struct;
|
|
|
+
|
|
|
+ rcu_periph_clock_enable(RCU_DMA0);
|
|
|
+
|
|
|
+ dma_deinit(DMA0, DMA_CH4);
|
|
|
+ dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;
|
|
|
+ dma_init_struct.memory_addr = (uint32_t)dmaBuffer;
|
|
|
+ dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
|
|
|
+ dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
|
|
|
+ dma_init_struct.number = bufferSize;
|
|
|
+ dma_init_struct.periph_addr = (uint32_t)(&USART_DATA(USART0));// ((uint32_t)0x40013804);
|
|
|
+ dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
|
|
|
+ dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;
|
|
|
+ dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
|
|
|
+ dma_init(DMA0, DMA_CH4, &dma_init_struct);
|
|
|
+
|
|
|
+ dma_circulation_disable(DMA0, DMA_CH4);
|
|
|
+ dma_memory_to_memory_disable(DMA0, DMA_CH4);
|
|
|
+
|
|
|
+ usart_dma_transmit_config(USART0, USART_DENT_ENABLE|USART_DENR_ENABLE);
|
|
|
+ //nvic_irq_enable(DMA0_Channel4_IRQn, 2, 2);
|
|
|
+
|
|
|
+ dma_interrupt_enable(DMA0, DMA_CH4, DMA_INT_FTF|DMA_INT_ERR);
|
|
|
+ dma_channel_enable(DMA0, DMA_CH4);
|
|
|
+}
|
|
|
+
|
|
|
+static const char* my_memmem(const uint8_t* haystack, size_t hlen, const char* needle, size_t nlen)
|
|
|
+{
|
|
|
+ const char* cur;
|
|
|
+ const char* last;
|
|
|
+
|
|
|
+ last = haystack + hlen - nlen;
|
|
|
+ for (cur = haystack; cur <= last; ++cur) {
|
|
|
+ if (cur[0] == needle[0] && memcmp(cur, needle, nlen) == 0) {
|
|
|
+ return cur;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+/*
|
|
|
+ * 函数名:static void extract_data_from_buffer(const char* buffer, uint32_t *len_ptr, uint16_t *checkCode_ptr)
|
|
|
+ * 输入参数:buffer字符串
|
|
|
+ * 输出参数:json有效字符串长度len_ptr,checkCode_ptr校验码指针
|
|
|
+ * 返回值:无
|
|
|
+ * 函数作用:eg. QFDWL: 621,3e23 从json信息最后端取出这段json的有效长度和校验码
|
|
|
+ */
|
|
|
+static void extract_data_from_buffer(const char *buffer, uint32_t *len_ptr, uint16_t *checkCode_ptr)
|
|
|
+{
|
|
|
+ char *start = strstr(buffer, "+QFDWL:");
|
|
|
+ if (start != NULL)
|
|
|
+ {
|
|
|
+ start += 8; // 跳过"+QFDWL:"
|
|
|
+ uint32_t len = 0;
|
|
|
+ sscanf(start, "%u,", &len); // 读取长度
|
|
|
+ start = strchr(start, ',') + 1; // 跳过逗号
|
|
|
+ uint16_t checkCode = 0;
|
|
|
+ sscanf(start, "%hx", &checkCode); // 读取16进制数据
|
|
|
+ // 将提取的数据存入形参
|
|
|
+ *len_ptr = len;
|
|
|
+ *checkCode_ptr = checkCode;
|
|
|
+ }
|
|
|
+}
|
|
|
+// 模块下载download校验值
|
|
|
+static uint16_t checksum(const uint8_t *str, uint16_t len)
|
|
|
+{
|
|
|
+ uint16_t sum = 0;
|
|
|
+ uint8_t odd = 0;
|
|
|
+
|
|
|
+ // 如果字符串长度为奇数,则将最后一个字符设置为高8位,低8位设置为0
|
|
|
+ if (len % 2 == 1)
|
|
|
+ {
|
|
|
+ odd = 1;
|
|
|
+ len--;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 将每两个字符作为一个16位的数值进行异或操作
|
|
|
+ for (uint16_t i = 0; i < len; i += 2)
|
|
|
+ {
|
|
|
+ sum ^= ((uint16_t)str[i] << 8) | (uint16_t)str[i + 1];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果字符串长度为奇数,则还需要将最后一个字符与0xFF00异或
|
|
|
+ if (odd)
|
|
|
+ {
|
|
|
+ sum ^= (uint16_t)str[len] << 8;
|
|
|
+ }
|
|
|
+ // 返回校验和
|
|
|
+ return sum;
|
|
|
+}
|
|
|
+
|