DSP28335的XINTF操作SRAM实验

1. 本次使用三兄弟的XDS28335开发板,研究一下XINTF操作SRAM的代码。哈弗结构,奇怪,DSP28335是哈弗结构,那么数据和程序空间应该独立的,为啥书上说采用统一的寻址方式?估计只是读写数据和程序的方法一样的意思。

2. 看下原理图部分,有地址线XA0-XA18,数据线XD0-XD15,XWEn是写信号(低电平有效),XRDn是读信号(低电平有效),F_CSn是片选信号(低电平有效)。

3. 看下芯片的XINTF章节介绍,最近TI把C2000系列划到MCU部分了,搞的找不到,Learn more(了解更多)。下图是DSP28335的内部地址空间,有3个区域,据说CCS可以通过仿真器直接访问XINTF连接的外部存储器,有点厉害。可以看下图的3个区域的地址空间,这里有个问题没明白,区域0的外部地址范围是0X00000-0X00FFF,如果要对区域0的第一个存储单元进行操作,需要将0X00000送到地址线,并将片选信号XZCS0拉低,这没问题,可是下面的0X0000 4000是什么地址?哎,好像明白了,0X0000 4000是DSP28335的内部地址,0X00000-0X00FFF是信号的地址,意思是程序里面写0X0000 4000这个地址,然后硬件上会把XZCS0拉低,XA(19:0)的值是0X00000,这个就是统一寻址的意思吧。本次SRAM用的是区域6。

4. 看下配置流程

5. 时钟的配置

6. 测试下代码,导入工程SXD_C28335SXD28335_PRO_1_V2Example_2833xCodeRunFromXintf,第一个问题下面是什么意思?百度了一下利用#pragma CODE_SECTION指令可以将程序从Flash搬到RAM中运行,从而提高程序执行速率,该方法需要完成以下四步。

第一步,利用#pragma CODE_SECTION指令关联程序和SECTIONS;主函数的一开始用#pragma CODE_SECTION 将中断函数 cpu_timer0_isr 和cpu_timer1_isr 指定到片外 SRAM 空间。 

// These two functions will be loaded into SARAM and copied to
// XINTF zone 6 for execution
#pragma CODE_SECTION(cpu_timer0_isr,"xintffuncs");
#pragma CODE_SECTION(cpu_timer1_isr,"xintffuncs");

第二步,为链接创建相关变量;

extern Uint16 XintffuncsLoadStart;
extern Uint16 XintffuncsLoadEnd;
extern Uint16 XintffuncsRunStart;
extern Uint16 XintffuncsLoadSize;

第三步,复制时间关键代码以及Flash设置代码到RAM;这个不懂,有什么用途?

memcpy(&XintffuncsRunStart, &XintffuncsLoadStart, (Uint32)&XintffuncsLoadSize);

第四步,修改CMD文件。这段程序的作用是将程序加载到片内 RAML1 空间中,运行时搬移到片外 ZONE6去 执 行 。 _XintffuncsLoadStart 为 变量加载的起始地址 、_XintffuncsLoadEnd 变量加载的结束地址、_XintffuncsRunStart 运行的起始地址、_XintffuncsLoadSize 加载代码的大小。这四个变量都是 CCS 自己算的(怎么算出来的,问题点?)。第一次接触这个机制,感觉很懵逼。把2个函数放到外部SRAM,那拷贝的时候怎么知道这个两个函数原来的地址和大小?理清思路,一个函数cpu_timer0_isr放到一个空间xintffuncs,这个空间配置如下(CMD文件只是配置地址空间而已):下面CMD文件只是为了生成4个变量给memcopy使用吗?

SECTIONS
{
   /* Setup for "boot to SARAM" mode: 
      The codestart section (found in DSP28_CodeStartBranch.asm)
      re-directs execution to the start of user code.  */
   codestart        : > BEGIN,     PAGE = 0
   ramfuncs         : > RAML0,     PAGE = 0  
   .text            : > RAML1,     PAGE = 0
   .cinit           : > RAML0,     PAGE = 0
   .pinit           : > RAML0,     PAGE = 0
   .switch          : > RAML0,     PAGE = 0

   xintffuncs       : LOAD = RAML1, 
                      RUN = ZONE6,
                      LOAD_START(_XintffuncsLoadStart),
                      LOAD_END(_XintffuncsLoadEnd),
                      RUN_START(_XintffuncsRunStart),
                      LOAD_SIZE(_XintffuncsLoadSize),
                      PAGE = 0
}

看下ZONE6的区域,既然4个变量是CCS自动算的。那么memcopy是什么用途?拷贝的是什么?是2个定时中断函数吗?指定到片外SRAM和可拷贝到片外SRAM的区别是什么?

   RAML1      : origin = 0x009000, length = 0x001000
   ZONE6      : origin = 0x180000, length = 0x001000 

看下这几个变量的定义,不过依然不太懂

00009741   _XintffuncsLoadEnd
00000029   _XintffuncsLoadSize
00009718   _XintffuncsLoadStart
00180000   _XintffuncsRunStart

7. 看下代码部分,关注关键点,是不是初始化区域6的SRAM之后,就可以把这两个中断函数复制到这个SRAM里面的意思?

// Initialize XINTF Zone 7
   init_zone6();  //首先要初始化访问 zone6 空间的时序

// Copy non-time critical code to XINTF
// This includes the following ISR functions: cpu_timer0_isr(), cpu_timer1_isr()
// The  XintffuncsLoadStart, XintffuncsLoadEnd, and XintffuncsRunStart
// symbols are created by the linker. Refer to the F28335_ram_xintf.cmd file.
   memcpy(&XintffuncsRunStart, &XintffuncsLoadStart, (Uint32)&XintffuncsLoadSize);

8. 本次例程有3个定时器中断函数,估计是2个拷贝到区域6的SRAM里面运行,一个在DSP28335的内部SRAM里面运行。

__interrupt void cpu_timer0_isr(void)
{
   CpuTimer0.InterruptCount++;
   // Acknowledge this interrupt to receive more interrupts from group 1
   PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}
__interrupt void cpu_timer1_isr(void)
{
   CpuTimer1.InterruptCount++;
   // The CPU acknowledges the interrupt.
   EDIS;
}
__interrupt void cpu_timer2_isr(void)
{  EALLOW;
   CpuTimer2.InterruptCount++;
   // The CPU acknowledges the interrupt.
   EDIS;
}

9. 看下XINTF的配置函数

void init_zone6(void)
{
    // Make sure the XINTF clock is enabled
    EALLOW;
    SysCtrlRegs.PCLKCR3.bit.XINTFENCLK = 1;
    EDIS;
    // Configure the GPIO for XINTF with a 16-bit data bus
    // This function is in DSP2833x_Xintf.c
    InitXintf16Gpio();
    EALLOW;
    // All Zones---------------------------------
    // Timing for all zones based on XTIMCLK = SYSCLKOUT
    XintfRegs.XINTCNF2.bit.XTIMCLK = 0;
    // Buffer up to 3 writes
    XintfRegs.XINTCNF2.bit.WRBUFF = 3;
    // XCLKOUT is enabled
    XintfRegs.XINTCNF2.bit.CLKOFF = 0;
    // XCLKOUT = XTIMCLK
    XintfRegs.XINTCNF2.bit.CLKMODE = 0;
    // Disable XHOLD to prevent XINTF bus from going into high impedance state
    // whenever TZ3 signal goes low. This occurs because TZ3 on GPIO14 is
    // shared with HOLD of XINTF
    XintfRegs.XINTCNF2.bit.HOLD = 1;
    // Zone 7------------------------------------
    // When using ready, ACTIVE must be 1 or greater
    // Lead must always be 1 or greater
    // Zone write timing
    XintfRegs.XTIMING6.bit.XWRLEAD = 1;
    XintfRegs.XTIMING6.bit.XWRACTIVE = 2;
    XintfRegs.XTIMING6.bit.XWRTRAIL = 1;
    // Zone read timing
    XintfRegs.XTIMING6.bit.XRDLEAD = 1;
    XintfRegs.XTIMING6.bit.XRDACTIVE = 3;
    XintfRegs.XTIMING6.bit.XRDTRAIL = 0;
    // don't double all Zone read/write lead/active/trail timing
    XintfRegs.XTIMING6.bit.X2TIMING = 0;
    // Zone will not sample XREADY signal
    XintfRegs.XTIMING6.bit.USEREADY = 0;
    XintfRegs.XTIMING6.bit.READYMODE = 0;
    // 1,1 = x16 data bus
    // 0,1 = x32 data bus
    // other values are reserved
    XintfRegs.XTIMING6.bit.XSIZE = 3;
    EDIS;
   //Force a pipeline flush to ensure that the write to
   //the last register configured occurs before returning.
   __asm(" RPT #7 || NOP");
}

10. 运行ccxml目标配置文件,启动,连接目标开发板,加载程序,

11. 首先将用于中断计数的 CpuTimer0.InterruptCount、CpuTimer1.InterruptCount 和 CpuTimer2.InterruptCount 添加到观察窗口中。并设置窗口为连续刷新。开始全速运行,可以看到这三个计数器会累加计数。我是全部加载到观察窗口了。

12. 看下内存空间,也可以通过View->Memory Browser查看cpu_timer0_isr 和cpu_timer1_isr 所在空间的地址。刚开始我选的Data,所以没找个这个函数,原来还有3个选项。切换到Program空间,找到函数。

13. DONE,飞翔吧,上一个妹子的照片

原文地址:https://www.cnblogs.com/429512065qhq/p/8433447.html