rpmsg_env_threadx.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774
  1. /*
  2. * Copyright 2020-2023 NXP
  3. * All rights reserved.
  4. *
  5. *
  6. * SPDX-License-Identifier: BSD-3-Clause
  7. */
  8. /**************************************************************************
  9. * FILE NAME
  10. *
  11. * rpmsg_env_threadx.c
  12. *
  13. *
  14. * DESCRIPTION
  15. *
  16. * This file is ThreadX Implementation of env layer for RPMsg_Lite.
  17. *
  18. *
  19. **************************************************************************/
  20. #include "rpmsg_compiler.h"
  21. #include "rpmsg_env.h"
  22. #include "rpmsg_lite.h"
  23. #include "tx_api.h"
  24. #include "tx_event_flags.h"
  25. #include "rpmsg_platform.h"
  26. #include "fsl_common.h"
  27. #include "fsl_component_mem_manager.h"
  28. #include <stdlib.h>
  29. #include <string.h>
  30. #include "virtqueue.h"
  31. static int32_t env_init_counter = 0;
  32. static TX_SEMAPHORE env_sema = {0};
  33. static TX_EVENT_FLAGS_GROUP event_group = {0};
  34. /* RL_ENV_MAX_MUTEX_COUNT is an arbitrary count greater than 'count'
  35. if the inital count is 1, this function behaves as a mutex
  36. if it is greater than 1, it acts as a "resource allocator" with
  37. the maximum of 'count' resources available.
  38. Currently, only the first use-case is applicable/applied in RPMsg-Lite.
  39. */
  40. #define RL_ENV_MAX_MUTEX_COUNT (10)
  41. /* Max supported ISR counts */
  42. #define ISR_COUNT (32U)
  43. /*!
  44. * Structure to keep track of registered ISR's.
  45. */
  46. struct isr_info
  47. {
  48. void *data;
  49. };
  50. static struct isr_info isr_table[ISR_COUNT];
  51. #if defined(RL_USE_ENVIRONMENT_CONTEXT) && (RL_USE_ENVIRONMENT_CONTEXT == 1)
  52. #error "This RPMsg-Lite port requires RL_USE_ENVIRONMENT_CONTEXT set to 0"
  53. #endif
  54. /*!
  55. * env_in_isr
  56. *
  57. * @returns - true, if currently in ISR
  58. *
  59. */
  60. static int32_t env_in_isr(void)
  61. {
  62. return platform_in_isr();
  63. }
  64. /*!
  65. * env_wait_for_link_up
  66. *
  67. * Wait until the link_state parameter of the rpmsg_lite_instance is set.
  68. * Utilize events to avoid busy loop implementation.
  69. *
  70. */
  71. uint32_t env_wait_for_link_up(volatile uint32_t *link_state, uint32_t link_id, uint32_t timeout_ms)
  72. {
  73. ULONG actual_events;
  74. if (*link_state != 1U)
  75. {
  76. if (RL_BLOCK == timeout_ms)
  77. {
  78. if (TX_SUCCESS ==
  79. tx_event_flags_get(&event_group, (1UL << link_id), TX_AND, &actual_events, TX_WAIT_FOREVER))
  80. {
  81. return 1U;
  82. }
  83. }
  84. else
  85. {
  86. if (TX_SUCCESS == tx_event_flags_get(&event_group, (1UL << link_id), TX_AND, &actual_events,
  87. ((timeout_ms * TX_TIMER_TICKS_PER_SECOND) / 1000)))
  88. {
  89. return 1U;
  90. }
  91. }
  92. return 0U;
  93. }
  94. else
  95. {
  96. return 1U;
  97. }
  98. }
  99. /*!
  100. * env_tx_callback
  101. *
  102. * Set event to notify task waiting in env_wait_for_link_up().
  103. *
  104. */
  105. void env_tx_callback(uint32_t link_id)
  106. {
  107. tx_event_flags_set(&event_group, (1UL << link_id), TX_OR);
  108. }
  109. /*!
  110. * env_init
  111. *
  112. * Initializes ThreadX environment.
  113. *
  114. */
  115. int32_t env_init(void)
  116. {
  117. int32_t retval;
  118. uint32_t regPrimask = DisableGlobalIRQ(); /* stop scheduler */
  119. /* verify 'env_init_counter' */
  120. RL_ASSERT(env_init_counter >= 0);
  121. if (env_init_counter < 0)
  122. {
  123. EnableGlobalIRQ(regPrimask); /* re-enable scheduler */
  124. return -1;
  125. }
  126. env_init_counter++;
  127. /* multiple call of 'env_init' - return ok */
  128. if (env_init_counter == 1)
  129. {
  130. /* first call */
  131. if (TX_SUCCESS != tx_semaphore_create((TX_SEMAPHORE *)&env_sema, NULL, 0))
  132. {
  133. EnableGlobalIRQ(regPrimask);
  134. return -1;
  135. }
  136. (void)tx_event_flags_create(&event_group, NULL);
  137. (void)memset(isr_table, 0, sizeof(isr_table));
  138. EnableGlobalIRQ(regPrimask);
  139. retval = platform_init();
  140. tx_semaphore_put((TX_SEMAPHORE *)&env_sema);
  141. return retval;
  142. }
  143. else
  144. {
  145. EnableGlobalIRQ(regPrimask);
  146. /* Get the semaphore and then return it,
  147. * this allows for platform_init() to block
  148. * if needed and other tasks to wait for the
  149. * blocking to be done.
  150. * This is in ENV layer as this is ENV specific.*/
  151. if (TX_SUCCESS == tx_semaphore_get((TX_SEMAPHORE *)&env_sema, TX_WAIT_FOREVER))
  152. {
  153. tx_semaphore_put((TX_SEMAPHORE *)&env_sema);
  154. }
  155. return 0;
  156. }
  157. }
  158. /*!
  159. * env_deinit
  160. *
  161. * Uninitializes ThreadX environment.
  162. *
  163. * @returns - execution status
  164. */
  165. int32_t env_deinit(void)
  166. {
  167. int32_t retval;
  168. uint32_t regPrimask = DisableGlobalIRQ(); /* stop scheduler */
  169. /* verify 'env_init_counter' */
  170. RL_ASSERT(env_init_counter > 0);
  171. if (env_init_counter <= 0)
  172. {
  173. EnableGlobalIRQ(regPrimask); /* re-enable scheduler */
  174. return -1;
  175. }
  176. /* counter on zero - call platform deinit */
  177. env_init_counter--;
  178. /* multiple call of 'env_deinit' - return ok */
  179. if (env_init_counter <= 0)
  180. {
  181. /* last call */
  182. (void)memset(isr_table, 0, sizeof(isr_table));
  183. retval = platform_deinit();
  184. (void)tx_event_flags_delete(&event_group);
  185. (void)memset(&event_group, 0, sizeof(event_group));
  186. (void)tx_semaphore_delete((TX_SEMAPHORE *)&env_sema);
  187. (void)memset(&env_sema, 0, sizeof(env_sema));
  188. EnableGlobalIRQ(regPrimask);
  189. return retval;
  190. }
  191. else
  192. {
  193. EnableGlobalIRQ(regPrimask);
  194. return 0;
  195. }
  196. }
  197. /*!
  198. * env_allocate_memory - implementation
  199. *
  200. * @param size
  201. */
  202. void *env_allocate_memory(uint32_t size)
  203. {
  204. return (MEM_BufferAlloc(size));
  205. }
  206. /*!
  207. * env_free_memory - implementation
  208. *
  209. * @param ptr
  210. */
  211. void env_free_memory(void *ptr)
  212. {
  213. if (ptr != ((void *)0))
  214. {
  215. MEM_BufferFree(ptr);
  216. }
  217. }
  218. /*!
  219. *
  220. * env_memset - implementation
  221. *
  222. * @param ptr
  223. * @param value
  224. * @param size
  225. */
  226. void env_memset(void *ptr, int32_t value, uint32_t size)
  227. {
  228. (void)memset(ptr, value, size);
  229. }
  230. /*!
  231. *
  232. * env_memcpy - implementation
  233. *
  234. * @param dst
  235. * @param src
  236. * @param len
  237. */
  238. void env_memcpy(void *dst, void const *src, uint32_t len)
  239. {
  240. (void)memcpy(dst, src, len);
  241. }
  242. /*!
  243. *
  244. * env_strcmp - implementation
  245. *
  246. * @param dst
  247. * @param src
  248. */
  249. int32_t env_strcmp(const char *dst, const char *src)
  250. {
  251. return (strcmp(dst, src));
  252. }
  253. /*!
  254. *
  255. * env_strncpy - implementation
  256. *
  257. * @param dest
  258. * @param src
  259. * @param len
  260. */
  261. void env_strncpy(char *dest, const char *src, uint32_t len)
  262. {
  263. (void)strncpy(dest, src, len);
  264. }
  265. /*!
  266. *
  267. * env_strncmp - implementation
  268. *
  269. * @param dest
  270. * @param src
  271. * @param len
  272. */
  273. int32_t env_strncmp(char *dest, const char *src, uint32_t len)
  274. {
  275. return (strncmp(dest, src, len));
  276. }
  277. /*!
  278. *
  279. * env_mb - implementation
  280. *
  281. */
  282. void env_mb(void)
  283. {
  284. MEM_BARRIER();
  285. }
  286. /*!
  287. * env_rmb - implementation
  288. */
  289. void env_rmb(void)
  290. {
  291. MEM_BARRIER();
  292. }
  293. /*!
  294. * env_wmb - implementation
  295. */
  296. void env_wmb(void)
  297. {
  298. MEM_BARRIER();
  299. }
  300. /*!
  301. * env_map_vatopa - implementation
  302. *
  303. * @param address
  304. */
  305. uint32_t env_map_vatopa(void *address)
  306. {
  307. return platform_vatopa(address);
  308. }
  309. /*!
  310. * env_map_patova - implementation
  311. *
  312. * @param address
  313. */
  314. void *env_map_patova(uint32_t address)
  315. {
  316. return platform_patova(address);
  317. }
  318. /*!
  319. * env_create_mutex
  320. *
  321. * Creates a mutex with the given initial count.
  322. *
  323. */
  324. #if defined(RL_USE_STATIC_API) && (RL_USE_STATIC_API == 1)
  325. int32_t env_create_mutex(void **lock, int32_t count, void *context)
  326. #else
  327. int32_t env_create_mutex(void **lock, int32_t count)
  328. #endif
  329. {
  330. TX_SEMAPHORE *semaphore_ptr;
  331. if (count > RL_ENV_MAX_MUTEX_COUNT)
  332. {
  333. return -1;
  334. }
  335. #if defined(RL_USE_STATIC_API) && (RL_USE_STATIC_API == 1)
  336. semaphore_ptr = (TX_SEMAPHORE *)context;
  337. #else
  338. semaphore_ptr = (TX_SEMAPHORE *)env_allocate_memory(sizeof(TX_SEMAPHORE));
  339. #endif
  340. if (semaphore_ptr == ((void *)0))
  341. {
  342. return -1;
  343. }
  344. if (TX_SUCCESS == tx_semaphore_create((TX_SEMAPHORE *)semaphore_ptr, NULL, count))
  345. {
  346. *lock = (void *)semaphore_ptr;
  347. return 0;
  348. }
  349. else
  350. {
  351. #if !(defined(RL_USE_STATIC_API) && (RL_USE_STATIC_API == 1))
  352. env_free_memory(semaphore_ptr);
  353. #endif
  354. return -1;
  355. }
  356. }
  357. /*!
  358. * env_delete_mutex
  359. *
  360. * Deletes the given lock
  361. *
  362. */
  363. void env_delete_mutex(void *lock)
  364. {
  365. (void)tx_semaphore_delete((TX_SEMAPHORE *)lock);
  366. #if !(defined(RL_USE_STATIC_API) && (RL_USE_STATIC_API == 1))
  367. env_free_memory(lock);
  368. #endif
  369. }
  370. /*!
  371. * env_lock_mutex
  372. *
  373. * Tries to acquire the lock, if lock is not available then call to
  374. * this function will suspend.
  375. */
  376. void env_lock_mutex(void *lock)
  377. {
  378. if (env_in_isr() == 0)
  379. {
  380. (void)tx_semaphore_get((TX_SEMAPHORE *)lock, TX_WAIT_FOREVER);
  381. }
  382. }
  383. /*!
  384. * env_unlock_mutex
  385. *
  386. * Releases the given lock.
  387. */
  388. void env_unlock_mutex(void *lock)
  389. {
  390. if (env_in_isr() == 0)
  391. {
  392. (void)tx_semaphore_put((TX_SEMAPHORE *)lock);
  393. }
  394. }
  395. /*!
  396. * env_create_sync_lock
  397. *
  398. * Creates a synchronization lock primitive. It is used
  399. * when signal has to be sent from the interrupt context to main
  400. * thread context.
  401. */
  402. #if defined(RL_USE_STATIC_API) && (RL_USE_STATIC_API == 1)
  403. int32_t env_create_sync_lock(void **lock, int32_t state, void *context)
  404. {
  405. return env_create_mutex(lock, state, context); /* state=1 .. initially free */
  406. }
  407. #else
  408. int32_t env_create_sync_lock(void **lock, int32_t state)
  409. {
  410. return env_create_mutex(lock, state); /* state=1 .. initially free */
  411. }
  412. #endif
  413. /*!
  414. * env_delete_sync_lock
  415. *
  416. * Deletes the given lock
  417. *
  418. */
  419. void env_delete_sync_lock(void *lock)
  420. {
  421. if (lock != ((void *)0))
  422. {
  423. env_delete_mutex(lock);
  424. }
  425. }
  426. /*!
  427. * env_acquire_sync_lock
  428. *
  429. * Tries to acquire the lock, if lock is not available then call to
  430. * this function waits for lock to become available.
  431. */
  432. void env_acquire_sync_lock(void *lock)
  433. {
  434. if (lock != ((void *)0))
  435. {
  436. env_lock_mutex(lock);
  437. }
  438. }
  439. /*!
  440. * env_release_sync_lock
  441. *
  442. * Releases the given lock.
  443. */
  444. void env_release_sync_lock(void *lock)
  445. {
  446. if (lock != ((void *)0))
  447. {
  448. env_unlock_mutex(lock);
  449. }
  450. }
  451. /*!
  452. * env_sleep_msec
  453. *
  454. * Suspends the calling thread for given time , in msecs.
  455. */
  456. void env_sleep_msec(uint32_t num_msec)
  457. {
  458. (void)tx_thread_sleep((num_msec * TX_TIMER_TICKS_PER_SECOND) / 1000);
  459. }
  460. /*!
  461. * env_register_isr
  462. *
  463. * Registers interrupt handler data for the given interrupt vector.
  464. *
  465. * @param vector_id - virtual interrupt vector number
  466. * @param data - interrupt handler data (virtqueue)
  467. */
  468. void env_register_isr(uint32_t vector_id, void *data)
  469. {
  470. RL_ASSERT(vector_id < ISR_COUNT);
  471. if (vector_id < ISR_COUNT)
  472. {
  473. isr_table[vector_id].data = data;
  474. }
  475. }
  476. /*!
  477. * env_unregister_isr
  478. *
  479. * Unregisters interrupt handler data for the given interrupt vector.
  480. *
  481. * @param vector_id - virtual interrupt vector number
  482. */
  483. void env_unregister_isr(uint32_t vector_id)
  484. {
  485. RL_ASSERT(vector_id < ISR_COUNT);
  486. if (vector_id < ISR_COUNT)
  487. {
  488. isr_table[vector_id].data = ((void *)0);
  489. }
  490. }
  491. /*!
  492. * env_enable_interrupt
  493. *
  494. * Enables the given interrupt
  495. *
  496. * @param vector_id - virtual interrupt vector number
  497. */
  498. void env_enable_interrupt(uint32_t vector_id)
  499. {
  500. (void)platform_interrupt_enable(vector_id);
  501. }
  502. /*!
  503. * env_disable_interrupt
  504. *
  505. * Disables the given interrupt
  506. *
  507. * @param vector_id - virtual interrupt vector number
  508. */
  509. void env_disable_interrupt(uint32_t vector_id)
  510. {
  511. (void)platform_interrupt_disable(vector_id);
  512. }
  513. /*!
  514. * env_map_memory
  515. *
  516. * Enables memory mapping for given memory region.
  517. *
  518. * @param pa - physical address of memory
  519. * @param va - logical address of memory
  520. * @param size - memory size
  521. * param flags - flags for cache/uncached and access type
  522. */
  523. void env_map_memory(uint32_t pa, uint32_t va, uint32_t size, uint32_t flags)
  524. {
  525. platform_map_mem_region(va, pa, size, flags);
  526. }
  527. /*!
  528. * env_disable_cache
  529. *
  530. * Disables system caches.
  531. *
  532. */
  533. void env_disable_cache(void)
  534. {
  535. platform_cache_all_flush_invalidate();
  536. platform_cache_disable();
  537. }
  538. /*!
  539. *
  540. * env_get_timestamp
  541. *
  542. * Returns a 64 bit time stamp.
  543. *
  544. *
  545. */
  546. uint64_t env_get_timestamp(void)
  547. {
  548. return tx_time_get();
  549. }
  550. /*========================================================= */
  551. /* Util data / functions */
  552. void env_isr(uint32_t vector)
  553. {
  554. struct isr_info *info;
  555. RL_ASSERT(vector < ISR_COUNT);
  556. if (vector < ISR_COUNT)
  557. {
  558. info = &isr_table[vector];
  559. virtqueue_notification((struct virtqueue *)info->data);
  560. }
  561. }
  562. /*
  563. * env_create_queue
  564. *
  565. * Creates a message queue.
  566. *
  567. * @param queue - pointer to created queue
  568. * @param length - maximum number of elements in the queue
  569. * @param element_size - queue element size in bytes
  570. * @param queue_static_storage - pointer to queue static storage buffer
  571. * @param queue_static_context - pointer to queue static context
  572. *
  573. * @return - status of function execution
  574. */
  575. #if defined(RL_USE_STATIC_API) && (RL_USE_STATIC_API == 1)
  576. int32_t env_create_queue(void **queue,
  577. int32_t length,
  578. int32_t element_size,
  579. uint8_t *queue_static_storage,
  580. rpmsg_static_queue_ctxt *queue_static_context)
  581. #else
  582. int32_t env_create_queue(void **queue, int32_t length, int32_t element_size)
  583. #endif
  584. {
  585. struct TX_QUEUE *queue_ptr = ((void *)0);
  586. char *msgq_buffer_ptr = ((void *)0);
  587. #if defined(RL_USE_STATIC_API) && (RL_USE_STATIC_API == 1)
  588. queue_ptr = (struct TX_QUEUE *)queue_static_context;
  589. msgq_buffer_ptr = (char *)queue_static_storage;
  590. #else
  591. queue_ptr = (struct TX_QUEUE *)env_allocate_memory(sizeof(TX_QUEUE));
  592. msgq_buffer_ptr = (char *)env_allocate_memory(length * element_size);
  593. #endif
  594. if ((queue_ptr == ((void *)0)) || (msgq_buffer_ptr == ((void *)0)))
  595. {
  596. return -1;
  597. }
  598. if (TX_SUCCESS == tx_queue_create((TX_QUEUE *)queue_ptr, NULL, (element_size / RL_WORD_SIZE),
  599. (VOID *)msgq_buffer_ptr, (length * element_size)))
  600. {
  601. *queue = (void *)queue_ptr;
  602. return 0;
  603. }
  604. else
  605. {
  606. #if !(defined(RL_USE_STATIC_API) && (RL_USE_STATIC_API == 1))
  607. env_free_memory(msgq_buffer_ptr);
  608. env_free_memory(queue_ptr);
  609. #endif
  610. return -1;
  611. }
  612. }
  613. /*!
  614. * env_delete_queue
  615. *
  616. * Deletes the message queue.
  617. *
  618. * @param queue - queue to delete
  619. */
  620. void env_delete_queue(void *queue)
  621. {
  622. tx_queue_delete((TX_QUEUE *)(queue));
  623. #if !(defined(RL_USE_STATIC_API) && (RL_USE_STATIC_API == 1))
  624. env_free_memory(((TX_QUEUE *)(queue))->tx_queue_start);
  625. env_free_memory(queue);
  626. #endif
  627. }
  628. /*!
  629. * env_put_queue
  630. *
  631. * Put an element in a queue.
  632. *
  633. * @param queue - queue to put element in
  634. * @param msg - pointer to the message to be put into the queue
  635. * @param timeout_ms - timeout in ms
  636. *
  637. * @return - status of function execution
  638. */
  639. int32_t env_put_queue(void *queue, void *msg, uintptr_t timeout_ms)
  640. {
  641. if (RL_BLOCK == timeout_ms)
  642. {
  643. if (TX_SUCCESS == tx_queue_send((TX_QUEUE *)(queue), msg, TX_WAIT_FOREVER))
  644. {
  645. return 1;
  646. }
  647. }
  648. else
  649. {
  650. if (TX_SUCCESS == tx_queue_send((TX_QUEUE *)(queue), msg, ((timeout_ms * TX_TIMER_TICKS_PER_SECOND) / 1000)))
  651. {
  652. return 1;
  653. }
  654. }
  655. return 0;
  656. }
  657. /*!
  658. * env_get_queue
  659. *
  660. * Get an element out of a queue.
  661. *
  662. * @param queue - queue to get element from
  663. * @param msg - pointer to a memory to save the message
  664. * @param timeout_ms - timeout in ms
  665. *
  666. * @return - status of function execution
  667. */
  668. int32_t env_get_queue(void *queue, void *msg, uintptr_t timeout_ms)
  669. {
  670. if (RL_BLOCK == timeout_ms)
  671. {
  672. if (TX_SUCCESS == tx_queue_receive((TX_QUEUE *)(queue), msg, TX_WAIT_FOREVER))
  673. {
  674. return 1;
  675. }
  676. }
  677. else
  678. {
  679. if (TX_SUCCESS == tx_queue_receive((TX_QUEUE *)(queue), msg, ((timeout_ms * TX_TIMER_TICKS_PER_SECOND) / 1000)))
  680. {
  681. return 1;
  682. }
  683. }
  684. return 0;
  685. }
  686. /*!
  687. * env_get_current_queue_size
  688. *
  689. * Get current queue size.
  690. *
  691. * @param queue - queue pointer
  692. *
  693. * @return - Number of queued items in the queue
  694. */
  695. int32_t env_get_current_queue_size(void *queue)
  696. {
  697. int32_t enqueued;
  698. ULONG available_storage;
  699. TX_THREAD *first_suspended;
  700. ULONG suspended_count;
  701. TX_QUEUE *next_queue;
  702. if (TX_SUCCESS == tx_queue_info_get((TX_QUEUE *)(queue), NULL, (ULONG *)&enqueued, &available_storage,
  703. &first_suspended, &suspended_count, &next_queue))
  704. {
  705. return enqueued;
  706. }
  707. else
  708. {
  709. return -1;
  710. }
  711. }