zoukankan      html  css  js  c++  java
  • 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工程下载
  • 相关阅读:
    CSU 1333 Funny Car Racing
    FZU 2195 检查站点
    FZU 2193 So Hard
    ZOJ 1655 FZU 1125 Transport Goods
    zoj 2750 Idiomatic Phrases Game
    hdu 1874 畅通工程续
    hdu 2489 Minimal Ratio Tree
    hdu 3398 String
    洛谷 P2158 [SDOI2008]仪仗队 解题报告
    POJ 1958 Strange Towers of Hanoi 解题报告
  • 原文地址:https://www.cnblogs.com/kenzhang1031/p/3239908.html
Copyright © 2011-2022 走看看