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_C28335\SXD28335_PRO_1_V2\Example_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,飛翔吧,上一個妹子的照片

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM