LPCOpen Platform
LPCOpen Platform for NXP LPC Microcontrollers
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
USBMemory.c
Go to the documentation of this file.
1 /*
2  * @brief Memory management for host mode
3  *
4  * @note
5  * Copyright(C) NXP Semiconductors, 2012
6  * All rights reserved.
7  *
8  * @par
9  * Software that is described herein is for illustrative purposes only
10  * which provides customers with programming information regarding the
11  * LPC products. This software is supplied "AS IS" without any warranties of
12  * any kind, and NXP Semiconductors and its licensor disclaim any and
13  * all warranties, express or implied, including all implied warranties of
14  * merchantability, fitness for a particular purpose and non-infringement of
15  * intellectual property rights. NXP Semiconductors assumes no responsibility
16  * or liability for the use of the software, conveys no license or rights under any
17  * patent, copyright, mask work right, or any other intellectual property rights in
18  * or to any products. NXP Semiconductors reserves the right to make changes
19  * in the software without notification. NXP Semiconductors also makes no
20  * representation or warranty that such application will be suitable for the
21  * specified use without further testing or modification.
22  *
23  * @par
24  * Permission to use, copy, modify, and distribute this software and its
25  * documentation is hereby granted, under NXP Semiconductors' and its
26  * licensor's relevant copyrights in the software, without fee, provided that it
27  * is used in conjunction with NXP Semiconductors microcontrollers. This
28  * copyright, permission, and disclaimer notice must appear in all copies of
29  * this code.
30  */
31 
32 #define __INCLUDE_FROM_USB_DRIVER
33 #include "USBMode.h"
34 
35 #ifdef USB_CAN_BE_HOST
36 
37 #include "../../../Common/Common.h"
38 #include "USBTask.h"
39 #include "LPC/HAL/HAL_LPC.h"
40 #include "USBMemory.h"
41 
42 /************************************************************************/
43 /* LOCAL SYMBOL DECLARATIION */
44 /************************************************************************/
45 typedef struct MemBlockInfo_t {
46  uint32_t size :15; // memory size of this block
47  uint32_t isFree :1; // indicate whether this memory block is free or used
48  uint32_t next :16; // offset (from head address) to the next block
49 } sMemBlockInfo, *PMemBlockInfo;
50 
51 /************************************************************************/
52 /* LOCAL DEFINE */
53 /************************************************************************/
54 #define ALIGN_FOUR_BYTES (4) // FIXME only m3 is 1 byte alignment
55 
56 /* FIXME the following dynamic allocation is temporarly */
57 
58 #define HEADER_SIZE (sizeof(sMemBlockInfo))
59 #define HEADER_POINTER(x) ((uint8_t *)x - sizeof(sMemBlockInfo))
60 #define NEXT_BLOCK(x) ( ((PMemBlockInfo) ( ((x)->next==0) ? NULL : head + (x)->next )) )
61 #define LINK_TO_THIS_BLOCK(x) ( ((uint32_t) ((x)-head)) )
62 
64 static uint8_t USB_Mem_Buffer[USBRAM_BUFFER_SIZE] ATTR_ALIGNED(4) __DATA(USBRAM_SECTION);
65 
66 void USB_Memory_Init(uint32_t Memory_Pool_Size)
67 {
68  PMemBlockInfo head = (PMemBlockInfo) USB_Mem_Buffer;
69 
70  head->next = 0;
71  head->size = (Memory_Pool_Size & 0xfffffffc) - HEADER_SIZE ;// align memory size
72  head->isFree = 1;
73 }
74 
75 uint8_t* USB_Memory_Alloc(uint32_t size)
76 {
77  PMemBlockInfo freeBlock, newBlock, blk_ptr = NULL;
78  PMemBlockInfo head = (PMemBlockInfo) USB_Mem_Buffer;
79 
80  /* Align the requested size by 4 bytes */
81  if ((size % ALIGN_FOUR_BYTES) != 0) {
82  size = (((size >> 2) << 2) + ALIGN_FOUR_BYTES);
83  }
84 
85  for (freeBlock = head; freeBlock != NULL; freeBlock = NEXT_BLOCK(freeBlock)) // 1st-fit technique
86  {
87  if ((freeBlock->isFree == 1) && (freeBlock->size >= size))
88  {
89  blk_ptr = freeBlock;
90  break;
91  }
92  }
93 
94  if (blk_ptr == NULL) {
95  return ((uint8_t *) NULL);
96  }
97 
98  if (blk_ptr->size <= HEADER_SIZE + size) // where (blk_size=size | blk_size=size+HEAD) then allocate whole block & do not create freeBlock
99  {
100  newBlock = blk_ptr;
101  //newBlock->size = blk_ptr->size;
102  //newBlock->next = blk_ptr->next;
103  newBlock->isFree = 0;
104  } else {
105  /* Locate empty block at end of found block */
106  freeBlock = (PMemBlockInfo) (((uint8_t *) blk_ptr) + size + HEADER_SIZE);
107  freeBlock->next = blk_ptr->next;
108  freeBlock->size = blk_ptr->size - (HEADER_SIZE + size);
109  freeBlock->isFree = 1;
110 
111  /* Locate new block at start of found block */
112  newBlock = blk_ptr;
113  newBlock->size = size;
114  newBlock->next = LINK_TO_THIS_BLOCK(freeBlock);
115  newBlock->isFree = 0;
116  }
117 
118  return (((uint8_t *) newBlock) + HEADER_SIZE);
119 }
120 
121 void USB_Memory_Free(uint8_t *ptr)
122 {
123  PMemBlockInfo prev;
124  PMemBlockInfo head = (PMemBlockInfo) USB_Mem_Buffer;
125  PMemBlockInfo blk_ptr;
126 
127  if (ptr == NULL)
128  {
129  return;
130  }
131 
132  blk_ptr = (PMemBlockInfo) HEADER_POINTER(ptr);
133 
134  if (blk_ptr->next != 0) // merge with next free block
135  {
136  if (NEXT_BLOCK(blk_ptr)->isFree == 1)
137  {
138  blk_ptr->size = blk_ptr->size + NEXT_BLOCK(blk_ptr)->size + HEADER_SIZE;
139  blk_ptr->next = NEXT_BLOCK(blk_ptr)->next;
140  }
141  }
142 
143  for (prev = head; prev != NULL; prev = NEXT_BLOCK(prev)) // merge with previous free block
144  {
145  if (NEXT_BLOCK(prev) == blk_ptr)
146  {
147  if (prev->isFree == 1)
148  {
149  prev->size = prev->size + blk_ptr->size + HEADER_SIZE;
150  prev->next = blk_ptr->next;
151  blk_ptr = prev;
152  }
153  break;
154  }
155  }
156 
157  blk_ptr->isFree = 1;
158 
159  return;
160 }
161 
162 #endif