AMP相关:2 Linux Mailbox子系统(基于TM32MP1的IPCC)概览
Mailbox子系统是一种用于处理期间的通信机制,通过消息队列和中断驱动信号来处理多个处理器之间的通信。主要包括Controller和Client两部分。
Mailbox子系统包括如下几部分:
- Mailbox子系统核心。
- Mailbox控制器驱动,比如STM32MP157的IPCC驱动。
- 使用Mailbox Controller驱动的Mailbox Client驱动,比如remoteproc作为Client通过Mailbox和M4通信。
Mailbox子系统大致工作流程是:
- 注册Mailbox Controller驱动到Mailbox子系统。
- Mailbox Client驱动申请通道。
- Mailbox Client发送数据,Mailbox Controller驱动配置硬件发送消息。当数据发送完成时,Mailbox Controller通过回调函数通知上层数据发送完成。
- Mailbox Controller接收到数据时,将底层接受到的数据回调给上层。
- 不使用通道时,Mailbox Client释放通道。
1 Mailbox配置
Mailbox Controller配置如下:
Device Drivers
Mailbox Hardware Support
Generic ARM smc mailbox
Mailbox Test Client
STM32 IPCC Mailbox
2 Mailbox文件
Mailbox Controller相关文件如下:
drivers/mailbox/
├── arm-smc-mailbox.c ├── mailbox.c--Mailbox子系统核心,提供Controller的注册/去注册,Channel申请释放和消息发送。 ├── mailbox-test.c--通用Mailbox测试示例。 ├── stm32-ipcc.c--ST的Mailbox Controller IPCC驱动。
3 Mailbox子系统以及API
3.1 Mailbox Controller API和数据结构
struct mbox_chan_ops定义了如何操作Maibox通道的操作函数集:
struct mbox_chan_ops { int (*send_data)(struct mbox_chan *chan, void *data);--发送数据。 int (*flush)(struct mbox_chan *chan, unsigned long timeout); int (*startup)(struct mbox_chan *chan);--启动通道。 void (*shutdown)(struct mbox_chan *chan);--关闭通道。 bool (*last_tx_done)(struct mbox_chan *chan);--检查发送完成。 bool (*peek_data)(struct mbox_chan *chan);--检查通道是否有未读取数据。 };
struct mbox_controller表示Mailbox控制器:
struct mbox_controller { struct device *dev;--与Mailbox关联的设备结构体。 const struct mbox_chan_ops *ops;--定义了如何与Mailbox通道交互的操作函数集。 struct mbox_chan *chans;--Mailbox包含的所有通道。 int num_chans;--Mailbox包含的通道数。 bool txdone_irq;--为真,则控制器支持通过中断来通知发送完成。 bool txdone_poll;--为真,则控制器支持轮询机制来查询发送完成。 unsigned txpoll_period;--轮询周期,单位为毫秒。 struct mbox_chan *(*of_xlate)(struct mbox_controller *mbox, const struct of_phandle_args *sp); /* Internal to API */ struct hrtimer poll_hrt; struct list_head node; };
一个Mailbox可以有一个或多个Channel,struct mbox_chan表示一个Mailbox通道:
struct mbox_chan { struct mbox_controller *mbox; unsigned txdone_method; struct mbox_client *cl; struct completion tx_complete; void *active_req; unsigned msg_count, msg_free; void *msg_data[MBOX_TX_QUEUE_LEN]; spinlock_t lock; /* Serialise access to the channel */ void *con_priv; };
Mailbox Controller的注册和去注册API如下:
int mbox_controller_register(struct mbox_controller *mbox); /* can sleep */ void mbox_controller_unregister(struct mbox_controller *mbox); /* can sleep */ int devm_mbox_controller_register(struct device *dev, struct mbox_controller *mbox); void devm_mbox_controller_unregister(struct device *dev, struct mbox_controller *mbox);
从Channel接收消息API:
void mbox_chan_received_data(struct mbox_chan *chan, void *data); /* atomic */ void mbox_chan_txdone(struct mbox_chan *chan, int r); /* atomic */
3.2 Mailbox Client API和数据结构
struct mbox_client表示一个Mailbox客户端:
struct mbox_client { struct device *dev;--指向客户端设备的设备结构体。 bool tx_block;--为真,客户端在发送消息时将阻塞,直到最后一条消息被传输完成。 unsigned long tx_tout;--定义客户端超时前等待消息传输完成的最大时间,以毫秒为单位。 bool knows_txdone; void (*rx_callback)(struct mbox_client *cl, void *mssg);--当Mailbox控制器接受到消息是,调用此函数来通知客户端。 void (*tx_prepare)(struct mbox_client *cl, void *mssg);--发送消息前,调用此函数来准备消息。 void (*tx_done)(struct mbox_client *cl, void *mssg, int r);--消息发送完成后,调用此函数来通知客户端发送操作的结构。 };
Mailbox Client获取释放Channel、发送消息等API:
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); int mbox_send_message(struct mbox_chan *chan, void *mssg); int mbox_flush(struct mbox_chan *chan, unsigned long timeout); void mbox_client_txdone(struct mbox_chan *chan, int r); /* atomic */ bool mbox_client_peek_data(struct mbox_chan *chan); /* atomic */ void mbox_free_channel(struct mbox_chan *chan); /* may sleep */
4 Mailbox硬件模块IPCC
IPCC(Inter-Process Communication Controller)处理器间通信控制器,,用于在两个 CPU之间进行信号交换。
IPCC 硬件模块有 6 个双向通道, 每个通道分为两个子通道, 6 个双向通道则共有 12 个子通道。
5 STM32 Mailbox驱动
5.1 STM32 IPCC DTS
IPCC DTS包括两个中断,分别是rx/tx:
ipcc: mailbox@4c001000 { compatible = "st,stm32mp1-ipcc"; #mbox-cells = <1>; reg = <0x4c001000 0x400>; st,proc-id = <0>; interrupts-extended = <&exti 61 1>, <&intc GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>; interrupt-names = "rx", "tx"; clocks = <&rcc IPCC>; wakeup-source; power-domains = <&pd_core>; status = "disabled"; };
5.2 STM32 IPCC驱动
IPCC驱动作为Mailbox控制器驱动负责:
- 获取中断号,并为tx/rx创建处理函数。
- 配置唤醒功能。
- 将IPCC作为Mailbox注册到Mailbox子系统。
stm32_ipcc_driver
stm32_ipcc_probe
platform_get_irq_byname--获取rx和tx中断。
devm_request_threaded_irq--注册rx和tx中断。
stm32_ipcc_rx_irq--A7 IPCC接收中断处理函数。
mbox_chan_received_data--调用Mailbox Client的rx_callback函数进行处理,即stm32_rproc_mb_callback。
stm32_ipcc_tx_irq--A7 IPCC发送中断处理函数。
mbox_chan_txdone
tx_tick
msg_submit--调用Mailbox Channel操作函数的send_data发送数据。
--调用Malbox Client的tx_don函数。
device_set_wakeup_capable
dev_pm_set_wake_irq
devm_mbox_controller_register--初始化mbox_controller后,将其注册到Mailbox Controller子系统。操作函数集为stm32_ipcc_ops。
stm32_ipcc_ops提供了对IPCC使能、关闭、发送数据的操作函数:
static const struct mbox_chan_ops stm32_ipcc_ops = { .send_data = stm32_ipcc_send_data, .startup = stm32_ipcc_startup, .shutdown = stm32_ipcc_shutdown, };