sys_arch.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  1. /*
  2. * Copyright (c) 2017 Simon Goldschmidt
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without modification,
  6. * are permitted provided that the following conditions are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright notice,
  9. * this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright notice,
  11. * this list of conditions and the following disclaimer in the documentation
  12. * and/or other materials provided with the distribution.
  13. * 3. The name of the author may not be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
  17. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  18. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
  19. * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  20. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
  21. * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  22. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  23. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  24. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  25. * OF SUCH DAMAGE.
  26. *
  27. * This file is part of the lwIP TCP/IP stack.
  28. *
  29. * Author: Simon Goldschmidt
  30. *
  31. */
  32. #include "debug.h"
  33. #include <lwip/opt.h>
  34. #include <lwip/arch.h>
  35. #include "tcpip.h"
  36. #include "lwip/init.h"
  37. #include "lwip/netif.h"
  38. #include "lwip/sio.h"
  39. #include "ethernetif.h"
  40. #if !NO_SYS
  41. #include "sys_arch.h"
  42. #endif
  43. #include <lwip/stats.h>
  44. #include <lwip/debug.h>
  45. #include <lwip/sys.h>
  46. #include "lwip/dhcp.h"
  47. #include <string.h>
  48. int errno;
  49. u32_t lwip_sys_now;
  50. struct sys_timeouts {
  51. struct sys_timeo *next;
  52. };
  53. struct timeoutlist
  54. {
  55. struct sys_timeouts timeouts;
  56. xTaskHandle pid;
  57. };
  58. #define SYS_THREAD_MAX 4
  59. static struct timeoutlist s_timeoutlist[SYS_THREAD_MAX];
  60. static u16_t s_nextthread = 0;
  61. u32_t
  62. sys_jiffies(void)
  63. {
  64. lwip_sys_now = xTaskGetTickCount();
  65. return lwip_sys_now;
  66. }
  67. u32_t
  68. sys_now(void)
  69. {
  70. lwip_sys_now = xTaskGetTickCount();
  71. return lwip_sys_now;
  72. }
  73. void
  74. sys_init(void)
  75. {
  76. int i;
  77. // Initialize the the per-thread sys_timeouts structures
  78. // make sure there are no valid pids in the list
  79. for(i = 0; i < SYS_THREAD_MAX; i++)
  80. {
  81. s_timeoutlist[i].pid = 0;
  82. s_timeoutlist[i].timeouts.next = NULL;
  83. }
  84. // keep track of how many threads have been created
  85. s_nextthread = 0;
  86. }
  87. struct sys_timeouts *sys_arch_timeouts(void)
  88. {
  89. int i;
  90. xTaskHandle pid;
  91. struct timeoutlist *tl;
  92. pid = xTaskGetCurrentTaskHandle( );
  93. for(i = 0; i < s_nextthread; i++)
  94. {
  95. tl = &(s_timeoutlist[i]);
  96. if(tl->pid == pid)
  97. {
  98. return &(tl->timeouts);
  99. }
  100. }
  101. return NULL;
  102. }
  103. sys_prot_t sys_arch_protect(void)
  104. {
  105. vPortEnterCritical();
  106. return 1;
  107. }
  108. void sys_arch_unprotect(sys_prot_t pval)
  109. {
  110. ( void ) pval;
  111. vPortExitCritical();
  112. }
  113. #if !NO_SYS
  114. //test_sys_arch_waiting_fn the_waiting_fn;
  115. //void
  116. //test_sys_arch_wait_callback(test_sys_arch_waiting_fn waiting_fn)
  117. //{
  118. // the_waiting_fn = waiting_fn;
  119. //}
  120. err_t
  121. sys_sem_new(sys_sem_t *sem, u8_t count)
  122. {
  123. /* 创建 sem */
  124. if(count <= 1)
  125. {
  126. *sem = xSemaphoreCreateBinary();
  127. if(count == 1)
  128. {
  129. sys_sem_signal(*sem);
  130. }
  131. }
  132. else
  133. *sem = xSemaphoreCreateCounting(count,count);
  134. #if SYS_STATS
  135. ++lwip_stats.sys.sem.used;
  136. if (lwip_stats.sys.sem.max < lwip_stats.sys.sem.used) {
  137. lwip_stats.sys.sem.max = lwip_stats.sys.sem.used;
  138. }
  139. #endif /* SYS_STATS */
  140. if(*sem != SYS_SEM_NULL)
  141. return ERR_OK;
  142. else
  143. {
  144. #if SYS_STATS
  145. ++lwip_stats.sys.sem.err;
  146. #endif /* SYS_STATS */
  147. printf("[sys_arch]:new sem fail!\n");
  148. return ERR_MEM;
  149. }
  150. }
  151. void
  152. sys_sem_free(sys_sem_t *sem)
  153. {
  154. #if SYS_STATS
  155. --lwip_stats.sys.sem.used;
  156. #endif /* SYS_STATS */
  157. /* 删除 sem */
  158. vSemaphoreDelete(*sem);
  159. *sem = SYS_SEM_NULL;
  160. }
  161. int sys_sem_valid(sys_sem_t *sem)
  162. {
  163. return (*sem != SYS_SEM_NULL);
  164. }
  165. void
  166. sys_sem_set_invalid(sys_sem_t *sem)
  167. {
  168. *sem = SYS_SEM_NULL;
  169. }
  170. /*
  171. 如果timeout参数不为零,则返回值为
  172. 等待信号量所花费的毫秒数。如果
  173. 信号量未在指定时间内发出信号,返回值为
  174. SYS_ARCH_TIMEOUT。如果线程不必等待信号量
  175. 该函数返回零。 */
  176. u32_t
  177. sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
  178. {
  179. u32_t wait_tick = 0;
  180. u32_t start_tick = 0 ;
  181. //看看信号量是否有效
  182. if(*sem == SYS_SEM_NULL)
  183. return SYS_ARCH_TIMEOUT;
  184. //首先获取开始等待信号量的时钟节拍
  185. start_tick = xTaskGetTickCount();
  186. //timeout != 0,需要将ms换成系统的时钟节拍
  187. if(timeout != 0)
  188. {
  189. //将ms转换成时钟节拍
  190. wait_tick = timeout / portTICK_PERIOD_MS;
  191. if (wait_tick == 0)
  192. wait_tick = 1;
  193. }
  194. else
  195. wait_tick = portMAX_DELAY; //一直阻塞
  196. //等待成功,计算等待的时间,否则就表示等待超时
  197. if(xSemaphoreTake(*sem, wait_tick) == pdTRUE)
  198. return ((xTaskGetTickCount()-start_tick)*portTICK_RATE_MS);
  199. else
  200. return SYS_ARCH_TIMEOUT;
  201. }
  202. void
  203. sys_sem_signal(sys_sem_t *sem)
  204. {
  205. if(xSemaphoreGive( *sem ) != pdTRUE)
  206. printf("[sys_arch]:sem signal fail!\n");
  207. }
  208. err_t
  209. sys_mutex_new(sys_mutex_t *mutex)
  210. {
  211. /* 创建 sem */
  212. *mutex = xSemaphoreCreateMutex();
  213. if(*mutex != SYS_MRTEX_NULL)
  214. return ERR_OK;
  215. else
  216. {
  217. printf("[sys_arch]:new mutex fail!\n");
  218. return ERR_MEM;
  219. }
  220. }
  221. void
  222. sys_mutex_free(sys_mutex_t *mutex)
  223. {
  224. vSemaphoreDelete(*mutex);
  225. }
  226. void
  227. sys_mutex_set_invalid(sys_mutex_t *mutex)
  228. {
  229. *mutex = SYS_MRTEX_NULL;
  230. }
  231. void
  232. sys_mutex_lock(sys_mutex_t *mutex)
  233. {
  234. xSemaphoreTake(*mutex,/* 互斥量句柄 */
  235. portMAX_DELAY); /* 等待时间 */
  236. }
  237. void
  238. sys_mutex_unlock(sys_mutex_t *mutex)
  239. {
  240. xSemaphoreGive( *mutex );//给出互斥量
  241. }
  242. sys_thread_t
  243. sys_thread_new(const char *name, lwip_thread_fn function, void *arg, int stacksize, int prio)
  244. {
  245. sys_thread_t handle = NULL;
  246. BaseType_t xReturn = pdPASS;
  247. /* 创建MidPriority_Task任务 */
  248. xReturn = xTaskCreate((TaskFunction_t )function, /* 任务入口函数 */
  249. (const char* )name,/* 任务名字 */
  250. (uint16_t )stacksize, /* 任务栈大小 */
  251. (void* )arg,/* 任务入口函数参数 */
  252. (UBaseType_t )prio, /* 任务的优先级 */
  253. (TaskHandle_t* )&handle);/* 任务控制块指针 */
  254. if(xReturn != pdPASS)
  255. {
  256. printf("[sys_arch]:create task fail!err:%#lx\n",xReturn);
  257. return NULL;
  258. }
  259. return handle;
  260. }
  261. err_t
  262. sys_mbox_new(sys_mbox_t *mbox, int size)
  263. {
  264. /* 创建Test_Queue */
  265. *mbox = xQueueCreate((UBaseType_t ) size,/* 消息队列的长度 */
  266. (UBaseType_t ) sizeof(void *));/* 消息的大小 */
  267. #if SYS_STATS
  268. ++lwip_stats.sys.mbox.used;
  269. if (lwip_stats.sys.mbox.max < lwip_stats.sys.mbox.used) {
  270. lwip_stats.sys.mbox.max = lwip_stats.sys.mbox.used;
  271. }
  272. #endif /* SYS_STATS */
  273. if(NULL == *mbox)
  274. return ERR_MEM;
  275. return ERR_OK;
  276. }
  277. void
  278. sys_mbox_free(sys_mbox_t *mbox)
  279. {
  280. if( uxQueueMessagesWaiting( *mbox ) )
  281. {
  282. /* Line for breakpoint. Should never break here! */
  283. portNOP();
  284. #if SYS_STATS
  285. lwip_stats.sys.mbox.err++;
  286. #endif /* SYS_STATS */
  287. // TODO notify the user of failure.
  288. }
  289. vQueueDelete(*mbox);
  290. #if SYS_STATS
  291. --lwip_stats.sys.mbox.used;
  292. #endif /* SYS_STATS */
  293. }
  294. int sys_mbox_valid(sys_mbox_t *mbox)
  295. {
  296. if (*mbox == SYS_MBOX_NULL)
  297. return 0;
  298. else
  299. return 1;
  300. }
  301. void
  302. sys_mbox_set_invalid(sys_mbox_t *mbox)
  303. {
  304. *mbox = SYS_MBOX_NULL;
  305. }
  306. void
  307. sys_mbox_post(sys_mbox_t *q, void *msg)
  308. {
  309. while(xQueueSend( *q, /* 消息队列的句柄 */
  310. &msg,/* 发送的消息内容 */
  311. portMAX_DELAY) != pdTRUE); /* 等待时间 */
  312. }
  313. err_t
  314. sys_mbox_trypost(sys_mbox_t *q, void *msg)
  315. {
  316. if(xQueueSend(*q,&msg,0) == pdPASS)
  317. return ERR_OK;
  318. else
  319. return ERR_MEM;
  320. }
  321. err_t
  322. sys_mbox_trypost_fromisr(sys_mbox_t *q, void *msg)
  323. {
  324. return sys_mbox_trypost(q, msg);
  325. }
  326. u32_t
  327. sys_arch_mbox_fetch(sys_mbox_t *q, void **msg, u32_t timeout)
  328. {
  329. void *dummyptr;
  330. u32_t wait_tick = 0;
  331. u32_t start_tick = 0 ;
  332. if ( msg == NULL ) //看看存储消息的地方是否有效
  333. msg = &dummyptr;
  334. //首先获取开始等待信号量的时钟节拍
  335. start_tick = sys_now();
  336. //timeout != 0,需要将ms换成系统的时钟节拍
  337. if(timeout != 0)
  338. {
  339. //将ms转换成时钟节拍
  340. wait_tick = timeout / portTICK_PERIOD_MS;
  341. if (wait_tick == 0)
  342. wait_tick = 1;
  343. }
  344. //一直阻塞
  345. else
  346. wait_tick = portMAX_DELAY;
  347. //等待成功,计算等待的时间,否则就表示等待超时
  348. if(xQueueReceive(*q,&(*msg), wait_tick) == pdTRUE)
  349. return ((sys_now() - start_tick)*portTICK_PERIOD_MS);
  350. else
  351. {
  352. *msg = NULL;
  353. return SYS_ARCH_TIMEOUT;
  354. }
  355. }
  356. u32_t
  357. sys_arch_mbox_tryfetch(sys_mbox_t *q, void **msg)
  358. {
  359. void *dummyptr;
  360. if ( msg == NULL )
  361. msg = &dummyptr;
  362. //等待成功,计算等待的时间
  363. if(xQueueReceive(*q,&(*msg), 0) == pdTRUE)
  364. return ERR_OK;
  365. else
  366. return SYS_MBOX_EMPTY;
  367. }
  368. #if LWIP_NETCONN_SEM_PER_THREAD
  369. #error LWIP_NETCONN_SEM_PER_THREAD==1 not supported
  370. #endif /* LWIP_NETCONN_SEM_PER_THREAD */
  371. #endif /* !NO_SYS */
  372. /* Variables Initialization */
  373. struct netif gnetif;
  374. ip4_addr_t ipaddr;
  375. ip4_addr_t netmask;
  376. ip4_addr_t gw;
  377. uint8_t IP_ADDRESS[4];
  378. uint8_t NETMASK_ADDRESS[4];
  379. uint8_t GATEWAY_ADDRESS[4];
  380. void TCPIP_Init(void)
  381. {
  382. tcpip_init(NULL, NULL);
  383. /* IP addresses initialization */
  384. /* USER CODE BEGIN 0 */
  385. #if LWIP_DHCP
  386. ip_addr_set_zero_ip4(&ipaddr);
  387. ip_addr_set_zero_ip4(&netmask);
  388. ip_addr_set_zero_ip4(&gw);
  389. #else
  390. IP4_ADDR(&ipaddr,IP_ADDR0,IP_ADDR1,IP_ADDR2,IP_ADDR3);
  391. IP4_ADDR(&netmask,NETMASK_ADDR0,NETMASK_ADDR1,NETMASK_ADDR2,NETMASK_ADDR3);
  392. IP4_ADDR(&gw,GW_ADDR0,GW_ADDR1,GW_ADDR2,GW_ADDR3);
  393. #endif /* USE_DHCP */
  394. /* USER CODE END 0 */
  395. /* Initilialize the LwIP stack without RTOS */
  396. /* add the network interface (IPv4/IPv6) without RTOS */
  397. netif_add(&gnetif, &ipaddr, &netmask, &gw, NULL, &ethernetif_init, &tcpip_input);
  398. /* Registers the default network interface */
  399. netif_set_default(&gnetif);
  400. if (netif_is_link_up(&gnetif))
  401. {
  402. /* When the netif is fully configured this function must be called */
  403. netif_set_up(&gnetif);
  404. }
  405. else
  406. {
  407. /* When the netif link is down this function must be called */
  408. netif_set_down(&gnetif);
  409. }
  410. #if LWIP_DHCP //若使用了DHCP
  411. int err;
  412. /* Creates a new DHCP client for this interface on the first call.
  413. Note: you must call dhcp_fine_tmr() and dhcp_coarse_tmr() at
  414. the predefined regular intervals after starting the client.
  415. You can peek in the netif->dhcp struct for the actual DHCP status.*/
  416. printf("本例程将使用DHCP动态分配IP地址,如果不需要则在lwipopts.h中将LWIP_DHCP定义为0\n\n");
  417. err = dhcp_start(&gnetif); //开启dhcp
  418. if(err == ERR_OK)
  419. printf("lwip dhcp init success...\n\n");
  420. else
  421. printf("lwip dhcp init fail...\n\n");
  422. while(ip_addr_cmp(&(gnetif.ip_addr),&ipaddr)) //等待dhcp分配的ip有效
  423. {
  424. vTaskDelay(1);
  425. }
  426. #endif
  427. printf("本地IP地址是:%d.%d.%d.%d\n\n", \
  428. ((gnetif.ip_addr.addr)&0x000000ff), \
  429. (((gnetif.ip_addr.addr)&0x0000ff00)>>8), \
  430. (((gnetif.ip_addr.addr)&0x00ff0000)>>16), \
  431. ((gnetif.ip_addr.addr)&0xff000000)>>24);
  432. }