mem_alloc.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. /**************************************************************************//**
  2. * @file mem_alloc.c
  3. * @version V1.10
  4. * @brief USB host library memory allocation functions.
  5. *
  6. * SPDX-License-Identifier: Apache-2.0
  7. *
  8. * @copyright (C) 2017 Nuvoton Technology Corp. All rights reserved.
  9. *****************************************************************************/
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include "NuMicro.h"
  14. #include "usb.h"
  15. /// @cond HIDDEN_SYMBOLS
  16. //#define MEM_DEBUG
  17. #ifdef MEM_DEBUG
  18. #define mem_debug rt_kprintf
  19. #else
  20. #define mem_debug(...)
  21. #endif
  22. #ifdef __ICCARM__
  23. #pragma data_alignment=32
  24. static uint8_t _mem_pool[MEM_POOL_UNIT_NUM][MEM_POOL_UNIT_SIZE];
  25. #else
  26. static uint8_t _mem_pool[MEM_POOL_UNIT_NUM][MEM_POOL_UNIT_SIZE] __attribute__((aligned(32)));
  27. #endif
  28. static uint8_t _unit_used[MEM_POOL_UNIT_NUM];
  29. static volatile int _usbh_mem_used;
  30. static volatile int _usbh_max_mem_used;
  31. static volatile int _mem_pool_used;
  32. UDEV_T * g_udev_list;
  33. uint8_t _dev_addr_pool[128];
  34. static volatile int _device_addr;
  35. static int _sidx = 0;;
  36. /*--------------------------------------------------------------------------*/
  37. /* Memory alloc/free recording */
  38. /*--------------------------------------------------------------------------*/
  39. void usbh_memory_init(void)
  40. {
  41. if (sizeof(TD_T) > MEM_POOL_UNIT_SIZE)
  42. {
  43. USB_error("TD_T - MEM_POOL_UNIT_SIZE too small!\n");
  44. while (1);
  45. }
  46. if (sizeof(ED_T) > MEM_POOL_UNIT_SIZE)
  47. {
  48. USB_error("ED_T - MEM_POOL_UNIT_SIZE too small!\n");
  49. while (1);
  50. }
  51. _usbh_mem_used = 0L;
  52. _usbh_max_mem_used = 0L;
  53. memset(_unit_used, 0, sizeof(_unit_used));
  54. _mem_pool_used = 0;
  55. _sidx = 0;
  56. g_udev_list = NULL;
  57. memset(_dev_addr_pool, 0, sizeof(_dev_addr_pool));
  58. _device_addr = 1;
  59. }
  60. uint32_t usbh_memory_used(void)
  61. {
  62. rt_kprintf("USB static memory: %d/%d, heap used: %d\n", _mem_pool_used, MEM_POOL_UNIT_NUM, _usbh_mem_used);
  63. return _usbh_mem_used;
  64. }
  65. static void memory_counter(int size)
  66. {
  67. _usbh_mem_used += size;
  68. if (_usbh_mem_used > _usbh_max_mem_used)
  69. _usbh_max_mem_used = _usbh_mem_used;
  70. }
  71. void * usbh_alloc_mem(int size)
  72. {
  73. void *p;
  74. p = malloc(size);
  75. if (p == NULL)
  76. {
  77. USB_error("usbh_alloc_mem failed! %d\n", size);
  78. return NULL;
  79. }
  80. memset(p, 0, size);
  81. memory_counter(size);
  82. return p;
  83. }
  84. void usbh_free_mem(void *p, int size)
  85. {
  86. free(p);
  87. memory_counter(0-size);
  88. }
  89. /*--------------------------------------------------------------------------*/
  90. /* USB device allocate/free */
  91. /*--------------------------------------------------------------------------*/
  92. UDEV_T * alloc_device(void)
  93. {
  94. UDEV_T *udev;
  95. udev = malloc(sizeof(*udev));
  96. if (udev == NULL)
  97. {
  98. USB_error("alloc_device failed!\n");
  99. return NULL;
  100. }
  101. memset(udev, 0, sizeof(*udev));
  102. memory_counter(sizeof(*udev));
  103. udev->cur_conf = -1; /* must! used to identify the first SET CONFIGURATION */
  104. udev->next = g_udev_list; /* chain to global device list */
  105. g_udev_list = udev;
  106. return udev;
  107. }
  108. void free_device(UDEV_T *udev)
  109. {
  110. UDEV_T *d;
  111. if (udev == NULL)
  112. return;
  113. if (udev->cfd_buff != NULL)
  114. usbh_free_mem(udev->cfd_buff, MAX_DESC_BUFF_SIZE);
  115. /*
  116. * Remove it from the global device list
  117. */
  118. if (g_udev_list == udev)
  119. {
  120. g_udev_list = g_udev_list->next;
  121. }
  122. else
  123. {
  124. d = g_udev_list;
  125. while (d != NULL)
  126. {
  127. if (d->next == udev)
  128. {
  129. d->next = udev->next;
  130. break;
  131. }
  132. d = d->next;
  133. }
  134. }
  135. free(udev);
  136. memory_counter(-sizeof(*udev));
  137. }
  138. int alloc_dev_address(void)
  139. {
  140. _device_addr++;
  141. if (_device_addr >= 128)
  142. _device_addr = 1;
  143. while (1)
  144. {
  145. if (_dev_addr_pool[_device_addr] == 0)
  146. {
  147. _dev_addr_pool[_device_addr] = 1;
  148. return _device_addr;
  149. }
  150. _device_addr++;
  151. if (_device_addr >= 128)
  152. _device_addr = 1;
  153. }
  154. }
  155. void free_dev_address(int dev_addr)
  156. {
  157. if (dev_addr < 128)
  158. _dev_addr_pool[dev_addr] = 0;
  159. }
  160. /*--------------------------------------------------------------------------*/
  161. /* UTR (USB Transfer Request) allocate/free */
  162. /*--------------------------------------------------------------------------*/
  163. UTR_T * alloc_utr(UDEV_T *udev)
  164. {
  165. UTR_T *utr;
  166. utr = malloc(sizeof(*utr));
  167. if (utr == NULL)
  168. {
  169. USB_error("alloc_utr failed!\n");
  170. return NULL;
  171. }
  172. memory_counter(sizeof(*utr));
  173. memset(utr, 0, sizeof(*utr));
  174. utr->udev = udev;
  175. mem_debug("[ALLOC] [UTR] - 0x%x\n", (int)utr);
  176. return utr;
  177. }
  178. void free_utr(UTR_T *utr)
  179. {
  180. if (utr == NULL)
  181. return;
  182. mem_debug("[FREE] [UTR] - 0x%x\n", (int)utr);
  183. free(utr);
  184. memory_counter(0-(int)sizeof(*utr));
  185. }
  186. /*--------------------------------------------------------------------------*/
  187. /* OHCI ED allocate/free */
  188. /*--------------------------------------------------------------------------*/
  189. ED_T * alloc_ohci_ED(void)
  190. {
  191. int i;
  192. ED_T *ed;
  193. for (i = 0; i < MEM_POOL_UNIT_NUM; i++)
  194. {
  195. if (_unit_used[i] == 0)
  196. {
  197. _unit_used[i] = 1;
  198. _mem_pool_used++;
  199. ed = (ED_T *)&_mem_pool[i];
  200. memset(ed, 0, sizeof(*ed));
  201. mem_debug("[ALLOC] [ED] - 0x%x\n", (int)ed);
  202. return ed;
  203. }
  204. }
  205. USB_error("alloc_ohci_ED failed!\n");
  206. return NULL;
  207. }
  208. void free_ohci_ED(ED_T *ed)
  209. {
  210. int i;
  211. for (i = 0; i < MEM_POOL_UNIT_NUM; i++)
  212. {
  213. if ((uint32_t)&_mem_pool[i] == (uint32_t)ed)
  214. {
  215. mem_debug("[FREE] [ED] - 0x%x\n", (int)ed);
  216. _unit_used[i] = 0;
  217. _mem_pool_used--;
  218. return;
  219. }
  220. }
  221. USB_debug("free_ohci_ED - not found! (ignored in case of multiple UTR)\n");
  222. }
  223. /*--------------------------------------------------------------------------*/
  224. /* OHCI TD allocate/free */
  225. /*--------------------------------------------------------------------------*/
  226. TD_T * alloc_ohci_TD(UTR_T *utr)
  227. {
  228. int i;
  229. TD_T *td;
  230. for (i = 0; i < MEM_POOL_UNIT_NUM; i++)
  231. {
  232. if (_unit_used[i] == 0)
  233. {
  234. _unit_used[i] = 1;
  235. _mem_pool_used++;
  236. td = (TD_T *)&_mem_pool[i];
  237. memset(td, 0, sizeof(*td));
  238. td->utr = utr;
  239. mem_debug("[ALLOC] [TD] - 0x%x\n", (int)td);
  240. return td;
  241. }
  242. }
  243. USB_error("alloc_ohci_TD failed!\n");
  244. return NULL;
  245. }
  246. void free_ohci_TD(TD_T *td)
  247. {
  248. int i;
  249. for (i = 0; i < MEM_POOL_UNIT_NUM; i++)
  250. {
  251. if ((uint32_t)&_mem_pool[i] == (uint32_t)td)
  252. {
  253. mem_debug("[FREE] [TD] - 0x%x\n", (int)td);
  254. _unit_used[i] = 0;
  255. _mem_pool_used--;
  256. return;
  257. }
  258. }
  259. USB_error("free_ohci_TD - not found!\n");
  260. }
  261. /*--------------------------------------------------------------------------*/
  262. /* EHCI QH allocate/free */
  263. /*--------------------------------------------------------------------------*/
  264. QH_T * alloc_ehci_QH(void)
  265. {
  266. int i;
  267. QH_T *qh = NULL;
  268. for (i = (_sidx+1) % MEM_POOL_UNIT_NUM; i != _sidx; i = (i+1) % MEM_POOL_UNIT_NUM)
  269. {
  270. if (_unit_used[i] == 0)
  271. {
  272. _unit_used[i] = 1;
  273. _sidx = i;
  274. _mem_pool_used++;
  275. qh = (QH_T *)&_mem_pool[i];
  276. memset(qh, 0, sizeof(*qh));
  277. mem_debug("[ALLOC] [QH] - 0x%x\n", (int)qh);
  278. break;
  279. }
  280. }
  281. if (qh == NULL)
  282. {
  283. USB_error("alloc_ehci_QH failed!\n");
  284. return NULL;
  285. }
  286. qh->Curr_qTD = QTD_LIST_END;
  287. qh->OL_Next_qTD = QTD_LIST_END;
  288. qh->OL_Alt_Next_qTD = QTD_LIST_END;
  289. qh->OL_Token = QTD_STS_HALT;
  290. return qh;
  291. }
  292. void free_ehci_QH(QH_T *qh)
  293. {
  294. int i;
  295. for (i = 0; i < MEM_POOL_UNIT_NUM; i++)
  296. {
  297. if ((uint32_t)&_mem_pool[i] == (uint32_t)qh)
  298. {
  299. mem_debug("[FREE] [QH] - 0x%x\n", (int)qh);
  300. _unit_used[i] = 0;
  301. _mem_pool_used--;
  302. return;
  303. }
  304. }
  305. USB_debug("free_ehci_QH - not found! (ignored in case of multiple UTR)\n");
  306. }
  307. /*--------------------------------------------------------------------------*/
  308. /* EHCI qTD allocate/free */
  309. /*--------------------------------------------------------------------------*/
  310. qTD_T * alloc_ehci_qTD(UTR_T *utr)
  311. {
  312. int i;
  313. qTD_T *qtd;
  314. for (i = (_sidx+1) % MEM_POOL_UNIT_NUM; i != _sidx; i = (i+1) % MEM_POOL_UNIT_NUM)
  315. {
  316. if (_unit_used[i] == 0)
  317. {
  318. _unit_used[i] = 1;
  319. _sidx = i;
  320. _mem_pool_used++;
  321. qtd = (qTD_T *)&_mem_pool[i];
  322. memset(qtd, 0, sizeof(*qtd));
  323. qtd->Next_qTD = QTD_LIST_END;
  324. qtd->Alt_Next_qTD = QTD_LIST_END;
  325. qtd->Token = 0x1197B3F; // QTD_STS_HALT; visit_qtd() will not remove a qTD with this mark. It means the qTD still not ready for transfer.
  326. qtd->utr = utr;
  327. mem_debug("[ALLOC] [qTD] - 0x%x\n", (int)qtd);
  328. return qtd;
  329. }
  330. }
  331. USB_error("alloc_ehci_qTD failed!\n");
  332. return NULL;
  333. }
  334. void free_ehci_qTD(qTD_T *qtd)
  335. {
  336. int i;
  337. for (i = 0; i < MEM_POOL_UNIT_NUM; i++)
  338. {
  339. if ((uint32_t)&_mem_pool[i] == (uint32_t)qtd)
  340. {
  341. mem_debug("[FREE] [qTD] - 0x%x\n", (int)qtd);
  342. _unit_used[i] = 0;
  343. _mem_pool_used--;
  344. return;
  345. }
  346. }
  347. USB_error("free_ehci_qTD 0x%x - not found!\n", (int)qtd);
  348. }
  349. /*--------------------------------------------------------------------------*/
  350. /* EHCI iTD allocate/free */
  351. /*--------------------------------------------------------------------------*/
  352. iTD_T * alloc_ehci_iTD(void)
  353. {
  354. int i;
  355. iTD_T *itd;
  356. for (i = (_sidx+1) % MEM_POOL_UNIT_NUM; i != _sidx; i = (i+1) % MEM_POOL_UNIT_NUM)
  357. {
  358. if (i+2 >= MEM_POOL_UNIT_NUM)
  359. continue;
  360. if ((_unit_used[i] == 0) && (_unit_used[i+1] == 0))
  361. {
  362. _unit_used[i] = _unit_used[i+1] = 1;
  363. _sidx = i+1;
  364. _mem_pool_used += 2;
  365. itd = (iTD_T *)&_mem_pool[i];
  366. memset(itd, 0, sizeof(*itd));
  367. mem_debug("[ALLOC] [iTD] - 0x%x\n", (int)itd);
  368. return itd;
  369. }
  370. }
  371. USB_error("alloc_ehci_iTD failed!\n");
  372. return NULL;
  373. }
  374. void free_ehci_iTD(iTD_T *itd)
  375. {
  376. int i;
  377. for (i = 0; i+1 < MEM_POOL_UNIT_NUM; i++)
  378. {
  379. if ((uint32_t)&_mem_pool[i] == (uint32_t)itd)
  380. {
  381. mem_debug("[FREE] [iTD] - 0x%x\n", (int)itd);
  382. _unit_used[i] = _unit_used[i+1] = 0;
  383. _mem_pool_used -= 2;
  384. return;
  385. }
  386. }
  387. USB_error("free_ehci_iTD 0x%x - not found!\n", (int)itd);
  388. }
  389. /*--------------------------------------------------------------------------*/
  390. /* EHCI iTD allocate/free */
  391. /*--------------------------------------------------------------------------*/
  392. siTD_T * alloc_ehci_siTD(void)
  393. {
  394. int i;
  395. siTD_T *sitd;
  396. for (i = (_sidx+1) % MEM_POOL_UNIT_NUM; i != _sidx; i = (i+1) % MEM_POOL_UNIT_NUM)
  397. {
  398. if (_unit_used[i] == 0)
  399. {
  400. _unit_used[i] = 1;
  401. _sidx = i;
  402. _mem_pool_used ++;
  403. sitd = (siTD_T *)&_mem_pool[i];
  404. memset(sitd, 0, sizeof(*sitd));
  405. mem_debug("[ALLOC] [siTD] - 0x%x\n", (int)sitd);
  406. return sitd;
  407. }
  408. }
  409. USB_error("alloc_ehci_siTD failed!\n");
  410. return NULL;
  411. }
  412. void free_ehci_siTD(siTD_T *sitd)
  413. {
  414. int i;
  415. for (i = 0; i < MEM_POOL_UNIT_NUM; i++)
  416. {
  417. if ((uint32_t)&_mem_pool[i] == (uint32_t)sitd)
  418. {
  419. mem_debug("[FREE] [siTD] - 0x%x\n", (int)sitd);
  420. _unit_used[i] = 0;
  421. _mem_pool_used--;
  422. return;
  423. }
  424. }
  425. USB_error("free_ehci_siTD 0x%x - not found!\n", (int)sitd);
  426. }
  427. /// @endcond HIDDEN_SYMBOLS
  428. /*** (C) COPYRIGHT 2017 Nuvoton Technology Corp. ***/