usb_osal_nuttx.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. /*
  2. * Copyright (c) 2024, sakumisu
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include "usb_osal.h"
  7. #include "usb_errno.h"
  8. #include <nuttx/config.h>
  9. #include <stddef.h>
  10. #include <stdlib.h>
  11. #include <stdio.h>
  12. #include <string.h>
  13. #include <assert.h>
  14. #include <debug.h>
  15. #include <pthread.h>
  16. #include <fcntl.h>
  17. #include <unistd.h>
  18. #include <sys/time.h>
  19. #include <sys/types.h>
  20. #include <sys/stat.h>
  21. #include <nuttx/kmalloc.h>
  22. #include <nuttx/mqueue.h>
  23. #include <nuttx/spinlock.h>
  24. #include <nuttx/irq.h>
  25. #include <nuttx/kthread.h>
  26. #include <nuttx/wdog.h>
  27. #include <nuttx/wqueue.h>
  28. #include <nuttx/semaphore.h>
  29. #include <nuttx/sched.h>
  30. #include <nuttx/signal.h>
  31. #if 1
  32. #error please modfiy all thread param (void *argument) with (int argc, char **argv), and argument = ((uintptr_t)strtoul(argv[1], NULL, 16));
  33. #endif
  34. struct mq_adpt {
  35. struct file mq; /* Message queue handle */
  36. uint32_t msgsize; /* Message size */
  37. char name[16]; /* Message queue name */
  38. };
  39. struct timer_adpt {
  40. struct usb_osal_timer timer;
  41. struct wdog_s wdog;
  42. };
  43. usb_osal_thread_t usb_osal_thread_create(const char *name, uint32_t stack_size, uint32_t prio, usb_thread_entry_t entry, void *args)
  44. {
  45. int pid;
  46. char *argv[2];
  47. char arg1[32];
  48. snprintf(arg1, 16, "%p", args);
  49. argv[0] = arg1;
  50. argv[1] = NULL;
  51. pid = kthread_create(name, prio, stack_size, (void *)entry,
  52. argv);
  53. if (pid > 0) {
  54. return (usb_osal_thread_t)pid;
  55. } else {
  56. return NULL;
  57. }
  58. }
  59. void usb_osal_thread_delete(usb_osal_thread_t thread)
  60. {
  61. pid_t pid = (pid_t)((uintptr_t)thread);
  62. kthread_delete(pid);
  63. }
  64. usb_osal_sem_t usb_osal_sem_create(uint32_t initial_count)
  65. {
  66. int ret;
  67. sem_t *sem;
  68. int tmp;
  69. tmp = sizeof(sem_t);
  70. sem = kmm_malloc(tmp);
  71. if (!sem) {
  72. //printf("ERROR: Failed to alloc %d memory\n", tmp);
  73. return NULL;
  74. }
  75. ret = nxsem_init(sem, 0, initial_count);
  76. if (ret) {
  77. //printf("ERROR: Failed to initialize sem error=%d\n", ret);
  78. kmm_free(sem);
  79. return NULL;
  80. }
  81. return (usb_osal_sem_t)sem;
  82. }
  83. void usb_osal_sem_delete(usb_osal_sem_t sem)
  84. {
  85. sem_t *__sem = (sem_t *)sem;
  86. nxsem_destroy(__sem);
  87. kmm_free(__sem);
  88. }
  89. int usb_osal_sem_take(usb_osal_sem_t sem, uint32_t timeout)
  90. {
  91. int ret;
  92. sem_t *__sem = (sem_t *)sem;
  93. if (timeout == 0xffffffff) {
  94. ret = nxsem_wait(__sem);
  95. } else {
  96. ret = nxsem_tickwait(__sem, MSEC2TICK(timeout));
  97. }
  98. if (ret) {
  99. return -USB_ERR_TIMEOUT;
  100. } else {
  101. return 0;
  102. }
  103. }
  104. int usb_osal_sem_give(usb_osal_sem_t sem)
  105. {
  106. int ret;
  107. sem_t *__sem = (sem_t *)sem;
  108. ret = nxsem_post(__sem);
  109. if (ret) {
  110. return -USB_ERR_INVAL;
  111. } else {
  112. return 0;
  113. }
  114. }
  115. void usb_osal_sem_reset(usb_osal_sem_t sem)
  116. {
  117. }
  118. usb_osal_mutex_t usb_osal_mutex_create(void)
  119. {
  120. int ret;
  121. mutex_t *mutex;
  122. int tmp;
  123. tmp = sizeof(mutex_t);
  124. mutex = kmm_malloc(tmp);
  125. if (!mutex) {
  126. //printf("ERROR: Failed to alloc %d memory\n", tmp);
  127. return NULL;
  128. }
  129. ret = nxmutex_init(mutex);
  130. if (ret) {
  131. //printf("ERROR: Failed to initialize mutex error=%d\n", ret);
  132. kmm_free(mutex);
  133. return NULL;
  134. }
  135. return (usb_osal_mutex_t)mutex;
  136. }
  137. void usb_osal_mutex_delete(usb_osal_mutex_t mutex)
  138. {
  139. mutex_t *__mutex = (mutex_t *)mutex;
  140. nxmutex_destroy(__mutex);
  141. kmm_free(__mutex);
  142. }
  143. int usb_osal_mutex_take(usb_osal_mutex_t mutex)
  144. {
  145. int ret;
  146. mutex_t *__mutex = (mutex_t *)mutex;
  147. ret = nxmutex_lock(__mutex);
  148. if (ret) {
  149. return -USB_ERR_INVAL;
  150. } else {
  151. return 0;
  152. }
  153. }
  154. int usb_osal_mutex_give(usb_osal_mutex_t mutex)
  155. {
  156. int ret;
  157. mutex_t *__mutex = (mutex_t *)mutex;
  158. ret = nxmutex_unlock(__mutex);
  159. if (ret) {
  160. return -USB_ERR_INVAL;
  161. } else {
  162. return 0;
  163. }
  164. }
  165. usb_osal_mq_t usb_osal_mq_create(uint32_t max_msgs)
  166. {
  167. struct mq_attr attr;
  168. struct mq_adpt *mq_adpt;
  169. int ret;
  170. mq_adpt = (struct mq_adpt *)kmm_malloc(sizeof(struct mq_adpt));
  171. if (!mq_adpt) {
  172. //printf("ERROR: Failed to kmm_malloc\n");
  173. return NULL;
  174. }
  175. snprintf(mq_adpt->name, sizeof(mq_adpt->name),
  176. "/tmp/%p", mq_adpt);
  177. attr.mq_maxmsg = max_msgs;
  178. attr.mq_msgsize = sizeof(uintptr_t);
  179. attr.mq_curmsgs = 0;
  180. attr.mq_flags = 0;
  181. ret = file_mq_open(&mq_adpt->mq, mq_adpt->name,
  182. O_RDWR | O_CREAT, 0644, &attr);
  183. if (ret < 0) {
  184. //printf("ERROR: Failed to create mqueue\n");
  185. kmm_free(mq_adpt);
  186. return NULL;
  187. }
  188. mq_adpt->msgsize = sizeof(uintptr_t);
  189. return (usb_osal_mq_t)mq_adpt;
  190. }
  191. void usb_osal_mq_delete(usb_osal_mq_t mq)
  192. {
  193. struct mq_adpt *mq_adpt = (struct mq_adpt *)mq;
  194. file_mq_close(&mq_adpt->mq);
  195. file_mq_unlink(mq_adpt->name);
  196. kmm_free(mq_adpt);
  197. }
  198. int usb_osal_mq_send(usb_osal_mq_t mq, uintptr_t addr)
  199. {
  200. struct mq_adpt *mq_adpt = (struct mq_adpt *)mq;
  201. int ret;
  202. /* send mq from isr, do not use timeout*/
  203. ret = file_mq_send(&mq_adpt->mq, (const char *)&addr, mq_adpt->msgsize, 0);
  204. if (ret < 0) {
  205. return -USB_ERR_INVAL;
  206. } else {
  207. return 0;
  208. }
  209. }
  210. static void msec2spec(struct timespec *timespec, uint32_t ticks)
  211. {
  212. uint32_t tmp;
  213. tmp = TICK2SEC(ticks);
  214. timespec->tv_sec += tmp;
  215. ticks -= SEC2TICK(tmp);
  216. tmp = TICK2NSEC(ticks);
  217. timespec->tv_nsec += tmp;
  218. }
  219. int usb_osal_mq_recv(usb_osal_mq_t mq, uintptr_t *addr, uint32_t timeout)
  220. {
  221. struct mq_adpt *mq_adpt = (struct mq_adpt *)mq;
  222. struct timespec __timeout;
  223. int ret;
  224. if (timeout == 0xffffffff)
  225. return file_mq_receive(&mq_adpt->mq, (char *)addr, mq_adpt->msgsize, 0);
  226. else {
  227. ret = clock_gettime(CLOCK_REALTIME, &__timeout);
  228. if (ret < 0) {
  229. //printf("ERROR: Failed to get time\n");
  230. return -USB_ERR_INVAL;
  231. }
  232. if (timeout) {
  233. msec2spec(&__timeout, timeout);
  234. }
  235. return file_mq_timedreceive(&mq_adpt->mq,
  236. (char *)addr,
  237. mq_adpt->msgsize,
  238. 0,
  239. &__timeout);
  240. }
  241. }
  242. static void os_timer_callback(wdparm_t arg)
  243. {
  244. struct timer_adpt *timer;
  245. timer = (struct timer_adpt *)arg;
  246. if (timer->timer.handler) {
  247. timer->timer.handler(timer->timer.argument);
  248. }
  249. if (timer->timer.is_period) {
  250. wd_start(&timer->wdog, timer->timer.ticks, os_timer_callback, arg);
  251. }
  252. }
  253. struct usb_osal_timer *usb_osal_timer_create(const char *name, uint32_t timeout_ms, usb_timer_handler_t handler, void *argument, bool is_period)
  254. {
  255. struct timer_adpt *timer = kmm_malloc(sizeof(struct timer_adpt));
  256. if (!timer) {
  257. return NULL;
  258. }
  259. memset((void *)timer, 0, sizeof(struct timer_adpt));
  260. timer->timer.handler = handler;
  261. timer->timer.argument = argument;
  262. timer->timer.ticks = MSEC2TICK(timeout_ms);
  263. timer->timer.is_period = is_period;
  264. return (struct usb_osal_timer *)timer;
  265. }
  266. void usb_osal_timer_delete(struct usb_osal_timer *timer)
  267. {
  268. struct timer_adpt *__timer = (struct timer_adpt *)timer;
  269. wd_cancel(&__timer->wdog);
  270. kmm_free(__timer);
  271. }
  272. void usb_osal_timer_start(struct usb_osal_timer *timer)
  273. {
  274. struct timer_adpt *__timer = (struct timer_adpt *)timer;
  275. wd_start(&__timer->wdog, __timer->timer.ticks, os_timer_callback, (wdparm_t)__timer);
  276. }
  277. void usb_osal_timer_stop(struct usb_osal_timer *timer)
  278. {
  279. struct timer_adpt *__timer = (struct timer_adpt *)timer;
  280. wd_cancel(&__timer->wdog);
  281. }
  282. size_t usb_osal_enter_critical_section(void)
  283. {
  284. irqstate_t flags;
  285. flags = enter_critical_section();
  286. return (size_t)flags;
  287. }
  288. void usb_osal_leave_critical_section(size_t flag)
  289. {
  290. leave_critical_section(flag);
  291. }
  292. void usb_osal_msleep(uint32_t delay)
  293. {
  294. useconds_t usec = delay * 1000;
  295. nxsig_usleep(usec);
  296. }