#include "main.h" #include "sys.h" #include "delay.h" #include "usart.h" #include "led.h" #include "usmart.h" #include "malloc.h" #include "mpu.h" #include "lan8720.h" #include "lwip/netif.h" #include "lwip_comm.h" #include "lwipopts.h" #include "includes.h" #include "stmflash.h" #include "lwip/opt.h" #include "lwip/lwip_sys.h" #include "lwip/api.h" #include "lwip/sockets.h" #define TCP_CLIENT_RX_BUFSIZE 2000 //接收缓冲区长度 #define REMOTE_PORT 6666 //定义远端主机的IP地址 #define LWIP_SEND_DATA 0X80 //定义有数据发送 void SystemClock_Config(void); void MX_GPIO_Init(void); int read_progress(); INT8U tcp_client_init(void); OS_EVENT *PREVENT; //发送eth信号量 OS_EVENT *MAIL; //邮箱 INT8U err; //错误地址 struct netconn *tcp_clientconn=NULL; //TCP CLIENT网络连接结构体 u8 tcp_client_flag; //TCP客户端数据发送标志位 u8 eth_send=0; u8 xc_send[4]={0}; u32 bufff=0; //大存 u8 sml_buf[1024]={0}; //小存 u32 *qq = (u32*)&sml_buf; int chunchucishu=0; //写flash次数 //要与flash存储进度挂钩 //最多28 u32 W_head_Addr=0x0803FC00; //每加了0x400才起作用 u32 W_tail_Addr=0x081FFFF4; //往上减 int Progress=0; u16_t server_port; ip_addr_t server_ipaddr; //START任务 //任务优先级 #define START_TASK_PRIO 10 //任务堆栈大小 #define START_STK_SIZE 128 //任务堆栈 OS_STK START_TASK_STK[START_STK_SIZE]; //任务函数 void start_task(void *pdata); //ORDER任务 //任务优先级 #define ORDER_TASK_PRIO 2 //任务堆栈大小 #define ORDER_STK_SIZE 512 //任务堆栈 OS_STK ORDER_TASK_STK[ORDER_STK_SIZE]; //任务函数 void order_task(void *pdata); //TCP客户端任务 #define TCPCLIENT_PRIO 6 //任务堆栈大小 #define TCPCLIENT_STK_SIZE 512 //任务堆栈 OS_STK TCPCLIENT_TASK_STK[TCPCLIENT_STK_SIZE]; //tcp客户端任务函数 static void tcp_client_thread(void *arg); //ETH发送任务 //任务优先级 #define ETH_SEND_TASK_PRIO 8 //任务堆栈大小 #define ETH_SEND_STK_SIZE 128 //任务堆栈 OS_STK ETH_SEND_TASK_STK[ETH_SEND_STK_SIZE]; //任务函数 void eth_send_task(); int connect_chack(); void write_flash(); void ethsend(u8 eth_sendd); int main(void) { Write_Through(); //开启强制透写! MPU_Memory_Protection(); //保护相关存储区域 Cache_Enable(); //打开L1-Cache HAL_Init(); SystemClock_Config(); delay_init(216); //延时初始化 MX_GPIO_Init(); MX_USART1_UART_Init(); HAL_UART_Receive_IT(&huart1,ð_send,1); // server_port = REMOTE_PORT; // IP4_ADDR(&server_ipaddr, lwipdev.remoteip[0],lwipdev.remoteip[1], lwipdev.remoteip[2],lwipdev.remoteip[3]); // ersae_all(); // STMFLASH_Write(0x081FFFFC,&bufff[0],1); //完成标志写入flash if(STMFLASH_ReadWord(0x081FFFFC) != 0xFFFFFFFF)ersae_all();//如果最后一个地址里面被写了数据,代表之前文件已经传完,擦除空间 // else Progress = read_progress();//查后面的,存到第几个包了,记录一下,一会接着要 LED0_Toggle(); OSInit(); //UCOS初始化 while(lwip_comm_init()); //lwip初始化 while(tcp_client_init()); //初始化tcp_server(创建tcp_server程) printf("客户端创建成功!\r\n"); OSTaskCreate(start_task,(void*)0,(OS_STK*)&START_TASK_STK[START_STK_SIZE-1],START_TASK_PRIO); OSStart(); //开启UCOS } //tcp客户端任务函数 static void tcp_client_thread(void *arg) { OS_CPU_SR cpu_sr; u32 data_len = 0; struct pbuf *q; struct netbuf *recvbuf; err_t recv_err; // static ip_addr_t server_ipaddr,loca_ipaddr; // static u16_t server_port,loca_port; LWIP_UNUSED_ARG(arg); // server_port = REMOTE_PORT; // IP4_ADDR(&server_ipaddr, lwipdev.remoteip[0],lwipdev.remoteip[1], lwipdev.remoteip[2],lwipdev.remoteip[3]); while (1) { if(connect_chack() == 1) { while(1) { /*recv_err = netconn_recv(tcp_clientconn,&recvbuf)*/ /*recv( tcp_clientconn->socket, &recvbuf, 1024, 0)*/ if((recv_err = netconn_recv(tcp_clientconn,&recvbuf)) == ERR_OK) //接收到数据 { OS_ENTER_CRITICAL(); //关中断 memset(sml_buf,0,TCP_CLIENT_RX_BUFSIZE); //数据接收缓冲区清零 for(q=recvbuf->p;q!=NULL;q=q->next) //遍历完整个pbuf链表 { //判断要拷贝到TCP_CLIENT_RX_BUFSIZE中的数据是否大于TCP_CLIENT_RX_BUFSIZE的剩余空间,如果大于 //的话就只拷贝TCP_CLIENT_RX_BUFSIZE中剩余长度的数据,否则的话就拷贝所有的数据 if(q->len > (TCP_CLIENT_RX_BUFSIZE-data_len)) memcpy(sml_buf+data_len,q->payload,(TCP_CLIENT_RX_BUFSIZE-data_len));//拷贝数据 else memcpy(sml_buf+data_len,q->payload,q->len); data_len += q->len; if(data_len > TCP_CLIENT_RX_BUFSIZE) break; //超出TCP客户端接收数组,跳出 } OS_EXIT_CRITICAL(); //开中断 if((data_len<10)&&(sml_buf[0]==0x6F)&&(sml_buf[1]==0x76)&&(sml_buf[2]==0x65)&&(sml_buf[3]==0x72)) { //如果接到结束符 ethsend(0x35); data_len=0; //复制完成后data_len要清零。 netbuf_delete(recvbuf); while(1) //等服务器发校验数目 { if((recv_err = netconn_recv(tcp_clientconn,&recvbuf)) == ERR_OK) //接收到数据 { OS_ENTER_CRITICAL(); //关中断 memset(sml_buf,0,TCP_CLIENT_RX_BUFSIZE); //数据接收缓冲区清零 for(q=recvbuf->p;q!=NULL;q=q->next) //遍历完整个pbuf链表 { //判断要拷贝到TCP_CLIENT_RX_BUFSIZE中的数据是否大于TCP_CLIENT_RX_BUFSIZE的剩余空间,如果大于 //的话就只拷贝TCP_CLIENT_RX_BUFSIZE中剩余长度的数据,否则的话就拷贝所有的数据 if(q->len > (TCP_CLIENT_RX_BUFSIZE-data_len)) memcpy(sml_buf+data_len,q->payload,(TCP_CLIENT_RX_BUFSIZE-data_len));//拷贝数据 else memcpy(sml_buf+data_len,q->payload,q->len); data_len += q->len; if(data_len > TCP_CLIENT_RX_BUFSIZE) break; //超出TCP客户端接收数组,跳出 } OS_EXIT_CRITICAL(); //开中断 data_len=0; //复制完成后data_len要清零。 netbuf_delete(recvbuf); break; } } int a=(int)sml_buf[0]*256+(int)sml_buf[1]; if(a == chunchucishu+Progress)//成功 { ethsend(0x36); //回馈传输成功信息 // chunchucishu=0; STMFLASH_Write(0x081FFFFC,&bufff,1); //完成标志写入flash netconn_close(tcp_clientconn); netconn_delete(tcp_clientconn); printf("服务器%d.%d.%d.%d断开连接\r\n",lwipdev.remoteip[0],lwipdev.remoteip[1], lwipdev.remoteip[2],lwipdev.remoteip[3]); break; } else //失败 { ethsend(0x37); // chunchucishu=0; STMFLASH_Write(0x081FFFFC,&bufff,1);//传输失败也要写东西 netconn_close(tcp_clientconn); netconn_delete(tcp_clientconn); printf("服务器%d.%d.%d.%d断开连接\r\n",lwipdev.remoteip[0],lwipdev.remoteip[1], lwipdev.remoteip[2],lwipdev.remoteip[3]); break; } } else //如果不是结束符,正常工作 { data_len=0; //复制完成后data_len要清零。 netbuf_delete(recvbuf); W_head_Addr += 0x400; write_flash(); } } else if(recv_err == ERR_CLSD) //关闭连接 { netconn_close(tcp_clientconn); netconn_delete(tcp_clientconn); printf("服务器%d.%d.%d.%d断开连接\r\n",lwipdev.remoteip[0],lwipdev.remoteip[1], lwipdev.remoteip[2],lwipdev.remoteip[3]); break; } } } } } int read_progress() { u32 addr = 0x081FFFF4; int a=0; while(STMFLASH_ReadWord(addr)!=0xFFFFFFFF) { a++; addr-=4; } return a; } void write_flash() { chunchucishu++; // if(STMFLASH_ReadWord(W_tail_Addr)==0XFFFFFFFF) STMFLASH_Write(W_tail_Addr,qq,1); //先把坑占了,先声明这个坑我要用了 W_tail_Addr-=4; STMFLASH_Write(W_head_Addr,qq,256); //再用这个坑 ethsend(0x34); } int connect_chack() { err_t err; static ip_addr_t loca_ipaddr; static u16_t loca_port; tcp_clientconn=netconn_new(NETCONN_TCP); //创建一个TCP链接 server_port = REMOTE_PORT; IP4_ADDR(&server_ipaddr, lwipdev.remoteip[0],lwipdev.remoteip[1], lwipdev.remoteip[2],lwipdev.remoteip[3]); err = netconn_connect(tcp_clientconn,&server_ipaddr,server_port);//连接服务器 if(err != ERR_OK) { netconn_delete(tcp_clientconn); //返回值不等于ERR_OK,删除tcp_clientconn连接 return 0; } else //处理新连接的数据 { // struct netbuf *recvbuf; tcp_clientconn->recv_timeout = 10; netconn_getaddr(tcp_clientconn,&loca_ipaddr,&loca_port,1); //获取本地IP主机IP地址和端口号 printf("连接上服务器%d.%d.%d.%d,本机端口号为:%d\r\n",lwipdev.remoteip[0],lwipdev.remoteip[1], lwipdev.remoteip[2],lwipdev.remoteip[3],loca_port); if((STMFLASH_ReadWord(0x081FFFF8) != 0xFFFFFFFF)&&(STMFLASH_ReadWord(0x081FFFFC) == 0xFFFFFFFF)) { Progress = read_progress(); xc_send[0]=0x30; xc_send[1]=(u8)STMFLASH_ReadWord(0x081FFFF8); xc_send[2]=Progress/256; xc_send[3]=Progress%256; netconn_write(tcp_clientconn ,&xc_send,4,NETCONN_COPY); W_tail_Addr = 0x081FFFF4 - 4*Progress; W_head_Addr = 0x0803FC00 + 0x400*Progress; printf("要续传了\n"); } return 1; } } void USART1_IRQHandler() { OSIntEnter(); HAL_UART_Receive_IT(&huart1,ð_send,1); OSMboxPost(MAIL,ð_send); //往邮箱MAIL里面发intrpt的地址 // if(eth_send==0xca)caca=1; // else OSSemPost(PREVENT); HAL_UART_IRQHandler(&huart1); __HAL_UART_ENABLE_IT(&huart1, UART_IT_ERR); __HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE); OSIntExit(); } void ethsend(u8 eth_sendd) { err = netconn_write(tcp_clientconn ,ð_sendd,1,NETCONN_COPY); //发送串口收到的指令 if(err != ERR_OK) { printf("发送失败\r\n"); } else printf("发送成功%d\r\n",eth_sendd); tcp_client_flag &= ~LWIP_SEND_DATA; } void order_task(void *pdata) { static void *M_num; //接收邮箱数据 static char num = 0; while(1) { M_num = OSMboxPend(MAIL,0,&err); //获取邮箱里面数据的地址 if(M_num != NULL) { num = *(char*)M_num; if(num == 0xca) //恢复如初 { LED0_Toggle(); chunchucishu=0; W_head_Addr=0x0803FC00; //每加了0x400才起作用 W_tail_Addr=0x081FFFF4; //往上减 Progress=0; ersae_all(); LED0_Toggle(); } else if((num == 0x31)||(num == 0x32)||(num == 0x33)) { eth_send = num; OSSemPost(PREVENT); // if(STMFLASH_ReadWord(0x081FFFF8) == 0xFFFFFFFF) // { u32 a; a=(u32)num; STMFLASH_Write(0x081FFFF8,&a,1);//记录文件序号 // } } else if((num == 0x38)||(num == 0x39)||(num == 0x3a)) { eth_send = num; OSSemPost(PREVENT); } else if(num == 0x22) { printf("连接结果是%d",connect_chack()); } else if(num == 0x11) { Progress = read_progress(); xc_send[0]=0x30; xc_send[1]=(u8)STMFLASH_ReadWord(0x081FFFF8); xc_send[2]=Progress/256; xc_send[3]=Progress%256; netconn_write(tcp_clientconn ,&xc_send,4,NETCONN_COPY); W_tail_Addr = 0x081FFFF4 - 4*Progress; W_head_Addr = 0x0803FC00 + 0x400*Progress; chunchucishu=0; printf("要续传了\n"); } } OSTimeDlyHMSM(0,0,0,500); //延时500ms } } //ETH发送任务 void eth_send_task(void *pdata) { while(1) { OSSemPend(PREVENT,0,&err); //申请信号量 err = netconn_write(tcp_clientconn ,ð_send,1,NETCONN_COPY); //发送串口收到的指令 if(err != ERR_OK) { printf("发送失败\r\n"); } else printf("发送成功%d\r\n",eth_send); tcp_client_flag &= ~LWIP_SEND_DATA; OSTimeDlyHMSM(0,0,0,500); //延时500ms } } //创建TCP客户端线程 //返回值:0 TCP客户端创建成功 // 其他 TCP客户端创建失败 INT8U tcp_client_init(void) { INT8U res; OS_CPU_SR cpu_sr; OS_ENTER_CRITICAL(); //关中断 OSTaskCreate(eth_send_task,(void*)0,(OS_STK*)Ð_SEND_TASK_STK[ETH_SEND_STK_SIZE-1],ETH_SEND_TASK_PRIO); //显示任务 res = OSTaskCreate(tcp_client_thread,(void*)0,(OS_STK*)&TCPCLIENT_TASK_STK[TCPCLIENT_STK_SIZE-1],TCPCLIENT_PRIO); //创建TCP客户端线程 PREVENT = OSSemCreate(1); //创建信号量 // W_FLASH = OSSemCreate(1); //创建信号量 OSSemPend(PREVENT,0,&err); // OSSemPend(W_FLASH,0,&err); OS_EXIT_CRITICAL(); //开中断 return res; } /* USER CODE BEGIN 4 */ //start任务 void start_task(void *pdata) { OS_CPU_SR cpu_sr; pdata = pdata ; static INT8U mbox; //邮箱 OSStatInit(); //初始化统计任务 OS_ENTER_CRITICAL(); //关中断 OSTaskCreate(order_task,(void*)0,(OS_STK*)&ORDER_TASK_STK[ORDER_STK_SIZE-1],ORDER_TASK_PRIO);//创建ORDER任务 // OSTaskCreate(write_flash,(void*)0,(OS_STK*)&FLASH_TASK_STK[FLASH_STK_SIZE-1],FLASH_TASK_PRIO);//创建LED任务 MAIL = OSMboxCreate((void*)mbox); //创建邮箱 OSTaskSuspend(OS_PRIO_SELF); //挂起start_task任务 OS_EXIT_CRITICAL(); //开中断 } /** * @brief System Clock Configuration * @retval None */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /** Configure the main internal regulator output voltage */ __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLM = 6; RCC_OscInitStruct.PLL.PLLN = 216; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; RCC_OscInitStruct.PLL.PLLQ = 2; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Activate the Over-Drive mode */ if (HAL_PWREx_EnableOverDrive() != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7) != HAL_OK) { Error_Handler(); } } /* USER CODE END 4 */ /** * @brief This function is executed in case of error occurrence. * @retval None */ void Error_Handler(void) { /* USER CODE BEGIN Error_Handler_Debug */ /* User can add his own implementation to report the HAL error return state */ __disable_irq(); while (1) { } /* USER CODE END Error_Handler_Debug */ } #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */ void assert_failed(uint8_t *file, uint32_t line) { /* USER CODE BEGIN 6 */ /* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /* USER CODE END 6 */ } #endif /* USE_FULL_ASSERT */ void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOH_CLK_ENABLE(); __HAL_RCC_GPIOF_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOF, GPIO_PIN_7|GPIO_PIN_6|GPIO_PIN_8, GPIO_PIN_SET); /*Configure GPIO pins : PF7 PF6 PF8 */ GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_6|GPIO_PIN_8; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOF, &GPIO_InitStruct); } /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/