【简介】
S32K3 是一款多核的芯片,多核的芯片的使用避免不了核间通讯,在之前的帖子中也介绍过一些核间通信的使用方式。
上述是本地直接使用S32K3 的MU/核减中断 来完成核间的信息交互的功能,NXP 在核间通讯方面也是提供了IPCF(Inter-Platform Communication Framework )的软件包基于上述的MU / 核间中断 + share memory 来实现核间的信息交互。
以下是IPCF 的软件价架构。

以下是基于IPCF 核间通讯的应用结构。

从上述 IPCF 的软件架构图上可以看出,IPCF 软件结构抽象分层为 ipc-shm、ipc-os、ipc-hw 三层,底层依托 S32K3 硬件 MU、核间中断与共享内存完成核间交互。ipc-hw 做硬件抽象,适配芯片通信硬件;ipc-os 封装操作系统同步、中断接口,兼容裸机、AUTOSAR 等系统;ipc-shm 实现共享内存管理、消息队列与核心通信逻辑,向上对接客户应用,分层解耦让框架移植性更强。
查看IPCF 的源码目录结构也是按照上述的划分进行管理的。

IPCF 的软件包NXP是作为S32DS的中间件的方式来释放的,可以从NXP下载到对应的软件包,安装后就会在S32DS的配置工具中看到IPCF的组件。

IPCF 是基于共享内存来进行数据通讯的,配置的时候需要为local core 和 remote core 分别配置一块共享内存。本地使用的S32K324 的片子来使用IPCF,查看本地的link file中的share memory 的地址配置如下:

按照上述的共享内存的地址分别为Core0 和 Core1 分配4KB的共享内存区域,以下是CORE0的IPCF配置,本地的硬件交互先使用 IRQ_NONE-POLLING 的方式实现。

以下是CORE1 的IPCF 配置。

上述配置后后IPCF的中间件代码就会被加入到工程之中。从上述的配置中可以看到Channle type 的配置,IPCF 中定义了 `IPC_SHM_MANAGED`、`IPC_SHM_UNMANAGED`、`IPC_SHM_SCMI` 三种类型。
三种类型的比较说明如下:

以下是IPCF中对 IPC_SHM_UNMANAGED 和 IPC_SHM_MANAGED 类型的memory layout 的说明。


本次试验先使用 UNMANAGED 的方式来使用IPCF 实现核间通讯,以下是UNMANAGED 方式通讯时序图。

上述流程也比较清晰:
step1:调用 ipc_shm_unmanaged_acquire 获取对应的地址,更新要发送的数据
step2:调用 ipc_shm_unmanaged_tx 将消息发送到对端
step3:对端收到后处理数据
本地在core1 段添加如下的代码,每秒往Core1 侧发送一条消息:
/** *****************************************************************************************************
* \file ipcf_core0_sample.c *
* \brief *
* *
* <table> *
* <tr><th>Date <th>Version *
* <tr><td>2026/07/07 <td>1.0.0 *
* </table> *
*******************************************************************************************************/
/********************************************************************************************************
* Include header files *
*******************************************************************************************************/
/* shm driver includes */
#include "ipc-shm.h"
#include "printf.h"
#include <string.h>
/* FreeRtos include file */
#include "FreeRTOS.h"
#include "task.h"
#define CTRL_CHAN_ID 0
#define CTRL_CHAN_SIZE 64
#define MAX_SAMPLE_MSG_LEN 32
#define SAMPLE_NUM_MSGS 100
static sint8 sharpstr[] = "#";
static sint8 hellostr[] = " HELLO from M7_1";
static sint8 send_buf[] = "CORE1 SENDING MESSAGES: ";
/**
* struct ipc_sample_app - sample app private data
* @ctrl_shm: control channel local shared memory
* @rx_count: number of received messaged
* @tx_count: number of transmitted messaged
* @expected_msgs: number of expected messages
* @last_rx_no_msg: last number of received message
* @last_rx_ch: last Rx channel id
*/
static struct ipc_sample_app {
sint8 *ctrl_shm;
volatile uint16 rx_count;
volatile uint16 tx_count;
uint16 expected_msgs;
uint16 last_rx_no_msg;
uint8 last_rx_ch;
} app;
const void* rx_cb_arg0 = &app;
/* alternative implementation of strtol */
uint32 ipc_strtol(sint8 *src)
{
uint32 res = 0;
while ((*src >= '0') && (*src <= '9')) {
res = res*10 + (*(src++) - '0');
}
return res;
}
/* alternative implementation of strlen */
uint32 ipc_strlen(const sint8 *src)
{
uint32 i;
for (i = 0; src[i] != '\0'; i++)
;
return i;
}
/* alternative implementation of strcpy */
void ipc_strcpy(sint8 *dst, const sint8 *src)
{
while ((*dst++ = *src++) != '\0')
;
}
/* alternative implementation of strrchr */
sint8 *ipc_strrchr(const sint8 *s, int c)
{
sint8 *rtnval = 0;
do {
if (*s == c)
rtnval = (sint8 *) s;
} while (*s++);
return rtnval;
}
/* convert positive base 10 number to string */
static void ipc_numtostr(uint16 num, sint8 *str)
{
uint16 tmp = num;
/* if is only zero must return 0 */
if (num == 0) {
*++str = '0';
}
/* advance string to least significant digit position */
while (tmp) {
++str;
tmp = tmp / 10;
}
*++str = '\0';
/* insert digits backwards */
while (num) {
*--str = num % 10 + '0';
num = num / 10;
}
}
void ipcf_chan_rx_cb0(void *arg, const uint8 instance, uint8 chan_id, void *mem)
{
sint8 err;
struct ipc_sample_app *cb_arg_sample =
(struct ipc_sample_app *)(*((uintptr *)arg));
}
/* send control message with number of data messages to be sent */
static int send_ctrl_msg(const uint8 instance, uint16 num_msgs)
{
/* last channel is control channel */
const uint8 chan_id = CTRL_CHAN_ID;
sint8 err;
/* write number of messages to be sent in control channel memory */
ipc_strcpy(app.ctrl_shm, send_buf);
ipc_numtostr(num_msgs, ipc_strrchr(app.ctrl_shm, ' '));
/* notify remote */
err = ipc_shm_unmanaged_tx(instance, chan_id);
if (err) {
return err;
}
return 0;
}
/**
* shm_demo() - shared memory demo
*
*/
void ipcf_shm_demo(void *pvParameters)
{
sint8 err = -IPC_SHM_E_INVAL;
/* init variables before use */
app.rx_count = 0;
/* wait until initialized or error */
do {
err = ipc_shm_init(&ipcf_shm_instances_cfg);
} while (err == -IPC_SHM_E_REMOTE_INIT_IN_PROGRESS);
if (err)
{
PRINTF("core1 ipc_shm_init failed %d \r\n", err);
} else {
PRINTF("core1 ipc_shm_init OK \r\n");
}
/* wait for remote core to initialize the shm driver */
while (ipc_shm_is_remote_ready(IPCF_INSTANCE0) != 0) {
/* busy wait */
}
PRINTF("core1 ipcf remote ready.\r\n");
/* acquire control channel memory once (unmanaged channel) */
app.ctrl_shm = ipc_shm_unmanaged_acquire(IPCF_INSTANCE0, CTRL_CHAN_ID);
if(!app.ctrl_shm)
{
PRINTF("core1 acquire memory failed.\r\n");
}
else
{
PRINTF("core1 acquire unmanaged memory ok.\r\n");
}
while(1)
{
uint16 num = 0;
/* signal number of messages to remote via control channel */
err = send_ctrl_msg(IPCF_INSTANCE0, num++);
vTaskDelay(1000);
}
}Core0 侧添加如下代码轮询状态,接收到消息打印CORE1 的数据信息。
/** *****************************************************************************************************
* \file ipcf_core0_sample.c *
* \brief *
* *
* <table> *
* <tr><th>Date <th>Version *
* <tr><td>2026/07/07 <td>1.0.0 *
* </table> *
*******************************************************************************************************/
/********************************************************************************************************
* Include header files *
*******************************************************************************************************/
/* shm driver includes */
#include "ipc-shm.h"
#include "printf.h"
#include <string.h>
/* FreeRtos include file */
#include "FreeRTOS.h"
#include "task.h"
#define CTRL_CHAN_ID 0
#define CTRL_CHAN_SIZE 64
#define MAX_SAMPLE_MSG_LEN 32
static sint8 sharpstr[] = "#";
static sint8 hellostr[] = " HELLO from M7_0";
static sint8 send_buf[] = "SENDING MESSAGES: ";
static sint8 repl_buf[] = "REPLIED MESSAGES: ";
/**
* struct ipc_sample_app - sample app private data
* @ctrl_shm: control channel local shared memory
* @rx_count: number of received messaged
* @tx_count: number of transmitted messaged
* @expected_msgs: number of expected messages
* @last_rx_no_msg: last number of received message
* @last_rx_ch: last Rx channel id
*/
static struct ipc_sample_app {
sint8 *ctrl_shm;
volatile uint16 rx_count;
volatile uint16 tx_count;
uint16 expected_msgs;
uint16 last_rx_no_msg;
uint8 last_rx_ch;
} app;
const void* rx_cb_arg0 = &app;
/* alternative implementation of strtol */
uint32 ipc_strtol(sint8 *src)
{
uint32 res = 0;
while ((*src >= '0') && (*src <= '9')) {
res = res*10 + (*(src++) - '0');
}
return res;
}
/* alternative implementation of strlen */
uint32 ipc_strlen(const sint8 *src)
{
uint32 i;
for (i = 0; src[i] != '\0'; i++)
;
return i;
}
/* alternative implementation of strcpy */
void ipc_strcpy(sint8 *dst, const sint8 *src)
{
while ((*dst++ = *src++) != '\0')
;
}
/* alternative implementation of strrchr */
sint8 *ipc_strrchr(const sint8 *s, int c)
{
sint8 *rtnval = 0;
do {
if (*s == c)
rtnval = (sint8 *) s;
} while (*s++);
return rtnval;
}
/* convert positive base 10 number to string */
static void ipc_numtostr(uint16 num, sint8 *str)
{
uint16 tmp = num;
/* if is only zero must return 0 */
if (num == 0) {
*++str = '0';
}
/* advance string to least significant digit position */
while (tmp) {
++str;
tmp = tmp / 10;
}
*++str = '\0';
/* insert digits backwards */
while (num) {
*--str = num % 10 + '0';
num = num / 10;
}
}
void ipcf_chan_rx_cb0(void *arg, const uint8 instance, uint8 chan_id, void *mem)
{
sint8 err;
struct ipc_sample_app *cb_arg_sample =
(struct ipc_sample_app *)(*((uintptr *)arg));
PRINTF("%s\r\n",(char *)mem);
}
/**
* shm_demo() - shared memory demo
*
*/
void ipcf_shm_demo(void *pvParameters)
{
sint8 err = -IPC_SHM_E_INVAL;
/* init variables before use */
app.tx_count = 0;
app.rx_count = 0;
/* wait until initialized or error */
do {
err = ipc_shm_init(&ipcf_shm_instances_cfg);
} while (err == -IPC_SHM_E_REMOTE_INIT_IN_PROGRESS);
if (err)
{
PRINTF("core0 ipc_shm_init failed %d \r\n", err);
} else {
PRINTF("core0 ipc_shm_init OK \r\n");
}
/* wait for remote core to initialize the shm driver */
while (ipc_shm_is_remote_ready(IPCF_INSTANCE0) != 0) {
/* busy wait */
}
PRINTF("core0 ipcf remote ready.\r\n");
/* acquire control channel memory once (unmanaged channel) */
app.ctrl_shm = ipc_shm_unmanaged_acquire(IPCF_INSTANCE0, CTRL_CHAN_ID);
if(!app.ctrl_shm)
{
PRINTF("acquire memory failed.\r\n");
}
else
{
PRINTF("acquire unmanaged memory ok.\r\n");
}
while(1)
{
ipc_shm_poll_channels(IPCF_INSTANCE0);
vTaskDelay(1000);
}
}上述代码运行结果如下 Core0 按照预期的接收到Core1 的消息并打印。

我要赚赏金
