2837xD之IPC通信(共享内存)

本文详细介绍了TI公司的双核DSP(F2837xD系列)通过IPC(进程间通信)进行通信的原理及具体实现。重点分析了共享内存(MessageRAM)的使用,包括如何在CPU1和CPU2之间分配共享RAM区域,数据交换流程,以及通过IPC标志通知对方CPU进行数据读取和写入的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

IPC通信基本原理

  • IPC通信是TI公司的一种双核通信方式,主要有:1.共享内存(Message RAM) 2.共享寄存器(Message register) 3.IPC lite 等等。本次分析的是TI公司的例程(基于2837xD)。

程序部分

一、CPU1程序注释

  • 例程目标:
// //###########################################################################
FILE:   RAM_management_cpu01.c
TITLE:  RAM management Example for F2837xD.

//This example shows how to assign shared RAM for use by both the CPU02 
//and CPU01 core.   //使用CPU1与CPU2进行通信
//Shared RAM regions are defined in  both the CPU02 and CPU01 linker files.
// In this example GS0 and GS14 are assigned to/owned by CPU02. The remaining 
// shared RAM regions are owned by CPU01.
//! In this example:
//! 
//! A pattern is written to c1_r_w_array and then IPC flag is sent to notify 
//! CPU02 that data is ready to be read. CPU02 then reads the data from
//! c2_r_array and writes a modified pattern to c2_r_w_array. Once CPU02 acknowledges
//! the IPC flag to , CPU01 reads the data from c1_r_array and compares with expected
//! result.
//! 
//! A Timed ISR is also serviced in both CPUs. The ISRs are copied into the shared 
//! RAM region owned by the respective CPUs. Each ISR toggles a GPIO. Watch GPIO31
//! and GPIO34 on oscilloscope. If using the control card watch LED1 and LED2 blink
//! at different rates.
//!  - c1_r_w_array[] is mapped to shared RAM GS1
//!  - c1_r_array[]   is mapped to shared RAM GS0
//!  - c2_r_array[]   is mapped to shared RAM GS1
//!  - c2_r_w_array[] is mapped to shared RAM GS0
//!  - cpu_timer0_isr in CPU02 is copied to shared RAM GS14 , toggles GPIO31
//!  - cpu_timer0_isr in CPU01 is copied to shared RAM GS15 , toggles GPIO34
//!
//! \b  Watch \b Variables
//!
//!  - error Indicates that the data written is not correctly received by the other CPU.
//
//###########################################################################
// $TI Release: F2837xD Support Library v190 $
// $Release Date: Mon Feb  1 16:51:57 CST 2016 $
// $Copyright: Copyright (C) 2013-2016 Texas Instruments Incorporated -
//             http://www.ti.com/ ALL RIGHTS RESERVED $
//###########################################################################;

以上文档说明指出

  • 1.Share RAM 区域需要在CPU1和CPU2的ilnk文件进行定义。
    2.本例中定义GS0和GS14属于CPU2,剩下的空间属于CPU1
    3.数据将被CPU1写入c1_r_w_array数组,然后通过IPC_flag通知CPU2。
    4.CPU2从c2_r_array读取数据,然后将修改后的数据写入c2_r_w_array,然后通过IPC_flag通知CPU1。

二、CPU1主程序部分

#include "F28x_Project.h"
#include "F2837xD_Ipc_drivers.h"

// Data exchange arrays  32*256=2^12
uint16_t c1_r_array[256];  
uint16_t c1_r_w_array[256]; 
#pragma DATA_SECTION(c1_r_array,"SHARERAMGS0"); // 分配到GS0(CPU2)
#pragma DATA_SECTION(c1_r_w_array,"SHARERAMGS1");// 分配到GS1(CPU1)

// Global variables 
uint16_t error;
uint16_t multiplier;

// External variables declared by linker.
extern uint16_t isrfuncLoadStart;
extern uint16_t isrfuncLoadEnd;
extern uint16_t isrfuncRunStart;
extern uint16_t isrfuncLoadSize;

// Prototype statements for functions found within this file.
__interrupt void cpu_timer0_isr(void);
#pragma CODE_SECTION(cpu_timer0_isr,"isrfunc") //中断程序放置到GS14

// Functions to read and write data
void Shared_Ram_dataRead_c1(void);
void Shared_Ram_dataWrite_c1(void);

void main(void)
{
  //1.初始化程序
  InitSysCtrl(); 

#ifdef _STANDALONE
#ifdef _FLASH
  //  Send boot command to allow the CPU02 application to begin execution
  IPCBootCPU2(C1C2_BROM_BOOTMODE_BOOT_FROM_FLASH);
#else
  //  Send boot command to allow the CPU02 application to begin execution
  IPCBootCPU2(C1C2_BROM_BOOTMODE_BOOT_FROM_RAM);
#endif
#endif  //引导CPU2启动

// 2.初始化GPIO:
  InitGpio();  // Skipped for this example

// 3.关中断
  DINT;

// 初始化PIE
 InitPieCtrl();

// 清除中断
 IER = 0x0000;
 IFR = 0x0000;

// 初始化PIE向量表
 InitPieVectTable();
 
// GPIO31属于CPU2
  GPIO_SetupPinMux(31,GPIO_MUX_CPU2,0);
  GPIO_SetupPinOptions(31, GPIO_OUTPUT,0);
  
// GPIO34属于CPU1
  GPIO_SetupPinMux(34,GPIO_MUX_CPU1,0);
  GPIO_SetupPinOptions(34, GPIO_OUTPUT,0);    

// 将GS0和GS14控制权给CPU2
  while( !(MemCfgRegs.GSxMSEL.bit.MSEL_GS0 &
  		 MemCfgRegs.GSxMSEL.bit.MSEL_GS14))
  {
  	EALLOW;
  	MemCfgRegs.GSxMSEL.bit.MSEL_GS0 = 1;//0:CPU1 is master for this memory
  										//1:CPU2 is master for this memory
  	MemCfgRegs.GSxMSEL.bit.MSEL_GS14 = 1;
  	EDIS;
  }

//  将中断函数拷贝进入GS14 RAM空间
  memcpy(&isrfuncRunStart, &isrfuncLoadStart, (uint32_t)&isrfuncLoadSize);

//指定中断函数
  EALLOW;  // This is needed to write to EALLOW protected registers
  PieVectTable.TIMER0_INT = &cpu_timer0_isr;
  EDIS;    // This is needed to disable write to EALLOW protected registers
  
///初始化定时器
 InitCpuTimers();   // For this example, only initialize the Cpu Timers    
 
//设置定时器2s
 ConfigCpuTimer(&CpuTimer0, 200, 2000000); 

//启动定时器
 CpuTimer0Regs.TCR.all = 0x4000; // Use write-only instruction to set TSS bit = 0
 
// 开始中断
 IER |= M_INT1;   
 
// 开PIE
 PieCtrlRegs.PIEIER1.bit.INTx7 = 1;   
 
// Enable global Interrupts and higher priority real-time debug events:
 EINT;   // 开全局中断
 ERTM;   // 开启实时中断  
  // Main Code
  error = 0;
  multiplier = 0;
  Shared_Ram_dataWrite_c1();  //给c1_r_w_array数组中写入数据内容为[0]:multiplier,[1]-[255]=1-255
  IPCLtoRFlagSet(IPC_FLAG10); /挂起中断信号FLAG10
  
  while(1)
  {          
      // 如果没有挂起中断标志(代表CPU2已经操作完毕,ACK了FLAG10)
      if(IPCLtoRFlagBusy(IPC_FLAG10) == 0)
      {
          Shared_Ram_dataRead_c1();  //读取c1_r_array中的数据
          
          if(multiplier++ > 255)
          {
              multiplier = 0;
          }                                   //multipliter++,单只能在0-255中间循环
      
          //给c1_r_w_array数组中写入数据内容为[0]:multiplier,[1]-[255]=1-255
          Shared_Ram_dataWrite_c1();
          IPCLtoRFlagSet(IPC_FLAG10);
      }
  }
}

__interrupt void cpu_timer0_isr(void)
{
 EALLOW;
 CpuTimer0.InterruptCount++;  //记录进入中断次数
 GpioDataRegs.GPBTOGGLE.bit.GPIO34 = 1;  //GPIO34翻转
 EDIS;
 PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;   //清除中断标志
}

void Shared_Ram_dataWrite_c1(void)  //写入c1_r_w_array中数据
{
  uint16_t index;

  // Use first location to write a multiplier.
  c1_r_w_array[0] = multiplier;  //0
  
  for(index = 1; index < 256; index++)
  {
      c1_r_w_array[index] = index;
      //the following code will attempt to write to a shared RAM
      //assigned to cpu2 and as a result will cause an error.
      //c1_r_array[index] = 1000 + index;
  }
}

//读取CPU2处理后的数据并进行校验是否进行了乘法
void Shared_Ram_dataRead_c1(void)
{
  uint16_t index;

  if(c1_r_array[0] == multiplier)
  {
     for(index = 1; index < 256; index++)
     {
         if(c1_r_array[index] != multiplier*c1_r_w_array[index])
         {
             error = 1;        
         }
     }
  }
  else
  {
      error = 1;
  }
}

三、CPU2主程序部分

#include "F28x_Project.h"     
#include "F2837xD_Ipc_drivers.h"

uint16_t c2_r_w_array[256];  
uint16_t c2_r_array[256];     
#pragma DATA_SECTION(c2_r_array,"SHARERAMGS1"); //分配给GS1(CPU1)
#pragma DATA_SECTION(c2_r_w_array,"SHARERAMGS0"); //分配给GS0(CPU2)

// External variables declared by linker.
extern uint16_t isrfuncLoadStart;
extern uint16_t isrfuncLoadEnd;
extern uint16_t isrfuncRunStart;
extern uint16_t isrfuncLoadSize;

// Prototype statements for functions found within this file.
__interrupt void cpu_timer0_isr(void);
#pragma CODE_SECTION(cpu_timer0_isr,"isrfunc")

void Shared_Ram_dataWrite_c2(void);// function to write data from shared RAM owned by c2

void main(void)
{

//   InitSysCtrl();


// InitGpio();  // Skipped for this example


 DINT;


 InitPieCtrl();


 IER = 0x0000;
 IFR = 0x0000;


 InitPieVectTable();

// CPU1未分配RAM就一直等待
 while(!( MemCfgRegs.GSxMSEL.bit.MSEL_GS0 &
  	    MemCfgRegs.GSxMSEL.bit.MSEL_GS14 ) )
 {


 }
//  将中断拷贝进入RAM
  memcpy(&isrfuncRunStart, &isrfuncLoadStart, (uint32_t)&isrfuncLoadSize);

 EALLOW;  // This is needed to write to EALLOW protected registers
 PieVectTable.TIMER0_INT = &cpu_timer0_isr;
 EDIS;    // This is needed to disable write to EALLOW protected registers


 InitCpuTimers();   // For this example, only initialize the Cpu Timers

//定时器设置为1s
 ConfigCpuTimer(&CpuTimer0, 200, 1000000);

// 启动定时器
 CpuTimer0Regs.TCR.all = 0x4000; // Use write-only instruction to set TSS bit = 0

// Step 5. User specific code, enable interrupts:

// Enable CPU int1 which is connected to CPU-Timer 0
 IER |= M_INT1;

// Enable TINT0 in the PIE: Group 1 interrupt 7
 PieCtrlRegs.PIEIER1.bit.INTx7 = 1;

// Enable global Interrupts and higher priority real-time debug events:
 EINT;   // Enable Global interrupt INTM
 ERTM;   // Enable Global realtime interrupt DBGM
 
 while(1)
 {
 //如果CPU1挂起了中断线FLAG10
      if(IPCRtoLFlagBusy(IPC_FLAG10) == 1)
      {       
          //Read c2_r_array and modify c2_r_w_array  
          Shared_Ram_dataWrite_c2();     //处理CPU1传送来的信息
       
          IPCRtoLFlagAcknowledge (IPC_FLAG10);            //应答
       }            
 }
}

// function definitions
__interrupt void cpu_timer0_isr(void)  //每1s进入一次中断程序
{
 EALLOW;
 CpuTimer0.InterruptCount++;
 GpioDataRegs.GPATOGGLE.bit.GPIO31 = 1; //灯光闪烁一次
 EDIS;
 PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}

// Read data from c2_r_array written by CPU01 and 
// modify and write into c2_r_w_array
// c2_r_array[0] is used to hold the multiplier value.
void Shared_Ram_dataWrite_c2(void)
{
  uint16_t index;
  uint16_t multiplier;
  
  multiplier = c2_r_array[0];
  c2_r_w_array[0] = multiplier;
  
  for(index = 1; index < 256; index ++)
  {
      c2_r_w_array[index] = multiplier*c2_r_array[index];
  }
}

致谢

本博客仅供记录学习过程和分享学习心得使用,感谢提供源码的公司。

第一次开博客了,想记录一下学习的过程。坐标武汉小硕一名,目前在学习dsp。现在想的是做出双核程序,CPU1跑算法,CPU2通过IPC交互信息后跑通信。

<think>好的,用户现在想了解Texas Instruments XDS110是什么以及它在CCS中的作用。我需要先回顾之前的对话,确保回答的一致性和准确性。之前用户遇到了XDS110的连接问题,已经给出了解决方案。现在用户的问题转向更基础的知识,需要详细解释XDS110的功能和作用。 首先,我需要确认用户可能的需求。用户可能刚开始使用TI的微控制器,需要了解调试工具的基本信息,或者他们在解决问题后想更深入了解工具本身。他们可能想知道XDS110在开发流程中的位置,以及为什么它对于CCS如此重要。 接下来,我要参考之前提供的引用内容。引用[1]提到XDS110的错误信息和固件更新方法,引用[2]和[3]涉及XDS100系列的设置和连接问题,而引用[4]同样涉及连接问题。不过,用户现在的问题是关于XDS110本身,所以需要结合这些信息中的相关内容,比如固件更新工具xdsdfu的位置,以及调试配置的设置。 我需要明确XDS110的基本定义,它的作用,以及它在CCS中的具体应用。可能需要分点说明,比如硬件组成、核心功能、在CCS中的作用等。同时,用户可能想知道XDS110与其他调试器(如XDS100系列)的区别,所以在比较部分需要简明扼要。 另外,用户可能对如何正确使用XDS110在CCS中感兴趣,比如配置步骤、常见问题的预防措施。需要结合之前提供的解决方案中的步骤,如固件更新、驱动检查等,来补充说明如何确保XDS110的正常工作。 还要注意回答的结构,确保清晰易懂。可能需要分为几个部分,如设备概述、核心功能、CCS中的作用、与其他调试器的比较、使用注意事项等。同时,要使用用户之前问题中提到的示例,比如xdsdfu工具的位置,以及在CCS中配置调试连接的方法。 最后,生成的相关问题需要引导用户进一步了解XDS110的使用技巧、故障排查或与其他工具的对比,这样有助于他们深入学习。例如,如何更新固件,XDS110与其他调试器的性能差异,或者常见错误的解决方法。 需要确保回答中的技术术语准确,同时用中文通俗易懂地表达。避免过于复杂的解释,但又要涵盖关键点,比如JTAG/SWD接口支持、实时调试功能、电源管理选项等。此外,引用之前的解决方案中的步骤,如使用xdsdfu工具更新固件,可以增强回答的实用性。 总结来说,回答需要全面覆盖XDS110的定义、功能、在CCS中的作用、与其他设备的比较以及使用注意事项,同时结合用户之前的经历,提供实际的操作示例和预防措施,确保用户不仅能理解理论,还能应用到实际开发中。</think>### Texas Instruments XDS110 详解及其在 CCS 中的作用 #### 一、XDS110 设备概述 **XDS110** 是 Texas Instruments(TI)推出的**全集成式调试探针**,专为 TI 微控制器(如 MSP430、MSPM0、C2000 等)和处理器设计。其核心功能是**建立 PC 端开发环境(如 CCS)与目标芯片之间的通信桥梁**,支持代码调试、程序烧录、实时数据监控等关键操作[^1]。 #### 二、核心功能与技术特性 1. **硬件构成** - 双核架构:包含 ARM Cortex-M3(调试控制) + 专用通信处理器 - 接口支持: $$ \text{JTAG/SWD (标准)} \quad \text{或} \quad \text{cJTAG (增强型)} $$ - 全速 USB 2.0 (480 Mbps) 2. **协议支持** | 协议类型 | 应用场景 | |----------------|--------------------------| | JTAG | 传统调试与边界扫描 | | SWD | 低引脚数调试(2线制) | | UART/SPI/I2C | 辅助通信通道 | #### 三、在 CCS 中的关键作用 1. **调试控制中枢** - 实时执行**断点调试**、寄存器/内存查看 - 支持**实时变量追踪**(例如通过 CCS 的 Expressions 窗口) ```c // 示例:调试过程中监控变量 volatile uint32_t sensor_value = 0; while(1) { sensor_value = ADC_read(); // 可在此行设置断点观察值变化 } ``` 2. **程序烧录引擎** - 支持多种烧录模式: $$ \text{Flash 编程} \rightarrow \text{通过 .out 或 .hex 文件} $$ $$ \text{RAM 调试} \rightarrow \text{直接加载到内存执行} $$ 3. **电源与时钟管理** - 可通过 CCS 界面配置目标板供电(默认 3.3V@500mA) - 动态调整 JTAG 时钟频率(建议范围: $$ 1\,\text{MHz} \leq f_{\text{TCLK}} \leq 15\,\text{MHz} $$ 过高频率可能导致通信失败[^2]) #### 四、与其他调试器的对比 | 特性 | XDS110 | XDS100v3 | |--------------------|----------------------------|--------------------------| | **供电能力** | 500mA | 200mA | | **固件更新** | 支持在线更新 (xdsdfu) | 需物理替换 | | **调试速度** | 最高 15 MHz | 最高 8 MHz | | **多核支持** | 是 | 否 | #### 五、典型应用配置流程(CCS 中) 1. **创建连接配置文件** - 文件类型:`.ccxml` - 选择芯片型号(如 MSPM0G3507) - 设置接口参数: ```xml <connection name="XDS110_JTAG"> <description>XDS110 via JTAG</description> <driver>Texas Instruments XDS110 USB Debug Probe</driver> <device>MSPM0G3507</device> </connection> ``` 2. **验证连接** - 在 CCS 中执行 **Test Connection** - 成功标志:返回设备 IDCODE $$ \text{IDCODE} = 0x0\text{x}1\text{be0}0\text{dd} (\text{示例值}) $$ #### 六、使用注意事项 1. **固件管理** - 定期检查固件版本: ```cmd xdsdfu -i ``` - 若版本低于 3.0.0.15,需按以下顺序更新: $$ \text{擦除} \rightarrow \text{烧录} \rightarrow \text{重启} $$[^1] 2. **环境隔离** - 避免同时连接多个调试器 - 关闭可能占用 USB 端口的软件(如串口助手、Zadig 等) --- ### 相关问题 1. 如何通过 xdsdfu 工具查看 XDS110 的固件版本? 2. XDS110 与 J-Link 在调试 TI 芯片时有何性能差异? 3. CCS 调试时出现 "Device ID mismatch" 错误应如何解决?
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Quikk

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值