コード例 #1
0
ファイル: remoteproc.c プロジェクト: PetrLukas/open-amp
/**
 * remoteproc_boot
 *
 * This function loads the image on the remote processor and starts
 * its execution from image load address.
 *
 * @param rproc - pointer to remoteproc instance to boot
 *
 * @param returns - status of function execution
 */
int remoteproc_boot(struct remote_proc *rproc) {

    void *load_addr;
    int status;

    if (!rproc) {
        return RPROC_ERR_PARAM;
    }

    /* Stop the remote CPU */
    hil_shutdown_cpu(rproc->proc);

    /* Load the firmware */
    status = remoteproc_loader_load_remote_firmware(rproc->loader);
    if (status == RPROC_SUCCESS) {
        load_addr = remoteproc_get_load_address(rproc->loader);
        if (load_addr != RPROC_ERR_PTR) {
            /* Start the remote cpu */
            status = hil_boot_cpu(rproc->proc,
                            (unsigned int) load_addr);
            if (status == RPROC_SUCCESS) {
                /* Wait for remote side to come up. This delay is arbitrary and may
                 * need adjustment for different configuration of remote systems */
                env_sleep_msec(RPROC_BOOT_DELAY);

                /* Initialize RPMSG "messaging" component */

                /* It is a work-around to work with remote Linux context. 
                   Since the upstream Linux rpmsg implementation always 
                   assumes itself to be an rpmsg master, we initialize
                   the remote device as an rpmsg master for remote Linux
                   configuration only. */
#if defined (OPENAMP_REMOTE_LINUX_ENABLE)
                status = rpmsg_init(rproc->proc->cpu_id, &rproc->rdev,
                                rproc->channel_created,
                                rproc->channel_destroyed, rproc->default_cb,
                                 RPMSG_MASTER);
#else
                status = rpmsg_init(rproc->proc->cpu_id, &rproc->rdev,
                                rproc->channel_created,
                                rproc->channel_destroyed, rproc->default_cb,
                                 RPMSG_REMOTE);
#endif
            }
        } else {
            status = RPROC_ERR_LOADER;
        }
    } else {
        status = RPROC_ERR_LOADER;
    }

    return status;
}
コード例 #2
0
ファイル: rpmsg.c プロジェクト: CharlesAndrews95/embeddedsw
int rpmsg_send_offchannel_raw(struct rpmsg_channel *rp_chnl, unsigned long src,
                unsigned long dst, char *data, int size, int wait) {
    struct remote_device *rdev;
    struct rpmsg_hdr *rp_hdr;
    void *buffer;
    int status = RPMSG_SUCCESS;
    unsigned short idx;
    int tick_count = 0;
    int buff_len;

    if (!rp_chnl) {
        return RPMSG_ERR_PARAM;
    }

    /* Get the associated remote device for channel. */
    rdev = rp_chnl->rdev;

    /* Validate device state */
    if (rp_chnl->state != RPMSG_CHNL_STATE_ACTIVE
                    || rdev->state != RPMSG_DEV_STATE_ACTIVE) {
        return RPMSG_ERR_DEV_STATE;
    }

    /* Lock the device to enable exclusive access to virtqueues */
    env_lock_mutex(rdev->lock);
    /* Get rpmsg buffer for sending message. */
    buffer = rpmsg_get_tx_buffer(rdev, &buff_len, &idx);
    if (!buffer && !wait) {
        status = RPMSG_ERR_NO_MEM;
    }
    env_unlock_mutex(rdev->lock);

    if (status == RPMSG_SUCCESS) {

        while (!buffer) {
            /*
             * Wait parameter is true - pool the buffer for
             * 15 secs as defined by the APIs.
             */
            env_sleep_msec(RPMSG_TICKS_PER_INTERVAL);
            env_lock_mutex(rdev->lock);
            buffer = rpmsg_get_tx_buffer(rdev, &buff_len, &idx);
            env_unlock_mutex(rdev->lock);
            tick_count += RPMSG_TICKS_PER_INTERVAL;
            if (tick_count >= (RPMSG_TICK_COUNT / RPMSG_TICKS_PER_INTERVAL)) {
                status = RPMSG_ERR_NO_BUFF;
                break;
            }
        }

        if (status == RPMSG_SUCCESS) {
            //FIXME : may be just copy the data size equal to buffer length and Tx it.
            if (size > (buff_len - sizeof(struct rpmsg_hdr)))
                status = RPMSG_ERR_BUFF_SIZE;

            if (status == RPMSG_SUCCESS) {
                rp_hdr = (struct rpmsg_hdr *) buffer;

                /* Initialize RPMSG header. */
                rp_hdr->dst = dst;
                rp_hdr->src = src;
                rp_hdr->len = size;

                /* Copy data to rpmsg buffer. */
                env_memcpy(rp_hdr->data, data, size);

                env_lock_mutex(rdev->lock);
                /* Enqueue buffer on virtqueue. */
                status = rpmsg_enqueue_buffer(rdev, buffer, buff_len, idx);
                if (status == RPMSG_SUCCESS) {
                    /* Let the other side know that there is a job to process. */
                    virtqueue_kick(rdev->tvq);
                }
                env_unlock_mutex(rdev->lock);
            }

        }
    }

    /* Do cleanup in case of error.*/
    if (status != RPMSG_SUCCESS) {
        rpmsg_free_buffer(rdev, buffer);
    }

    return status;
}