mailbox数据发送和接收的过程
2017-09-19 15:29
671 查看
我们知道在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)\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_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\n", 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; }
相关文章推荐
- JAVA编码转换的详细过程理解—>浏览器和服务器的接收和发送数据的编码
- NB-IOT之一个完整的BC95 UDP从开机到数据发送接收过程
- JAVA编码转换的详细过程理解—>浏览器和服务器的接收和发送数据的编码
- TCP带外数据学习总结(概念,发送接收过程,数据到达检测,代码实现)
- JAVA编码转换的详细过程理解—>浏览器和服务器的接收和发送数据的编码
- JAVA编码转换的详细过程理解—>浏览器和服务器的接收和发送数据的编码
- 安卓向服务器发送数据和服务器接收数据全过程
- 初涉Ajax,以post或get方法发送数据,以json或xml形式接收服务器返回的请求
- TCP block方式时,接收端接收数据太慢,导致发送端阻塞
- C# Net.Sockets 使用TcpListener发送接收数据
- usart 串口的发送-接收数据(正点改编)
- 消息队列发送数据和接收数据
- spring MVC 中json格式数据发送与接收
- 向ESB发送和接收数据
- 32 ART DMA 接收未知长度的数据和发送
- 用HttpURLConnection 在Java后台发送请求并接收返回数据
- C#使用UdpClient发送和接收UDP数据示例
- android网络通信 接收和发送数据详解
- C#进行Socket 连接发送和接收数据
- vue 集成 axios 发送post请求 payload导致后台无法接收到数据问题