M480 BSP  V3.05.001
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
31 static uint8_t _mem_pool[MEM_POOL_UNIT_NUM][MEM_POOL_UNIT_SIZE];
32 #else
33 static uint8_t _mem_pool[MEM_POOL_UNIT_NUM][MEM_POOL_UNIT_SIZE] __attribute__((aligned(32)));
34 #endif
35 static uint8_t _unit_used[MEM_POOL_UNIT_NUM];
36 
37 static volatile int _usbh_mem_used;
38 static volatile int _usbh_max_mem_used;
39 static volatile int _mem_pool_used;
40 
41 
42 UDEV_T * g_udev_list;
43 
44 uint8_t _dev_addr_pool[128];
45 static volatile int _device_addr;
46 
47 static int _sidx = 0;;
48 
49 /*--------------------------------------------------------------------------*/
50 /* Memory alloc/free recording */
51 /*--------------------------------------------------------------------------*/
52 
53 void 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 
80 uint32_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 
86 static 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 
93 void * 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 
109 void 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 
120 UDEV_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 
138 void 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 
173 int 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 
193 void 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 
203 UTR_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 
220 void 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 
234 ED_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 
255 void 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 /*--------------------------------------------------------------------------*/
275 TD_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 
298 void 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 /*--------------------------------------------------------------------------*/
318 QH_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 
348 void 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 /*--------------------------------------------------------------------------*/
368 qTD_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 
395 void 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 /*--------------------------------------------------------------------------*/
415 iTD_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 
440 void 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 /*--------------------------------------------------------------------------*/
460 siTD_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 
482 void 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 
NuMicro peripheral access layer header file.
void *__dso_handle __attribute__((weak))
Definition: _syscalls.c:35
UDEV_T * udev
Definition: usbh_uac.h:111
USB Host library header file.
#define NULL
NULL pointer.
Definition: M480.h:604