| LPCOpen Platform v1.03 LPCOpen Platform for NXP LPC Microcontrollers

- Main Page
- Modules
- Data Structures
- Files
- Related Pages

- File List
- Globals

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 "HAL/HAL.h"
40 #include "USBMemory.h"
41
42 /************************************************************************/
43 /* LOCAL SYMBOL DECLARATIION */
44 /************************************************************************/
45 #define TEST_NEW_ALLOC 0
46
47 #if TEST_NEW_ALLOC
48
49 typedef struct MemBlockInfo_t {
50 uint32_t size :15; // memory size of this block
51 uint32_t type :2; // indicate whether this memory block is free, pad or used
52 uint32_t next :15; // offset (from head address) to the next block
53 } sMemBlockInfo, *PMemBlockInfo;
54
55 typedef enum
56 {
57 MEM_FREE = 0,
58 MEM_PAD,
59 MEM_USED,
60 }enMemBlockType;
61
62 #else
63
64 typedef struct MemBlockInfo_t {
65 uint32_t size :15; // memory size of this block
66 uint32_t isFree :1; // indicate whether this memory block is free or used
67 uint32_t next :16; // offset (from head address) to the next block
68 } sMemBlockInfo, *PMemBlockInfo;
69
70 #endif
71 /************************************************************************/
72 /* LOCAL DEFINE */
73 /************************************************************************/
74 #define ALIGN_FOUR_BYTES (4) // FIXME only m3 is 1 byte alignment
75
76 /* FIXME the following dynamic allocation is temporarly */
77
78 #define HEADER_SIZE (sizeof(sMemBlockInfo))
79 #define HEADER_POINTER(x) ((uint8_t *)x - sizeof(sMemBlockInfo))
80 #define NEXT_BLOCK(x) ((PMemBlockInfo) ( ((x)->next==0) ? 0 : ((uint32_t)head +(x)->next) ))
81 #define LINK_TO_THIS_BLOCK(x) (((uint32_t)(x))-((uint32_t)head))
82
83 PRAGMA_ALIGN_4
84 static uint8_t USB_Mem_Buffer[USBRAM_BUFFER_SIZE] ATTR_ALIGNED(4) __BSS(USBRAM_SECTION);
85
86 void USB_Memory_Init(uint32_t Memory_Pool_Size)
87 {
88 PMemBlockInfo head = (PMemBlockInfo) USB_Mem_Buffer;
89
90 head->next = 0;
91 head->size = (Memory_Pool_Size & 0xfffffffc) - HEADER_SIZE ;// align memory size
92 #if TEST_NEW_ALLOC
93 head->type = MEM_FREE;
94 #else
95 head->isFree = 1;
96 #endif
97 }
98
99 uint8_t* USB_Memory_Alloc(uint32_t size, uint32_t num_aligned_bytes)
100 {
101 PMemBlockInfo freeBlock=NULL, newBlock, blk_ptr = NULL;
102 PMemBlockInfo head = (PMemBlockInfo) USB_Mem_Buffer;
103
104 #if TEST_NEW_ALLOC
105 for (blk_ptr = head; blk_ptr != NULL; blk_ptr = NEXT_BLOCK(blk_ptr)) // 1st-fit technique
106 {
107 if (((blk_ptr->type == MEM_FREE)||(blk_ptr->type == MEM_PAD)) && (blk_ptr->size >= size))
108 {
109 /* Filter by requested size */
110 if (blk_ptr->size <= HEADER_SIZE + size) // where (blk_size=size | blk_size=size+HEAD) then allocate whole block & do not create freeBlock
111 {
112 blk_ptr->next = 0;
113 blk_ptr->type = MEM_USED;
114 } else {
115 /* Locate empty block at end of found block */
116 freeBlock = (PMemBlockInfo) (((uint32_t) blk_ptr) + size + HEADER_SIZE);
117 freeBlock->next = blk_ptr->next;
118 freeBlock->size = blk_ptr->size - (HEADER_SIZE + size);
119 freeBlock->type = blk_ptr->type;
120
121 /* Locate new block at start of found block */
122 blk_ptr->size = size;
123 blk_ptr->next = LINK_TO_THIS_BLOCK(freeBlock);
124 blk_ptr->type = MEM_USED;
125 }
126 /* Filter by requested alignment*/
127 if(num_aligned_bytes > 0)
128 {
129 uint32_t pad_size = (((uint32_t)blk_ptr) + HEADER_SIZE) % num_aligned_bytes;
130 if(pad_size == 0) break; //block found
131 else //not fit alignment
132 if(blk_ptr->next != 0) //break if this is the last block in chain
133 {
134 uint32_t padBlkSize;
135
136 if((num_aligned_bytes - pad_size) >= HEADER_SIZE)
137 padBlkSize = num_aligned_bytes - pad_size - HEADER_SIZE;
138 else
139 padBlkSize = 2*num_aligned_bytes - pad_size - HEADER_SIZE;
140
141 if(padBlkSize > freeBlock->size) //not enough space to create new pad
142 {
143 blk_ptr->next = freeBlock->next;
144 blk_ptr->size = freeBlock->size + HEADER_SIZE + size;
145 blk_ptr->type = MEM_PAD;
146 }
147 else //there is space for new pad
148 {
149 newBlock = (PMemBlockInfo) (((uint32_t) blk_ptr) + HEADER_SIZE + padBlkSize);
150 newBlock->next = freeBlock->next;
151 newBlock->type = freeBlock->type;
152 newBlock->size = freeBlock->size + HEADER_SIZE + size - padBlkSize;
153
154 blk_ptr->size = padBlkSize;
155 blk_ptr->next = LINK_TO_THIS_BLOCK(newBlock);
156 blk_ptr->type = MEM_PAD;
157 }
158 }
159 }
160 else if(blk_ptr->type == MEM_USED) break;
161 }
162 }
163
164 if (blk_ptr == NULL) {
165 return ((uint8_t *) NULL);
166 }
167
168 return (((uint8_t *) blk_ptr) + HEADER_SIZE);
169
170 #else
171 /* Align the requested size by 4 bytes */
172 if ((size % ALIGN_FOUR_BYTES) != 0) {
173 size = (((size >> 2) << 2) + ALIGN_FOUR_BYTES);
174 }
175
176 for (freeBlock = head; freeBlock != NULL; freeBlock = NEXT_BLOCK(freeBlock)) // 1st-fit technique
177 {
178 if ((freeBlock->isFree == 1) && (freeBlock->size >= size))
179 {
180 blk_ptr = freeBlock;
181 break;
182 }
183 }
184
185 if (blk_ptr == NULL) {
186 return ((uint8_t *) NULL);
187 }
188
189 if (blk_ptr->size <= HEADER_SIZE + size) // where (blk_size=size | blk_size=size+HEAD) then allocate whole block & do not create freeBlock
190 {
191 newBlock = blk_ptr;
192 //newBlock->size = blk_ptr->size;
193 //newBlock->next = blk_ptr->next;
194 newBlock->isFree = 0;
195 } else {
196 /* Locate empty block at end of found block */
197 freeBlock = (PMemBlockInfo) (((uint8_t *) blk_ptr) + size + HEADER_SIZE);
198 freeBlock->next = blk_ptr->next;
199 freeBlock->size = blk_ptr->size - (HEADER_SIZE + size);
200 freeBlock->isFree = 1;
201
202 /* Locate new block at start of found block */
203 newBlock = blk_ptr;
204 newBlock->size = size;
205 newBlock->next = LINK_TO_THIS_BLOCK(freeBlock);
206 newBlock->isFree = 0;
207 }
208
209 return (((uint8_t *) newBlock) + HEADER_SIZE);
210 #endif
211 }
212
213 void USB_Memory_Free(uint8_t *ptr)
214 {
215 PMemBlockInfo prev;
216 PMemBlockInfo head = (PMemBlockInfo) USB_Mem_Buffer;
217 PMemBlockInfo blk_ptr;
218
219 if (ptr == NULL)
220 {
221 return;
222 }
223
224 blk_ptr = (PMemBlockInfo) HEADER_POINTER(ptr);
225
226 #if TEST_NEW_ALLOC
227
228 bool being_pad = false;
229 if (blk_ptr->next != 0) // merge with next free block
230 {
231 if ((NEXT_BLOCK(blk_ptr)->type == MEM_FREE)||(NEXT_BLOCK(blk_ptr)->type == MEM_PAD))
232 {
233 blk_ptr->size = blk_ptr->size + NEXT_BLOCK(blk_ptr)->size + HEADER_SIZE;
234 blk_ptr->next = NEXT_BLOCK(blk_ptr)->next;
235 blk_ptr->type = NEXT_BLOCK(blk_ptr)->type;
236 }
237 else being_pad = true;
238 }
239
240 for (prev = head; prev != NULL; prev = NEXT_BLOCK(prev)) // merge with previous free block
241 {
242 if (NEXT_BLOCK(prev) == blk_ptr)
243 {
244 if ((prev->type == MEM_FREE)||(prev->type == MEM_PAD))
245 {
246 prev->size = prev->size + blk_ptr->size + HEADER_SIZE;
247 prev->next = blk_ptr->next;
248 }
249 else if(being_pad == true) // prev&next blocks are used
250 blk_ptr->type = MEM_PAD;
251
252 break;
253 }
254 }
255
256 #else
257 if (blk_ptr->next != 0) // merge with next free block
258 {
259 if (NEXT_BLOCK(blk_ptr)->isFree == 1)
260 {
261 blk_ptr->size = blk_ptr->size + NEXT_BLOCK(blk_ptr)->size + HEADER_SIZE;
262 blk_ptr->next = NEXT_BLOCK(blk_ptr)->next;
263 }
264 }
265
266 for (prev = head; prev != NULL; prev = NEXT_BLOCK(prev)) // merge with previous free block
267 {
268 if (NEXT_BLOCK(prev) == blk_ptr)
269 {
270 if (prev->isFree == 1)
271 {
272 prev->size = prev->size + blk_ptr->size + HEADER_SIZE;
273 prev->next = blk_ptr->next;
274 blk_ptr = prev;
275 }
276 break;
277 }
278 }
279
280 blk_ptr->isFree = 1;
281
282 #endif
283 return;
284 }
285
286 #endif