You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

537 lines
18 KiB

  1. #include "main.h"
  2. #include "sys.h"
  3. #include "delay.h"
  4. #include "usart.h"
  5. #include "led.h"
  6. #include "usmart.h"
  7. #include "malloc.h"
  8. #include "mpu.h"
  9. #include "lan8720.h"
  10. #include "lwip/netif.h"
  11. #include "lwip_comm.h"
  12. #include "lwipopts.h"
  13. #include "includes.h"
  14. #include "stmflash.h"
  15. #include "lwip/opt.h"
  16. #include "lwip/lwip_sys.h"
  17. #include "lwip/api.h"
  18. #include "lwip/sockets.h"
  19. #define TCP_CLIENT_RX_BUFSIZE 2000 //接收缓冲区长度
  20. #define REMOTE_PORT 6666 //定义远端主机的IP地址
  21. #define LWIP_SEND_DATA 0X80 //定义有数据发送
  22. void SystemClock_Config(void);
  23. void MX_GPIO_Init(void);
  24. int read_progress();
  25. INT8U tcp_client_init(void);
  26. OS_EVENT *PREVENT; //发送eth信号量
  27. OS_EVENT *MAIL; //邮箱
  28. INT8U err; //错误地址
  29. struct netconn *tcp_clientconn=NULL; //TCP CLIENT网络连接结构体
  30. u8 tcp_client_flag; //TCP客户端数据发送标志位
  31. u8 eth_send=0;
  32. u8 xc_send[4]={0};
  33. u32 bufff=0; //大存
  34. u8 sml_buf[1024]={0}; //小存
  35. u32 *qq = (u32*)&sml_buf;
  36. int chunchucishu=0; //写flash次数 //要与flash存储进度挂钩 //最多28
  37. u32 W_head_Addr=0x0803FC00; //每加了0x400才起作用
  38. u32 W_tail_Addr=0x081FFFF4; //往上减
  39. int Progress=0;
  40. u16_t server_port;
  41. ip_addr_t server_ipaddr;
  42. //START任务
  43. //任务优先级
  44. #define START_TASK_PRIO 10
  45. //任务堆栈大小
  46. #define START_STK_SIZE 128
  47. //任务堆栈
  48. OS_STK START_TASK_STK[START_STK_SIZE];
  49. //任务函数
  50. void start_task(void *pdata);
  51. //ORDER任务
  52. //任务优先级
  53. #define ORDER_TASK_PRIO 2
  54. //任务堆栈大小
  55. #define ORDER_STK_SIZE 512
  56. //任务堆栈
  57. OS_STK ORDER_TASK_STK[ORDER_STK_SIZE];
  58. //任务函数
  59. void order_task(void *pdata);
  60. //TCP客户端任务
  61. #define TCPCLIENT_PRIO 6
  62. //任务堆栈大小
  63. #define TCPCLIENT_STK_SIZE 512
  64. //任务堆栈
  65. OS_STK TCPCLIENT_TASK_STK[TCPCLIENT_STK_SIZE];
  66. //tcp客户端任务函数
  67. static void tcp_client_thread(void *arg);
  68. //ETH发送任务
  69. //任务优先级
  70. #define ETH_SEND_TASK_PRIO 8
  71. //任务堆栈大小
  72. #define ETH_SEND_STK_SIZE 128
  73. //任务堆栈
  74. OS_STK ETH_SEND_TASK_STK[ETH_SEND_STK_SIZE];
  75. //任务函数
  76. void eth_send_task();
  77. int connect_chack();
  78. void write_flash();
  79. void ethsend(u8 eth_sendd);
  80. int main(void)
  81. {
  82. Write_Through(); //开启强制透写!
  83. MPU_Memory_Protection(); //保护相关存储区域
  84. Cache_Enable(); //打开L1-Cache
  85. HAL_Init();
  86. SystemClock_Config();
  87. delay_init(216); //延时初始化
  88. MX_GPIO_Init();
  89. MX_USART1_UART_Init();
  90. HAL_UART_Receive_IT(&huart1,&eth_send,1);
  91. // server_port = REMOTE_PORT;
  92. // IP4_ADDR(&server_ipaddr, lwipdev.remoteip[0],lwipdev.remoteip[1], lwipdev.remoteip[2],lwipdev.remoteip[3]);
  93. // ersae_all();
  94. // STMFLASH_Write(0x081FFFFC,&bufff[0],1); //完成标志写入flash
  95. if(STMFLASH_ReadWord(0x081FFFFC) != 0xFFFFFFFF)ersae_all();//如果最后一个地址里面被写了数据,代表之前文件已经传完,擦除空间
  96. // else Progress = read_progress();//查后面的,存到第几个包了,记录一下,一会接着要
  97. LED0_Toggle();
  98. OSInit(); //UCOS初始化
  99. while(lwip_comm_init()); //lwip初始化
  100. while(tcp_client_init()); //初始化tcp_server(创建tcp_server程)
  101. printf("客户端创建成功!\r\n");
  102. OSTaskCreate(start_task,(void*)0,(OS_STK*)&START_TASK_STK[START_STK_SIZE-1],START_TASK_PRIO);
  103. OSStart(); //开启UCOS
  104. }
  105. //tcp客户端任务函数
  106. static void tcp_client_thread(void *arg)
  107. {
  108. OS_CPU_SR cpu_sr;
  109. u32 data_len = 0;
  110. struct pbuf *q;
  111. struct netbuf *recvbuf;
  112. err_t recv_err;
  113. // static ip_addr_t server_ipaddr,loca_ipaddr;
  114. // static u16_t server_port,loca_port;
  115. LWIP_UNUSED_ARG(arg);
  116. // server_port = REMOTE_PORT;
  117. // IP4_ADDR(&server_ipaddr, lwipdev.remoteip[0],lwipdev.remoteip[1], lwipdev.remoteip[2],lwipdev.remoteip[3]);
  118. while (1)
  119. {
  120. if(connect_chack() == 1)
  121. {
  122. while(1)
  123. { /*recv_err = netconn_recv(tcp_clientconn,&recvbuf)*/
  124. /*recv( tcp_clientconn->socket, &recvbuf, 1024, 0)*/
  125. if((recv_err = netconn_recv(tcp_clientconn,&recvbuf)) == ERR_OK) //接收到数据
  126. {
  127. OS_ENTER_CRITICAL(); //关中断
  128. memset(sml_buf,0,TCP_CLIENT_RX_BUFSIZE); //数据接收缓冲区清零
  129. for(q=recvbuf->p;q!=NULL;q=q->next) //遍历完整个pbuf链表
  130. {
  131. //判断要拷贝到TCP_CLIENT_RX_BUFSIZE中的数据是否大于TCP_CLIENT_RX_BUFSIZE的剩余空间,如果大于
  132. //的话就只拷贝TCP_CLIENT_RX_BUFSIZE中剩余长度的数据,否则的话就拷贝所有的数据
  133. if(q->len > (TCP_CLIENT_RX_BUFSIZE-data_len)) memcpy(sml_buf+data_len,q->payload,(TCP_CLIENT_RX_BUFSIZE-data_len));//拷贝数据
  134. else memcpy(sml_buf+data_len,q->payload,q->len);
  135. data_len += q->len;
  136. if(data_len > TCP_CLIENT_RX_BUFSIZE) break; //超出TCP客户端接收数组,跳出
  137. }
  138. OS_EXIT_CRITICAL(); //开中断
  139. if((data_len<10)&&(sml_buf[0]==0x6F)&&(sml_buf[1]==0x76)&&(sml_buf[2]==0x65)&&(sml_buf[3]==0x72))
  140. { //如果接到结束符
  141. ethsend(0x35);
  142. data_len=0; //复制完成后data_len要清零。
  143. netbuf_delete(recvbuf);
  144. while(1) //等服务器发校验数目
  145. {
  146. if((recv_err = netconn_recv(tcp_clientconn,&recvbuf)) == ERR_OK) //接收到数据
  147. {
  148. OS_ENTER_CRITICAL(); //关中断
  149. memset(sml_buf,0,TCP_CLIENT_RX_BUFSIZE); //数据接收缓冲区清零
  150. for(q=recvbuf->p;q!=NULL;q=q->next) //遍历完整个pbuf链表
  151. {
  152. //判断要拷贝到TCP_CLIENT_RX_BUFSIZE中的数据是否大于TCP_CLIENT_RX_BUFSIZE的剩余空间,如果大于
  153. //的话就只拷贝TCP_CLIENT_RX_BUFSIZE中剩余长度的数据,否则的话就拷贝所有的数据
  154. if(q->len > (TCP_CLIENT_RX_BUFSIZE-data_len)) memcpy(sml_buf+data_len,q->payload,(TCP_CLIENT_RX_BUFSIZE-data_len));//拷贝数据
  155. else memcpy(sml_buf+data_len,q->payload,q->len);
  156. data_len += q->len;
  157. if(data_len > TCP_CLIENT_RX_BUFSIZE) break; //超出TCP客户端接收数组,跳出
  158. }
  159. OS_EXIT_CRITICAL(); //开中断
  160. data_len=0; //复制完成后data_len要清零。
  161. netbuf_delete(recvbuf);
  162. break;
  163. }
  164. }
  165. int a=(int)sml_buf[0]*256+(int)sml_buf[1];
  166. if(a == chunchucishu+Progress)//成功
  167. {
  168. ethsend(0x36); //回馈传输成功信息
  169. // chunchucishu=0;
  170. STMFLASH_Write(0x081FFFFC,&bufff,1); //完成标志写入flash
  171. netconn_close(tcp_clientconn);
  172. netconn_delete(tcp_clientconn);
  173. printf("服务器%d.%d.%d.%d断开连接\r\n",lwipdev.remoteip[0],lwipdev.remoteip[1], lwipdev.remoteip[2],lwipdev.remoteip[3]);
  174. break;
  175. }
  176. else //失败
  177. {
  178. ethsend(0x37);
  179. // chunchucishu=0;
  180. STMFLASH_Write(0x081FFFFC,&bufff,1);//传输失败也要写东西
  181. netconn_close(tcp_clientconn);
  182. netconn_delete(tcp_clientconn);
  183. printf("服务器%d.%d.%d.%d断开连接\r\n",lwipdev.remoteip[0],lwipdev.remoteip[1], lwipdev.remoteip[2],lwipdev.remoteip[3]);
  184. break;
  185. }
  186. }
  187. else //如果不是结束符,正常工作
  188. {
  189. data_len=0; //复制完成后data_len要清零。
  190. netbuf_delete(recvbuf);
  191. W_head_Addr += 0x400;
  192. write_flash();
  193. }
  194. }
  195. else if(recv_err == ERR_CLSD) //关闭连接
  196. {
  197. netconn_close(tcp_clientconn);
  198. netconn_delete(tcp_clientconn);
  199. printf("服务器%d.%d.%d.%d断开连接\r\n",lwipdev.remoteip[0],lwipdev.remoteip[1], lwipdev.remoteip[2],lwipdev.remoteip[3]);
  200. break;
  201. }
  202. }
  203. }
  204. }
  205. }
  206. int read_progress()
  207. {
  208. u32 addr = 0x081FFFF4;
  209. int a=0;
  210. while(STMFLASH_ReadWord(addr)!=0xFFFFFFFF)
  211. {
  212. a++;
  213. addr-=4;
  214. }
  215. return a;
  216. }
  217. void write_flash()
  218. {
  219. chunchucishu++;
  220. // if(STMFLASH_ReadWord(W_tail_Addr)==0XFFFFFFFF)
  221. STMFLASH_Write(W_tail_Addr,qq,1); //先把坑占了,先声明这个坑我要用了
  222. W_tail_Addr-=4;
  223. STMFLASH_Write(W_head_Addr,qq,256); //再用这个坑
  224. ethsend(0x34);
  225. }
  226. int connect_chack()
  227. {
  228. err_t err;
  229. static ip_addr_t loca_ipaddr;
  230. static u16_t loca_port;
  231. tcp_clientconn=netconn_new(NETCONN_TCP); //创建一个TCP链接
  232. server_port = REMOTE_PORT;
  233. IP4_ADDR(&server_ipaddr, lwipdev.remoteip[0],lwipdev.remoteip[1], lwipdev.remoteip[2],lwipdev.remoteip[3]);
  234. err = netconn_connect(tcp_clientconn,&server_ipaddr,server_port);//连接服务器
  235. if(err != ERR_OK)
  236. {
  237. netconn_delete(tcp_clientconn); //返回值不等于ERR_OK,删除tcp_clientconn连接
  238. return 0;
  239. }
  240. else //处理新连接的数据
  241. {
  242. // struct netbuf *recvbuf;
  243. tcp_clientconn->recv_timeout = 10;
  244. netconn_getaddr(tcp_clientconn,&loca_ipaddr,&loca_port,1); //获取本地IP主机IP地址和端口号
  245. printf("连接上服务器%d.%d.%d.%d,本机端口号为:%d\r\n",lwipdev.remoteip[0],lwipdev.remoteip[1], lwipdev.remoteip[2],lwipdev.remoteip[3],loca_port);
  246. if((STMFLASH_ReadWord(0x081FFFF8) != 0xFFFFFFFF)&&(STMFLASH_ReadWord(0x081FFFFC) == 0xFFFFFFFF))
  247. {
  248. Progress = read_progress();
  249. xc_send[0]=0x30;
  250. xc_send[1]=(u8)STMFLASH_ReadWord(0x081FFFF8);
  251. xc_send[2]=Progress/256;
  252. xc_send[3]=Progress%256;
  253. netconn_write(tcp_clientconn ,&xc_send,4,NETCONN_COPY);
  254. W_tail_Addr = 0x081FFFF4 - 4*Progress;
  255. W_head_Addr = 0x0803FC00 + 0x400*Progress;
  256. printf("要续传了\n");
  257. }
  258. return 1;
  259. }
  260. }
  261. void USART1_IRQHandler()
  262. {
  263. OSIntEnter();
  264. HAL_UART_Receive_IT(&huart1,&eth_send,1);
  265. OSMboxPost(MAIL,&eth_send); //往邮箱MAIL里面发intrpt的地址
  266. // if(eth_send==0xca)caca=1;
  267. // else OSSemPost(PREVENT);
  268. HAL_UART_IRQHandler(&huart1);
  269. __HAL_UART_ENABLE_IT(&huart1, UART_IT_ERR);
  270. __HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE);
  271. OSIntExit();
  272. }
  273. void ethsend(u8 eth_sendd)
  274. {
  275. err = netconn_write(tcp_clientconn ,&eth_sendd,1,NETCONN_COPY); //发送串口收到的指令
  276. if(err != ERR_OK)
  277. {
  278. printf("发送失败\r\n");
  279. }
  280. else printf("发送成功%d\r\n",eth_sendd);
  281. tcp_client_flag &= ~LWIP_SEND_DATA;
  282. }
  283. void order_task(void *pdata)
  284. {
  285. static void *M_num; //接收邮箱数据
  286. static char num = 0;
  287. while(1)
  288. {
  289. M_num = OSMboxPend(MAIL,0,&err); //获取邮箱里面数据的地址
  290. if(M_num != NULL)
  291. {
  292. num = *(char*)M_num;
  293. if(num == 0xca) //恢复如初
  294. {
  295. LED0_Toggle();
  296. chunchucishu=0;
  297. W_head_Addr=0x0803FC00; //每加了0x400才起作用
  298. W_tail_Addr=0x081FFFF4; //往上减
  299. Progress=0;
  300. ersae_all();
  301. LED0_Toggle();
  302. }
  303. else if((num == 0x31)||(num == 0x32)||(num == 0x33))
  304. {
  305. eth_send = num;
  306. OSSemPost(PREVENT);
  307. // if(STMFLASH_ReadWord(0x081FFFF8) == 0xFFFFFFFF)
  308. // {
  309. u32 a;
  310. a=(u32)num;
  311. STMFLASH_Write(0x081FFFF8,&a,1);//记录文件序号
  312. // }
  313. }
  314. else if((num == 0x38)||(num == 0x39)||(num == 0x3a))
  315. {
  316. eth_send = num;
  317. OSSemPost(PREVENT);
  318. }
  319. else if(num == 0x22)
  320. {
  321. printf("连接结果是%d",connect_chack());
  322. }
  323. else if(num == 0x11)
  324. {
  325. Progress = read_progress();
  326. xc_send[0]=0x30;
  327. xc_send[1]=(u8)STMFLASH_ReadWord(0x081FFFF8);
  328. xc_send[2]=Progress/256;
  329. xc_send[3]=Progress%256;
  330. netconn_write(tcp_clientconn ,&xc_send,4,NETCONN_COPY);
  331. W_tail_Addr = 0x081FFFF4 - 4*Progress;
  332. W_head_Addr = 0x0803FC00 + 0x400*Progress;
  333. chunchucishu=0;
  334. printf("要续传了\n");
  335. }
  336. }
  337. OSTimeDlyHMSM(0,0,0,500); //延时500ms
  338. }
  339. }
  340. //ETH发送任务
  341. void eth_send_task(void *pdata)
  342. {
  343. while(1)
  344. {
  345. OSSemPend(PREVENT,0,&err); //申请信号量
  346. err = netconn_write(tcp_clientconn ,&eth_send,1,NETCONN_COPY); //发送串口收到的指令
  347. if(err != ERR_OK)
  348. {
  349. printf("发送失败\r\n");
  350. }
  351. else printf("发送成功%d\r\n",eth_send);
  352. tcp_client_flag &= ~LWIP_SEND_DATA;
  353. OSTimeDlyHMSM(0,0,0,500); //延时500ms
  354. }
  355. }
  356. //创建TCP客户端线程
  357. //返回值:0 TCP客户端创建成功
  358. // 其他 TCP客户端创建失败
  359. INT8U tcp_client_init(void)
  360. {
  361. INT8U res;
  362. OS_CPU_SR cpu_sr;
  363. OS_ENTER_CRITICAL(); //关中断
  364. OSTaskCreate(eth_send_task,(void*)0,(OS_STK*)&ETH_SEND_TASK_STK[ETH_SEND_STK_SIZE-1],ETH_SEND_TASK_PRIO); //显示任务
  365. res = OSTaskCreate(tcp_client_thread,(void*)0,(OS_STK*)&TCPCLIENT_TASK_STK[TCPCLIENT_STK_SIZE-1],TCPCLIENT_PRIO); //创建TCP客户端线程
  366. PREVENT = OSSemCreate(1); //创建信号量
  367. // W_FLASH = OSSemCreate(1); //创建信号量
  368. OSSemPend(PREVENT,0,&err);
  369. // OSSemPend(W_FLASH,0,&err);
  370. OS_EXIT_CRITICAL(); //开中断
  371. return res;
  372. }
  373. /* USER CODE BEGIN 4 */
  374. //start任务
  375. void start_task(void *pdata)
  376. {
  377. OS_CPU_SR cpu_sr;
  378. pdata = pdata ;
  379. static INT8U mbox; //邮箱
  380. OSStatInit(); //初始化统计任务
  381. OS_ENTER_CRITICAL(); //关中断
  382. OSTaskCreate(order_task,(void*)0,(OS_STK*)&ORDER_TASK_STK[ORDER_STK_SIZE-1],ORDER_TASK_PRIO);//创建ORDER任务
  383. // OSTaskCreate(write_flash,(void*)0,(OS_STK*)&FLASH_TASK_STK[FLASH_STK_SIZE-1],FLASH_TASK_PRIO);//创建LED任务
  384. MAIL = OSMboxCreate((void*)mbox); //创建邮箱
  385. OSTaskSuspend(OS_PRIO_SELF); //挂起start_task任务
  386. OS_EXIT_CRITICAL(); //开中断
  387. }
  388. /**
  389. * @brief System Clock Configuration
  390. * @retval None
  391. */
  392. void SystemClock_Config(void)
  393. {
  394. RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  395. RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  396. /** Configure the main internal regulator output voltage
  397. */
  398. __HAL_RCC_PWR_CLK_ENABLE();
  399. __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  400. /** Initializes the RCC Oscillators according to the specified parameters
  401. * in the RCC_OscInitTypeDef structure.
  402. */
  403. RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  404. RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  405. RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  406. RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  407. RCC_OscInitStruct.PLL.PLLM = 6;
  408. RCC_OscInitStruct.PLL.PLLN = 216;
  409. RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  410. RCC_OscInitStruct.PLL.PLLQ = 2;
  411. if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  412. {
  413. Error_Handler();
  414. }
  415. /** Activate the Over-Drive mode
  416. */
  417. if (HAL_PWREx_EnableOverDrive() != HAL_OK)
  418. {
  419. Error_Handler();
  420. }
  421. /** Initializes the CPU, AHB and APB buses clocks
  422. */
  423. RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
  424. |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  425. RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  426. RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  427. RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  428. RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
  429. if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7) != HAL_OK)
  430. {
  431. Error_Handler();
  432. }
  433. }
  434. /* USER CODE END 4 */
  435. /**
  436. * @brief This function is executed in case of error occurrence.
  437. * @retval None
  438. */
  439. void Error_Handler(void)
  440. {
  441. /* USER CODE BEGIN Error_Handler_Debug */
  442. /* User can add his own implementation to report the HAL error return state */
  443. __disable_irq();
  444. while (1)
  445. {
  446. }
  447. /* USER CODE END Error_Handler_Debug */
  448. }
  449. #ifdef USE_FULL_ASSERT
  450. /**
  451. * @brief Reports the name of the source file and the source line number
  452. * where the assert_param error has occurred.
  453. * @param file: pointer to the source file name
  454. * @param line: assert_param error line source number
  455. * @retval None
  456. */
  457. void assert_failed(uint8_t *file, uint32_t line)
  458. {
  459. /* USER CODE BEGIN 6 */
  460. /* User can add his own implementation to report the file name and line number,
  461. ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  462. /* USER CODE END 6 */
  463. }
  464. #endif /* USE_FULL_ASSERT */
  465. void MX_GPIO_Init(void)
  466. {
  467. GPIO_InitTypeDef GPIO_InitStruct = {0};
  468. /* GPIO Ports Clock Enable */
  469. __HAL_RCC_GPIOA_CLK_ENABLE();
  470. __HAL_RCC_GPIOH_CLK_ENABLE();
  471. __HAL_RCC_GPIOF_CLK_ENABLE();
  472. __HAL_RCC_GPIOB_CLK_ENABLE();
  473. /*Configure GPIO pin Output Level */
  474. HAL_GPIO_WritePin(GPIOF, GPIO_PIN_7|GPIO_PIN_6|GPIO_PIN_8, GPIO_PIN_SET);
  475. /*Configure GPIO pins : PF7 PF6 PF8 */
  476. GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_6|GPIO_PIN_8;
  477. GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  478. GPIO_InitStruct.Pull = GPIO_NOPULL;
  479. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  480. HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
  481. }
  482. /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/