核间通信队列(IPC Queue library)实现了双向核间通信功能, 它结合了 MAILBOX 的通知机制与软件循环buffer,使得核间通信类似于两颗芯片间的串口通信。 函数库最多支持4条queue同时工作,每条queue与一对收发buffer绑定(收发buffer是可选的,如果配置为NULL,则只提供中断通知功能),按用户配置映射到对应的硬件通道, 平台支持的硬件通道号可以查看对应的ipc_hw_port.h。
以HCPU与LCPU的通信为例,由ipc_hw_port.h可知,0~7为HCPU与LCPU间的硬件通道,选择通道0,调用 ipc_queue_init() 配置好收发buffer的地址和接收回调函数, 如果成功则返回一个有效的queue handle,然后调用 ipc_queue_open() 打开通道,之后就可以正常收发数据了。
调用 ipc_queue_write() 可以发送数据给对端,发送的数据会被写入配置好的tx_buffer,同时接收端会收到通知中断(接收端已经打开了对应相应的IPC queue)。 如果对端发送了数据,ipc_queue_init() 注册的接收回调会被触发,可以调用 ipc_queue_read() 从rx_buffer里读取数据。
需要注意的是,HCPU配置的rx_buffer地址应与LCPU配置的tx_buffer_alias地址相同,即指向tx_buffer,HCPU配置的tx_buffer_alias则与LCPU的rx_buffer地址相同, tx_buffer必需是发送方所在子系统的RAM地址,即HCPU需要在自己的RAM空间里分配一块buffer作为发送buffer,这样才能避免对端子系统还未被唤醒的情况下也能写入数据,tx_buffer由发送方管理。 因为接收端可能无法直接访问发送端的地址空间,所以使用tx_buffer_alias指定接收端可访问的tx_buffer对应的地址空间,两个地址实际指向同一块物理buffer。 tx_buffer与rx_buffer的关系见图1
函数库的架构如图2所示,API接口定义在ipc_queue.h中,ipc_queue.c为平台无关的实现,ipc_hw.c封装了ButterFli的 MAILBOX 接口,为ipc_queue.c提供中断服务, 但因为不同系列的ButterFli芯片的硬件通道配置不同,每个芯片有各自的ipc_hw_port.c,在文件中定义变量ipc_hw_obj描述硬件通道,并实现中断处理函数。 ipc_queue.c提供接口ipc_queue_data_ind让中断处理函数通知上层新数据的到来。
对于RT-Thread平台,可以使用 IPC Queue Wrapper Device 提供的API,将IPC Queue封装成RT Device。
ipc_queue_read或者ipc_queue_write读写数据,调用者需要做好互斥,避免重入。 但如果是访问不同的queue,可以不做互斥。例如,thread_1使用ipc_queue_write往queue_0中写入数据,thread_2使用ipc_queue_write往queue_1中写入数据, 因为操作的是不同的queue,并不需要做互斥保护,但如果两个线程都是往queue_0里写数据,调用ipc_queue_write前就需要做互斥了。选中SiFli Middleware->Enable IPC Queue Library使能函数库
以下的测试代码展示使用硬件通道0作为HCPU与LCPU的双向通信通道,HCPU的0x20000000地址作为发送buffer,LCPU的0x20100000地址作为LCPU的发送buffer, HCPU_ADDR_2_LCPU_ADDR用于把HCPU地址转换到LCPU的地址空间,LCPU_ADDR_2_HCPU_ADDR类似。