sys_arch.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618
  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 <goldsimon@gmx.de>
  30. *
  31. */
  32. /*
  33. * Copyright (c) 2021-2022 HPMicro
  34. *
  35. * SPDX-License-Identifier: BSD-3-Clause
  36. *
  37. */
  38. /* lwIP includes. */
  39. #include "lwip/debug.h"
  40. #include "lwip/def.h"
  41. #include "lwip/sys.h"
  42. #include "lwip/mem.h"
  43. #include "lwip/stats.h"
  44. #include "lwip/tcpip.h"
  45. #if !NO_SYS
  46. #include "FreeRTOS.h"
  47. #include "semphr.h"
  48. #endif
  49. #if !NO_SYS
  50. #include "sys_arch.h"
  51. #endif
  52. int errno;
  53. #if !NO_SYS
  54. /** Set this to 1 if you want the stack size passed to sys_thread_new() to be
  55. * interpreted as number of stack words (FreeRTOS-like).
  56. * Default is that they are interpreted as byte count (lwIP-like).
  57. */
  58. #ifndef LWIP_FREERTOS_THREAD_STACKSIZE_IS_STACKWORDS
  59. #define LWIP_FREERTOS_THREAD_STACKSIZE_IS_STACKWORDS 0
  60. #endif
  61. /** Set this to 1 to use a mutex for SYS_ARCH_PROTECT() critical regions.
  62. * Default is 0 and locks interrupts/scheduler for SYS_ARCH_PROTECT().
  63. */
  64. #ifndef LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX
  65. #define LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX 0
  66. #endif
  67. /** Set this to 1 to include a sanity check that SYS_ARCH_PROTECT() and
  68. * SYS_ARCH_UNPROTECT() are called matching.
  69. */
  70. #ifndef LWIP_FREERTOS_SYS_ARCH_PROTECT_SANITY_CHECK
  71. #define LWIP_FREERTOS_SYS_ARCH_PROTECT_SANITY_CHECK 0
  72. #endif
  73. /** Set this to 1 to let sys_mbox_free check that queues are empty when freed */
  74. #ifndef LWIP_FREERTOS_CHECK_QUEUE_EMPTY_ON_FREE
  75. #define LWIP_FREERTOS_CHECK_QUEUE_EMPTY_ON_FREE 0
  76. #endif
  77. /** Set this to 1 to enable core locking check functions in this port.
  78. * For this to work, you'll have to define LWIP_ASSERT_CORE_LOCKED()
  79. * and LWIP_MARK_TCPIP_THREAD() correctly in your lwipopts.h! */
  80. #ifndef LWIP_FREERTOS_CHECK_CORE_LOCKING
  81. #define LWIP_FREERTOS_CHECK_CORE_LOCKING 1
  82. #endif
  83. /** Set this to 0 to implement sys_now() yourself, e.g. using a hw timer.
  84. * Default is 1, where FreeRTOS ticks are used to calculate back to ms.
  85. */
  86. #ifndef LWIP_FREERTOS_SYS_NOW_FROM_FREERTOS
  87. #define LWIP_FREERTOS_SYS_NOW_FROM_FREERTOS 1
  88. #endif
  89. #if !configSUPPORT_DYNAMIC_ALLOCATION
  90. # error "lwIP FreeRTOS port requires configSUPPORT_DYNAMIC_ALLOCATION"
  91. #endif
  92. #if !INCLUDE_vTaskDelay
  93. # error "lwIP FreeRTOS port requires INCLUDE_vTaskDelay"
  94. #endif
  95. #if !INCLUDE_vTaskSuspend
  96. # error "lwIP FreeRTOS port requires INCLUDE_vTaskSuspend"
  97. #endif
  98. #if LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX || !LWIP_COMPAT_MUTEX
  99. #if !configUSE_MUTEXES
  100. # error "lwIP FreeRTOS port requires configUSE_MUTEXES"
  101. #endif
  102. #endif
  103. #if SYS_LIGHTWEIGHT_PROT && LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX
  104. static SemaphoreHandle_t sys_arch_protect_mutex;
  105. #endif
  106. #if SYS_LIGHTWEIGHT_PROT && LWIP_FREERTOS_SYS_ARCH_PROTECT_SANITY_CHECK
  107. static sys_prot_t sys_arch_protect_nesting;
  108. #endif
  109. /* Initialize this module (see description in sys.h) */
  110. void
  111. sys_init(void)
  112. {
  113. #if SYS_LIGHTWEIGHT_PROT && LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX
  114. /* initialize sys_arch_protect global mutex */
  115. sys_arch_protect_mutex = xSemaphoreCreateRecursiveMutex();
  116. LWIP_ASSERT("failed to create sys_arch_protect mutex",
  117. sys_arch_protect_mutex != NULL);
  118. #endif /* SYS_LIGHTWEIGHT_PROT && LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX */
  119. }
  120. #if configUSE_16_BIT_TICKS == 1
  121. #error This port requires 32 bit ticks or timer overflow will fail
  122. #endif
  123. #if LWIP_FREERTOS_SYS_NOW_FROM_FREERTOS
  124. u32_t sys_now(void)
  125. {
  126. return xTaskGetTickCount() * portTICK_PERIOD_MS;
  127. }
  128. #else
  129. u32_t sys_now(void)
  130. {
  131. return 0;
  132. }
  133. #endif
  134. u32_t sys_jiffies(void)
  135. {
  136. return xTaskGetTickCount();
  137. }
  138. #if SYS_LIGHTWEIGHT_PROT
  139. sys_prot_t sys_arch_protect(void)
  140. {
  141. #if LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX
  142. BaseType_t ret;
  143. LWIP_ASSERT("sys_arch_protect_mutex != NULL", sys_arch_protect_mutex != NULL);
  144. ret = xSemaphoreTakeRecursive(sys_arch_protect_mutex, portMAX_DELAY);
  145. LWIP_ASSERT("sys_arch_protect failed to take the mutex", ret == pdTRUE);
  146. #else /* LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX */
  147. taskENTER_CRITICAL();
  148. #endif /* LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX */
  149. #if LWIP_FREERTOS_SYS_ARCH_PROTECT_SANITY_CHECK
  150. {
  151. /* every nested call to sys_arch_protect() returns an increased number */
  152. sys_prot_t ret = sys_arch_protect_nesting;
  153. sys_arch_protect_nesting++;
  154. LWIP_ASSERT("sys_arch_protect overflow", sys_arch_protect_nesting > ret);
  155. return ret;
  156. }
  157. #else
  158. return 1;
  159. #endif
  160. }
  161. void sys_arch_unprotect(sys_prot_t pval)
  162. {
  163. #if LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX
  164. BaseType_t ret;
  165. #endif
  166. #if LWIP_FREERTOS_SYS_ARCH_PROTECT_SANITY_CHECK
  167. LWIP_ASSERT("unexpected sys_arch_protect_nesting", sys_arch_protect_nesting > 0);
  168. sys_arch_protect_nesting--;
  169. LWIP_ASSERT("unexpected sys_arch_protect_nesting", sys_arch_protect_nesting == pval);
  170. #endif
  171. #if LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX
  172. LWIP_ASSERT("sys_arch_protect_mutex != NULL", sys_arch_protect_mutex != NULL);
  173. ret = xSemaphoreGiveRecursive(sys_arch_protect_mutex);
  174. LWIP_ASSERT("sys_arch_unprotect failed to give the mutex", ret == pdTRUE);
  175. #else /* LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX */
  176. taskEXIT_CRITICAL();
  177. #endif /* LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX */
  178. LWIP_UNUSED_ARG(pval);
  179. }
  180. #endif /* SYS_LIGHTWEIGHT_PROT */
  181. void sys_arch_msleep(u32_t delay_ms)
  182. {
  183. TickType_t delay_ticks = delay_ms / portTICK_RATE_MS;
  184. vTaskDelay(delay_ticks);
  185. }
  186. #if !LWIP_COMPAT_MUTEX
  187. /* Create a new mutex*/
  188. err_t sys_mutex_new(sys_mutex_t *mutex)
  189. {
  190. LWIP_ASSERT("mutex != NULL", mutex != NULL);
  191. mutex->mut = xSemaphoreCreateRecursiveMutex();
  192. if (mutex->mut == NULL) {
  193. SYS_STATS_INC(mutex.err);
  194. return ERR_MEM;
  195. }
  196. SYS_STATS_INC_USED(mutex);
  197. return ERR_OK;
  198. }
  199. void sys_mutex_lock(sys_mutex_t *mutex)
  200. {
  201. BaseType_t ret;
  202. LWIP_ASSERT("mutex != NULL", mutex != NULL);
  203. LWIP_ASSERT("mutex->mut != NULL", mutex->mut != NULL); /* NOLINT */
  204. ret = xSemaphoreTakeRecursive(mutex->mut, portMAX_DELAY);
  205. LWIP_ASSERT("failed to take the mutex", ret == pdTRUE);
  206. }
  207. void sys_mutex_unlock(sys_mutex_t *mutex)
  208. {
  209. BaseType_t ret;
  210. LWIP_ASSERT("mutex != NULL", mutex != NULL);
  211. LWIP_ASSERT("mutex->mut != NULL", mutex->mut != NULL); /* NOLINT */
  212. ret = xSemaphoreGiveRecursive(mutex->mut);
  213. LWIP_ASSERT("failed to give the mutex", ret == pdTRUE);
  214. }
  215. void sys_mutex_free(sys_mutex_t *mutex)
  216. {
  217. LWIP_ASSERT("mutex != NULL", mutex != NULL);
  218. LWIP_ASSERT("mutex->mut != NULL", mutex->mut != NULL); /* NOLINT */
  219. SYS_STATS_DEC(mutex.used);
  220. vSemaphoreDelete(mutex->mut);
  221. mutex->mut = NULL;
  222. }
  223. #endif /* !LWIP_COMPAT_MUTEX */
  224. err_t sys_sem_new(sys_sem_t *sem, u8_t initial_count)
  225. {
  226. LWIP_ASSERT("sem != NULL", sem != NULL);
  227. LWIP_ASSERT("initial_count invalid (not 0 or 1)",
  228. (initial_count == 0) || (initial_count == 1));
  229. sem->sem = xSemaphoreCreateBinary();
  230. if (sem->sem == NULL) {
  231. SYS_STATS_INC(sem.err);
  232. return ERR_MEM;
  233. }
  234. SYS_STATS_INC_USED(sem);
  235. if (initial_count == 1) {
  236. BaseType_t ret = xSemaphoreGive(sem->sem);
  237. LWIP_ASSERT("sys_sem_new: initial give failed", ret == pdTRUE);
  238. }
  239. return ERR_OK;
  240. }
  241. void sys_sem_signal(sys_sem_t *sem)
  242. {
  243. BaseType_t ret;
  244. LWIP_ASSERT("sem != NULL", sem != NULL);
  245. LWIP_ASSERT("sem->sem != NULL", sem->sem != NULL); /* NOLINT */
  246. ret = xSemaphoreGive(sem->sem);
  247. /* queue full is OK, this is a signal only... */
  248. LWIP_ASSERT("sys_sem_signal: sane return value",
  249. (ret == pdTRUE) || (ret == errQUEUE_FULL));
  250. }
  251. u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout_ms)
  252. {
  253. BaseType_t ret;
  254. LWIP_ASSERT("sem != NULL", sem != NULL);
  255. LWIP_ASSERT("sem->sem != NULL", sem->sem != NULL); /* NOLINT */
  256. if (!timeout_ms) {
  257. /* wait infinite */
  258. ret = xSemaphoreTake(sem->sem, portMAX_DELAY);
  259. LWIP_ASSERT("taking semaphore failed", ret == pdTRUE);
  260. } else {
  261. TickType_t timeout_ticks = timeout_ms / portTICK_RATE_MS;
  262. ret = xSemaphoreTake(sem->sem, timeout_ticks);
  263. if (ret == errQUEUE_EMPTY) {
  264. /* timed out */
  265. return SYS_ARCH_TIMEOUT;
  266. }
  267. LWIP_ASSERT("taking semaphore failed", ret == pdTRUE);
  268. }
  269. /* Old versions of lwIP required us to return the time waited.
  270. This is not the case any more. Just returning != SYS_ARCH_TIMEOUT
  271. here is enough. */
  272. return 1;
  273. }
  274. void sys_sem_free(sys_sem_t *sem)
  275. {
  276. LWIP_ASSERT("sem != NULL", sem != NULL);
  277. LWIP_ASSERT("sem->sem != NULL", sem->sem != NULL); /* NOLINT */
  278. SYS_STATS_DEC(sem.used);
  279. vSemaphoreDelete(sem->sem);
  280. sem->sem = NULL;
  281. }
  282. err_t sys_mbox_new(sys_mbox_t *mbox, int size)
  283. {
  284. LWIP_ASSERT("mbox != NULL", mbox != NULL); /* NOLINT */
  285. LWIP_ASSERT("size > 0", size > 0);
  286. mbox->mbx = xQueueCreate((UBaseType_t)size, sizeof(void *));
  287. if (mbox->mbx == NULL) {
  288. SYS_STATS_INC(mbox.err);
  289. return ERR_MEM;
  290. }
  291. SYS_STATS_INC_USED(mbox);
  292. return ERR_OK;
  293. }
  294. void sys_mbox_post(sys_mbox_t *mbox, void *msg)
  295. {
  296. BaseType_t ret;
  297. LWIP_ASSERT("mbox != NULL", mbox != NULL);
  298. LWIP_ASSERT("mbox->mbx != NULL", mbox->mbx != NULL); /* NOLINT */
  299. ret = xQueueSendToBack(mbox->mbx, &msg, portMAX_DELAY);
  300. LWIP_ASSERT("mbox post failed", ret == pdTRUE);
  301. }
  302. err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg)
  303. {
  304. BaseType_t ret;
  305. LWIP_ASSERT("mbox != NULL", mbox != NULL);
  306. LWIP_ASSERT("mbox->mbx != NULL", mbox->mbx != NULL); /* NOLINT */
  307. ret = xQueueSendToBack(mbox->mbx, &msg, 0);
  308. if (ret == pdTRUE) {
  309. return ERR_OK;
  310. } else {
  311. LWIP_ASSERT("mbox trypost failed", ret == errQUEUE_FULL);
  312. SYS_STATS_INC(mbox.err);
  313. return ERR_MEM;
  314. }
  315. }
  316. err_t sys_mbox_trypost_fromisr(sys_mbox_t *mbox, void *msg)
  317. {
  318. BaseType_t ret;
  319. BaseType_t xHigherPriorityTaskWoken = pdFALSE;
  320. LWIP_ASSERT("mbox != NULL", mbox != NULL);
  321. LWIP_ASSERT("mbox->mbx != NULL", mbox->mbx != NULL); /* NOLINT */
  322. ret = xQueueSendToBackFromISR(mbox->mbx, &msg, &xHigherPriorityTaskWoken);
  323. if (ret == pdTRUE) {
  324. if (xHigherPriorityTaskWoken == pdTRUE) {
  325. return ERR_NEED_SCHED;
  326. }
  327. return ERR_OK;
  328. } else {
  329. LWIP_ASSERT("mbox trypost failed", ret == errQUEUE_FULL);
  330. SYS_STATS_INC(mbox.err);
  331. return ERR_MEM;
  332. }
  333. }
  334. u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout_ms)
  335. {
  336. BaseType_t ret;
  337. void *msg_dummy;
  338. LWIP_ASSERT("mbox != NULL", mbox != NULL);
  339. LWIP_ASSERT("mbox->mbx != NULL", mbox->mbx != NULL); /* NOLINT */
  340. if (!msg) {
  341. msg = &msg_dummy;
  342. }
  343. if (!timeout_ms) {
  344. /* wait infinite */
  345. ret = xQueueReceive(mbox->mbx, &(*msg), portMAX_DELAY);
  346. LWIP_ASSERT("mbox fetch failed", ret == pdTRUE);
  347. } else {
  348. TickType_t timeout_ticks = timeout_ms / portTICK_RATE_MS;
  349. ret = xQueueReceive(mbox->mbx, &(*msg), timeout_ticks);
  350. if (ret == errQUEUE_EMPTY) {
  351. /* timed out */
  352. *msg = NULL;
  353. return SYS_ARCH_TIMEOUT;
  354. }
  355. LWIP_ASSERT("mbox fetch failed", ret == pdTRUE);
  356. }
  357. /* Old versions of lwIP required us to return the time waited.
  358. This is not the case any more. Just returning != SYS_ARCH_TIMEOUT
  359. here is enough. */
  360. return 1;
  361. }
  362. u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg)
  363. {
  364. BaseType_t ret;
  365. void *msg_dummy;
  366. LWIP_ASSERT("mbox != NULL", mbox != NULL);
  367. LWIP_ASSERT("mbox->mbx != NULL", mbox->mbx != NULL); /* NOLINT */
  368. if (!msg) {
  369. msg = &msg_dummy;
  370. }
  371. ret = xQueueReceive(mbox->mbx, &(*msg), 0);
  372. if (ret == errQUEUE_EMPTY) {
  373. *msg = NULL;
  374. return SYS_MBOX_EMPTY;
  375. }
  376. LWIP_ASSERT("mbox fetch failed", ret == pdTRUE);
  377. /* Old versions of lwIP required us to return the time waited.
  378. This is not the case any more. Just returning != SYS_ARCH_TIMEOUT
  379. here is enough. */
  380. return 1;
  381. }
  382. void sys_mbox_free(sys_mbox_t *mbox)
  383. {
  384. LWIP_ASSERT("mbox != NULL", mbox != NULL);
  385. LWIP_ASSERT("mbox->mbx != NULL", mbox->mbx != NULL); /* NOLINT */
  386. #if LWIP_FREERTOS_CHECK_QUEUE_EMPTY_ON_FREE
  387. {
  388. UBaseType_t msgs_waiting = uxQueueMessagesWaiting(mbox->mbx);
  389. LWIP_ASSERT("mbox quence not empty", msgs_waiting == 0);
  390. if (msgs_waiting != 0) {
  391. SYS_STATS_INC(mbox.err);
  392. }
  393. }
  394. #endif
  395. vQueueDelete(mbox->mbx);
  396. SYS_STATS_DEC(mbox.used);
  397. }
  398. sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio)
  399. {
  400. TaskHandle_t rtos_task;
  401. BaseType_t ret;
  402. sys_thread_t lwip_thread;
  403. size_t rtos_stacksize;
  404. LWIP_ASSERT("invalid stacksize", stacksize > 0);
  405. #if LWIP_FREERTOS_THREAD_STACKSIZE_IS_STACKWORDS
  406. rtos_stacksize = (size_t)stacksize;
  407. #else
  408. rtos_stacksize = (size_t)stacksize / sizeof(StackType_t);
  409. #endif
  410. /* lwIP's lwip_thread_fn matches FreeRTOS' TaskFunction_t, so we can pass the
  411. thread function without adaption here. */
  412. ret = xTaskCreate(thread, name, (configSTACK_DEPTH_TYPE)rtos_stacksize, arg, prio, &rtos_task);
  413. LWIP_ASSERT("task creation failed", ret == pdTRUE);
  414. lwip_thread.thread_handle = rtos_task;
  415. return lwip_thread;
  416. }
  417. #if LWIP_NETCONN_SEM_PER_THREAD
  418. #if configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0
  419. sys_sem_t *sys_arch_netconn_sem_get(void)
  420. {
  421. void *ret;
  422. TaskHandle_t task = xTaskGetCurrentTaskHandle();
  423. LWIP_ASSERT("task != NULL", task != NULL);
  424. ret = pvTaskGetThreadLocalStoragePointer(task, 0);
  425. return ret;
  426. }
  427. void sys_arch_netconn_sem_alloc(void)
  428. {
  429. void *ret;
  430. TaskHandle_t task = xTaskGetCurrentTaskHandle();
  431. LWIP_ASSERT("task != NULL", task != NULL);
  432. ret = pvTaskGetThreadLocalStoragePointer(task, 0);
  433. if (ret == NULL) {
  434. sys_sem_t *sem;
  435. err_t err;
  436. /* need to allocate the memory for this semaphore */
  437. sem = mem_malloc(sizeof(sys_sem_t));
  438. LWIP_ASSERT("sem != NULL", sem != NULL);
  439. err = sys_sem_new(sem, 0);
  440. LWIP_ASSERT("err == ERR_OK", err == ERR_OK);
  441. LWIP_ASSERT("sem invalid", sys_sem_valid(sem));
  442. vTaskSetThreadLocalStoragePointer(task, 0, sem);
  443. }
  444. }
  445. void sys_arch_netconn_sem_free(void)
  446. {
  447. void *ret;
  448. TaskHandle_t task = xTaskGetCurrentTaskHandle();
  449. LWIP_ASSERT("task != NULL", task != NULL);
  450. ret = pvTaskGetThreadLocalStoragePointer(task, 0);
  451. if (ret != NULL) {
  452. sys_sem_t *sem = ret;
  453. sys_sem_free(sem);
  454. mem_free(sem);
  455. vTaskSetThreadLocalStoragePointer(task, 0, NULL);
  456. }
  457. }
  458. #else /* configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 */
  459. #error LWIP_NETCONN_SEM_PER_THREAD needs configNUM_THREAD_LOCAL_STORAGE_POINTERS
  460. #endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 */
  461. #endif /* LWIP_NETCONN_SEM_PER_THREAD */
  462. #if LWIP_FREERTOS_CHECK_CORE_LOCKING
  463. #if LWIP_TCPIP_CORE_LOCKING
  464. /** Flag the core lock held. A counter for recursive locks. */
  465. static u8_t lwip_core_lock_count;
  466. static TaskHandle_t lwip_core_lock_holder_thread;
  467. void sys_lock_tcpip_core(void)
  468. {
  469. sys_mutex_lock(&lock_tcpip_core);
  470. if (lwip_core_lock_count == 0) {
  471. lwip_core_lock_holder_thread = xTaskGetCurrentTaskHandle();
  472. }
  473. lwip_core_lock_count++;
  474. }
  475. void sys_unlock_tcpip_core(void)
  476. {
  477. lwip_core_lock_count--;
  478. if (lwip_core_lock_count == 0) {
  479. lwip_core_lock_holder_thread = 0;
  480. }
  481. sys_mutex_unlock(&lock_tcpip_core);
  482. }
  483. #endif /* LWIP_TCPIP_CORE_LOCKING */
  484. #if !NO_SYS
  485. static TaskHandle_t lwip_tcpip_thread;
  486. #endif
  487. void sys_mark_tcpip_thread(void)
  488. {
  489. #if !NO_SYS
  490. lwip_tcpip_thread = xTaskGetCurrentTaskHandle();
  491. #endif
  492. }
  493. void sys_check_core_locking(void)
  494. {
  495. /* Embedded systems should check we are NOT in an interrupt context here */
  496. /* E.g. core Cortex-M3/M4 ports:
  497. configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
  498. Instead, we use more generic FreeRTOS functions here, which should fail from ISR: */
  499. taskENTER_CRITICAL();
  500. taskEXIT_CRITICAL();
  501. #if !NO_SYS
  502. if (lwip_tcpip_thread != 0) {
  503. TaskHandle_t current_thread = xTaskGetCurrentTaskHandle();
  504. #if LWIP_TCPIP_CORE_LOCKING
  505. LWIP_ASSERT("Function called without core lock",
  506. current_thread == lwip_core_lock_holder_thread && lwip_core_lock_count > 0);
  507. #else /* LWIP_TCPIP_CORE_LOCKING */
  508. LWIP_ASSERT("Function called from wrong thread", current_thread == lwip_tcpip_thread);
  509. #endif /* LWIP_TCPIP_CORE_LOCKING */
  510. }
  511. #endif /* !NO_SYS */
  512. }
  513. #endif /* LWIP_FREERTOS_CHECK_CORE_LOCKING*/
  514. #else
  515. static uint32_t sys_tick = 0;
  516. void sys_timer_callback(void)
  517. {
  518. sys_tick++;
  519. }
  520. u32_t sys_now(void)
  521. {
  522. return (u32_t)sys_tick;
  523. }
  524. #endif