2837xD之IPC通信(共享内存)_ipcltorflagset-程序员宅基地

技术标签: dsp  2837x  ipc  

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交互信息后跑通信。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_42151264/article/details/106903203

智能推荐

攻防世界_难度8_happy_puzzle_攻防世界困难模式攻略图文-程序员宅基地

文章浏览阅读645次。这个肯定是末尾的IDAT了,因为IDAT必须要满了才会开始一下个IDAT,这个明显就是末尾的IDAT了。,对应下面的create_head()代码。,对应下面的create_tail()代码。不要考虑爆破,我已经试了一下,太多情况了。题目来源:UNCTF。_攻防世界困难模式攻略图文

达梦数据库的导出(备份)、导入_达梦数据库导入导出-程序员宅基地

文章浏览阅读2.9k次,点赞3次,收藏10次。偶尔会用到,记录、分享。1. 数据库导出1.1 切换到dmdba用户su - dmdba1.2 进入达梦数据库安装路径的bin目录,执行导库操作  导出语句:./dexp cwy_init/[email protected]:5236 file=cwy_init.dmp log=cwy_init_exp.log 注释:   cwy_init/init_123..._达梦数据库导入导出

js引入kindeditor富文本编辑器的使用_kindeditor.js-程序员宅基地

文章浏览阅读1.9k次。1. 在官网上下载KindEditor文件,可以删掉不需要要到的jsp,asp,asp.net和php文件夹。接着把文件夹放到项目文件目录下。2. 修改html文件,在页面引入js文件:<script type="text/javascript" src="./kindeditor/kindeditor-all.js"></script><script type="text/javascript" src="./kindeditor/lang/zh-CN.js"_kindeditor.js

STM32学习过程记录11——基于STM32G431CBU6硬件SPI+DMA的高效WS2812B控制方法-程序员宅基地

文章浏览阅读2.3k次,点赞6次,收藏14次。SPI的详情简介不必赘述。假设我们通过SPI发送0xAA,我们的数据线就会变为10101010,通过修改不同的内容,即可修改SPI中0和1的持续时间。比如0xF0即为前半周期为高电平,后半周期为低电平的状态。在SPI的通信模式中,CPHA配置会影响该实验,下图展示了不同采样位置的SPI时序图[1]。CPOL = 0,CPHA = 1:CLK空闲状态 = 低电平,数据在下降沿采样,并在上升沿移出CPOL = 0,CPHA = 0:CLK空闲状态 = 低电平,数据在上升沿采样,并在下降沿移出。_stm32g431cbu6

计算机网络-数据链路层_接收方收到链路层数据后,使用crc检验后,余数为0,说明链路层的传输时可靠传输-程序员宅基地

文章浏览阅读1.2k次,点赞2次,收藏8次。数据链路层习题自测问题1.数据链路(即逻辑链路)与链路(即物理链路)有何区别?“电路接通了”与”数据链路接通了”的区别何在?2.数据链路层中的链路控制包括哪些功能?试讨论数据链路层做成可靠的链路层有哪些优点和缺点。3.网络适配器的作用是什么?网络适配器工作在哪一层?4.数据链路层的三个基本问题(帧定界、透明传输和差错检测)为什么都必须加以解决?5.如果在数据链路层不进行帧定界,会发生什么问题?6.PPP协议的主要特点是什么?为什么PPP不使用帧的编号?PPP适用于什么情况?为什么PPP协议不_接收方收到链路层数据后,使用crc检验后,余数为0,说明链路层的传输时可靠传输

软件测试工程师移民加拿大_无证移民,未受过软件工程师的教育(第1部分)-程序员宅基地

文章浏览阅读587次。软件测试工程师移民加拿大 无证移民,未受过软件工程师的教育(第1部分) (Undocumented Immigrant With No Education to Software Engineer(Part 1))Before I start, I want you to please bear with me on the way I write, I have very little gen...

随便推点

Thinkpad X250 secure boot failed 启动失败问题解决_安装完系统提示secureboot failure-程序员宅基地

文章浏览阅读304次。Thinkpad X250笔记本电脑,装的是FreeBSD,进入BIOS修改虚拟化配置(其后可能是误设置了安全开机),保存退出后系统无法启动,显示:secure boot failed ,把自己惊出一身冷汗,因为这台笔记本刚好还没开始做备份.....根据错误提示,到bios里面去找相关配置,在Security里面找到了Secure Boot选项,发现果然被设置为Enabled,将其修改为Disabled ,再开机,终于正常启动了。_安装完系统提示secureboot failure

C++如何做字符串分割(5种方法)_c++ 字符串分割-程序员宅基地

文章浏览阅读10w+次,点赞93次,收藏352次。1、用strtok函数进行字符串分割原型: char *strtok(char *str, const char *delim);功能:分解字符串为一组字符串。参数说明:str为要分解的字符串,delim为分隔符字符串。返回值:从str开头开始的一个个被分割的串。当没有被分割的串时则返回NULL。其它:strtok函数线程不安全,可以使用strtok_r替代。示例://借助strtok实现split#include <string.h>#include <stdio.h&_c++ 字符串分割

2013第四届蓝桥杯 C/C++本科A组 真题答案解析_2013年第四届c a组蓝桥杯省赛真题解答-程序员宅基地

文章浏览阅读2.3k次。1 .高斯日记 大数学家高斯有个好习惯:无论如何都要记日记。他的日记有个与众不同的地方,他从不注明年月日,而是用一个整数代替,比如:4210后来人们知道,那个整数就是日期,它表示那一天是高斯出生后的第几天。这或许也是个好习惯,它时时刻刻提醒着主人:日子又过去一天,还有多少时光可以用于浪费呢?高斯出生于:1777年4月30日。在高斯发现的一个重要定理的日记_2013年第四届c a组蓝桥杯省赛真题解答

基于供需算法优化的核极限学习机(KELM)分类算法-程序员宅基地

文章浏览阅读851次,点赞17次,收藏22次。摘要:本文利用供需算法对核极限学习机(KELM)进行优化,并用于分类。

metasploitable2渗透测试_metasploitable2怎么进入-程序员宅基地

文章浏览阅读1.1k次。一、系统弱密码登录1、在kali上执行命令行telnet 192.168.26.1292、Login和password都输入msfadmin3、登录成功,进入系统4、测试如下:二、MySQL弱密码登录:1、在kali上执行mysql –h 192.168.26.129 –u root2、登录成功,进入MySQL系统3、测试效果:三、PostgreSQL弱密码登录1、在Kali上执行psql -h 192.168.26.129 –U post..._metasploitable2怎么进入

Python学习之路:从入门到精通的指南_python人工智能开发从入门到精通pdf-程序员宅基地

文章浏览阅读257次。本文将为初学者提供Python学习的详细指南,从Python的历史、基础语法和数据类型到面向对象编程、模块和库的使用。通过本文,您将能够掌握Python编程的核心概念,为今后的编程学习和实践打下坚实基础。_python人工智能开发从入门到精通pdf