Keil MDK使用J-LINK分別在Sram,Nor Flash以及Sdram中調試代碼的原理和方法


一、概述

MDK開發ARM裸機程序時,在調試階段通常是先讓程序在SDRAM中執行,以加快調試速度,也避免頻繁燒寫Nor Flash,因此需要知道如何指定程序在哪個位置執行。本文以realarm 2410開發板為例,進行描述。該開發板使用S3C2410A做為CPU,有2MB的 Nor Flash,以及64MB的SDRAM,4KB的SRAM。程序可直接在Nor Flash中調試和運行,如果代碼小於4KB,也可以直接在SRAM中運行,然而在SDRAM 中運行,就需要事先用腳本初始化SDRAM,才能把程序加載到SDRAM中執行。

realarm2410使用Nor Flash時的內存映射,如下圖:

image

圖1

                                          

下面詳細說明各種情況。

 

二、程序在Nor Flash中調試

由圖1可見,CPU復位后PC指針為0,正好代碼在Flash中執行,因此,無需修改PC指針,僅需在程序的初始化部分初始化SDRAM,以及分配好Stack以及Heap則可,要使用分散加載文件*.sct指定程序鏈接加載的位置,分散加載文件如下:

; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************
LR_ROM1 0x0 0x00200000  {    ; load region size_region
  ER_ROM1 0x0 0x00200000  {  ; load address = execution address
   *.o (RESET, +First)
   *(InRoot$$Sections)
   .ANY (+RO)
  }
  RW_STACK 0x33ff3000   {  ; RW data
   *(STACK)
  }
  RW_HEAP 0x33ef3000   {  ; RW data
   *(HEAP)
  }
  RW_RAM1 0x30000000 0x04000000  {  ; RW data
   .ANY (+RW +ZI)
  }
  RW_IRAM1 0x40000000 0x00001000  {
   .ANY (+RW +ZI)
  }
}

分散加載文件LoadToFlash.sct

 

該分散加載文件把RO指定到0x0開始大小為0x200000的位置,即2MB的Flash中,RW指定在起始地址為0x30000000大小為0x4000000的64MB的SDRAM中,0x40000000開始的大小為0x1000的4KB的SRAM也作為RW區使用,而Stack則在SDRAM的0x33ff3000開始,Heap則在0x33ef3000開始。大小在初始化程序中指定,如下:

UND_Stack_Size  EQU     0x00000400
SVC_Stack_Size  EQU     0x00001000
ABT_Stack_Size  EQU     0x00000400
FIQ_Stack_Size  EQU     0x00001000
IRQ_Stack_Size  EQU     0x00001000
USR_Stack_Size  EQU     0x00001800
 
        
Stack_Size      EQU     (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size + \
                         FIQ_Stack_Size + IRQ_Stack_Size + USR_Stack_Size)
 
        
                AREA    STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem       SPACE   Stack_Size
 
        
Stack_Top       EQU     Stack_Mem + Stack_Size
 
        
 
        
 
        
Heap_Size       EQU     0x00100000
 
        
                AREA    HEAP, NOINIT, READWRITE, ALIGN=3
Heap_Mem        SPACE   Heap_Size

 

那么,SDRAM除了20KB的Stack和1MB的 Heap外,都當成了RW。SDRAM分配圖如下:

image

圖2

 

總而言之,要實現Flash調試代碼,需實現以下步驟:

  1. 通過設計分散加載文件,指定RO在Flash,同時分配好其它的RW以及Stack和Heap的地址,並配置工程使用分散加載文件來鏈接;
  2. S3C2410A.s要初始化SDRAM,並分配好Stack和Heap;
  3. 工程中設置使用J-LINK為Flash編程,並設置好Flash的編程算法,勾選調試前需更新代碼;
  4. 在工程設置中設置為調試前更新代碼;具體需特別說明的工程設置圖如下:
image

圖3:指定Link按照LoadToFlash.sct規則執行

 

image

圖4:指定使用J-LINK/J-TRACK ARM來調試程序

 

image

圖5:一定要勾選Update Target before Debugging

 

圖5按下settings按鍵,設置Flash下載設置和編程算法,realarm2410使用的SST39VF1601,MDK有現成的編程算法,直接按下ADD按鍵,選擇芯片型號則可,如圖6。

image

圖6:Flash編程設置

 

如此,在MDK中執行start debug則可進入Flash中調試代碼了。

 

提供跑馬燈程序的MDK工程,注意選擇好Target為DebugInFlash。

跑馬燈的MDK工程下載

 

三、程序在SRAM中調試

有了前面在Flash中調試所述的原理基礎,設置為SRAM中調試就好辦了,按以下步驟:

  1. 要保證程序小於4KB,RO放到SRAM中;
  2. 如果使用的RW段、Stack和Heap還是放到SDRAM中,那么依然要在S3C2410A.s中初始化;
  3. Debug前要執行一個初始化腳本,因為SRAM 地址從0x40000000開始,因此需要在初始化腳本中把PC指針設置到0x40000000中;
  4. 一定不可勾選調試前更新代碼這個選項,否則start debug時會提示錯誤,實際上SRAM調試的代碼不可燒寫到Flash中執行。

附上分散加載文件和工程配置圖如下:

; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************
LR_ROM1 0x40000000 0x00001000  {    ; load region size_region
  ER_ROM1 0x40000000 0x00001000  {  ; load address = execution address
   *.o (RESET, +First)
   *(InRoot$$Sections)
   .ANY (+RO)
  }
  RW_STACK 0x33ff3000   {  ; RW data
   *(STACK)
  }
  RW_HEAP 0x33ef3000   {  ; RW data
   *(HEAP)
  }
  RW_RAM1 0x33000000 0x00e00000  {  ; RW data
   .ANY (+RW +ZI)
  }
}
 
image

圖7:設置Debug的初始化文件為init_sram_RunFromSram.ini

 

init_sram_RunFromSram.ini文件如下:

FUNC void SetupForStart (void) {
 
        
// <o> Program Entry Point
  PC = 0x40000000;
}
 
        
 
        
SetupForStart();                        // Setup for Running

 

image

圖8:不可勾選Update target before Debugging,可設為使用外部工具

 

提供跑馬燈程序的MDK工程下載,注意選擇好Target為DebugInSram。

跑馬燈的MDK工程下載

 

四、程序在SDRAM中調試

有了前面所述的原理基礎,設置為SDRAM中調試基本和SRAM的相似,但是,有以下兩個不同點:

  1. SDRAM不受4KB大小限制;
  2. SDRAM需要初始化才能使用,因此在debug初始化文件中需要增加初始化SDRAM,並且把要調試程序的按照axf格式加載到SDRAM中;
  3. 初始化程序S3C2410A.s中不可再初始化,因為debug初始化腳本已經初始化過了,而且加載了程序,如果再初始化那會把程序給破壞點了。

還是用分散加載文件指定RO、RW、Stack以及Heap的位置,把RO分配到SDRAM的起始的2MB中,其它和前面一樣,文件如下:

; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************
 
        
LR_ROM1 0x30000000 0x00200000  {    ; load region size_region
  ER_ROM1 0x30000000 0x00200000  {  ; load address = execution address
   *.o (RESET, +First)
   *(InRoot$$Sections)
   .ANY (+RO)
  }
  RW_STACK 0x33ff3000   {  ; RW data
   *(STACK)
  }
  RW_HEAP 0x33ef3000   {  ; RW data
   *(HEAP)
  }
  RW_RAM1 0x31000000 0x03000000  {  ; RW data
   .ANY (+RW +ZI)
  }
  RW_IRAM1 0x40000000 0x00001000  {
   .ANY (+RW +ZI)
  }
}

 

Debug初始化文件如下:

FUNC void SetupForStart (void) {
 
        
// <o> Program Entry Point
  PC = 0x30000000;
}
 
        
 
        
FUNC void Init (void) {
  _WDWORD(0x4A000008, 0xFFFFFFFF);      // Disable All Interrupts
 
        
  _WDWORD(0x53000000, 0x00000000);      // Disable Watchdog Timer
  
                                        // Clock Setup 
                                        // FCLK = 150 MHz, HCLK = FCLK/2 MHz, PCLK = HCLK/2 MHz
  _WDWORD(0x4C000000, 0x0FFF0FFF);      // LOCKTIME
  _WDWORD(0x4C000014, 0x0000000F);      // CLKDIVN
  _WDWORD(0x4C000004, 0x00043011);      // MPLLCON
  _WDWORD(0x4C000008, 0x00038021);      // UPLLCON
  _WDWORD(0x4C00000C, 0x001FFFF0);      // CLKCON
 
        
                                        // Memory Controller Setup for SDRAM
  _WDWORD(0x48000000, 0x22000000);      // BWSCON
  _WDWORD(0x4800001C, 0x00018005);      // BANKCON6
  _WDWORD(0x48000020, 0x00018005);      // BANKCON7
  _WDWORD(0x48000024, 0x008404F3);      // REFRESH
  _WDWORD(0x48000028, 0x00000032);      // BANKSIZE
    
  _WDWORD(0x4800002C, 0x00000020);      // MRSRB6
  _WDWORD(0x48000030, 0x00000020);      // MRSRB7
 
        
  _WDWORD(0x56000000, 0x000003FF);      // GPACON: Enable Address lines for SDRAM
    
}
 
        
 
        
// Reset chip with watchdog, because nRST line is routed on hardware in a way 
// that it can not be pulled low with ULINK
 
        
_WDWORD(0x40000000, 0xEAFFFFFE);        // Load RAM addr 0 with branch to itself
CPSR = 0x000000D3;                      // Disable interrupts
PC   = 0x40000000;                      // Position PC to start of RAM
_WDWORD(0x53000000, 0x00000021);        // Enable Watchdog
g, 0                                    // Wait for Watchdog to reset chip
 
        
Init();                                 // Initialize memory
LOAD .\led_InSdram.axf INCREMENTAL      // Download program
SetupForStart();                        // Setup for Running

腳本中的Init函數對寄存器的操作含義可以查閱S3C2410的寄存器手冊,實現的就是關中斷,看門狗,設置時鍾,初始化內存控制器。LOAD .\led_InSdram.axf INCREMENTAL作用就是把led_InSdram.axf文件加載進去,axf為elf格式的文件,本身帶有加載的地址,因此只要分散加載文件按這只正確了,編譯鏈接后生成的axf文件就有了正確的加載地址;最后把PC設置到RO的基址0x30000000執行代碼。

 

S3C2410A.s需關閉內存控制器的初始化功能,找到這一行代碼:MC_SETUP        EQU     1;改為MC_SETUP        EQU     0。

 

提供跑馬燈程序的MDK工程下載,注意選擇好Target為DebugInSdrSram。並記得修改MC_SETUP        EQU     0。

跑馬燈的MDK工程下載


免責聲明!

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



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