这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 行业应用 » 汽车电子 » 【S32K3XX】IPCF 核间通讯模块UNMANAGED方式使用

共1条 1/1 1 跳转至

【S32K3XX】IPCF 核间通讯模块UNMANAGED方式使用

高工
2026-07-08 16:02:52     打赏

【简介】

S32K3 是一款多核的芯片,多核的芯片的使用避免不了核间通讯,在之前的帖子中也介绍过一些核间通信的使用方式。

【S32K3XX】核间通信MU使用

【S32K3XX】Core-to-Core 中断使用

上述是本地直接使用S32K3 的MU/核减中断 来完成核间的信息交互的功能,NXP 在核间通讯方面也是提供了IPCF(Inter-Platform Communication Framework   )的软件包基于上述的MU / 核间中断 + share memory 来实现核间的信息交互。

以下是IPCF 的软件价架构。

IPCF Architecture Block Diagram

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

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

查看IPCF 的源码目录结构也是按照上述的划分进行管理的。

image.png

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

image.png

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

image.png

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

image.png

以下是CORE1 的IPCF 配置。

image.png

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

三种类型的比较说明如下:

image.png

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

image.png

image.png

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

image.png


   上述流程也比较清晰:

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 的消息并打印。

image.png


共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]