]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - processor-sdk/open-amp.git/blob - apps/samples/master/nucleus/matrix_multiply/nucleus_linux/matrix_multiply.c
Correcting application message.
[processor-sdk/open-amp.git] / apps / samples / master / nucleus / matrix_multiply / nucleus_linux / matrix_multiply.c
1 /* This is a sample demonstration application that showcases usage of remoteproc
2 and rpmsg APIs. This application is meant to run on the master CPU running Nucleus
3 and showcases booting of linux remote firmware using remoteproc and 
4 IPC with remote firmware using rpmsg; Nucleus on master core acts as a remoteproc master
5 but as an rpmsg remote;It brings up a remote Linux based 
6 firmware which acts as an rpmsg master and offloads matrix multiplication to Nucleus.
7 Linux app generates two random matrices and transmits them to Nucleus which computes 
8 the product and transmits results back to Linux. Once Linux application is complete, it
9 requests a shutdown from Nucleus. Nucleus acknowledges with a shutdown message which results
10 in Linux starting a system halt. Nucleus shutsdown the remote core after a reasonable delay which allows
11 Linux to gracefully shutdown. */
13 /* Including required headers */
14 #include  <stdio.h>
15 #include <string.h>
16 #include <stdlib.h>
17 #include "open_amp.h"
18 #include "nucleus.h"
19 #include "kernel/nu_kernel.h"
21 /* Define the main task's stack size */
22 #define STACK_SIZE      (NU_MIN_STACK_SIZE * 64)
24 /* Define the main task's priority */
25 #define TASK_PRIORITY   26
27 /* Define the main task's time slice */
28 #define TASK_SLICE      20
30 #define MAX_SIZE        6
31 #define NUM_MATRIX      2
32 /* Shutdown message ID */
33 #define SHUTDOWN_MSG                    0xEF56A55A
35 typedef struct _matrix
36 {
37     unsigned long size;
38     unsigned long elements[MAX_SIZE][MAX_SIZE];
39 } matrix;
42 static  matrix  matrix_array[NUM_MATRIX];
44 static  matrix matrix_result;
46 /* Prototypes */
47 static void Main_Task_Entry( UNSIGNED argc , VOID *argv );
49 /* Application provided callbacks */
50 void rpmsg_channel_created( struct rpmsg_channel *rp_chnl );
51 void rpmsg_channel_deleted( struct rpmsg_channel *rp_chnl );
52 void rpmsg_read_cb( struct rpmsg_channel *rp_chnl , void *data , int len , void * pric , unsigned long src );
54 /* Globals */
55 NU_TASK Task_Control_Block;
56 NU_SEMAPHORE App_Sem;
57 struct rpmsg_endpoint *rp_ept;
58 struct rpmsg_channel *app_rp_chnl;
59 char fw1_name []= "firmware1";
61 static int shutdown_received = 0;
63 static void Matrix_Multiply(const matrix *m, const matrix *n, matrix *r)
64 {
65     int i, j, k;
67     r->size = m->size;
69     for (i = 0; i < m->size; ++i) {
70         for (j = 0; j < n->size; ++j) {
71             r->elements[i][j] = 0;
72         }
73     }
75     for (i = 0; i < m->size; ++i) {
76         for (j = 0; j < n->size; ++j) {
77             for (k = 0; k < r->size; ++k) {
78                 r->elements[i][j] += m->elements[i][k] * n->elements[k][j];
79             }
80         }
81     }
82 }
85 /***********************************************************************
86  * *
87  * *   FUNCTION
88  * *
89  * *       Application_Initialize
90  * *
91  * *   DESCRIPTION
92  * *
93  * *       Demo application entry point
94  *
95  * ***********************************************************************/
96 VOID Application_Initialize(NU_MEMORY_POOL* mem_pool , NU_MEMORY_POOL* uncached_mem_pool )
97 {
98     VOID *pointer;
99     STATUS status = NU_SUCCESS;
101     /* Reference unused parameters to avoid toolset warnings */
102     NU_UNUSED_PARAM( uncached_mem_pool );
104     if (status == NU_SUCCESS)
105     {
106         status = NU_Allocate_Memory(mem_pool, &pointer, STACK_SIZE, NU_NO_SUSPEND);
108         /* Create the main task for matrix processing */
109         if ( status == NU_SUCCESS )
110         {
111             status = NU_Create_Task( &Task_Control_Block , "MAIN" , Main_Task_Entry , 0 ,
112             uncached_mem_pool , pointer , STACK_SIZE , TASK_PRIORITY , TASK_SLICE ,
113             NU_PREEMPT , NU_START );
114         }
115         if(status == NU_SUCCESS)
116         {
117             status = NU_Create_Semaphore(&App_Sem ,"APP_SEM", 0, NU_FIFO);
118         }
119     }
121     /* Check to see if previous operations were successful */
122     if ( status != NU_SUCCESS )
123     {
124         /* Loop forever */
125         while ( 1 );
126     }
129 /***********************************************************************
130  * *
131  * *   FUNCTION
132  * *
133  * *       Main_Task_Entry
134  * *
135  * *   DESCRIPTION
136  * *
137  * *       Entry function for the main task. This task prints a hello world
138  * *       message.
139  * *
140  * ***********************************************************************/
141 static VOID Main_Task_Entry( UNSIGNED argc , VOID *argv ) {
143     struct remote_proc *proc;
144     NU_MEMORY_POOL     *sys_pool_ptr;
145     STATUS             status;
146     int shutdown_msg = SHUTDOWN_MSG;
148     status = NU_System_Memory_Get(&sys_pool_ptr, NU_NULL);
149     
150     /* Start first firmware*/
151     if(status == NU_SUCCESS)
152     {   
153                 printf("\n\n\r************************************");
154                 printf("*******************************************\r\n");
155                 printf("\r\n              Matrix Multiplication Application \r\n");
156                 printf("\r\n");
157                 printf("\r\nThis sample application will boot a remote Linux firmware \r\n");
158                 printf("\r\nThis sample application will boot a remote Linux firmware \r\n");
159                 printf("\r\nand handle offloaded matrix multiplication operations from\r\n");
160                 printf("\r\nLinux RPMSG master to Nuclues RPMS Remote \r\n");
162                 printf("\r\n******************************************");
163                 printf("*************************************\n\r\n");
164     
165     
166         printf("\r\n\nLoading remote context : %s \r\n" , fw1_name);
167         
168         printf("\r\n******************************************");
169                 printf("*************************************\n\r\n");
170             
171         status = remoteproc_init((void *) fw1_name, rpmsg_channel_created, rpmsg_channel_deleted, rpmsg_read_cb, &proc);
172     }
173     
174     if((!status) && (proc))
175     {
176         printf("\r\n\n********************************************\r\n");
177         printf("BOOTING LINUX REMOTE FIRMWARE");
178             printf("\r\n********************************************\r\n\n");
179         status = remoteproc_boot(proc);
180     }
181     
182     if(!status)
183     {
184         while(1)
185         {
186                         NU_Obtain_Semaphore(&App_Sem, NU_SUSPEND);
187          
188                 if(shutdown_received == 1)
189                 {
190                             break;      
191                 }
192                 
193                         /* Process received data and multiple matrices. */
194                         Matrix_Multiply(&matrix_array[0], &matrix_array[1], &matrix_result);
196                         /* Send the result of matrix multiplication back to master. */
197                         rpmsg_send(app_rp_chnl, &matrix_result, sizeof(matrix));
198             }
199             
200                 /* Send shutdown message to remote */
201                 rpmsg_send(app_rp_chnl, &shutdown_msg, sizeof(int));
202                 
203                 /* The remote Linux kernel requires around ~15 seconds to shutdown itself. Wait. */
204                 NU_Sleep(100 * 18);
205                 
206                 remoteproc_shutdown(proc);
207                 
208                 remoteproc_deinit(proc);
209     }
210     else
211     {
212         printf("\r\n\nLoading remote context: %s failed \r\n" , fw1_name);
213     }            
216 /* This callback gets invoked when the remote chanl is created */
217 void rpmsg_channel_created(struct rpmsg_channel *rp_chnl) {
219     app_rp_chnl = rp_chnl;
220     rp_ept = rpmsg_create_ept(rp_chnl , rpmsg_read_cb ,RPMSG_NULL , RPMSG_ADDR_ANY);
223 /* This callback gets invoked when the remote channel is deleted */
224 void rpmsg_channel_deleted(struct rpmsg_channel *rp_chnl) {
226     rpmsg_destroy_ept(rp_ept);
229 /* This is the read callback, note we are in a task context when this callback
230 is invoked, so kernel primitives can be used freely */
231 void rpmsg_read_cb(struct rpmsg_channel *rp_chnl, void *data, int len,
232                 void * priv, unsigned long src) {
234     if ((*(int *) data) == SHUTDOWN_MSG)
235     {
236                 shutdown_received  = 1;
237     }
238         
239     memcpy(matrix_array, data, len);
241     NU_Release_Semaphore(&App_Sem);