1 /* This test is designed to test the ux_utility_memory_.... */
2
3 #include <stdio.h>
4 #include "tx_api.h"
5 #include "ux_api.h"
6 #include "ux_system.h"
7 #include "ux_utility.h"
8
9 #include "ux_host_stack.h"
10 #include "ux_device_stack.h"
11
12 #include "ux_device_class_cdc_acm.h"
13 #include "ux_host_class_cdc_acm.h"
14
15 #include "ux_host_class_dpump.h"
16 #include "ux_device_class_dpump.h"
17
18 #include "ux_host_class_hid.h"
19 #include "ux_device_class_hid.h"
20
21 #include "ux_host_class_storage.h"
22 #include "ux_device_class_storage.h"
23
24 #include "ux_test_dcd_sim_slave.h"
25 #include "ux_test_hcd_sim_host.h"
26 #include "ux_test_utility_sim.h"
27
28
29 /* Define USBX test constants. */
30
31 #define UX_TEST_STACK_SIZE 4096
32 #define UX_TEST_BUFFER_SIZE 2048
33 #define UX_TEST_RUN 1
34 #define UX_TEST_MEMORY_SIZE (64*1024)
35
36 #define LSB(x) ( (x) & 0x00ff)
37 #define MSB(x) (((x) & 0xff00) >> 8)
38
39 /* Configuration descriptor 9 bytes */
40 #define CFG_DESC(wTotalLength, bNumInterfaces, bConfigurationValue)\
41 /* Configuration 1 descriptor 9 bytes */\
42 0x09, 0x02, LSB(wTotalLength), MSB(wTotalLength),\
43 (bNumInterfaces), (bConfigurationValue), 0x00,\
44 0x40, 0x00,
45 #define CFG_DESC_LEN 9
46
47 /* DPUMP interface descriptors. */
48 #define DPUMP_IFC_DESC(ifc, alt, nb_ep) \
49 /* Interface descriptor */\
50 0x09, 0x04, (ifc), (alt), (nb_ep), 0x99, 0x99, 0x99, 0x00,
51
52 #define DPUMP_IFC_EP_DESC(epaddr, eptype, epsize) \
53 /* Endpoint descriptor */\
54 0x07, 0x05, (epaddr), (eptype), LSB(epsize), MSB(epsize), 0x01,
55
56 #define DPUMP_IFC_DESC_ALL_LEN(nb_ep) (9 + (nb_ep) * 7)
57
58 #define CFG_DESC_ALL_LEN (CFG_DESC_LEN + DPUMP_IFC_DESC_ALL_LEN(4))
59
60 #define CFG_DESC_ALL \
61 CFG_DESC(CFG_DESC_ALL_LEN, 1, 1)\
62 DPUMP_IFC_DESC(0, 0, 4)\
63 DPUMP_IFC_EP_DESC(0x81, 2, 64)\
64 DPUMP_IFC_EP_DESC(0x02, 2, 64)\
65 DPUMP_IFC_EP_DESC(0x83, 1, 64)\
66 DPUMP_IFC_EP_DESC(0x84, 3, 64)\
67
68 extern UCHAR ux_test_speed_up_mem_allocate_until_flagged;
69
70 /* Define the counters used in the test application... */
71
72 static ULONG thread_0_counter;
73 static ULONG thread_1_counter;
74 static ULONG error_counter;
75
76 static UCHAR error_callback_ignore = UX_FALSE;
77 static ULONG error_callback_counter;
78
79 static UCHAR buffer[UX_TEST_BUFFER_SIZE];
80
81 /* Define USBX test global variables. */
82
83 static UX_HOST_CLASS *class_driver;
84 static UX_HOST_CLASS_DPUMP *dpump;
85 static UX_SLAVE_CLASS_DPUMP *dpump_slave = UX_NULL;
86
87 static UCHAR device_framework_full_speed[] = {
88
89 /* Device descriptor 18 bytes */
90 0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08,
91 0xec, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
92 0x00, 0x01,
93
94 CFG_DESC_ALL
95 };
96 #define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED sizeof(device_framework_full_speed)
97
98 static UCHAR device_framework_high_speed[] = {
99
100 /* Device descriptor */
101 0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
102 0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02,
103 0x03, 0x01,
104
105 /* Device qualifier descriptor */
106 0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
107 0x01, 0x00,
108
109 CFG_DESC_ALL
110 };
111 #define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED sizeof(device_framework_high_speed)
112
113 /* String Device Framework :
114 Byte 0 and 1 : Word containing the language ID : 0x0904 for US
115 Byte 2 : Byte containing the index of the descriptor
116 Byte 3 : Byte containing the length of the descriptor string
117 */
118
119 static UCHAR string_framework[] = {
120
121 /* Manufacturer string descriptor : Index 1 */
122 0x09, 0x04, 0x01, 0x0c,
123 0x45, 0x78, 0x70, 0x72,0x65, 0x73, 0x20, 0x4c,
124 0x6f, 0x67, 0x69, 0x63,
125
126 /* Product string descriptor : Index 2 */
127 0x09, 0x04, 0x02, 0x0c,
128 0x44, 0x61, 0x74, 0x61, 0x50, 0x75, 0x6d, 0x70,
129 0x44, 0x65, 0x6d, 0x6f,
130
131 /* Serial Number string descriptor : Index 3 */
132 0x09, 0x04, 0x03, 0x04,
133 0x30, 0x30, 0x30, 0x31
134 };
135 #define STRING_FRAMEWORK_LENGTH sizeof(string_framework)
136
137 /* Multiple languages are supported on the device, to add
138 a language besides English, the unicode language code must
139 be appended to the language_id_framework array and the length
140 adjusted accordingly. */
141 static UCHAR language_id_framework[] = {
142
143 /* English. */
144 0x09, 0x04
145 };
146 #define LANGUAGE_ID_FRAMEWORK_LENGTH sizeof(language_id_framework)
147
148 /* Define prototypes for external Host Controller's (HCDs), classes and clients. */
149
150 static VOID ux_test_instance_activate(VOID *dpump_instance);
151 static VOID ux_test_instance_deactivate(VOID *dpump_instance);
152
153 UINT _ux_host_class_dpump_entry(UX_HOST_CLASS_COMMAND *command);
154 UINT ux_hcd_sim_initialize(UX_HCD *hcd);
155 UINT _ux_host_class_dpump_write(UX_HOST_CLASS_DPUMP *dpump, UCHAR * data_pointer,
156 ULONG requested_length, ULONG *actual_length);
157 UINT _ux_host_class_dpump_read (UX_HOST_CLASS_DPUMP *dpump, UCHAR *data_pointer,
158 ULONG requested_length, ULONG *actual_length);
159
160 static TX_THREAD ux_test_thread_simulation_0;
161 static TX_THREAD ux_test_thread_simulation_1;
162 static void ux_test_thread_simulation_0_entry(ULONG);
163 static void ux_test_thread_simulation_1_entry(ULONG);
164
165
166 /* Define the ISR dispatch. */
167
168 extern VOID (*test_isr_dispatch)(void);
169
170
171 /* Prototype for test control return. */
172
173 void test_control_return(UINT status);
174
175 /* Simulator actions. */
176
177 static UX_TEST_HCD_SIM_ACTION endpoint0x83_create_del_skip[] = {
178 /* function, request to match,
179 port action, port status,
180 request action, request EP, request data, request actual length, request status,
181 status, additional callback,
182 no_return */
183 { UX_HCD_CREATE_ENDPOINT, NULL,
184 UX_FALSE, 0,
185 UX_TEST_MATCH_EP, 0x83, UX_NULL, 0, 0,
186 UX_SUCCESS},
187 { UX_HCD_CREATE_ENDPOINT, NULL,
188 UX_FALSE, 0,
189 UX_TEST_MATCH_EP, 0x83, UX_NULL, 0, 0,
190 UX_SUCCESS},
191 { 0 }
192 };
193
194 /* Define the ISR dispatch routine. */
195
test_isr(void)196 static void test_isr(void)
197 {
198
199 /* For further expansion of interrupt-level testing. */
200 }
201
202
error_callback(UINT system_level,UINT system_context,UINT error_code)203 static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
204 {
205
206 error_callback_counter ++;
207
208 if (!error_callback_ignore)
209 {
210 {
211 /* Failed test. */
212 printf("Error #%d, system_level: %d, system_context: %d, error_code: 0x%x\n", __LINE__, system_level, system_context, error_code);
213 // test_control_return(1);
214 }
215 }
216 }
217
break_on_dpump_ready(VOID)218 static UINT break_on_dpump_ready(VOID)
219 {
220
221 UINT status;
222 UX_HOST_CLASS *class;
223
224 /* Find the main data pump container. */
225 status = ux_host_stack_class_get(_ux_system_host_class_dpump_name, &class);
226 if (status != UX_SUCCESS)
227 /* Do not break. */
228 return UX_SUCCESS;
229
230 /* Find the instance. */
231 status = ux_host_stack_class_instance_get(class, 0, (VOID **) &dpump);
232 if (status != UX_SUCCESS)
233 /* Do not break. */
234 return UX_SUCCESS;
235
236 if (dpump -> ux_host_class_dpump_state != UX_HOST_CLASS_INSTANCE_LIVE)
237 /* Do not break. */
238 return UX_SUCCESS;
239
240 return 1;
241 }
242
break_on_removal(VOID)243 static UINT break_on_removal(VOID)
244 {
245
246 UINT status;
247 UX_DEVICE *device;
248
249 status = ux_host_stack_device_get(0, &device);
250 if (status == UX_SUCCESS)
251 /* Do not break. */
252 return UX_SUCCESS;
253
254 return 1;
255 }
256
257
test_ux_device_class_dpump_entry(UX_SLAVE_CLASS_COMMAND * command)258 static UINT test_ux_device_class_dpump_entry(UX_SLAVE_CLASS_COMMAND *command)
259 {
260 switch(command->ux_slave_class_command_request)
261 {
262 case UX_SLAVE_CLASS_COMMAND_INITIALIZE:
263 case UX_SLAVE_CLASS_COMMAND_QUERY:
264 case UX_SLAVE_CLASS_COMMAND_CHANGE:
265 return UX_SUCCESS;
266
267 default:
268 return UX_NO_CLASS_MATCH;
269 }
270 }
271
test_ux_host_class_dpump_entry(UX_HOST_CLASS_COMMAND * command)272 static UINT test_ux_host_class_dpump_entry(UX_HOST_CLASS_COMMAND *command)
273 {
274 switch (command -> ux_host_class_command_request)
275 {
276 case UX_HOST_CLASS_COMMAND_QUERY:
277 default:
278 return _ux_host_class_dpump_entry(command);
279 }
280 }
281
282 /* Define what the initial system looks like. */
283
284 #ifdef CTEST
test_application_define(void * first_unused_memory)285 void test_application_define(void *first_unused_memory)
286 #else
287 void usbx_ux_utility_memory_test_application_define(void *first_unused_memory)
288 #endif
289 {
290
291 UINT status;
292 CHAR *stack_pointer;
293 CHAR *memory_pointer;
294 CHAR *rpool_start;
295 CHAR *cpool_start;
296 ULONG rpool_size;
297 ULONG cpool_size;
298 ULONG rpool_free[2];
299 ULONG cpool_free[2];
300 VOID *ptr;
301 UINT n, i, j;
302 const CHAR flags[] = {
303 UX_REGULAR_MEMORY, UX_CACHE_SAFE_MEMORY, 0xFF
304 };
305 const CHAR expect_error[] = {
306 UX_FALSE, UX_FALSE, UX_TRUE
307 };
308 const ULONG aligns[] = {
309 UX_NO_ALIGN, /* 0 */
310 UX_ALIGN_MIN, /* 0xf */
311 UX_SAFE_ALIGN, /* 0xffffffff */
312 UX_ALIGN_32,
313 UX_ALIGN_64,
314 UX_ALIGN_128,
315 UX_ALIGN_256,
316 UX_ALIGN_512,
317 UX_ALIGN_1024,
318 UX_ALIGN_2048,
319 UX_ALIGN_4096,
320 UX_MAX_SCATTER_GATHER_ALIGNMENT,
321 };
322
323 /* Inform user. */
324 printf("Running ux_utility_memory_... Test.................................. ");
325
326 /* Initialize the free memory pointer. */
327 stack_pointer = (CHAR *) first_unused_memory;
328 memory_pointer = stack_pointer + (UX_TEST_STACK_SIZE * 2);
329
330 for (n = 0; n < 3; n ++)
331 {
332
333 switch(n)
334 {
335 case 0:
336 rpool_start = memory_pointer;
337 rpool_size = UX_TEST_MEMORY_SIZE;
338 cpool_start = memory_pointer + UX_TEST_MEMORY_SIZE;
339 cpool_size = UX_TEST_MEMORY_SIZE;
340 break;
341 case 1:
342 rpool_start = memory_pointer + UX_TEST_MEMORY_SIZE;
343 rpool_size = UX_TEST_MEMORY_SIZE;
344 cpool_start = memory_pointer;
345 cpool_size = UX_TEST_MEMORY_SIZE;
346 break;
347 default:
348 rpool_start = memory_pointer;
349 rpool_size = UX_TEST_MEMORY_SIZE * 2;
350 cpool_start = UX_NULL;
351 cpool_size = 0;
352 }
353
354 /* Initialize USBX Memory. */
355 status = ux_system_initialize(rpool_start, rpool_size, cpool_start, cpool_size);
356
357 /* Check for error. */
358 if (status != UX_SUCCESS)
359 {
360
361 printf("ERROR #%d.%d\n", __LINE__, n);
362 test_control_return(1);
363 }
364
365 /* Register the error callback. */
366 _ux_utility_error_callback_register(error_callback);
367 for (j = 0; j < sizeof(aligns)/sizeof(aligns[0]); j ++)
368 {
369 /* Save memory level. */
370 rpool_free[0] = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
371 cpool_free[0] = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_CACHE_SAFE] -> ux_byte_pool_available;
372
373 error_callback_ignore = UX_TRUE;
374
375 /* Allocate all. */
376 ux_test_utility_sim_mem_allocate_until_align_flagged(0, aligns[j], UX_REGULAR_MEMORY);
377 ux_test_utility_sim_mem_allocate_until_align_flagged(0, aligns[j], UX_CACHE_SAFE_MEMORY);
378
379 rpool_free[1] = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
380 cpool_free[1] = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_CACHE_SAFE] -> ux_byte_pool_available;
381
382 /* Check. */
383 if (rpool_free[0] <= rpool_free[1])
384 {
385
386 printf("ERROR #%d.%d.%d: Expect regular pool level down\n", __LINE__, n, j);
387 error_counter ++;
388 }
389
390 if (cpool_free[0] <= cpool_free[1] && cpool_start)
391 {
392
393 printf("ERROR #%d.%d.%d: Expect cache safe pool level down\n", __LINE__, n, j);
394 error_counter ++;
395 }
396
397 error_callback_ignore = UX_FALSE;
398
399 /* Free All. */
400 ux_test_utility_sim_mem_free_all_flagged(UX_REGULAR_MEMORY);
401 ux_test_utility_sim_mem_free_all_flagged(UX_CACHE_SAFE_MEMORY);
402
403 rpool_free[1] = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
404 cpool_free[1] = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_CACHE_SAFE] -> ux_byte_pool_available;
405
406 /* Check. */
407 if (rpool_free[0] != rpool_free[1])
408 {
409
410 printf("ERROR #%d.%d.%d: Regular pool level diff %lu -> %lu\n", __LINE__, n, j, rpool_free[0], rpool_free[1]);
411 error_counter ++;
412 }
413 if (cpool_free[0] != cpool_free[1])
414 {
415
416 printf("ERROR #%d.%d.%d: Cache safe pool level diff %lu -> %lu\n", __LINE__, n, j, cpool_free[0], cpool_free[1]);
417 error_counter ++;
418 }
419
420 for (i = 0; i < sizeof(flags); i ++)
421 {
422
423 /* Save pool level. */
424 rpool_free[0] = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
425 cpool_free[0] = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_CACHE_SAFE] -> ux_byte_pool_available;
426
427 /* Error callback setting. */
428 error_callback_ignore = expect_error[i];
429
430 /* Allocate. */
431 ptr = ux_utility_memory_allocate(aligns[j], flags[i], 8);
432
433 /* Error case. */
434 if (expect_error[i])
435 {
436
437 if (ptr != UX_NULL)
438 {
439
440 printf("ERROR #%d.%d.%d.%d: Expect fail\n", __LINE__, n, j, i);
441 error_counter ++;
442 }
443 }
444 else
445 {
446
447 /* No error. */
448 if (ptr == UX_NULL)
449 {
450
451 printf("ERROR #%d.%d.%d.%d: memory allocate fail\n", __LINE__, n, j, i);
452 error_counter ++;
453 }
454
455 /* Save pool level. */
456 rpool_free[1] = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
457 cpool_free[1] = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_CACHE_SAFE] -> ux_byte_pool_available;
458
459 if (!(rpool_free[1] < rpool_free[0] || cpool_free[1] < cpool_free[0]))
460 {
461
462 printf("ERROR #%d.%d.%d.%d: Expect pool level down\n", __LINE__, n, j, i);
463 error_counter ++;
464 }
465
466 ux_utility_memory_free(ptr);
467 }
468
469 /* Save pool level. */
470 rpool_free[1] = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
471 cpool_free[1] = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_CACHE_SAFE] -> ux_byte_pool_available;
472
473 if (rpool_free[0] != rpool_free[1])
474 {
475
476 printf("ERROR #%d.%d.%d.%d: Expect no regular pool change but %lu -> %lu\n", __LINE__, n, j, i, rpool_free[0], rpool_free[1]);
477 error_counter ++;
478 }
479 if (cpool_free[0] != cpool_free[1])
480 {
481
482 printf("ERROR #%d.%d.%d.%d: Expect no cache safe pool change but %lu -> %lu\n", __LINE__, n, j, i, cpool_free[0], cpool_free[1]);
483 error_counter ++;
484 }
485
486 }
487 }
488
489 /* Uninitialize */
490 ux_system_uninitialize();
491
492 }
493
494 /* Test the case where there isn't enough left over memory for a new memory block after needing to do an alignment. */
495 {
496 static UCHAR dummy_memory[1024];
497
498 ALIGN_TYPE int_ptr = (ALIGN_TYPE) dummy_memory;
499
500 int_ptr += 2*sizeof(UX_MEMORY_BLOCK);
501
502 int_ptr += 31;
503 int_ptr &= ~(31);
504
505 int_ptr += 1;
506 int_ptr -= sizeof(UX_MEMORY_BLOCK);
507
508 UX_MEMORY_BLOCK *dummy_block = (UX_MEMORY_BLOCK *) (int_ptr - sizeof(UX_MEMORY_BLOCK));
509 // dummy_block->ux_memory_block_next = UX_NULL;
510 // dummy_block->ux_memory_block_previous = UX_NULL;
511 // dummy_block->ux_memory_block_size = (16 + 8 + 31 + ((sizeof(UCHAR *)) + (sizeof(ALIGN_TYPE))) + 1;
512 // dummy_block->ux_memory_block_status = UX_MEMORY_UNUSED;
513
514 // _ux_system->ux_system_regular_memory_pool_start = dummy_block;
515 // _ux_system->ux_system_regular_memory_pool_size = dummy_block->ux_memory_block_size + sizeof(UX_MEMORY_BLOCK);
516 ULONG dummy_block_size = (16 + 8 + 31 + sizeof(UX_MEMORY_BLOCK)) + 1;
517 _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_start = (UCHAR*)dummy_block;
518 _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available = dummy_block_size;
519
520 ux_utility_memory_allocate(31, UX_REGULAR_MEMORY, 16);
521 }
522
523 /* Test allocate memory of size 0. */
524 rpool_free[0] = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
525 ptr = _ux_utility_memory_allocate_mulc_safe(UX_NO_ALIGN, UX_REGULAR_MEMORY, 1, 0);
526 if (ptr)
527 {
528 _ux_utility_memory_free(ptr);
529 }
530 if (rpool_free[0] != _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available)
531 {
532 printf("ERROR %d : expect no pool level change but %ld -> %ld\n", __LINE__, rpool_free[0], _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available);
533 error_counter ++;
534 }
535
536 /* Create the simulation thread. */
537 status = tx_thread_create(&ux_test_thread_simulation_0, "test simulation", ux_test_thread_simulation_0_entry, 0,
538 stack_pointer, UX_TEST_STACK_SIZE,
539 20, 20, 1, TX_AUTO_START);
540
541 /* Check for error. */
542 if (status != TX_SUCCESS)
543 {
544
545 printf("ERROR #%d\n", __LINE__);
546 test_control_return(1);
547 }
548 }
549
ux_test_thread_simulation_0_entry(ULONG arg)550 static void ux_test_thread_simulation_0_entry(ULONG arg)
551 {
552 /* Sleep for a tick to make sure everything is complete. */
553 tx_thread_sleep(1);
554
555 /* Check for errors from other threads. */
556 if (error_counter)
557 {
558
559 /* Test error. */
560 printf("ERROR #%d: total %ld errors\n", __LINE__, error_counter);
561 test_control_return(1);
562 }
563 else
564 {
565
566 /* Successful test. */
567 printf("SUCCESS!\n");
568 test_control_return(0);
569 }
570 }