zoukankan      html  css  js  c++  java
  • 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,飞翔吧,上一个妹子的照片

  • 相关阅读:
    numpy基本使用2
    python 继承 多态
    动态规划算法题(5题)
    利用栈非递归实现块排
    数据结构
    对Node的优点和缺点提出了自己的看法?
    前后端交互流程,如何进行交互
    Web App、Hybrid App与Native App的设计差异
    什么叫优雅降级和渐进增强?
    常用博客
  • 原文地址:https://www.cnblogs.com/429512065qhq/p/8433447.html
Copyright © 2011-2022 走看看