void communication_task(){ int status; rsc_info.rsc_tab = (struct resource_table *)&resources; rsc_info.size = sizeof(resources); zynqMP_r5_gic_initialize(); /* Initialize RPMSG framework */ status = remoteproc_resource_init(&rsc_info, rpmsg_channel_created, rpmsg_channel_deleted, rpmsg_read_cb ,&proc); if (status < 0) { return; } #ifdef USE_FREERTOS comm_queueset = xQueueCreateSet( 2 ); xQueueAddToSet( OpenAMPInstPtr.send_queue, comm_queueset); xQueueAddToSet( OpenAMPInstPtr.lock, comm_queueset); #else env_create_sync_lock(&OpenAMPInstPtr.lock,LOCKED); #endif env_enable_interrupt(VRING1_IPI_INTR_VECT,0,0); while (1) { #ifdef USE_FREERTOS QueueSetMemberHandle_t xActivatedMember; xActivatedMember = xQueueSelectFromSet( comm_queueset, portMAX_DELAY); if( xActivatedMember == OpenAMPInstPtr.lock ) { env_acquire_sync_lock(OpenAMPInstPtr.lock); process_communication(OpenAMPInstPtr); } if (xActivatedMember == OpenAMPInstPtr.send_queue) { xQueueReceive( OpenAMPInstPtr.send_queue, &send_data, 0 ); rpmsg_send(app_rp_chnl, send_data.data, send_data.length); } #else env_acquire_sync_lock(OpenAMPInstPtr.lock); process_communication(OpenAMPInstPtr); echo_test(); /* Wait for the result data on queue */ if(pq_qlength(OpenAMPInstPtr.send_queue) > 0) { send_data = pq_dequeue(OpenAMPInstPtr.send_queue); /* Send the result of echo_test back to master. */ rpmsg_send(app_rp_chnl, send_data->data, send_data->length); } #endif } }
/************************************************************************* * * FUNCTION * * _open * * DESCRIPTION * * Open a file. Minimal implementation * *************************************************************************/ int _open(const char * filename, int flags, int mode) { int filename_len = strlen(filename) + 1; int payload_size = sizeof(struct _sys_rpc) + filename_len; int retval = -1; if ((!filename) || (filename_len > FILE_NAME_LEN)) { return -1; } /* Construct rpc payload */ rpc_data->rpc->id = OPEN_SYSCALL_ID; rpc_data->rpc->sys_call_args.int_field1 = flags; rpc_data->rpc->sys_call_args.int_field2 = mode; rpc_data->rpc->sys_call_args.data_len = filename_len; memcpy(&rpc_data->rpc->sys_call_args.data, filename, filename_len); /* Transmit rpc request */ env_lock_mutex(rpc_data->rpc_lock); send_rpc((void*) rpc_data->rpc, payload_size); env_unlock_mutex(rpc_data->rpc_lock); /* Wait for response from proxy on master */ env_acquire_sync_lock(rpc_data->sync_lock); /* Obtain return args and return to caller */ if (rpc_data->rpc_response->id == OPEN_SYSCALL_ID) { retval = rpc_data->rpc_response->sys_call_args.int_field1; } return retval; }
/************************************************************************* * * FUNCTION * * _write * * DESCRIPTION * * Low level function to redirect IO to serial. * *************************************************************************/ int _write(int fd, const char * ptr, int len) { int retval = -1; int payload_size = sizeof(struct _sys_rpc) + len; int null_term = 0; if (fd == 1) { null_term = 1; } rpc_data->rpc->id = WRITE_SYSCALL_ID; rpc_data->rpc->sys_call_args.int_field1 = fd; rpc_data->rpc->sys_call_args.int_field2 = len; rpc_data->rpc->sys_call_args.data_len = len + null_term; memcpy(rpc_data->rpc->sys_call_args.data, ptr, len); if (null_term) { *(char*) (rpc_data->rpc->sys_call_args.data + len + null_term) = 0; } env_lock_mutex(rpc_data->rpc_lock); send_rpc((void*) rpc_data->rpc, payload_size); env_unlock_mutex(rpc_data->rpc_lock); env_acquire_sync_lock(rpc_data->sync_lock); if (rpc_data->rpc_response->id == WRITE_SYSCALL_ID) { retval = rpc_data->rpc_response->sys_call_args.int_field1; } return retval; }
/************************************************************************* * * FUNCTION * * _read * * DESCRIPTION * * Low level function to redirect IO to serial. * *************************************************************************/ int _read(int fd, char * buffer, int buflen) { int payload_size = sizeof(struct _sys_rpc); int retval = -1; if (!buffer || !buflen) return retval; /* Construct rpc payload */ rpc_data->rpc->id = READ_SYSCALL_ID; rpc_data->rpc->sys_call_args.int_field1 = fd; rpc_data->rpc->sys_call_args.int_field2 = buflen; rpc_data->rpc->sys_call_args.data_len = 0; /*not used*/ /* Transmit rpc request */ env_lock_mutex(rpc_data->rpc_lock); get_response=0; send_rpc((void*) rpc_data->rpc, payload_size); env_unlock_mutex(rpc_data->rpc_lock); /* Wait for response from proxy on master */ env_acquire_sync_lock(rpc_data->sync_lock); /* Obtain return args and return to caller */ if (rpc_data->rpc_response->id == READ_SYSCALL_ID) { if (rpc_data->rpc_response->sys_call_args.int_field1 > 0) { memcpy(buffer, rpc_data->rpc_response->sys_call_args.data, rpc_data->rpc_response->sys_call_args.data_len); } retval = rpc_data->rpc_response->sys_call_args.int_field1; } return retval; }
/* wait for data and return data pointer when available */ void buffer_pull(void **data, int *len) { /* empty ? then block-wait for notification of new data*/ while (rb.head == rb.tail) env_acquire_sync_lock(rb.sync_lock); *data = (void *)&rb.buffer[sizeof(int)][rb.tail]; *len = *(int *)&rb.buffer[0][rb.tail]; rb.tail = (rb.tail + 1) % RB_SZ; }
/************************************************************************* * * FUNCTION * * _close * * DESCRIPTION * * Close a file. Minimal implementation * *************************************************************************/ int _close(int fd) { int payload_size = sizeof(struct _sys_rpc); int retval = -1; rpc_data->rpc->id = CLOSE_SYSCALL_ID; rpc_data->rpc->sys_call_args.int_field1 = fd; rpc_data->rpc->sys_call_args.int_field2 = 0; /*not used*/ rpc_data->rpc->sys_call_args.data_len = 0; /*not used*/ env_lock_mutex(rpc_data->rpc_lock); send_rpc((void*) rpc_data->rpc, payload_size); env_unlock_mutex(rpc_data->rpc_lock); /* Wait for response from proxy on master */ env_acquire_sync_lock(rpc_data->sync_lock); if (rpc_data->rpc_response->id == CLOSE_SYSCALL_ID) { retval = rpc_data->rpc_response->sys_call_args.int_field1; } return retval; }
/*-----------------------------------------------------------------------------* * Application specific *-----------------------------------------------------------------------------*/ static void rpc_demo(void) { int fd, bytes_written, bytes_read; char fname[] = "remote.file"; char wbuff[50]; char rbuff[1024]; char ubuff[50]; float fdata; int idata; int ret; int status = 0; /* Initialize HW and SW components/objects */ init_system(); env_create_sync_lock(&chnl_cb_flag, LOCKED); /* Resource table needs to be provided to remoteproc_resource_init() */ rsc_info.rsc_tab = (struct resource_table *)&resources; rsc_info.size = sizeof(resources); /* Initialize OpenAMP framework */ status = remoteproc_resource_init(&rsc_info, rpmsg_channel_created, rpmsg_channel_deleted, rpmsg_read_cb, &proc); if (RPROC_SUCCESS != status) { /* print error directly on serial port */ xil_printf("Error: initializing OpenAMP framework\n"); return; } /* wait for notification that will happen on channel creation (interrupt) */ env_acquire_sync_lock(chnl_cb_flag); /* redirect I/Os */ rpmsg_retarget_init(app_rp_chnl, shutdown_cb); printf("\r\nRemote>Baremetal Remote Procedure Call (RPC) Demonstration\r\n"); printf("\r\nRemote>***************************************************\r\n"); printf("\r\nRemote>Rpmsg based retargetting to proxy initialized..\r\n"); /* Remote performing file IO on Master */ printf("\r\nRemote>FileIO demo ..\r\n"); printf("\r\nRemote>Creating a file on master and writing to it..\r\n"); fd = open(fname, REDEF_O_CREAT | REDEF_O_WRONLY | REDEF_O_APPEND, S_IRUSR | S_IWUSR); printf("\r\nRemote>Opened file '%s' with fd = %d\r\n", fname, fd); sprintf(wbuff, "This is a test string being written to file.."); bytes_written = write(fd, wbuff, strlen(wbuff)); printf("\r\nRemote>Wrote to fd = %d, size = %d, content = %s\r\n", fd, bytes_written, wbuff); close(fd); printf("\r\nRemote>Closed fd = %d\r\n", fd); /* Remote performing file IO on Master */ printf("\r\nRemote>Reading a file on master and displaying its contents..\r\n"); fd = open(fname, REDEF_O_RDONLY, S_IRUSR | S_IWUSR); printf("\r\nRemote>Opened file '%s' with fd = %d\r\n", fname, fd); bytes_read = read(fd, rbuff, 1024); *(char*) (&rbuff[0] + bytes_read + 1) = 0; printf( "\r\nRemote>Read from fd = %d, size = %d, printing contents below .. %s\r\n", fd, bytes_read, rbuff); close(fd); printf("\r\nRemote>Closed fd = %d\r\n", fd); while (1) { /* Remote performing STDIO on Master */ printf("\r\nRemote>Remote firmware using scanf and printf ..\r\n"); printf("\r\nRemote>Scanning user input from master..\r\n"); printf("\r\nRemote>Enter name\r\n"); ret = scanf("%s", ubuff); if (ret) { printf("\r\nRemote>Enter age\r\n"); ret = scanf("%d", &idata); if(ret) { printf("\r\nRemote>Enter value for pi\r\n"); ret = scanf("%f", &fdata); if(ret) { printf("\r\nRemote>User name = '%s'\r\n", ubuff); printf("\r\nRemote>User age = '%d'\r\n", idata); printf("\r\nRemote>User entered value of pi = '%f'\r\n", fdata); } } } if(!ret) { scanf("%s", ubuff); printf("Remote> Invalid value. Starting again...."); } else { printf("\r\nRemote>Repeat demo ? (enter yes or no) \r\n"); scanf("%s", ubuff); if((strcmp(ubuff,"no")) && (strcmp(ubuff,"yes"))) { printf("\r\nRemote>Invalid option. Starting again....\r\n"); } else if((!strcmp(ubuff,"no"))) { printf("\r\nRemote>RPC retargetting quitting ...\r\n"); sprintf(wbuff, RPC_CHANNEL_READY_TO_CLOSE); rpmsg_retarget_send(wbuff, sizeof(RPC_CHANNEL_READY_TO_CLOSE) + 1); break; } } } printf("\r\nRemote> Firmware's rpmsg-openamp-demo-channel going down! \r\n"); }