static int rpmsg_pingpong_probe(struct rpmsg_channel *rpdev) { int err; dev_info(&rpdev->dev, "new channel: 0x%x -> 0x%x!\n", rpdev->src, rpdev->dst); /* * send a message to our remote processor, and tell remote * processor about this channel */ err = rpmsg_send(rpdev, MSG, strlen(MSG)); if (err) { dev_err(&rpdev->dev, "rpmsg_send failed: %d\n", err); return err; } rpmsg_pingpong = 0; rx_count = 0; err = rpmsg_sendto(rpdev, (void *)(&rpmsg_pingpong), 4, rpdev->dst); if (err) { dev_err(&rpdev->dev, "rpmsg_send failed: %d\n", err); return err; } return 0; }
static void mat_mul_demo(void) { while (1) { void *data; int len; /* wait for data... */ buffer_pull(&data, &len); /* Process incoming message/data */ if (*(int *)data == SHUTDOWN_MSG) { /* disable interrupts and free resources */ remoteproc_resource_deinit(proc); break; } else { env_memcpy(matrix_array, data, len); /* Process received data and multiple matrices. */ Matrix_Multiply(&matrix_array[0], &matrix_array[1], &matrix_result); /* Send result back */ if (RPMSG_SUCCESS != rpmsg_send(app_rp_chnl, &matrix_result, sizeof(matrix))) { xil_printf("Error: rpmsg_send failed\n"); } } } }
static int qcom_glink_ssr_notify(struct notifier_block *nb, unsigned long event, void *data) { struct glink_ssr *ssr = container_of(nb, struct glink_ssr, nb); struct do_cleanup_msg msg; char *ssr_name = data; int ret; ssr->seq_num++; reinit_completion(&ssr->completion); memset(&msg, 0, sizeof(msg)); msg.command = cpu_to_le32(GLINK_SSR_DO_CLEANUP); msg.seq_num = cpu_to_le32(ssr->seq_num); msg.name_len = cpu_to_le32(strlen(ssr_name)); strlcpy(msg.name, ssr_name, sizeof(msg.name)); ret = rpmsg_send(ssr->ept, &msg, sizeof(msg)); if (ret < 0) dev_err(ssr->dev, "failed to send cleanup message\n"); ret = wait_for_completion_timeout(&ssr->completion, HZ); if (!ret) dev_err(ssr->dev, "timeout waiting for cleanup done message\n"); return NOTIFY_DONE; }
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); matrix_mul(); if(pq_qlength(OpenAMPInstPtr.send_queue) > 0) { send_data = pq_dequeue(OpenAMPInstPtr.send_queue); /* Send the result of matrix multiplication back to master. */ rpmsg_send(app_rp_chnl, send_data->data, send_data->length); } #endif } }
static void rpmsg_read_cb(struct rpmsg_channel *rp_chnl, void *data, int len, void * priv, unsigned long src) { if ((*(int *) data) == SHUTDOWN_MSG) { remoteproc_resource_deinit(proc); } else { /* Send data back to master*/ rpmsg_send(rp_chnl, data, len); } }
static void mat_mul_demo(void *unused_arg) { int status = 0; (void)unused_arg; /* Create buffer to send data between RPMSG callback and processing task */ buffer_create(); /* Initialize HW and SW components/objects */ init_system(); /* 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) { xil_printf("Error: initializing OpenAMP framework\n"); return; } /* Stay in data processing loop until we receive a 'shutdown' message */ while (1) { void *data; int len; /* wait for data... */ buffer_pull(&data, &len); /* Process incoming message/data */ if (*(int *)data == SHUTDOWN_MSG) { /* disable interrupts and free resources */ remoteproc_resource_deinit(proc); /* Terminate this task */ vTaskDelete(NULL); break; } else { env_memcpy(matrix_array, data, len); /* Process received data and multiple matrices. */ Matrix_Multiply(&matrix_array[0], &matrix_array[1], &matrix_result); /* Send result back */ if (RPMSG_SUCCESS != rpmsg_send(app_rp_chnl, &matrix_result, sizeof(matrix))) { xil_printf("Error: rpmsg_send failed\n"); } } } }
/** * rpmsg_ns_callback * * This callback handles name service announcement from the remote device * and creates/deletes rpmsg channels. * * @param server_chnl - pointer to server channel control block. * @param data - pointer to received messages * @param len - length of received data * @param priv - any private data * @param src - source address * * @return void */ void rpmsg_ns_callback(struct rpmsg_channel *server_chnl, void *data, int len, void *priv, unsigned long src) { struct remote_device *rdev; struct rpmsg_channel *rp_chnl; struct rpmsg_ns_msg *ns_msg; struct llist *node; rdev = (struct remote_device *) priv; //FIXME: This assumes same name string size for channel name both on master //and remote. If this is not the case then we will have to parse the //message contents. ns_msg = (struct rpmsg_ns_msg *) data; ns_msg->name[len - 1] = '\0'; if (ns_msg->flags & RPMSG_NS_DESTROY) { node = rpmsg_rdev_get_chnl_node_from_id(rdev, ns_msg->name); if (node) { rp_chnl = (struct rpmsg_channel *) node->data; if (rdev->channel_destroyed) { rdev->channel_destroyed(rp_chnl); } rpmsg_destroy_ept(rp_chnl->rp_ept); _rpmsg_delete_channel(rp_chnl); } } else { rp_chnl = _rpmsg_create_channel(rdev, ns_msg->name, 0x00, ns_msg->addr); if (rp_chnl) { rp_chnl->state = RPMSG_CHNL_STATE_ACTIVE; /* Create default endpoint for channel */ rp_chnl->rp_ept = rpmsg_create_ept(rp_chnl, rdev->default_cb, rdev, RPMSG_ADDR_ANY); if (rp_chnl->rp_ept) { rp_chnl->src = rp_chnl->rp_ept->addr; /* * Echo back the NS message to remote in order to * complete the connection stage. Remote will know the endpoint * address from this point onward which will enable it to send * message without waiting for any application level message from * master. */ rpmsg_send(rp_chnl,data,len); if (rdev->channel_created) { rdev->channel_created(rp_chnl); } } } } }
static int rpmsg_rfs_probe(struct rpmsg_channel *rpdev) { int ret = 0; struct rpmsg_ns_msg nsm; nsm.addr = rpdev->dst; memcpy(nsm.name, rpdev->id.name, RPMSG_NAME_SIZE); nsm.flags = 0; rpmsg_send(rpdev, &nsm, sizeof(nsm)); return ret; }
static void rpmsg_read_cb(struct rpmsg_channel *rp_chnl, void *data, int len, void * priv, unsigned long src) { if ((*(int *) data) == SHUTDOWN_MSG) { shutdown_called = 1; } else { /* Send data back to master*/ rpmsg_send(rp_chnl, data, len); } }
/** * qcom_rpm_smd_write - write @buf to @type:@id * @rpm: rpm handle * @type: resource type * @id: resource identifier * @buf: the data to be written * @count: number of bytes in @buf */ int qcom_rpm_smd_write(struct qcom_smd_rpm *rpm, int state, u32 type, u32 id, void *buf, size_t count) { static unsigned msg_id = 1; int left; int ret; struct { struct qcom_rpm_header hdr; struct qcom_rpm_request req; u8 payload[]; } *pkt; size_t size = sizeof(*pkt) + count; /* SMD packets to the RPM may not exceed 256 bytes */ if (WARN_ON(size >= 256)) return -EINVAL; pkt = kmalloc(size, GFP_KERNEL); if (!pkt) return -ENOMEM; mutex_lock(&rpm->lock); pkt->hdr.service_type = cpu_to_le32(RPM_SERVICE_TYPE_REQUEST); pkt->hdr.length = cpu_to_le32(sizeof(struct qcom_rpm_request) + count); pkt->req.msg_id = cpu_to_le32(msg_id++); pkt->req.flags = cpu_to_le32(state); pkt->req.type = cpu_to_le32(type); pkt->req.id = cpu_to_le32(id); pkt->req.data_len = cpu_to_le32(count); memcpy(pkt->payload, buf, count); ret = rpmsg_send(rpm->rpm_channel, pkt, size); if (ret) goto out; left = wait_for_completion_timeout(&rpm->ack, RPM_REQUEST_TIMEOUT); if (!left) ret = -ETIMEDOUT; else ret = rpm->ack_status; out: kfree(pkt); mutex_unlock(&rpm->lock); return ret; }
/* * process requests from remote core */ static void rpmsg_rfs_recv(struct rpmsg_channel *rpdev, void *data, int len, void *priv, u32 src) { struct aipc_rfs_msg *msg = (struct aipc_rfs_msg*)data; int cmd = msg->msg_type; if (cmd < 0 || cmd >= ARRAY_SIZE(msg_handler)) { EMSG("unknown rfs command %d\n", cmd); return; } msg_handler[cmd](msg); rpmsg_send(rpdev, msg, msg->msg_len); }
static int reply( struct imt_rpc_req *req, int cmd, int len, uint32_t rsp ) { int ret; req->cmd = cmd; req->len = len; req->rsp = rsp; ret = rpmsg_send(rpdev, req, req->len); if (ret) { ERR("imt: rpsend failed: %d", ret); return 1; } return 0; }
static void rpmsg_read_cb(struct rpmsg_channel *rp_chnl, void *data, int len, void *priv, unsigned long src) { if ((*(int *)data) == SHUTDOWN_MSG) { remoteproc_resource_deinit(proc); } else { env_memcpy(matrix_array, data, len); /* Process received data and multiple matrices. */ Matrix_Multiply(&matrix_array[0], &matrix_array[1], &matrix_result); /* Send the result of matrix multiplication back to master. */ rpmsg_send(app_rp_chnl, &matrix_result, sizeof(matrix)); } }
/* Application entry point */ int main() { int status; struct remote_proc *proc; int shutdown_msg = SHUTDOWN_MSG; int i; /* Switch to System Mode */ SWITCH_TO_SYS_MODE(); /* Initialize HW system components */ init_system(); status = remoteproc_init((void *) fw_name, rpmsg_channel_created, rpmsg_channel_deleted, rpmsg_read_cb, &proc); if(!status) { status = remoteproc_boot(proc); } if(status) { return -1; } while (1) { if(shutdown_called == 1) { break; } sleep(); } /* Send shutdown message to remote */ rpmsg_send(app_rp_chnl, &shutdown_msg, sizeof(int)); for (i = 0; i < 100000; i++) { sleep(); } remoteproc_shutdown(proc); remoteproc_deinit(proc); return 0; }
static int rpmsg_sample_probe(struct rpmsg_channel *rpdev) { int ret; dev_info(&rpdev->dev, "new channel: 0x%x -> 0x%x!\n", rpdev->src, rpdev->dst); /* send a message to our remote processor */ ret = rpmsg_send(rpdev, MSG, strlen(MSG)); if (ret) { dev_err(&rpdev->dev, "rpmsg_send failed: %d\n", ret); return ret; } return 0; }
static int connect(void) { char buffer[16]; struct imt_rpc_req *req = (struct imt_rpc_req*)buffer; int ret; // send a connect msg req->id = 0x00; req->len = 16; req->cmd = IMT_CONNECT; req->par = 0x42; req->rsp = 0x00; ret = rpmsg_send(rpdev, req, req->len); if (ret) { ERR("imt: rpsend failed: %d", ret); return ret; } return 0; }
static void rpmsg_sample_cb(struct rpmsg_channel *rpdev, void *data, int len, void *priv, u32 src) { int ret; static int rx_count; dev_info(&rpdev->dev, "incoming msg %d (src: 0x%x)\n", ++rx_count, src); print_hex_dump(KERN_DEBUG, __func__, DUMP_PREFIX_NONE, 16, 1, data, len, true); /* samples should not live forever */ if (rx_count >= MSG_LIMIT) { dev_info(&rpdev->dev, "goodbye!\n"); return; } /* send a new message now */ ret = rpmsg_send(rpdev, MSG, strlen(MSG)); if (ret) dev_err(&rpdev->dev, "rpmsg_send failed: %d\n", ret); }
int main() { struct remote_proc *proc; int uninit = 0; struct ept_cmd_data *ept_data; #ifdef ZYNQ7_BAREMETAL /* Switch to System Mode */ SWITCH_TO_SYS_MODE(); #endif /* Initialize HW system components */ init_system(); rsc_info.rsc_tab = (struct resource_table *)&resources; rsc_info.size = sizeof(resources); /* This API creates the virtio devices for this remote node and initializes other relevant resources defined in the resource table */ remoteproc_resource_init(&rsc_info, rpmsg_channel_created, rpmsg_channel_deleted, rpmsg_read_default_cb, &proc); for (;;) { if (intr_flag) { struct command *cmd = (struct command *)r_buffer; if (cmd->comm_start == CMD_START) { unsigned int cm_code = cmd->comm_code; void *data = cmd->data; switch (cm_code) { case CREATE_EPT: ept_data = (struct ept_cmd_data *)data; rp_ept = rpmsg_create_ept(app_rp_chnl, rpmsg_read_ept_cb, RPMSG_NULL, ept_data->dst); if (rp_ept) { /* Send data back to ack. */ rpmsg_sendto(app_rp_chnl, r_buffer, Len, Src); } break; case DELETE_EPT: rpmsg_destroy_ept(rp_ept); rpmsg_sendto(app_rp_chnl, r_buffer, Len, Src); break; case CREATE_CHNL: break; case DELETE_CHNL: rpmsg_sendto(app_rp_chnl, r_buffer, Len, Src); remoteproc_resource_deinit(proc); uninit = 1; break; case QUERY_FW_NAME: rpmsg_send(app_rp_chnl, &firmware_name[0], strlen(firmware_name) + 1); break; default: rpmsg_sendto(app_rp_chnl, r_buffer, Len, Src); break; } } else { rpmsg_sendto(app_rp_chnl, r_buffer, Len, Src); } intr_flag = 0; if (uninit) break; } sleep(); } return 0; }
/* Application entry point */ int main() { int status; struct remote_proc *proc; int i; int shutdown_msg = SHUTDOWN_MSG; /* Switch to System Mode */ SWITCH_TO_SYS_MODE(); /* Initialize HW system components */ init_system(); status = remoteproc_init((void *) fw_name, rpmsg_channel_created, rpmsg_channel_deleted, rpmsg_read_cb, &proc); if(!status) { status = remoteproc_boot(proc); } if(status) { return -1; } while (1) { if (int_flag) { if(shutdown_called == 1) { break; } /* Process received data and multiple matrices. */ Matrix_Multiply(&matrix_array[0], &matrix_array[1], &matrix_result); /* Send the result of matrix multiplication back to master. */ rpmsg_send(app_rp_chnl, &matrix_result, sizeof(matrix)); int_flag = 0; sleep(); } sleep(); } /* Send shutdown message to remote */ rpmsg_send(app_rp_chnl, &shutdown_msg, sizeof(int)); for (i = 0; i < 100000; i++) { sleep(); } remoteproc_shutdown(proc); remoteproc_deinit(proc); return 0; }