TMS320F28388D使用sysconfig配置IPC

article/2025/8/28 15:09:39

第1章 配置IPC底层代码

使用IPC的动机:

我计划我的项目中要使用RS485,CANFD通信和EtherCAT通信,由于通信种类较多,而对于电机控制来说大部分数据都是重复的,并且有些数据可以很久才改变一次,所以我计划使用CPU2做FOC算法控制电机,使用CPU1与上位机进行通信,使用IPC做电机参数之间的通信。

实现目的:

CPU1与CPU2之间可以相互发送数据,数据支持浮点数。通信速度尽可能快和稳定。

下面的代码只有几百行,但是网上资料较少,问了TI工程师也没有答复,整了两三天才整出来,制作不易,希望点赞收藏加个关注,后期会不定时更新单片机的学习笔记。

1.1 CPU1的sysconfig配置

我的CPU1主要是用来做通信的,其实做通信最好是使用CM核,因为他是cortex-M内核,对信息的接收比较好,但是由于网上对这个核的资料很少,并且不能使用sysconfig进行配置,开发速度比较慢,综合起来就使用了CPU1做通信,CPU2做其他外设的控制代码,去跑算法。我的想法是使用CPU1能够主动发送和读取CPU2的数据,CPU2是跑算法和其他外设控制的,所以CPU1的IPC不需要被CPU2的中断,CPU2的数据应能够被CPU1中断。但是看很多解释以及芯片手册,貌似必须要有IPC中断才能接收数据,这点现在依然有疑问。知道的伙伴还望解答。

CPU1的sysconfig配置为:
在这里插入图片描述

第一行配置为选择CPU2的boot Mode即启动模式,Sysconfig对其的解释为在FLASH启动,配置完成后仍然需要在CPU1主函数中调用

Device_bootCPU2(BOOT_MODE_CPU2);函数来使能CPU2.

第二行配置为选择IPC的FLAG,CPU的IPC一共有32个标志,这里使用了IPC_FLAG0用作通信触发CPU2的中断,使用IPC_FLAG31来作为标志来同步两个CPU时钟。

第三行配置为选择能使CPU1的IPC_FLAG0,必须要勾选下面的对号,用来触发CPU2的接收中断。

第四行配置为使能IPC_FLAG31来作为标志来同步两个CPU时钟。可以选测0~31任一。

第五行配置为CPU1接收CPU2的IPC触发中断,IPC的中断有IPC0-3四个,这里选择了IPC1,也可使用IPC0,IPC1,IPC2,IPC3。

第六行配置为使能PIE里对应的中断。

1.2 CPU2的sysconfig配置

CPU2的sysconfig配置为

在这里插入图片描述

第一行配置为使用了IPC_FLAG1,IPC_FLAG31。

第二行配置为使能IPC_FLAG1,用于配置触发CPU1接收IPC中断的FLAG。

第三行配置为使能IPC_FLAG31,用于同步CPU核的时钟,可用其他FLAG,但要与CPU1的对应。

第四行配置为打开CPU2的IPC0中断,用于触发接收CPU1通过IPC_FLAG0发送的数据的中断

第五行为开启IPC0中断函数

第2章 IPC的应用层代码

2.1 CPU1的主函数IPC代码

第一步:根据1.1的介绍,需要先执行开启CPU2的代码,即:

Device_bootCPU2(BOOT_MODE_CPU2);

第二步:清除IPC标志位,通过IPC_FLAG31同步两个CPU时钟,代码如下

    IPC_clearFlagLtoR(IPC_CPU1_L_CPU2_R, IPC_FLAG_ALL);//清除IPC的所有标志位IPC_sync(IPC_CPU1_L_CPU2_R, IPC_FLAG31);//通过IPC_FLAG31同步两个CPU时钟

第一行解释为:清除CPU1与CPU2通信的IPC的所有FLAG。

第二行解释为:同步CPU时钟代码。

第三步:设置要发送的信息,代码为下:

#pragma DATA_SECTION(readData,"MSGRAM_CPU1_TO_CPU2")
float readData[10];
int i,j;
for(i=0; i<10; i++)
{j++;readData[i] = i + j*0.5f;
}

第一行解释为:是 TI 编译器的一条 编译指令(pragma 指令),用于将变量 readData 放入指定的内存段 "MSGRAM_CPU1_TO_CPU2" 中,而不是默认的数据段(如 .data.bss

地址在:

MEMORY
{CPU1TOCPU2RAM   : origin = 0x03A000, length = 0x000800CPU2TOCPU1RAM   : origin = 0x03B000, length = 0x000800}SECTIONS
{MSGRAM_CPU1_TO_CPU2 : > CPU1TOCPU2RAM, type=NOINITMSGRAM_CPU2_TO_CPU1 : > CPU2TOCPU1RAM, type=NOINIT}

第二行解释位:定义数据类型,定义为了一个数组。

第三,四,五行解释为:对数据进行初始化。

第四步:发送数据

while(1)
{DEVICE_DELAY_US(5000000);IPC_sendCommand(IPC_CPU1_L_CPU2_R, IPC_FLAG0, IPC_ADDR_CORRECTION_ENABLE,IPC_CMD_READ_MEM, (uint32_t)readData, 10);for(i=0; i<10; i++){j++;readData[i] = i + j*0.5f;}
}

延迟是为了防止数据发送较快,看不出效果,IPC_sendCommand函数中为要发送的数据,数据使用了地址修正功能,

为对数据发送没有影响,可以理解为对数据的功能进行标定,方便对数据进行存储,处理。

CPU1主函数总代码为:

#include "driverlib.h"
#include "device.h"
#include "board.h"
#include "IPC.h"
#include "stdio.h"
#include "Interrupt.h"
#include "string.h"
#include "Modbus.h"
#pragma DATA_SECTION(readData,"MSGRAM_CPU1_TO_CPU2")
float readData[10];
int i,j;
void main(void)
{Device_init();//初始化所有时钟以及外设Interrupt_initModule();//初始化PIE,清除所有PIE寄存器,失能CPU中断Interrupt_initVectorTable();//初始化PIE向量表Board_init();//初始化来自SysConfig的配置Device_bootCPU2(BOOT_MODE_CPU2);//启动CPU2核心部分TX_EN;//RS485发送信息使能IPC_clearFlagLtoR(IPC_CPU1_L_CPU2_R, IPC_FLAG_ALL);//清除IPC的所有标志位IPC_sync(IPC_CPU1_L_CPU2_R, IPC_FLAG31);//通过IPC_FLAG31同步两个CPU时钟EINT;//使能全部中断ERTM;//使能允许调试setvbuf(stdout, NULL, _IONBF, 0);//防止发送堵塞while(1){DEVICE_DELAY_US(5000000);IPC_sendCommand(IPC_CPU1_L_CPU2_R, IPC_FLAG0, IPC_ADDR_CORRECTION_ENABLE,IPC_CMD_READ_MEM, (uint32_t)readData, 10);for(i=0; i<10; i++){j++;readData[i] = i + j*0.5f;}}
}

我是接着我上个文章的代码写的,使用这个主要是为了好测试,若有不懂的代码可以观看我的另一篇博客:TMS320F28388使用sysconfig配置SCI通信(RS485+FIFO+Modbus)

2.2 CPU1的IPC中断代码

__interrupt void IPC_1_ISR(void)
{int i;uint32_t command, addr, data;IPC_readCommand(IPC_CPU1_L_CPU2_R, IPC_FLAG1, IPC_ADDR_CORRECTION_ENABLE,&command, &addr, &data);if(command == IPC_CMD_RESP){float* recvData = (float*)addr;for(i=0; i<data; i++){printf("Float[%d] = %f\r\n", i, recvData[i]);}}IPC_ackFlagRtoL(IPC_CPU1_L_CPU2_R, IPC_FLAG1);Interrupt_clearACKGroup(IPC_1_INTERRUPT_ACK_GROUP);}

2.3 CPU2的主函数IPC代码

第一步:同CPU1的一样,清除IPC标志位,通过IPC_FLAG31同步两个CPU时钟,代码如下

IPC_clearFlagLtoR(IPC_CPU2_L_CPU1_R, IPC_FLAG_ALL);//清除IPC的所有标志位
IPC_sync(IPC_CPU2_L_CPU1_R, IPC_FLAG31);//通过IPC_FLAG31同步两个CPU时钟

第一行解释为:清除CPU1与CPU2通信的IPC的所有FLAG。

第二行解释为:同步CPU时钟代码。

第二步:设置要发送的信息,代码为下:

#pragma DATA_SECTION(Data,"MSGRAM_CPU2_TO_CPU1")
float Data[10];
int i,j;
for(i = 0; i < 10; i++)
{Data[i] = i + j*0.1f; // 与CPU1的内容区分
}

第一行解释为:同CPU1一样,是 TI 编译器的一条 编译指令(pragma 指令),用于将变量 Data 放入指定的内存段 "MSGRAM_CPU2_TO_CPU1" 中,而不是默认的数据段(如 .data.bss

地址在:

MEMORY
{CPU1TOCPU2RAM   : origin = 0x03A000, length = 0x000800CPU2TOCPU1RAM   : origin = 0x03B000, length = 0x000800}SECTIONS
{MSGRAM_CPU1_TO_CPU2 : > CPU1TOCPU2RAM, type=NOINITMSGRAM_CPU2_TO_CPU1 : > CPU2TOCPU1RAM, type=NOINIT}

第二行解释位:定义发送数据类型,定义为了一个数组。

第三,四,五行解释为:对数据进行初始化。

第四步:发送数据

while(1)
{DEVICE_DELAY_US(5000000);IPC_sendCommand(IPC_CPU2_L_CPU1_R, IPC_FLAG1, IPC_ADDR_CORRECTION_ENABLE,IPC_CMD_RESP, (uint32_t)Data, 10);for(i = 0; i < 10; i++){Data[i] = i + j*0.1f; // 与CPU1的内容区分}
}

延迟是为了防止数据发送较快,看不出效果,IPC_sendCommand函数中为要发送的数据,数据使用了地址修正功能,

为对数据发送没有影响,可以理解为对数据的功能进行标定,方便对数据进行存储,处理。

CPU2主函数总代码为:

#include "driverlib.h"
#include "device.h"
#include "board.h"
#include "IPC.h"
#include "Interrupt.h"
#include "stdio.h"
int i,j;
#pragma DATA_SECTION(Data, "MSGRAM_CPU2_TO_CPU1")
float Data[10];
void main(void)
{Device_init();//初始化设备时钟和外设Interrupt_initModule();//初始化PIE,清除PIE寄存器,失能CPU中断Interrupt_initVectorTable();//初始化PIE向量表Board_init();//初始化SysConfig配置的外设IPC_clearFlagLtoR(IPC_CPU2_L_CPU1_R, IPC_FLAG_ALL);//清除IPC的所有标志位IPC_sync(IPC_CPU2_L_CPU1_R, IPC_FLAG31);//通过IPC_FLAG31同步两个CPU时钟EINT;//使能所有中断ERTM;//使能允许调试while(1){DEVICE_DELAY_US(5000000);IPC_sendCommand(IPC_CPU2_L_CPU1_R, IPC_FLAG1, IPC_ADDR_CORRECTION_ENABLE,IPC_CMD_RESP, (uint32_t)Data, 10);j++;for(i = 0; i < 10; i++){Data[i] = i + j*0.1f; // 与CPU1的内容区分}}
}

2.4 CPU2的IPC中断代码为

__interrupt void IPC_0_ISR()
{int i;uint32_t command, addr, data;IPC_readCommand(IPC_CPU2_L_CPU1_R, IPC_FLAG0, IPC_ADDR_CORRECTION_ENABLE,&command, &addr, &data);if(command == IPC_CMD_READ_MEM){float* recvData = (float*)addr;for(i=0; i<data; i++){printf("Float[%d] = %f\r\n", i, recvData[i]);}}IPC_ackFlagRtoL(IPC_CPU2_L_CPU1_R, IPC_FLAG0);Interrupt_clearACKGroup(IPC_0_INTERRUPT_ACK_GROUP);
}

第三章 测试结果

CPU1接收到的数据为:

在这里插入图片描述

该数据是由CPU2发送的,发送的数据代码为:

for(i = 0; i < 10; i++)
{Data[i] = i + j*0.1f; // 与CPU1的内容区分
}

CPU1接收到的数据符合我们想要发送的数据。通信正常,关于如何使用printf函数,我的上一篇博客有详细的介绍。链接为:TMS320F28388使用sysconfig配置SCI通信(RS485+FIFO+Modbus)

CPU2接收到的数据为:

在这里插入图片描述

该数据是由CPU1发送的,发送的数据代码为:

for(i=0; i<10; i++)
{j++;readData[i] = i + j*0.5f;
}

CPU2接收到的数据也符合我们想要发送的数据。通信正常,关于如何使用printf函数打印到控制台,我的上一篇博客也有详细的介绍。链接为:TMS320F28388使用sysconfig配置SCI通信(RS485+FIFO+Modbus)

制作不易,使用请点赞收藏。


http://www.hkcw.cn/article/ddbDlYyIMj.shtml

相关文章

Linux的线程同步

一、互斥锁&#xff08;互斥量&#xff09; 互斥锁是一种特殊的变量&#xff0c;有上锁&#xff08;lock&#xff09;和解锁&#xff08;unlock&#xff09;两种状态。 当处于解锁状态时&#xff0c;线程想获取该互斥锁&#xff0c;就可以获取不被阻塞&#xff0c;互斥锁变为…

.NET WinForm图像识别二维码/条形码

需求:图像识别出一张图片中的二维码或者条形码&#xff0c;并读取其中的内容。 一、安装ZXing.NET(此处建议使用0.14.0&#xff0c;高版本的不少地方进行优化&#xff0c;如果能处理好也可) Install-Package ZXing.Net 二、WinForm示例代码&#xff08;含关键优化&#xff0…

理解教材意图轻松积累常见数列

教学感悟 以前在传授数列时只是机械的要求学生记住常见的数列&#xff0c;至于“哪些才算是常见的数列&#xff1f;这些数列是怎么来的”&#xff0c;心里比较糊涂&#xff0c;在有一次的教学中&#xff0c;偶然回忆起&#xff1a;函数教学时教材要求掌握一些常见的函数&#…

[预训练]Encoder-only架构的预训练任务核心机制

原创文章1FFN前馈网络与激活函数技术解析&#xff1a;Transformer模型中的关键模块2Transformer掩码技术全解析&#xff1a;分类、原理与应用场景3【大模型技术】Attention注意力机制详解一4Transformer核心技术解析LCPO方法&#xff1a;精准控制推理长度的新突破5Transformer模…

【大模型MCP】MCP 深度解析:AI 时代的「USB-C」接口——原理、对比、实战代码与行业落地

摘要 模型上下文协议 (Model Context Protocol, MCP) 诞生于 2024 年11月&#xff0c;由 Anthropic 牵头&#xff0c;在 2025-03-26 发布 1.0 正式规范。它以 JSON-RPC 2.0 消息结构承载于 WebSocket / SSE 等全双工传输之上&#xff0c;把「初始化 → 工具目录 → 调用 → 结…

超声波清洗机的作用是什么?使用超声波清洗机可以去除毛刺吗?

在现代制造业中&#xff0c;表面质量对产品的性能和外观至关重要。超声波清洗机作为一种高效的清洗工具&#xff0c;在去除表面污垢和缺陷方面发挥着关键作用。本文深圳科伟达将介绍超声波清洗机的作用&#xff0c;以及它是否能够有效去除毛刺。 超声波清洗机的作用&#xff1…

非常好看网站维护带倒计时模板+维护结束模板

非常好看网站维护带倒计时模板维护结束模板 网站维护带倒计时模板维护结束模板.zip - 蓝奏云

STM32F103_Bootloader程序开发05 - Keil修改生成文件的路径与文件名,自动生成bin格式文件

导言 通过Keil的相关配置&#xff0c;可以灵活地修改输出文件的保存路径及文件名称。在Bootloader程序开发过程中&#xff0c;合理配置输出文件对于后续固件升级和自动化脚本处理至关重要。完成路径和文件名配置后&#xff0c;还可以借助Keil自带的fromelf.exe工具&#xff0c;…

【MQ】消息队列的核心价值及技术选型

文章目录 一、什么是消息队列二、消息队列的核心功能三、主流消息队列技术对比ActiveMQ&#xff1a;逐渐淡出的老牌产品Kafka&#xff1a;大数据领域的王者RabbitMQ&#xff1a;企业级可靠选择Apache Pulsar&#xff1a;云原生时代的"新贵"NATS&#xff1a;轻量级消息…

本地部署消息代理软件 RabbitMQ 并实现外部访问( Windows 版本 )

RabbitMQ 是由 Erlang 语言开发的 消息中间件&#xff0c;是一种应用程序之间的通信方法。支持多种编程和语言和协议发展&#xff0c;用于实现分布式系统的可靠消息传递和异步通信等方面。 本文将详细介绍如何在 Windows 系统本地部署 RabbitMQ 并结合路由侠实现外网访问本…

如何在 Odoo 18 中创建 PDF 报告

如何在 Odoo 18 中创建 PDF 报告 Qweb 是 Odoo 强大的模板引擎&#xff0c;旨在轻松将 XML 数据转换为 HTML 文档。其功能特性包括基于属性的自定义、条件逻辑、动态内容插入及多样化的报告模板选项。这种多功能性使 Qweb 成为制作个性化、视觉吸引力强的报告、电子邮件和文档…

【面板数据】上市公司供应链网络地位数据(2001-2024年)

企业是产业链供应链的微观主体&#xff0c;其供应链网络布局是增强产业链供应链稳定性的重中之重&#xff0c;企业在供应链网络中的地位&#xff0c;已成为衡量其市场影响力和风险承受能力的重要指标。本次是上市公司供应链网络地位数据&#xff0c;数据年份为2001-2024年。 一…

EasyFileCount(文件查重工具) v3.0.5.1 便携版

EasyFileCount 是一款免费方便、快捷的文件管理软件&#xff0c;采用Java开发&#xff0c;主打一个清爽简洁、安全无害的使用体验&#xff0c;支持多盘高性能扫描。遍历扫描文件夹的速度还算比较快的&#xff0c;当然所谓的快慢取决于CPU、系统、硬盘种类、文件或文件夹的数量等…

【在线五子棋对战】一、项目简介 环境搭建

文章目录 Ⅰ. 项目简介Ⅱ. 开发环境Ⅲ. 核心技术Ⅳ. 环境搭建① CentOS-7.6环境搭建1、安装wget工具2、更换软件源3、安装第三方软件源4、安装lrzsz传输工具5、安装高版本gcc/g编译器6、安装gdb调试器7、安装git8、安装cmake9、安装boost库10、安装Jsoncpp库11、安装MySQL数据库…

MFC坦克大战游戏制作

MFC坦克大战游戏制作 前言 现在的游戏制作一般是easyx&#xff0c;有没有直接只用mfc框架的&#xff0c;笔者研究了一番&#xff0c;做出了一个雏形&#xff0c;下面把遇到的问题总结出来 一、MFC框架制作游戏 初步设想&#xff0c;MFC可以选用 对话框 或者 单文档 结构&…

12:遨博机器人SDK二次开发

一、流程步骤 1.获取当前点关节坐标 2.走当前点关节坐标 1.获取目标点x,y,z&#xff08;位置坐标&#xff0c;以m为单位&#xff0c;需要*1000变成mm&#xff09;和四元素&#xff08;位姿坐标&#xff09; 2.四元素→欧拉角&#xff08;弧度制&#xff09; 3.欧拉角&#x…

XPlifeapp:高效打印,便捷生活

在数字化时代&#xff0c;虽然电子设备的使用越来越普遍&#xff0c;但打印的需求依然存在。无论是学生需要打印课表、资料&#xff0c;还是职场人士需要打印名片、报告&#xff0c;一个高效便捷的打印软件都能大大提高工作效率。XPlifeapp就是这样一款超级好用的手机打印软件&…

DeepSeekMath:突破开放式语言模型中数学推理能力的极限

摘要 由于数学推理具有复杂且结构化的特性&#xff0c;这对语言模型构成了重大挑战。在本文中&#xff0c;我们介绍了 DeepSeekMath 7B 模型&#xff0c;该模型在 DeepSeek-Coder-Base-v1.5 7B 模型的基础上&#xff0c;使用从 Common Crawl 获取的 1200 亿个与数学相关的标记…

OpenBayes 教程上新丨谷歌发布 MedGemma,基于 Gemma 3 构建,专攻医学文本与图像理解

在 Google I/O 2025 大会上&#xff0c;公司 CEO Sundar Pichai 在活动首日的主题演讲中便分享了多项创新&#xff0c;例如 Gemini 2.5 的全系列升级&#xff0c;Agent Mode 上线 Chrome&#xff0c;编码智能体 Jules 开启公测&#xff0c;Android XR 正式版亮相等等。而在一众…

【数据结构】栈和队列(下)

目录 一、队列&#xff08;先进先出的特殊结构&#xff09; 队列的概念与结构 二、代码实现 1、定义队列的结构 2、队列的初始化操作 3、判空操作 4、入队操作 5、出队操作 6、取队头、队尾操作 7、队列销毁操作 8、队列中有效数据个数 9、测试代码 10、.h文件 一…