M480 BSP V3.0.7000
The Board Support Package for M480 Series
mem_alloc.c
Go to the documentation of this file.
1/**************************************************************************/
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13
14#include "NuMicro.h"
15
16#include "usb.h"
17
19
20//#define MEM_DEBUG
21
22#ifdef MEM_DEBUG
23#define mem_debug printf
24#else
25#define mem_debug(...)
26#endif
27
28#ifdef __ICCARM__
29#pragma data_alignment=32
30static uint8_t _mem_pool[MEM_POOL_UNIT_NUM][MEM_POOL_UNIT_SIZE];
31#else
32static uint8_t _mem_pool[MEM_POOL_UNIT_NUM][MEM_POOL_UNIT_SIZE] __attribute__((aligned(32)));
33#endif
34static uint8_t _unit_used[MEM_POOL_UNIT_NUM];
35
36static volatile int _usbh_mem_used;
37static volatile int _usbh_max_mem_used;
38static volatile int _mem_pool_used;
39
40UDEV_T * g_udev_list;
41
42uint8_t _dev_addr_pool[128];
43static volatile int _device_addr;
44
45static int _sidx = 0;;
46
47/*--------------------------------------------------------------------------*/
48/* Memory alloc/free recording */
49/*--------------------------------------------------------------------------*/
50
51void usbh_memory_init(void)
52{
53 if (sizeof(TD_T) > MEM_POOL_UNIT_SIZE)
54 {
55 USB_error("TD_T - MEM_POOL_UNIT_SIZE too small!\n");
56 while (1);
57 }
58
59 if (sizeof(ED_T) > MEM_POOL_UNIT_SIZE)
60 {
61 USB_error("ED_T - MEM_POOL_UNIT_SIZE too small!\n");
62 while (1);
63 }
64
65 _usbh_mem_used = 0L;
66 _usbh_max_mem_used = 0L;
67
68 memset(_unit_used, 0, sizeof(_unit_used));
69 _mem_pool_used = 0;
70 _sidx = 0;
71
72 g_udev_list = NULL;
73
74 memset(_dev_addr_pool, 0, sizeof(_dev_addr_pool));
75 _device_addr = 1;
76}
77
78uint32_t usbh_memory_used(void)
79{
80 printf("USB static memory: %d/%d, heap used: %d\n", _mem_pool_used, MEM_POOL_UNIT_NUM, _usbh_mem_used);
81 return _usbh_mem_used;
82}
83
84static void memory_counter(int size)
85{
86 _usbh_mem_used += size;
87 if (_usbh_mem_used > _usbh_max_mem_used)
88 _usbh_max_mem_used = _usbh_mem_used;
89}
90
91void * usbh_alloc_mem(int size)
92{
93 void *p;
94
95 p = malloc(size);
96 if (p == NULL)
97 {
98 USB_error("usbh_alloc_mem failed! %d\n", size);
99 return NULL;
100 }
101
102 memset(p, 0, size);
103 memory_counter(size);
104 return p;
105}
106
107void usbh_free_mem(void *p, int size)
108{
109 free(p);
110 memory_counter(0-size);
111}
112
113
114/*--------------------------------------------------------------------------*/
115/* USB device allocate/free */
116/*--------------------------------------------------------------------------*/
117
118UDEV_T * alloc_device(void)
119{
120 UDEV_T *udev;
121
122 udev = malloc(sizeof(*udev));
123 if (udev == NULL)
124 {
125 USB_error("alloc_device failed!\n");
126 return NULL;
127 }
128 memset(udev, 0, sizeof(*udev));
129 memory_counter(sizeof(*udev));
130 udev->cur_conf = -1; /* must! used to identify the first SET CONFIGURATION */
131 udev->next = g_udev_list; /* chain to global device list */
132 g_udev_list = udev;
133 return udev;
134}
135
136void free_device(UDEV_T *udev)
137{
138 UDEV_T *d;
139
140 if (udev == NULL)
141 return;
142
143 if (udev->cfd_buff != NULL)
144 usbh_free_mem(udev->cfd_buff, MAX_DESC_BUFF_SIZE);
145
146 /*
147 * Remove it from the global device list
148 */
149 if (g_udev_list == udev)
150 {
151 g_udev_list = g_udev_list->next;
152 }
153 else
154 {
155 d = g_udev_list;
156 while (d != NULL)
157 {
158 if (d->next == udev)
159 {
160 d->next = udev->next;
161 break;
162 }
163 d = d->next;
164 }
165 }
166
167 free(udev);
168 memory_counter(-sizeof(*udev));
169}
170
171int alloc_dev_address(void)
172{
173 _device_addr++;
174
175 if (_device_addr >= 128)
176 _device_addr = 1;
177
178 while (1)
179 {
180 if (_dev_addr_pool[_device_addr] == 0)
181 {
182 _dev_addr_pool[_device_addr] = 1;
183 return _device_addr;
184 }
185 _device_addr++;
186 if (_device_addr >= 128)
187 _device_addr = 1;
188 }
189}
190
191void free_dev_address(int dev_addr)
192{
193 if (dev_addr < 128)
194 _dev_addr_pool[dev_addr] = 0;
195}
196
197/*--------------------------------------------------------------------------*/
198/* UTR (USB Transfer Request) allocate/free */
199/*--------------------------------------------------------------------------*/
200
201UTR_T * alloc_utr(UDEV_T *udev)
202{
203 UTR_T *utr;
204
205 utr = malloc(sizeof(*utr));
206 if (utr == NULL)
207 {
208 USB_error("alloc_utr failed!\n");
209 return NULL;
210 }
211 memory_counter(sizeof(*utr));
212 memset(utr, 0, sizeof(*utr));
213 utr->udev = udev;
214 mem_debug("[ALLOC] [UTR] - 0x%x\n", (int)utr);
215 return utr;
216}
217
218void free_utr(UTR_T *utr)
219{
220 if (utr == NULL)
221 return;
222
223 mem_debug("[FREE] [UTR] - 0x%x\n", (int)utr);
224 free(utr);
225 memory_counter(0-(int)sizeof(*utr));
226}
227
228/*--------------------------------------------------------------------------*/
229/* OHCI ED allocate/free */
230/*--------------------------------------------------------------------------*/
231
232ED_T * alloc_ohci_ED(void)
233{
234 uint32_t irq_state = __get_PRIMASK();
235 int i;
236 ED_T *ed;
237
238 __disable_irq();
239
240 for (i = 0; i < MEM_POOL_UNIT_NUM; i++)
241 {
242 if (_unit_used[i] == 0)
243 {
244 _unit_used[i] = 1;
245 _mem_pool_used++;
246
247 __set_PRIMASK(irq_state);
248
249 ed = (ED_T *)&_mem_pool[i];
250 memset(ed, 0, sizeof(*ed));
251 mem_debug("[ALLOC] [ED] - 0x%x\n", (int)ed);
252 return ed;
253 }
254 }
255 __set_PRIMASK(irq_state);
256 USB_error("alloc_ohci_ED failed!\n");
257 return NULL;
258}
259
260void free_ohci_ED(ED_T *ed)
261{
262 uint32_t irq_state = __get_PRIMASK();
263 int i;
264
265 __disable_irq();
266
267 for (i = 0; i < MEM_POOL_UNIT_NUM; i++)
268 {
269 if ((uint32_t)&_mem_pool[i] == (uint32_t)ed)
270 {
271 _unit_used[i] = 0;
272 _mem_pool_used--;
273 __set_PRIMASK(irq_state);
274 mem_debug("[FREE] [ED] - 0x%x\n", (int)ed);
275 return;
276 }
277 }
278 __set_PRIMASK(irq_state);
279 USB_debug("free_ohci_ED - not found! (ignored in case of multiple UTR)\n");
280}
281
282/*--------------------------------------------------------------------------*/
283/* OHCI TD allocate/free */
284/*--------------------------------------------------------------------------*/
285TD_T * alloc_ohci_TD(UTR_T *utr)
286{
287 uint32_t irq_state = __get_PRIMASK();
288 int i;
289 TD_T *td;
290
291 __disable_irq();
292
293 for (i = 0; i < MEM_POOL_UNIT_NUM; i++)
294 {
295 if (_unit_used[i] == 0)
296 {
297 _unit_used[i] = 1;
298 _mem_pool_used++;
299
300 __set_PRIMASK(irq_state);
301
302 td = (TD_T *)&_mem_pool[i];
303 memset(td, 0, sizeof(*td));
304 td->utr = utr;
305 mem_debug("[ALLOC] [TD] - 0x%x\n", (int)td);
306 return td;
307 }
308 }
309 __set_PRIMASK(irq_state);
310 USB_error("alloc_ohci_TD failed!\n");
311 return NULL;
312}
313
314void free_ohci_TD(TD_T *td)
315{
316 uint32_t irq_state = __get_PRIMASK();
317 int i;
318
319 __disable_irq();
320
321 for (i = 0; i < MEM_POOL_UNIT_NUM; i++)
322 {
323 if ((uint32_t)&_mem_pool[i] == (uint32_t)td)
324 {
325 _unit_used[i] = 0;
326 _mem_pool_used--;
327 __set_PRIMASK(irq_state);
328 mem_debug("[FREE] [TD] - 0x%x\n", (int)td);
329 return;
330 }
331 }
332 __set_PRIMASK(irq_state);
333 USB_error("free_ohci_TD - not found!\n");
334}
335
336/*--------------------------------------------------------------------------*/
337/* EHCI QH allocate/free */
338/*--------------------------------------------------------------------------*/
339QH_T * alloc_ehci_QH(void)
340{
341 uint32_t irq_state = __get_PRIMASK();
342 int i;
343 QH_T *qh = NULL;
344
345 __disable_irq();
346
347 for (i = (_sidx+1) % MEM_POOL_UNIT_NUM; i != _sidx; i = (i+1) % MEM_POOL_UNIT_NUM)
348 {
349 if (_unit_used[i] == 0)
350 {
351 _unit_used[i] = 1;
352 _sidx = i;
353 _mem_pool_used++;
354
355 __set_PRIMASK(irq_state);
356
357 qh = (QH_T *)&_mem_pool[i];
358 memset(qh, 0, sizeof(*qh));
359 mem_debug("[ALLOC] [QH] - 0x%x\n", (int)qh);
360 break;
361 }
362 }
363 if (qh == NULL)
364 {
365 __set_PRIMASK(irq_state);
366 USB_error("alloc_ehci_QH failed!\n");
367 return NULL;
368 }
369 qh->Curr_qTD = QTD_LIST_END;
370 qh->OL_Next_qTD = QTD_LIST_END;
371 qh->OL_Alt_Next_qTD = QTD_LIST_END;
372 qh->OL_Token = QTD_STS_HALT;
373 return qh;
374}
375
376void free_ehci_QH(QH_T *qh)
377{
378 uint32_t irq_state = __get_PRIMASK();
379 int i;
380
381 __disable_irq();
382
383 for (i = 0; i < MEM_POOL_UNIT_NUM; i++)
384 {
385 if ((uint32_t)&_mem_pool[i] == (uint32_t)qh)
386 {
387 _unit_used[i] = 0;
388 _mem_pool_used--;
389 __set_PRIMASK(irq_state);
390 mem_debug("[FREE] [QH] - 0x%x\n", (int)qh);
391 return;
392 }
393 }
394 __set_PRIMASK(irq_state);
395 USB_debug("free_ehci_QH - not found! (ignored in case of multiple UTR)\n");
396}
397
398/*--------------------------------------------------------------------------*/
399/* EHCI qTD allocate/free */
400/*--------------------------------------------------------------------------*/
401qTD_T * alloc_ehci_qTD(UTR_T *utr)
402{
403 uint32_t irq_state = __get_PRIMASK();
404 int i;
405 qTD_T *qtd;
406
407 __disable_irq();
408
409 for (i = (_sidx+1) % MEM_POOL_UNIT_NUM; i != _sidx; i = (i+1) % MEM_POOL_UNIT_NUM)
410 {
411 if (_unit_used[i] == 0)
412 {
413 _unit_used[i] = 1;
414 _sidx = i;
415 _mem_pool_used++;
416
417 __set_PRIMASK(irq_state);
418
419 qtd = (qTD_T *)&_mem_pool[i];
420 memset(qtd, 0, sizeof(*qtd));
421 qtd->Next_qTD = QTD_LIST_END;
422 qtd->Alt_Next_qTD = QTD_LIST_END;
423 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.
424 qtd->utr = utr;
425 mem_debug("[ALLOC] [qTD] - 0x%x\n", (int)qtd);
426 return qtd;
427 }
428 }
429 __set_PRIMASK(irq_state);
430 USB_error("alloc_ehci_qTD failed!\n");
431 return NULL;
432}
433
434void free_ehci_qTD(qTD_T *qtd)
435{
436 uint32_t irq_state = __get_PRIMASK();
437 int i;
438
439 __disable_irq();
440
441 for (i = 0; i < MEM_POOL_UNIT_NUM; i++)
442 {
443 if ((uint32_t)&_mem_pool[i] == (uint32_t)qtd)
444 {
445 _unit_used[i] = 0;
446 _mem_pool_used--;
447 __set_PRIMASK(irq_state);
448 mem_debug("[FREE] [qTD] - 0x%x\n", (int)qtd);
449 return;
450 }
451 }
452 __set_PRIMASK(irq_state);
453 USB_error("free_ehci_qTD 0x%x - not found!\n", (int)qtd);
454}
455
456/*--------------------------------------------------------------------------*/
457/* EHCI iTD allocate/free */
458/*--------------------------------------------------------------------------*/
459iTD_T * alloc_ehci_iTD(void)
460{
461 uint32_t irq_state = __get_PRIMASK();
462 int i;
463 iTD_T *itd;
464
465 __disable_irq();
466
467 for (i = (_sidx+1) % MEM_POOL_UNIT_NUM; i != _sidx; i = (i+1) % MEM_POOL_UNIT_NUM)
468 {
469 if (i+2 >= MEM_POOL_UNIT_NUM)
470 continue;
471
472 if ((_unit_used[i] == 0) && (_unit_used[i+1] == 0))
473 {
474 _unit_used[i] = _unit_used[i+1] = 1;
475 _sidx = i+1;
476 _mem_pool_used += 2;
477
478 __set_PRIMASK(irq_state);
479
480 itd = (iTD_T *)&_mem_pool[i];
481 memset(itd, 0, sizeof(*itd));
482 mem_debug("[ALLOC] [iTD] - 0x%x\n", (int)itd);
483 return itd;
484 }
485 }
486 __set_PRIMASK(irq_state);
487 USB_error("alloc_ehci_iTD failed!\n");
488 return NULL;
489}
490
491void free_ehci_iTD(iTD_T *itd)
492{
493 uint32_t irq_state = __get_PRIMASK();
494 int i;
495
496 __disable_irq();
497
498 for (i = 0; i+1 < MEM_POOL_UNIT_NUM; i++)
499 {
500 if ((uint32_t)&_mem_pool[i] == (uint32_t)itd)
501 {
502 _unit_used[i] = _unit_used[i+1] = 0;
503 _mem_pool_used -= 2;
504 __set_PRIMASK(irq_state);
505 mem_debug("[FREE] [iTD] - 0x%x\n", (int)itd);
506 return;
507 }
508 }
509 __set_PRIMASK(irq_state);
510 USB_error("free_ehci_iTD 0x%x - not found!\n", (int)itd);
511}
512
513/*--------------------------------------------------------------------------*/
514/* EHCI iTD allocate/free */
515/*--------------------------------------------------------------------------*/
516siTD_T * alloc_ehci_siTD(void)
517{
518 uint32_t irq_state = __get_PRIMASK();
519 int i;
520 siTD_T *sitd;
521
522 __disable_irq();
523
524 for (i = (_sidx+1) % MEM_POOL_UNIT_NUM; i != _sidx; i = (i+1) % MEM_POOL_UNIT_NUM)
525 {
526 if (_unit_used[i] == 0)
527 {
528 _unit_used[i] = 1;
529 _sidx = i;
530 _mem_pool_used ++;
531
532 __set_PRIMASK(irq_state);
533
534 sitd = (siTD_T *)&_mem_pool[i];
535 memset(sitd, 0, sizeof(*sitd));
536 mem_debug("[ALLOC] [siTD] - 0x%x\n", (int)sitd);
537 return sitd;
538 }
539 }
540 __set_PRIMASK(irq_state);
541 USB_error("alloc_ehci_siTD failed!\n");
542 return NULL;
543}
544
545void free_ehci_siTD(siTD_T *sitd)
546{
547 uint32_t irq_state = __get_PRIMASK();
548 int i;
549
550 __disable_irq();
551
552 for (i = 0; i < MEM_POOL_UNIT_NUM; i++)
553 {
554 if ((uint32_t)&_mem_pool[i] == (uint32_t)sitd)
555 {
556 _unit_used[i] = 0;
557 _mem_pool_used--;
558 __set_PRIMASK(irq_state);
559 mem_debug("[FREE] [siTD] - 0x%x\n", (int)sitd);
560 return;
561 }
562 }
563 __set_PRIMASK(irq_state);
564 USB_error("free_ehci_siTD 0x%x - not found!\n", (int)sitd);
565}
566
568
569/*** (C) COPYRIGHT 2017 Nuvoton Technology Corp. ***/
570
void *__dso_handle __attribute__((weak))
Definition: _syscalls.c:35
NuMicro peripheral access layer header file.
#define NULL
NULL pointer.
Definition: M480.h:605
USB Host library header file.