首页 > 编程知识 正文

mailbox核间通信原理,mailbox机制

时间:2023-05-05 21:15:47 阅读:246845 作者:2896

我们知道在client 在通过mbox_send_message给controller发送数据的时候必须指定channel。例如下面的codedc_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的channelstruct 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,这样别人就可以继续使用这个channelvoid mbox_free_channel(struct mbox_chan *chan); /* may sleep */其中mbox_request_channel_byname是mbox_request_channel的一个包装。所以这里直接看看mbox_request_channelstruct 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,并最终startupret = chan->mbox->ops->startup(chan);if (ret) {dev_err(dev, "Unable to startup the chan (%d)n", 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_interruptret = request_irq(mlink->irq, mhu_rx_interrupt, IRQF_SHARED, "mhu_link", chan);if (ret) {dev_err(chan->mbox->dev,"Unable to acquire IRQ %dn", 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_submitif (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_datastatic 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;}

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。