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