mailbox数据发送和接收的过程【转】

摘要:
下面我们来看一下mbox_ request_ Channel结构mbox_ chan*mbox_请求_ Channel{structdevice*dev=cl-˃dev;structmbox_controller*mbox;struct_of_handle_argsspec;struct mbox_chan*chan;unsignedlongflags;intrt;spin_lock_irqsave;chan-˃msg_free=0;chan-˃message_count=0;chan-˃active_req=NULL;chan-˃cl=cl;init_completion;//初始化chan并最终启动=chan-˃mbox-˃ops-˃start p;如果{dev_err;mbox_free_channel;chan=err_PTR;}}与前一个臂_ mbox在mhu中定义。c_chan_ Ops作为示例静态仪器mbox_chan_ opsmhu_ Ops={.send_data=mhu_send_data,.startup=mhu_startup,.shutdown=mhu_shutdown,.last_tx_done=mhu_last_tx_done,};staticintmhu_ Startup{structmhu_link*mlink=chan-˃con_priv;u32val;interrt;val=readl_relieve;write_relied;最初,注册了一个中断,其回调函数为mhu_rx_cruptret=request_irq;if{dev_err;return;}return0;}中断函数如下:当客户端将mbox传递给控制器时,send_Message发送数据后,arm_mhu将向cotroller生成一个中断。Err){chan-˃active_req=data;chan-˃msg_count--;}最后,通过调用控件生成s

转自:https://blog.csdn.net/tiantao2012/article/details/78030580

我们知道在client 在通过mbox_send_message给controller发送数据的时候必须指定channel。例如下面的code
    dc_sync->mbox =
(&dc_sync->cl, 0);
    /* Populate data packet */
    /* sp.abc = 123; etc */
    /* Send message to remote in blocking mode */
    mbox_send_message(dc_sync->mbox, &sp);
    /* At this point 'sp' has been sent */
目前kernel提供了两种方法得到mailbox的channel
struct mbox_chan *mbox_request_channel_byname(struct mbox_client *cl,const char *name);
struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index);
使用完成后调用mbox_free_channel 释放channel,这样别人就可以继续使用这个channel
void mbox_free_channel(struct mbox_chan *chan); /* may sleep */
其中mbox_request_channel_byname是mbox_request_channel的一个包装。所以这里直接看看mbox_request_channel
struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index)
{
    struct device *dev = cl->dev;
    struct mbox_controller *mbox;
    struct of_phandle_args spec;
    struct mbox_chan *chan;
    unsigned long flags;
    int ret;


    spin_lock_irqsave(&chan->lock, flags);
    chan->msg_free = 0;
    chan->msg_count = 0;
    chan->active_req = NULL;
    chan->cl = cl;
    init_completion(&chan->tx_complete);

    //初始化chan,并最终startup
    ret = chan->mbox->ops->startup(chan);
    if (ret) {
        dev_err(dev, "Unable to startup the chan (%d) ", ret);
        mbox_free_channel(chan);
        chan = ERR_PTR(ret);
    }
}
以之前的arm_mhu.c 中定义的mbox_chan_ops为例
static const struct mbox_chan_ops mhu_ops = {
    .send_data = mhu_send_data,
    .startup = mhu_startup,
    .shutdown = mhu_shutdown,
    .last_tx_done = mhu_last_tx_done,
};

static int mhu_startup(struct mbox_chan *chan)
{
    struct mhu_link *mlink = chan->con_priv;
    u32 val;
    int ret;

    val = readl_relaxed(mlink->tx_reg + INTR_STAT_OFS);
    writel_relaxed(val, mlink->tx_reg + INTR_CLR_OFS);
原来就是注册了一个中断,其回调函数是mhu_rx_interrupt
    ret = request_irq(mlink->irq, mhu_rx_interrupt,
              IRQF_SHARED, "mhu_link", chan);
    if (ret) {
        dev_err(chan->mbox->dev,
            "Unable to acquire IRQ %d ", mlink->irq);
        return ret;
    }

    return 0;
}
这个中断函数如下:
当client 给controller 通过mbox_send_message发送数据后,arm_mhu 会产生一个中断给cotroller。
static irqreturn_t mhu_rx_interrupt(int irq, void *p)
{
    struct mbox_chan *chan = p;
    struct mhu_link *mlink = chan->con_priv;
    u32 val;

    val = readl_relaxed(mlink->rx_reg + INTR_STAT_OFS);
    if (!val)
        return IRQ_NONE;
controller调用mbox_chan_received_data 就可以得到client发送来的数据
    mbox_chan_received_data(chan, (void *)&val);

    writel_relaxed(val, mlink->rx_reg + INTR_CLR_OFS);

    return IRQ_HANDLED;
}
void mbox_chan_received_data(struct mbox_chan *chan, void *mssg)
{
    读去数据后,调用client的rx_callback 通知client
    /* No buffering the received data */
    if (chan->cl->rx_callback)
        chan->cl->rx_callback(chan->cl, mssg);
}


controller接收数据的flow 清楚了,再看看client是如何调用mbox_send_message 发送数据的
mbox_send_message->msg_submit
    if (chan->cl->tx_prepare)
        chan->cl->tx_prepare(chan->cl, data);
    /* Try to submit a message to the MBOX controller */
    err = chan->mbox->ops->send_data(chan, data);
    if (!err) {
        chan->active_req = data;
        chan->msg_count--;
    }
最终还是调用controll而的send_data 发送数据,本例controller的send_data函数为mhu_send_data
static int mhu_send_data(struct mbox_chan *chan, void *data)
{
    struct mhu_link *mlink = chan->con_priv;
    u32 *arg = data;
就是写controller的一个寄存器就行了,client写了之后后触发中断,controller会在中断中读到数据,并通过mbox_chan_received_data 通知client已经读取数据了
    writel_relaxed(*arg, mlink->tx_reg + INTR_SET_OFS);

    return 0;
}

————————————————
版权声明:本文为CSDN博主「tiantao2012」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/tiantao2012/article/details/78030580

免责声明:文章转载自《mailbox数据发送和接收的过程【转】》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇设置node服务器的端口及运行环境用tcping检查网站开放的端口下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

vue可调整大小和可拖动的组件---vue-draggable-resizable

border:位置:调整大小=“onResize”:{{width}};{{高度}}<importVueDraggableResizablefrom'vue-dragable-resizeable'导出默认值{data:height:methods:y){this.x=xthis.y=y}}}<...

html2canvas踩坑日记

在html2canvas<html2canvas(document.querySelector(“#capture”)).then(canvas=>{document.body.appendChild(canvas)});//图片地址是文档。身体appendChild(画布);...

微信小程序的模板消息与小程序订阅消息

有关获取分发权限的更多信息,请参阅applet侧消息订阅接口wx的步骤3。requestSubscribeMessage。有关发出订阅消息的调用接口的更多信息,请参阅服务器端消息发送接口subscribeMessage。sendwx。requestSubscribeMessage(Objectobject)基本库2.8.2。必须填写参数Objectobjec...

C# 没落了吗?

首先,这个数字--------------------------------------------C#是否正在衰落与微软的整个平台密切相关。近年来,使用C#的人越来越少,这也是因为越来越少的人专门为Microsoft平台开发产品。现在是移动时代,微软基本上错过了互联网和移动互联网这两波浪潮。现在生活不容易。在软件工程中,人们常说“唯一不变的就是改变本身”...

Java 安全之:csrf攻击总结

最近,我在维护一些旧项目。在调试期间,我发现请求被反复拒绝。我仔细查看了项目的源代码,发现存在csrftoken验证。我借此机会了解了csrf攻击,并将其总结成一篇论文。受攻击的网站无法阻止攻击。在整个过程中,攻击者无法获取受害者的登录凭据,只能“冒充”。CSRF攻击成功,因为服务器将攻击者发送的请求误认为是用户的请求。服务器通过验证请求是否携带正确的令牌来...

python中如何调用.py文件

步骤3来自。文件名不应与Python中的文件名相同,并且没有必要添加Py后缀。询问开发人员,“理论上,如果当前包的内容已经加载到python虚拟机中,如果您再次加载包,它将不会输出,导入相当于无效”。...