[processor-sdk/open-amp.git] / apps / tests / master / nucleus / func_test_suite / nucleus_nucleusbm / func_test_suite.c
1 /* This is a test demonstration application that tests usage of remoteproc
2 and rpmsg APIs. This application is meant to run on the master CPU running Nucleus
3 and showcases booting of two sub-sequent remote firmware cycles using remoteproc and
4 IPC with remote firmware using rpmsg; 1. It brings up a remote Nucleus based remote
5 firmware which can respond to test calls, 2. It brings up a baremetal based
6 remote firmware which can respond to test calls. Master app executes tests to validate
7 the rpmsg APIs and shutsdown the core once the test has been completed.*/
9 /* Including required headers */
11 #include <stdio.h>
12 #include <string.h>
13 #include <stdlib.h>
14 #include "open_amp.h"
15 #include "test_suite.h"
16 #include "nucleus.h"
17 #include "kernel/nu_kernel.h"
20 /* Prototypes */
21 static void Main_Task_Entry( UNSIGNED argc , VOID *argv );
23 /* Application provided callbacks */
24 void rpmsg_channel_created( struct rpmsg_channel *rp_chnl );
25 void rpmsg_channel_deleted( struct rpmsg_channel *rp_chnl );
26 void rpmsg_read_default_cb( struct rpmsg_channel *rp_chnl , void *data , int len , void * pric ,
27 unsigned long src );
28 void rpmsg_read_ept1_cb( struct rpmsg_channel *rp_chnl , void *data , int len , void * pric ,
29 unsigned long src );
30 void rpmsg_read_ept2_cb( struct rpmsg_channel *rp_chnl , void *data , int len , void * pric ,
31 unsigned long src );
33 int test_rpmsg_send(struct rpmsg_channel *rpmsg_chnl);
34 int test_rpmsg_send_offchannel(struct rpmsg_channel *rpmsg_chnl, unsigned long src, unsigned long dst);
36 int test_rpmsg_create_ept(struct rpmsg_channel *rpmsg_chnl);
38 int test_remoteproc_multiple_lifecycles(char * firmware_name);
40 int test_rpmsg_send_offchannel_impl(struct rpmsg_channel *rpmsg_chnl, unsigned long src, unsigned long dst);
42 int test_rpmsg_send_impl(struct rpmsg_channel *rpmsg_chnl);
44 int test_rpmsg_remote_channel_deletion(struct rpmsg_channel *rpmsg_chnl, char *channel_name);
46 int test_execute_suite(char * firmware_name);
49 /* Globals */
50 NU_TASK Task_Control_Block;
51 NU_SEMAPHORE App_Sem, Remote_Del_Sem;
52 struct rpmsg_endpoint *rp_ept1 , *rp_ept2;
53 struct rpmsg_channel *app_rp_chnl;
54 char fw_name1[] = "firmware1";
55 char fw_name2[] = "firmware2";
57 struct _payload* p_payload = NULL;
58 struct _payload* r_payload = NULL;
59 static const char display_string[] = ".";
60 /***********************************************************************
61 * *
62 * * FUNCTION
63 * *
64 * * Application_Initialize
65 * *
66 * * DESCRIPTION
67 * *
68 * * Demo application entry point
69 *
70 * ***********************************************************************/
71 VOID Application_Initialize(
72 NU_MEMORY_POOL* mem_pool , NU_MEMORY_POOL* uncached_mem_pool )
73 {
74 VOID *pointer;
75 STATUS status = NU_SUCCESS;
77 /* Reference unused parameters to avoid toolset warnings */
78 NU_UNUSED_PARAM( uncached_mem_pool );
80 if ( status == NU_SUCCESS )
81 {
82 status = NU_Allocate_Memory(mem_pool, &pointer, STACK_SIZE, NU_NO_SUSPEND);
84 /* Create the main task for matrix processing */
85 if ( status == NU_SUCCESS )
86 {
87 status = NU_Create_Task( &Task_Control_Block , "MAIN" , Main_Task_Entry , 0 ,
88 uncached_mem_pool , pointer , STACK_SIZE , TASK_PRIORITY , TASK_SLICE ,
89 NU_PREEMPT , NU_START );
90 }
91 if ( status == NU_SUCCESS )
92 {
93 status = NU_Create_Semaphore( &App_Sem , "APP_SEM" , 0 , NU_FIFO );
94 }
96 if ( status == NU_SUCCESS )
97 {
98 status = NU_Create_Semaphore( &Remote_Del_Sem , "Del_SEM" , 0 , NU_FIFO );
99 }
101 NU_Allocate_Memory(uncached_mem_pool , (VOID **)&r_payload, 512 , NU_SUSPEND);
102 }
104 /* Check to see if previous operations were successful */
105 if ( status != NU_SUCCESS )
106 {
107 /* Loop forever */
108 while ( 1 );
109 }
110 }
112 /***********************************************************************
113 * *
114 * * FUNCTION
115 * *
116 * * Main_Task_Entry
117 * *
118 * * DESCRIPTION
119 * *
120 * * Entry function for the main task. This task prints a hello world
121 * * message.
122 * *
123 * ***********************************************************************/
124 static VOID Main_Task_Entry( UNSIGNED argc , VOID *argv )
125 {
126 printf("\n\n\r************************************");
127 printf("*******************************************\r\n");
128 printf("\r\n OpenAMP Test Suite \r\n");
129 printf("\r\n");
130 printf("\r\nThis test suite will execute multiple test cases for rpmsg and rempteproc \r\n");
131 printf("\r\nAPIs available within OpenAMP \r\n");
133 printf("\r\n******************************************");
134 printf("*************************************\n\r\n");
136 test_execute_suite(fw_name1);
138 test_execute_suite(fw_name2);
141 }
143 /* This callback gets invoked when the remote chanl is created */
144 void rpmsg_channel_created( struct rpmsg_channel *rp_chnl )
145 {
146 app_rp_chnl = rp_chnl;
148 rp_ept1 = rpmsg_create_ept(rp_chnl , rpmsg_read_ept1_cb , RPMSG_NULL , RPMSG_ADDR_ANY);
150 NU_Release_Semaphore( &App_Sem );
151 }
153 /* This callback gets invoked when the remote channel is deleted */
154 void rpmsg_channel_deleted( struct rpmsg_channel *rp_chnl )
155 {
156 rpmsg_destroy_ept( rp_ept1 );
158 NU_Release_Semaphore( &Remote_Del_Sem );
160 }
162 /* This is the read callback, note we are in a task context when this callback
163 is invoked, so kernel primitives can be used freely */
164 void rpmsg_read_default_cb( struct rpmsg_channel *rp_chnl , void *data , int len , void * priv ,
165 unsigned long src )
166 {
167 memcpy( r_payload , data , len );
168 NU_Release_Semaphore( &App_Sem );
169 }
171 void rpmsg_read_ept1_cb( struct rpmsg_channel *rp_chnl , void *data , int len , void * priv ,
172 unsigned long src )
173 {
174 memcpy( r_payload , data , len );
175 NU_Release_Semaphore( &App_Sem );
176 }
178 void rpmsg_read_ept2_cb( struct rpmsg_channel *rp_chnl , void *data , int len , void * priv ,
179 unsigned long src )
180 {
181 memcpy( r_payload , data , len );
182 NU_Release_Semaphore( &App_Sem );
183 }
186 int test_execute_suite(char * firmware_name)
187 {
188 struct remote_proc *proc;
189 int status;
190 char default_channel[] = "rpmsg-openamp-demo-channel";
191 struct command* cmd;
192 NU_MEMORY_POOL *sys_pool_ptr;
194 printf("\n\n\r************************************");
195 printf("*******************************************\r\n");
196 printf( "\r\nBoot remote context : %s \r\n" , firmware_name );
197 printf("\r\n******************************************");
198 printf("*************************************\n\r\n");
200 status = remoteproc_init( (void *) firmware_name ,rpmsg_channel_created, rpmsg_channel_deleted, rpmsg_read_default_cb, &proc);
202 if (status)
203 {
204 printf( "\r\n CRITICAL ERROR: remoteproc_init call for remote context %s failed \r\n", firmware_name);
206 return -1;
207 }
209 status = remoteproc_boot( proc );
211 if (status)
212 {
213 printf( "\r\n CRITICAL ERROR: remoteproc_boot call for remote context %s failed \r\n", firmware_name);
215 return -1;
216 }
218 /* Wait for channel creation event */
219 NU_Obtain_Semaphore( &App_Sem , NU_SUSPEND );
221 /* Obtain remote firmware name */
222 NU_System_Memory_Get(NU_NULL, &sys_pool_ptr);
223 status = NU_Allocate_Memory(sys_pool_ptr , (void **)&(cmd), sizeof(struct command), NU_SUSPEND);
224 cmd->comm_start=CMD_START;
225 cmd->comm_code = QUERY_FW_NAME;
226 status = rpmsg_send(app_rp_chnl, cmd, sizeof(struct command));
227 NU_Deallocate_Memory(cmd);
229 /* Wait to receive firmware name */
230 NU_Obtain_Semaphore( &App_Sem , NU_SUSPEND );
232 printf("\r\nREMOTE FIRMWARE NAME : %s \r\n", (char*)r_payload);
234 /* Test rpmsg_send API */
235 status = test_rpmsg_send(app_rp_chnl);
237 if(!status)
238 {
239 printf( "\r\nRESULT: PASSED \r\n" );
240 }
241 else
242 {
243 printf( "\r\nRESULT: FAILED \r\n" );
244 }
246 /* Test rpmsg_send_offchannel API. */
247 status = test_rpmsg_send_offchannel(app_rp_chnl, rp_ept1->addr, app_rp_chnl->dst);
249 if(!status)
250 {
251 printf( "\r\nRESULT: PASSED \r\n" );
252 }
253 else
254 {
255 printf( "\r\nRESULT: FAILED \r\n" );
256 }
258 status = test_rpmsg_create_ept(app_rp_chnl);
260 if(!status)
261 {
262 printf( "\r\nRESULT: PASSED \r\n" );
263 }
264 else
265 {
266 printf( "\r\nRESULT: FAILED \r\n" );
267 }
269 printf("\n\n\r************************************");
270 printf("*******************************************\r\n");
271 printf(" This test case will test channel deletion \r\n");
272 printf("******************************************");
273 printf("*************************************\r\n\n");
275 status = test_rpmsg_remote_channel_deletion(app_rp_chnl, default_channel);
277 if(!status)
278 {
279 printf( "\r\nRESULT: PASSED \r\n" );
280 }
281 else
282 {
283 printf( "\r\nRESULT: FAILED \r\n" );
284 }
286 printf("\n\n\r************************************");
287 printf("*******************************************\r\n");
288 printf( "\r\n\nShutdown remote context : %s \r\n" , firmware_name );
289 printf("******************************************");
290 printf("*************************************\r\n\n");
292 status = remoteproc_shutdown(proc);
293 if(!status)
294 {
295 status = remoteproc_deinit(proc);
296 }
298 if(!status)
299 {
300 status = test_remoteproc_multiple_lifecycles(firmware_name);
301 }
303 if(!status)
304 {
305 printf( "\r\nRESULT: PASSED \r\n" );
306 }
307 else
308 {
309 printf( "\r\nRESULT: FAILED \r\n" );
310 }
312 printf("\r\nFUNCTIONAL TEST SUITE COMPLETED EXECUTION! \r\n");
314 return status;
315 }
317 int test_remoteproc_multiple_lifecycles(char * firmware_name)
318 {
319 int i, status;
320 struct remote_proc *proc;
322 printf("\n\n\r************************************");
323 printf("*******************************************\r\n");
324 printf(" This test case will test multiple lifecycles for firmware: %s \r\n", firmware_name);
325 printf("******************************************");
326 printf("*************************************\r\n\n");
328 for(i = 0; i < 10; i++)
329 {
330 status = remoteproc_init( (void *) firmware_name ,rpmsg_channel_created, rpmsg_channel_deleted, rpmsg_read_default_cb, &proc);
332 if (status)
333 {
334 printf( "\r\n ERROR: remoteproc_init failed\r\n");
336 break;
337 }
339 printf("\n\n\r************************************");
340 printf("*******************************************\r\n");
341 printf( "\r\n\nBoot remote context : %s \r\n" , firmware_name );
342 printf("******************************************");
343 printf("*************************************\r\n\n");
345 status = remoteproc_boot( proc );
347 if (status)
348 {
349 printf( "\r\n ERROR: remoteproc_boot failed\r\n");
351 break;
352 }
354 /* Wait for channel creation event */
355 status = NU_Obtain_Semaphore( &App_Sem , NU_SUSPEND );
357 if (!status)
358 {
359 status = test_rpmsg_send_impl(app_rp_chnl);
360 }
362 if(!status){
363 test_rpmsg_remote_channel_deletion(app_rp_chnl , app_rp_chnl->name);
364 }
366 printf("\n\n\r************************************");
367 printf("*******************************************\r\n");
368 printf( "\r\n\nShutdown remote context : %s \r\n" , firmware_name );
369 printf("******************************************");
370 printf("*************************************\r\n\n");
372 if (!status)
373 {
374 status = remoteproc_shutdown(proc);
375 }
376 if (status)
377 {
378 printf( "\r\n ERROR: remoteproc_shutdown failed\r\n");
380 break;
381 }
382 status = remoteproc_deinit(proc);
384 if (status)
385 {
386 printf( "\r\n ERROR: remoteproc_deinit failed\r\n");
388 break;
389 }
391 printf("%s", display_string);
393 }
395 return status;
396 }
398 int test_rpmsg_remote_channel_deletion(struct rpmsg_channel *rpmsg_chnl, char *channel_name)
399 {
400 struct command *cmd;
401 int status;
402 NU_MEMORY_POOL *sys_pool_ptr;
403 struct chnl_cmd_data *chnl_data;
405 NU_System_Memory_Get(NU_NULL, &sys_pool_ptr);
407 status = NU_Allocate_Memory(sys_pool_ptr ,
408 (void **)&(cmd), sizeof(struct command)+ sizeof(struct chnl_cmd_data), NU_SUSPEND);
410 cmd->comm_code = DELETE_CHNL;
411 cmd->comm_start = CMD_START;
413 chnl_data = (struct chnl_cmd_data *)cmd->data;
415 strncpy(chnl_data->name , channel_name, sizeof(struct chnl_cmd_data));
417 /* Let the other side that uninit its resources */
418 status = rpmsg_send( rpmsg_chnl , cmd , sizeof(struct command) + sizeof(struct chnl_cmd_data) );
419 if(status)
420 {
421 return status;
422 }
423 /* Wait for echo back */
424 status = NU_Obtain_Semaphore( &App_Sem , NU_SUSPEND);
425 /* Wait for channel deletion event */
426 status = NU_Obtain_Semaphore( &Remote_Del_Sem , NU_SUSPEND);
428 return status;
429 }
431 int test_rpmsg_create_ept(struct rpmsg_channel *rpmsg_chnl)
432 {
433 struct command *cmd;
434 int status, i;
435 struct ept_cmd_data *ept_data;
436 NU_MEMORY_POOL *sys_pool_ptr;
437 struct rpmsg_endpoint *test_ept[NUM_TEST_EPS];
439 NU_System_Memory_Get(NU_NULL, &sys_pool_ptr);
441 status = NU_Allocate_Memory(sys_pool_ptr ,
442 (void **)&(cmd), sizeof(struct command) + sizeof(struct ept_cmd_data), NU_SUSPEND);
444 if(status != NU_SUCCESS)
445 {
446 return status;
447 }
448 printf("\n\n\r************************************");
449 printf("*******************************************\r\n");
450 printf(" This test case will test rpmsg_create_ept API \r\n");
451 printf("******************************************");
452 printf("*************************************\r\n\n");
454 for(i = 0; i < NUM_TEST_EPS; i++)
455 {
456 /* Tell the remote to create a new endpoint. */
457 cmd->comm_code = CREATE_EPT;
458 cmd->comm_start = CMD_START;
460 /* Send create endpoint command to remote */
461 ept_data = (struct ept_cmd_data *)cmd->data;
462 ept_data->dst= EPT_TEST_ADDR + i;
463 ept_data->src= EPT_TEST_ADDR + i;
465 /* Let the other side know that it needs to create endpoint with the given address */
466 status = rpmsg_send(rpmsg_chnl, cmd, sizeof(struct command) + sizeof(struct ept_cmd_data));
468 if(!status)
469 {
470 /* Wait for ack */
471 status = NU_Obtain_Semaphore(&App_Sem , NU_SUSPEND);
472 }
474 if(!status)
475 {
476 printf("\r\nCreating an endpoint at address: %d \r\n", EPT_TEST_ADDR + i);
478 test_ept[i] = rpmsg_create_ept(rpmsg_chnl , rpmsg_read_ept2_cb , RPMSG_NULL , EPT_TEST_ADDR + i);
480 if ( !test_ept[i] )
481 {
482 status = -1;
484 printf("\r\n ERROR: rpmsg_create_ept API failed for endpoint address: %d \r\n", EPT_TEST_ADDR + i);
485 }
487 }
488 if(!status)
489 {
490 printf("\r\nTesting payloads on endpoint at address: %d \r\n", EPT_TEST_ADDR + i);
492 status = test_rpmsg_send_offchannel_impl(rpmsg_chnl, test_ept[i]->addr, test_ept[i]->addr);
493 }
495 if(!status)
496 {
497 /* Tell the remote to delete the endpoint. */
498 cmd->comm_code = DELETE_EPT;
499 cmd->comm_start = CMD_START;
500 /* Send delete endpoint command to remote */
501 ept_data = (struct ept_cmd_data *)cmd->data;
502 ept_data->dst= EPT_TEST_ADDR + i;
503 ept_data->src= EPT_TEST_ADDR + i;
505 /* Let the other side know that it needs to delete endpoint with the given address */
506 status = rpmsg_send(rpmsg_chnl, cmd, sizeof(struct command) + sizeof(struct ept_cmd_data));
507 }
509 if(!status)
510 {
511 /* Wait for ack */
512 status = NU_Obtain_Semaphore(&App_Sem , NU_SUSPEND);
513 }
515 if(!status)
516 {
517 rpmsg_destroy_ept(test_ept[i]);
518 }
519 }
521 NU_Deallocate_Memory(cmd);
522 if(status)
523 while(1);
525 return status;
526 }
528 int test_rpmsg_send_impl(struct rpmsg_channel *rpmsg_chnl)
529 {
530 struct command cmd;
531 int status;
532 int i, size, idx;
533 NU_MEMORY_POOL *sys_pool_ptr;
535 NU_System_Memory_Get(NU_NULL, &sys_pool_ptr);
536 /* Tell the remote to be prepared for echo payloads. */
537 cmd.comm_start = CMD_START;
538 cmd.comm_code = START_ECHO;
540 status = rpmsg_send(rpmsg_chnl, &cmd, sizeof(struct command));
542 if(!status)
543 {
544 /* Wait for cmd ack. */
545 status = NU_Obtain_Semaphore(&App_Sem , NU_SUSPEND);
546 if(status)
547 while(1);
549 printf("\r\nTransmitting paylaods to remote \r\n");
551 for(i = 0, size=PAYLOAD_MIN_SIZE; i < NUM_PAYLOADS; i++, size++)
552 {
553 NU_Allocate_Memory(sys_pool_ptr , (void**)&p_payload, sizeof(struct _payload) + size , NU_SUSPEND );
555 p_payload->num = i;
556 p_payload->size = size;
558 /* Setup the buffer with a pattern*/
559 memset(p_payload->data, 0xA5, size);
561 /* Send data to remote side. */
562 status = rpmsg_send(rpmsg_chnl, p_payload, sizeof(struct _payload) + size);
564 if(status != 0)
565 {
566 break;
567 }
569 /* Wait for echo. */
570 status = NU_Obtain_Semaphore(&App_Sem , NU_SUSPEND);
572 /* Validate the data integrity. */
573 for(idx = 0; idx < r_payload->size; idx++)
574 {
575 if(p_payload->data[idx] != r_payload->data[idx])
576 {
577 status = -1;
578 break;
579 }
580 }
582 if(status != 0)
583 {
584 break;
585 }
587 NU_Deallocate_Memory(p_payload);
588 printf("%s", display_string);
589 }
590 if(status)
591 while(1);
592 cmd.comm_start = CMD_START;
593 cmd.comm_code = STOP_ECHO;
595 status = rpmsg_send(rpmsg_chnl, &cmd, sizeof(struct command));
596 if(status)
597 while(1);
599 /* Wait for echo. */
600 status = NU_Obtain_Semaphore(&App_Sem , NU_SUSPEND);
601 if(status)
602 while(1);
603 }
606 return status;
607 }
608 int test_rpmsg_send(struct rpmsg_channel *rpmsg_chnl)
609 {
610 printf("\n\n\r************************************");
611 printf("*******************************************\r\n");
612 printf(" This test case will test rpmsg_send API \r\n");
613 printf("******************************************");
614 printf("*************************************\r\n\n");
616 return test_rpmsg_send_impl(rpmsg_chnl);
617 }
619 int test_rpmsg_send_offchannel_impl(struct rpmsg_channel *rpmsg_chnl, unsigned long src, unsigned long dst)
620 {
621 struct command cmd;
622 int status;
623 int i, size, idx;
624 NU_MEMORY_POOL *sys_pool_ptr;
625 NU_System_Memory_Get(NU_NULL, &sys_pool_ptr);
627 /* Tell the remote to be prepared for echo payloads. */
628 cmd.comm_code = START_ECHO;
629 cmd.comm_start = CMD_START;
630 status = rpmsg_send(rpmsg_chnl, &cmd, sizeof(struct command));
632 if(!status)
633 {
634 /* Wait for cmd ack. */
635 status = NU_Obtain_Semaphore(&App_Sem , NU_SUSPEND);
636 if(status)
637 while(1);
639 for(i = 0, size=PAYLOAD_MIN_SIZE; i < NUM_PAYLOADS; i++, size++)
640 {
641 NU_Allocate_Memory(sys_pool_ptr , (void**)&p_payload, sizeof(struct _payload) + size , NU_SUSPEND );
642 p_payload->num = i;
643 p_payload->size = size;
645 /* Setup the buffer with a pattern*/
646 memset(p_payload->data, 0xA5, size);
648 /* Send data to remote side. */
649 status = rpmsg_send_offchannel(app_rp_chnl, src, dst, p_payload ,
650 sizeof(struct _payload) + size);
652 if(status)
653 {
654 break;
655 }
657 /* Wait for echo. */
658 status = NU_Obtain_Semaphore(&App_Sem , NU_SUSPEND);
660 /* Validate the data integrity. */
661 for(idx = 0; idx < r_payload->size; idx++)
662 {
663 if(p_payload->data[idx] != r_payload->data[idx])
664 {
665 status = -1;
666 break;
667 }
668 }
670 if(status)
671 {
672 break;
673 }
675 printf("%s", display_string);
676 NU_Deallocate_Memory(p_payload);
677 }
678 cmd.comm_start = CMD_START;
679 cmd.comm_code = STOP_ECHO;
681 status = rpmsg_send(rpmsg_chnl, &cmd, sizeof(struct command));
682 /* Wait for cmd ack. */
683 status = NU_Obtain_Semaphore(&App_Sem , NU_SUSPEND);
684 if(status)
685 while(1);
686 }
688 return status;
689 }
691 int test_rpmsg_send_offchannel(struct rpmsg_channel *rpmsg_chnl, unsigned long src, unsigned long dst)
692 {
693 printf("\n\n\r************************************");
694 printf("*******************************************\r\n");
695 printf(" This test case will test rpmsg_send_offchannel API \r\n");
696 printf("******************************************");
697 printf("*************************************\r\n\n");
699 return test_rpmsg_send_offchannel_impl(rpmsg_chnl, src, dst);
700 }