#include "ec800.h" #include "delay.h" #include "string.h" #include #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; }