硬汉嵌入式论坛

 找回密码
 立即注册
查看: 4078|回复: 7
收起左侧

[以太网] 终于打通LwIP配合RTX5和FreeRTOS的带CMSIS-RTOS V2封装层的多任务版本,直接使用MDK的RTE环境添加

[复制链接]

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107077
QQ
发表于 2019-5-10 03:13:40 | 显示全部楼层 |阅读模式
不容易,各种坑踩了遍。

KEIL是真的懒了,MDK集成的LwIP驱动文件多任务支持有问题。好几个函数有误。

幸亏ST搞了,驱动文件支持CMSIS-RTOS V1和V2两种封装层,简单修改直接用上了。

  1. /*
  2. * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
  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: Adam Dunkels <adam@sics.se>
  30. *
  31. */

  32. /* lwIP includes. */
  33. #include "lwip/debug.h"
  34. #include "lwip/def.h"
  35. #include "lwip/sys.h"
  36. #include "lwip/mem.h"
  37. #include "lwip/stats.h"

  38. #if !NO_SYS

  39. #include "cmsis_os.h"

  40. #if defined(LWIP_SOCKET_SET_ERRNO) && defined(LWIP_PROVIDE_ERRNO)
  41. int errno;
  42. #endif

  43. /*-----------------------------------------------------------------------------------*/
  44. //  Creates an empty mailbox.
  45. err_t sys_mbox_new(sys_mbox_t *mbox, int size)
  46. {
  47. #if (osCMSIS < 0x20000U)
  48.   osMessageQDef(QUEUE, size, void *);
  49.   *mbox = osMessageCreate(osMessageQ(QUEUE), NULL);
  50. #else
  51.   *mbox = osMessageQueueNew(size, sizeof(void *), NULL);
  52. #endif
  53. #if SYS_STATS
  54.   ++lwip_stats.sys.mbox.used;
  55.   if(lwip_stats.sys.mbox.max < lwip_stats.sys.mbox.used)
  56.   {
  57.     lwip_stats.sys.mbox.max = lwip_stats.sys.mbox.used;
  58.   }
  59. #endif /* SYS_STATS */
  60.   if(*mbox == NULL)
  61.     return ERR_MEM;

  62.   return ERR_OK;
  63. }

  64. /*-----------------------------------------------------------------------------------*/
  65. /*
  66.   Deallocates a mailbox. If there are messages still present in the
  67.   mailbox when the mailbox is deallocated, it is an indication of a
  68.   programming error in lwIP and the developer should be notified.
  69. */
  70. void sys_mbox_free(sys_mbox_t *mbox)
  71. {
  72. #if (osCMSIS < 0x20000U)
  73.   if(osMessageWaiting(*mbox))
  74. #else
  75.   if(osMessageQueueGetCount(*mbox))
  76. #endif
  77.   {
  78.     /* Line for breakpoint.  Should never break here! */
  79.     portNOP();
  80. #if SYS_STATS
  81.     lwip_stats.sys.mbox.err++;
  82. #endif /* SYS_STATS */

  83.   }
  84. #if (osCMSIS < 0x20000U)
  85.   osMessageDelete(*mbox);
  86. #else
  87.   osMessageQueueDelete(*mbox);
  88. #endif
  89. #if SYS_STATS
  90.   --lwip_stats.sys.mbox.used;
  91. #endif /* SYS_STATS */
  92. }

  93. /*-----------------------------------------------------------------------------------*/
  94. //   Posts the "msg" to the mailbox.
  95. void sys_mbox_post(sys_mbox_t *mbox, void *data)
  96. {
  97. #if (osCMSIS < 0x20000U)
  98.   while(osMessagePut(*mbox, (uint32_t)data, osWaitForever) != osOK);
  99. #else
  100.   while(osMessageQueuePut(*mbox, &data, 0, osWaitForever) != osOK);
  101. #endif
  102. }


  103. /*-----------------------------------------------------------------------------------*/
  104. //   Try to post the "msg" to the mailbox.
  105. err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg)
  106. {
  107.   err_t result;
  108. #if (osCMSIS < 0x20000U)
  109.   if(osMessagePut(*mbox, (uint32_t)msg, 0) == osOK)
  110. #else
  111.   if(osMessageQueuePut(*mbox, &msg, 0, 0) == osOK)
  112. #endif
  113.   {
  114.     result = ERR_OK;
  115.   }
  116.   else
  117.   {
  118.     // could not post, queue must be full
  119.     result = ERR_MEM;

  120. #if SYS_STATS
  121.     lwip_stats.sys.mbox.err++;
  122. #endif /* SYS_STATS */
  123.   }

  124.   return result;
  125. }

  126. /*-----------------------------------------------------------------------------------*/
  127. /*
  128.   Blocks the thread until a message arrives in the mailbox, but does
  129.   not block the thread longer than "timeout" milliseconds (similar to
  130.   the sys_arch_sem_wait() function). The "msg" argument is a result
  131.   parameter that is set by the function (i.e., by doing "*msg =
  132.   ptr"). The "msg" parameter maybe NULL to indicate that the message
  133.   should be dropped.

  134.   The return values are the same as for the sys_arch_sem_wait() function:
  135.   Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a
  136.   timeout.

  137.   Note that a function with a similar name, sys_mbox_fetch(), is
  138.   implemented by lwIP.
  139. */
  140. u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout)
  141. {
  142. #if (osCMSIS < 0x20000U)
  143.   osEvent event;
  144.   uint32_t starttime = osKernelSysTick();
  145. #else
  146.   osStatus_t status;
  147.   uint32_t starttime = osKernelGetTickCount();
  148. #endif
  149.   if(timeout != 0)
  150.   {
  151. #if (osCMSIS < 0x20000U)
  152.     event = osMessageGet (*mbox, timeout);

  153.     if(event.status == osEventMessage)
  154.     {
  155.       *msg = (void *)event.value.v;
  156.       return (osKernelSysTick() - starttime);
  157.     }
  158. #else
  159.     status = osMessageQueueGet(*mbox, msg, 0, timeout);
  160.     if (status == osOK)
  161.     {
  162.       return (osKernelGetTickCount() - starttime);
  163.     }
  164. #endif
  165.     else
  166.     {
  167.       return SYS_ARCH_TIMEOUT;
  168.     }
  169.   }
  170.   else
  171.   {
  172. #if (osCMSIS < 0x20000U)
  173.     event = osMessageGet (*mbox, osWaitForever);
  174.     *msg = (void *)event.value.v;
  175.     return (osKernelSysTick() - starttime);
  176. #else
  177.     osMessageQueueGet(*mbox, msg, 0, osWaitForever );
  178.     return (osKernelGetTickCount() - starttime);
  179. #endif
  180.   }
  181. }

  182. /*-----------------------------------------------------------------------------------*/
  183. /*
  184.   Similar to sys_arch_mbox_fetch, but if message is not ready immediately, we'll
  185.   return with SYS_MBOX_EMPTY.  On success, 0 is returned.
  186. */
  187. u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg)
  188. {
  189. #if (osCMSIS < 0x20000U)
  190.   osEvent event;

  191.   event = osMessageGet (*mbox, 0);

  192.   if(event.status == osEventMessage)
  193.   {
  194.     *msg = (void *)event.value.v;
  195. #else
  196.   if (osMessageQueueGet(*mbox, msg, 0, 0) == osOK)
  197.   {
  198. #endif
  199.     return ERR_OK;
  200.   }
  201.   else
  202.   {
  203.     return SYS_MBOX_EMPTY;
  204.   }
  205. }
  206. /*----------------------------------------------------------------------------------*/
  207. int sys_mbox_valid(sys_mbox_t *mbox)
  208. {
  209.   if (*mbox == SYS_MBOX_NULL)
  210.     return 0;
  211.   else
  212.     return 1;
  213. }
  214. /*-----------------------------------------------------------------------------------*/
  215. void sys_mbox_set_invalid(sys_mbox_t *mbox)
  216. {
  217.   *mbox = SYS_MBOX_NULL;
  218. }

  219. /*-----------------------------------------------------------------------------------*/
  220. //  Creates a new semaphore. The "count" argument specifies
  221. //  the initial state of the semaphore.
  222. err_t sys_sem_new(sys_sem_t *sem, u8_t count)
  223. {
  224. #if (osCMSIS < 0x20000U)
  225.   osSemaphoreDef(SEM);
  226.   *sem = osSemaphoreCreate (osSemaphore(SEM), 1);
  227. #else
  228.   *sem = osSemaphoreNew(UINT16_MAX, count, NULL);
  229. #endif

  230.   if(*sem == NULL)
  231.   {
  232. #if SYS_STATS
  233.     ++lwip_stats.sys.sem.err;
  234. #endif /* SYS_STATS */
  235.     return ERR_MEM;
  236.   }

  237.   if(count == 0)        // Means it can't be taken
  238.   {
  239. #if (osCMSIS < 0x20000U)
  240.     osSemaphoreWait(*sem, 0);
  241. #else
  242.     osSemaphoreAcquire(*sem, 0);
  243. #endif
  244.   }

  245. #if SYS_STATS
  246.   ++lwip_stats.sys.sem.used;
  247.   if (lwip_stats.sys.sem.max < lwip_stats.sys.sem.used) {
  248.     lwip_stats.sys.sem.max = lwip_stats.sys.sem.used;
  249.   }
  250. #endif /* SYS_STATS */

  251.   return ERR_OK;
  252. }

  253. /*-----------------------------------------------------------------------------------*/
  254. /*
  255.   Blocks the thread while waiting for the semaphore to be
  256.   signaled. If the "timeout" argument is non-zero, the thread should
  257.   only be blocked for the specified time (measured in
  258.   milliseconds).

  259.   If the timeout argument is non-zero, the return value is the number of
  260.   milliseconds spent waiting for the semaphore to be signaled. If the
  261.   semaphore wasn't signaled within the specified time, the return value is
  262.   SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore
  263.   (i.e., it was already signaled), the function may return zero.

  264.   Notice that lwIP implements a function with a similar name,
  265.   sys_sem_wait(), that uses the sys_arch_sem_wait() function.
  266. */
  267. u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
  268. {
  269. #if (osCMSIS < 0x20000U)
  270.   uint32_t starttime = osKernelSysTick();
  271. #else
  272.   uint32_t starttime = osKernelGetTickCount();
  273. #endif
  274.   if(timeout != 0)
  275.   {
  276. #if (osCMSIS < 0x20000U)
  277.     if(osSemaphoreWait (*sem, timeout) == osOK)
  278.     {
  279.       return (osKernelSysTick() - starttime);
  280. #else
  281.     if(osSemaphoreAcquire(*sem, timeout) == osOK)
  282.     {
  283.         return (osKernelGetTickCount() - starttime);
  284. #endif
  285.     }
  286.     else
  287.     {
  288.       return SYS_ARCH_TIMEOUT;
  289.     }
  290.   }
  291.   else
  292.   {
  293. #if (osCMSIS < 0x20000U)
  294.     while(osSemaphoreWait (*sem, osWaitForever) != osOK);
  295.     return (osKernelSysTick() - starttime);
  296. #else
  297.     while(osSemaphoreAcquire(*sem, osWaitForever) != osOK);
  298.     return (osKernelGetTickCount() - starttime);
  299. #endif
  300.   }
  301. }

  302. /*-----------------------------------------------------------------------------------*/
  303. // Signals a semaphore
  304. void sys_sem_signal(sys_sem_t *sem)
  305. {
  306.   osSemaphoreRelease(*sem);
  307. }

  308. /*-----------------------------------------------------------------------------------*/
  309. // Deallocates a semaphore
  310. void sys_sem_free(sys_sem_t *sem)
  311. {
  312. #if SYS_STATS
  313.   --lwip_stats.sys.sem.used;
  314. #endif /* SYS_STATS */

  315.   osSemaphoreDelete(*sem);
  316. }
  317. /*-----------------------------------------------------------------------------------*/
  318. int sys_sem_valid(sys_sem_t *sem)
  319. {
  320.   if (*sem == SYS_SEM_NULL)
  321.     return 0;
  322.   else
  323.     return 1;
  324. }

  325. /*-----------------------------------------------------------------------------------*/
  326. void sys_sem_set_invalid(sys_sem_t *sem)
  327. {
  328.   *sem = SYS_SEM_NULL;
  329. }

  330. /*-----------------------------------------------------------------------------------*/
  331. #if (osCMSIS < 0x20000U)
  332. osMutexId lwip_sys_mutex;
  333. osMutexDef(lwip_sys_mutex);
  334. #else
  335. osMutexId_t lwip_sys_mutex;
  336. #endif
  337. // Initialize sys arch
  338. void sys_init(void)
  339. {
  340. #if (osCMSIS < 0x20000U)
  341.   lwip_sys_mutex = osMutexCreate(osMutex(lwip_sys_mutex));
  342. #else
  343.   lwip_sys_mutex = osMutexNew(NULL);
  344. #endif
  345. }
  346. /*-----------------------------------------------------------------------------------*/
  347.                                       /* Mutexes*/
  348. /*-----------------------------------------------------------------------------------*/
  349. /*-----------------------------------------------------------------------------------*/
  350. #if LWIP_COMPAT_MUTEX == 0
  351. /* Create a new mutex*/
  352. err_t sys_mutex_new(sys_mutex_t *mutex) {

  353. #if (osCMSIS < 0x20000U)
  354.   osMutexDef(MUTEX);
  355.   *mutex = osMutexCreate(osMutex(MUTEX));
  356. #else
  357.   *mutex = osMutexNew(NULL);
  358. #endif

  359.   if(*mutex == NULL)
  360.   {
  361. #if SYS_STATS
  362.     ++lwip_stats.sys.mutex.err;
  363. #endif /* SYS_STATS */
  364.     return ERR_MEM;
  365.   }

  366. #if SYS_STATS
  367.   ++lwip_stats.sys.mutex.used;
  368.   if (lwip_stats.sys.mutex.max < lwip_stats.sys.mutex.used) {
  369.     lwip_stats.sys.mutex.max = lwip_stats.sys.mutex.used;
  370.   }
  371. #endif /* SYS_STATS */
  372.   return ERR_OK;
  373. }
  374. /*-----------------------------------------------------------------------------------*/
  375. /* Deallocate a mutex*/
  376. void sys_mutex_free(sys_mutex_t *mutex)
  377. {
  378. #if SYS_STATS
  379.       --lwip_stats.sys.mutex.used;
  380. #endif /* SYS_STATS */

  381.   osMutexDelete(*mutex);
  382. }
  383. /*-----------------------------------------------------------------------------------*/
  384. /* Lock a mutex*/
  385. void sys_mutex_lock(sys_mutex_t *mutex)
  386. {
  387. #if (osCMSIS < 0x20000U)
  388.   osMutexWait(*mutex, osWaitForever);
  389. #else
  390.   osMutexAcquire(*mutex, osWaitForever);
  391. #endif
  392. }

  393. /*-----------------------------------------------------------------------------------*/
  394. /* Unlock a mutex*/
  395. void sys_mutex_unlock(sys_mutex_t *mutex)
  396. {
  397.   osMutexRelease(*mutex);
  398. }
  399. #endif /*LWIP_COMPAT_MUTEX*/
  400. /*-----------------------------------------------------------------------------------*/
  401. // TODO
  402. /*-----------------------------------------------------------------------------------*/
  403. /*
  404.   Starts a new thread with priority "prio" that will begin its execution in the
  405.   function "thread()". The "arg" argument will be passed as an argument to the
  406.   thread() function. The id of the new thread is returned. Both the id and
  407.   the priority are system dependent.
  408. */
  409. sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread , void *arg, int stacksize, int prio)
  410. {
  411. #if (osCMSIS < 0x20000U)
  412.   const osThreadDef_t os_thread_def = { (char *)name, (os_pthread)thread, (osPriority)prio, 0, stacksize};
  413.   return osThreadCreate(&os_thread_def, arg);
  414. #else
  415.   const osThreadAttr_t attributes = {
  416.                         .name = name,
  417.                         .stack_size = stacksize,
  418.                         .priority = (osPriority_t)prio,
  419.                       };
  420.   return osThreadNew(thread, arg, &attributes);
  421. #endif
  422. }

  423. /*
  424.   This optional function does a "fast" critical region protection and returns
  425.   the previous protection level. This function is only called during very short
  426.   critical regions. An embedded system which supports ISR-based drivers might
  427.   want to implement this function by disabling interrupts. Task-based systems
  428.   might want to implement this by using a mutex or disabling tasking. This
  429.   function should support recursive calls from the same task or interrupt. In
  430.   other words, sys_arch_protect() could be called while already protected. In
  431.   that case the return value indicates that it is already protected.

  432.   sys_arch_protect() is only required if your port is supporting an operating
  433.   system.

  434.   Note: This function is based on FreeRTOS API, because no equivalent CMSIS-RTOS
  435.         API is available
  436. */
  437. sys_prot_t sys_arch_protect(void)
  438. {
  439. #if (osCMSIS < 0x20000U)
  440.   osMutexWait(lwip_sys_mutex, osWaitForever);
  441. #else
  442.   osMutexAcquire(lwip_sys_mutex, osWaitForever);
  443. #endif
  444.   return (sys_prot_t)1;
  445. }


  446. /*
  447.   This optional function does a "fast" set of critical region protection to the
  448.   value specified by pval. See the documentation for sys_arch_protect() for
  449.   more information. This function is only required if your port is supporting
  450.   an operating system.

  451.   Note: This function is based on FreeRTOS API, because no equivalent CMSIS-RTOS
  452.         API is available
  453. */
  454. void sys_arch_unprotect(sys_prot_t pval)
  455. {
  456.   ( void ) pval;
  457.   osMutexRelease(lwip_sys_mutex);
  458. }

  459. #endif /* !NO_SYS */
复制代码







回复

使用道具 举报

2

主题

3

回帖

9

积分

新手上路

积分
9
发表于 2019-6-10 13:40:17 | 显示全部楼层
up一下,看看,可以请教楼主一些问题吗?
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107077
QQ
 楼主| 发表于 2019-6-11 10:55:20 | 显示全部楼层
233_MCkj4 发表于 2019-6-10 13:40
up一下,看看,可以请教楼主一些问题吗?

没问题,请留言
回复

使用道具 举报

0

主题

1

回帖

1

积分

新手上路

积分
1
发表于 2020-3-26 11:33:32 | 显示全部楼层
支持,我用上了
回复

使用道具 举报

10

主题

19

回帖

49

积分

初级会员

积分
49
发表于 2020-4-27 16:57:48 | 显示全部楼层
请问一下,用keil生成的lwip,ping的时间过长,作为服务器连接上去的时候响应时间也过长,基本在1s左右,请问一下有可能是哪里出问题?
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107077
QQ
 楼主| 发表于 2020-4-27 17:35:11 | 显示全部楼层
nextstation 发表于 2020-4-27 16:57
请问一下,用keil生成的lwip,ping的时间过长,作为服务器连接上去的时候响应时间也过长,基本在1s左右,请 ...

你的程序框架问题,没有移植好。

今天在群友的反馈下,也解决了一个之前移植的问题,本周准备升级下。
回复

使用道具 举报

10

主题

19

回帖

49

积分

初级会员

积分
49
发表于 2020-4-27 17:40:45 | 显示全部楼层
nextstation 发表于 2020-4-27 16:57
请问一下,用keil生成的lwip,ping的时间过长,作为服务器连接上去的时候响应时间也过长,基本在1s左右,请 ...

八成是中断触发的lwip协议太多,任务处理不过来导致的延时
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107077
QQ
 楼主| 发表于 2020-4-27 17:47:32 | 显示全部楼层
nextstation 发表于 2020-4-27 17:40
八成是中断触发的lwip协议太多,任务处理不过来导致的延时

下载一个我这个里面的FreeRTOS版测试即可:

http://www.armbbs.cn/forum.php?m ... &extra=page%3D1
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-16 22:18 , Processed in 0.174563 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表