| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503 |
- /**************************************************************************//**
- * @file mem_alloc.c
- * @version V1.10
- * @brief USB host library memory allocation functions.
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * @copyright (C) 2017 Nuvoton Technology Corp. All rights reserved.
- *****************************************************************************/
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "NuMicro.h"
- #include "usb.h"
- /// @cond HIDDEN_SYMBOLS
- //#define MEM_DEBUG
- #ifdef MEM_DEBUG
- #define mem_debug rt_kprintf
- #else
- #define mem_debug(...)
- #endif
- #ifdef __ICCARM__
- #pragma data_alignment=32
- static uint8_t _mem_pool[MEM_POOL_UNIT_NUM][MEM_POOL_UNIT_SIZE];
- #else
- static uint8_t _mem_pool[MEM_POOL_UNIT_NUM][MEM_POOL_UNIT_SIZE] __attribute__((aligned(32)));
- #endif
- static uint8_t _unit_used[MEM_POOL_UNIT_NUM];
- static volatile int _usbh_mem_used;
- static volatile int _usbh_max_mem_used;
- static volatile int _mem_pool_used;
- UDEV_T * g_udev_list;
- uint8_t _dev_addr_pool[128];
- static volatile int _device_addr;
- static int _sidx = 0;;
- /*--------------------------------------------------------------------------*/
- /* Memory alloc/free recording */
- /*--------------------------------------------------------------------------*/
- void usbh_memory_init(void)
- {
- if (sizeof(TD_T) > MEM_POOL_UNIT_SIZE)
- {
- USB_error("TD_T - MEM_POOL_UNIT_SIZE too small!\n");
- while (1);
- }
- if (sizeof(ED_T) > MEM_POOL_UNIT_SIZE)
- {
- USB_error("ED_T - MEM_POOL_UNIT_SIZE too small!\n");
- while (1);
- }
- _usbh_mem_used = 0L;
- _usbh_max_mem_used = 0L;
- memset(_unit_used, 0, sizeof(_unit_used));
- _mem_pool_used = 0;
- _sidx = 0;
- g_udev_list = NULL;
- memset(_dev_addr_pool, 0, sizeof(_dev_addr_pool));
- _device_addr = 1;
- }
- uint32_t usbh_memory_used(void)
- {
- rt_kprintf("USB static memory: %d/%d, heap used: %d\n", _mem_pool_used, MEM_POOL_UNIT_NUM, _usbh_mem_used);
- return _usbh_mem_used;
- }
- static void memory_counter(int size)
- {
- _usbh_mem_used += size;
- if (_usbh_mem_used > _usbh_max_mem_used)
- _usbh_max_mem_used = _usbh_mem_used;
- }
- void * usbh_alloc_mem(int size)
- {
- void *p;
- p = malloc(size);
- if (p == NULL)
- {
- USB_error("usbh_alloc_mem failed! %d\n", size);
- return NULL;
- }
- memset(p, 0, size);
- memory_counter(size);
- return p;
- }
- void usbh_free_mem(void *p, int size)
- {
- free(p);
- memory_counter(0-size);
- }
- /*--------------------------------------------------------------------------*/
- /* USB device allocate/free */
- /*--------------------------------------------------------------------------*/
- UDEV_T * alloc_device(void)
- {
- UDEV_T *udev;
- udev = malloc(sizeof(*udev));
- if (udev == NULL)
- {
- USB_error("alloc_device failed!\n");
- return NULL;
- }
- memset(udev, 0, sizeof(*udev));
- memory_counter(sizeof(*udev));
- udev->cur_conf = -1; /* must! used to identify the first SET CONFIGURATION */
- udev->next = g_udev_list; /* chain to global device list */
- g_udev_list = udev;
- return udev;
- }
- void free_device(UDEV_T *udev)
- {
- UDEV_T *d;
- if (udev == NULL)
- return;
- if (udev->cfd_buff != NULL)
- usbh_free_mem(udev->cfd_buff, MAX_DESC_BUFF_SIZE);
- /*
- * Remove it from the global device list
- */
- if (g_udev_list == udev)
- {
- g_udev_list = g_udev_list->next;
- }
- else
- {
- d = g_udev_list;
- while (d != NULL)
- {
- if (d->next == udev)
- {
- d->next = udev->next;
- break;
- }
- d = d->next;
- }
- }
- free(udev);
- memory_counter(-sizeof(*udev));
- }
- int alloc_dev_address(void)
- {
- _device_addr++;
- if (_device_addr >= 128)
- _device_addr = 1;
- while (1)
- {
- if (_dev_addr_pool[_device_addr] == 0)
- {
- _dev_addr_pool[_device_addr] = 1;
- return _device_addr;
- }
- _device_addr++;
- if (_device_addr >= 128)
- _device_addr = 1;
- }
- }
- void free_dev_address(int dev_addr)
- {
- if (dev_addr < 128)
- _dev_addr_pool[dev_addr] = 0;
- }
- /*--------------------------------------------------------------------------*/
- /* UTR (USB Transfer Request) allocate/free */
- /*--------------------------------------------------------------------------*/
- UTR_T * alloc_utr(UDEV_T *udev)
- {
- UTR_T *utr;
- utr = malloc(sizeof(*utr));
- if (utr == NULL)
- {
- USB_error("alloc_utr failed!\n");
- return NULL;
- }
- memory_counter(sizeof(*utr));
- memset(utr, 0, sizeof(*utr));
- utr->udev = udev;
- mem_debug("[ALLOC] [UTR] - 0x%x\n", (int)utr);
- return utr;
- }
- void free_utr(UTR_T *utr)
- {
- if (utr == NULL)
- return;
- mem_debug("[FREE] [UTR] - 0x%x\n", (int)utr);
- free(utr);
- memory_counter(0-(int)sizeof(*utr));
- }
- /*--------------------------------------------------------------------------*/
- /* OHCI ED allocate/free */
- /*--------------------------------------------------------------------------*/
- ED_T * alloc_ohci_ED(void)
- {
- int i;
- ED_T *ed;
- for (i = 0; i < MEM_POOL_UNIT_NUM; i++)
- {
- if (_unit_used[i] == 0)
- {
- _unit_used[i] = 1;
- _mem_pool_used++;
- ed = (ED_T *)&_mem_pool[i];
- memset(ed, 0, sizeof(*ed));
- mem_debug("[ALLOC] [ED] - 0x%x\n", (int)ed);
- return ed;
- }
- }
- USB_error("alloc_ohci_ED failed!\n");
- return NULL;
- }
- void free_ohci_ED(ED_T *ed)
- {
- int i;
- for (i = 0; i < MEM_POOL_UNIT_NUM; i++)
- {
- if ((uint32_t)&_mem_pool[i] == (uint32_t)ed)
- {
- mem_debug("[FREE] [ED] - 0x%x\n", (int)ed);
- _unit_used[i] = 0;
- _mem_pool_used--;
- return;
- }
- }
- USB_debug("free_ohci_ED - not found! (ignored in case of multiple UTR)\n");
- }
- /*--------------------------------------------------------------------------*/
- /* OHCI TD allocate/free */
- /*--------------------------------------------------------------------------*/
- TD_T * alloc_ohci_TD(UTR_T *utr)
- {
- int i;
- TD_T *td;
- for (i = 0; i < MEM_POOL_UNIT_NUM; i++)
- {
- if (_unit_used[i] == 0)
- {
- _unit_used[i] = 1;
- _mem_pool_used++;
- td = (TD_T *)&_mem_pool[i];
- memset(td, 0, sizeof(*td));
- td->utr = utr;
- mem_debug("[ALLOC] [TD] - 0x%x\n", (int)td);
- return td;
- }
- }
- USB_error("alloc_ohci_TD failed!\n");
- return NULL;
- }
- void free_ohci_TD(TD_T *td)
- {
- int i;
- for (i = 0; i < MEM_POOL_UNIT_NUM; i++)
- {
- if ((uint32_t)&_mem_pool[i] == (uint32_t)td)
- {
- mem_debug("[FREE] [TD] - 0x%x\n", (int)td);
- _unit_used[i] = 0;
- _mem_pool_used--;
- return;
- }
- }
- USB_error("free_ohci_TD - not found!\n");
- }
- /*--------------------------------------------------------------------------*/
- /* EHCI QH allocate/free */
- /*--------------------------------------------------------------------------*/
- QH_T * alloc_ehci_QH(void)
- {
- int i;
- QH_T *qh = NULL;
- for (i = (_sidx+1) % MEM_POOL_UNIT_NUM; i != _sidx; i = (i+1) % MEM_POOL_UNIT_NUM)
- {
- if (_unit_used[i] == 0)
- {
- _unit_used[i] = 1;
- _sidx = i;
- _mem_pool_used++;
- qh = (QH_T *)&_mem_pool[i];
- memset(qh, 0, sizeof(*qh));
- mem_debug("[ALLOC] [QH] - 0x%x\n", (int)qh);
- break;
- }
- }
- if (qh == NULL)
- {
- USB_error("alloc_ehci_QH failed!\n");
- return NULL;
- }
- qh->Curr_qTD = QTD_LIST_END;
- qh->OL_Next_qTD = QTD_LIST_END;
- qh->OL_Alt_Next_qTD = QTD_LIST_END;
- qh->OL_Token = QTD_STS_HALT;
- return qh;
- }
- void free_ehci_QH(QH_T *qh)
- {
- int i;
- for (i = 0; i < MEM_POOL_UNIT_NUM; i++)
- {
- if ((uint32_t)&_mem_pool[i] == (uint32_t)qh)
- {
- mem_debug("[FREE] [QH] - 0x%x\n", (int)qh);
- _unit_used[i] = 0;
- _mem_pool_used--;
- return;
- }
- }
- USB_debug("free_ehci_QH - not found! (ignored in case of multiple UTR)\n");
- }
- /*--------------------------------------------------------------------------*/
- /* EHCI qTD allocate/free */
- /*--------------------------------------------------------------------------*/
- qTD_T * alloc_ehci_qTD(UTR_T *utr)
- {
- int i;
- qTD_T *qtd;
- for (i = (_sidx+1) % MEM_POOL_UNIT_NUM; i != _sidx; i = (i+1) % MEM_POOL_UNIT_NUM)
- {
- if (_unit_used[i] == 0)
- {
- _unit_used[i] = 1;
- _sidx = i;
- _mem_pool_used++;
- qtd = (qTD_T *)&_mem_pool[i];
- memset(qtd, 0, sizeof(*qtd));
- qtd->Next_qTD = QTD_LIST_END;
- qtd->Alt_Next_qTD = QTD_LIST_END;
- 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.
- qtd->utr = utr;
- mem_debug("[ALLOC] [qTD] - 0x%x\n", (int)qtd);
- return qtd;
- }
- }
- USB_error("alloc_ehci_qTD failed!\n");
- return NULL;
- }
- void free_ehci_qTD(qTD_T *qtd)
- {
- int i;
- for (i = 0; i < MEM_POOL_UNIT_NUM; i++)
- {
- if ((uint32_t)&_mem_pool[i] == (uint32_t)qtd)
- {
- mem_debug("[FREE] [qTD] - 0x%x\n", (int)qtd);
- _unit_used[i] = 0;
- _mem_pool_used--;
- return;
- }
- }
- USB_error("free_ehci_qTD 0x%x - not found!\n", (int)qtd);
- }
- /*--------------------------------------------------------------------------*/
- /* EHCI iTD allocate/free */
- /*--------------------------------------------------------------------------*/
- iTD_T * alloc_ehci_iTD(void)
- {
- int i;
- iTD_T *itd;
- for (i = (_sidx+1) % MEM_POOL_UNIT_NUM; i != _sidx; i = (i+1) % MEM_POOL_UNIT_NUM)
- {
- if (i+2 >= MEM_POOL_UNIT_NUM)
- continue;
- if ((_unit_used[i] == 0) && (_unit_used[i+1] == 0))
- {
- _unit_used[i] = _unit_used[i+1] = 1;
- _sidx = i+1;
- _mem_pool_used += 2;
- itd = (iTD_T *)&_mem_pool[i];
- memset(itd, 0, sizeof(*itd));
- mem_debug("[ALLOC] [iTD] - 0x%x\n", (int)itd);
- return itd;
- }
- }
- USB_error("alloc_ehci_iTD failed!\n");
- return NULL;
- }
- void free_ehci_iTD(iTD_T *itd)
- {
- int i;
- for (i = 0; i+1 < MEM_POOL_UNIT_NUM; i++)
- {
- if ((uint32_t)&_mem_pool[i] == (uint32_t)itd)
- {
- mem_debug("[FREE] [iTD] - 0x%x\n", (int)itd);
- _unit_used[i] = _unit_used[i+1] = 0;
- _mem_pool_used -= 2;
- return;
- }
- }
- USB_error("free_ehci_iTD 0x%x - not found!\n", (int)itd);
- }
- /*--------------------------------------------------------------------------*/
- /* EHCI iTD allocate/free */
- /*--------------------------------------------------------------------------*/
- siTD_T * alloc_ehci_siTD(void)
- {
- int i;
- siTD_T *sitd;
- for (i = (_sidx+1) % MEM_POOL_UNIT_NUM; i != _sidx; i = (i+1) % MEM_POOL_UNIT_NUM)
- {
- if (_unit_used[i] == 0)
- {
- _unit_used[i] = 1;
- _sidx = i;
- _mem_pool_used ++;
- sitd = (siTD_T *)&_mem_pool[i];
- memset(sitd, 0, sizeof(*sitd));
- mem_debug("[ALLOC] [siTD] - 0x%x\n", (int)sitd);
- return sitd;
- }
- }
- USB_error("alloc_ehci_siTD failed!\n");
- return NULL;
- }
- void free_ehci_siTD(siTD_T *sitd)
- {
- int i;
- for (i = 0; i < MEM_POOL_UNIT_NUM; i++)
- {
- if ((uint32_t)&_mem_pool[i] == (uint32_t)sitd)
- {
- mem_debug("[FREE] [siTD] - 0x%x\n", (int)sitd);
- _unit_used[i] = 0;
- _mem_pool_used--;
- return;
- }
- }
- USB_error("free_ehci_siTD 0x%x - not found!\n", (int)sitd);
- }
- /// @endcond HIDDEN_SYMBOLS
- /*** (C) COPYRIGHT 2017 Nuvoton Technology Corp. ***/
|