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工程下载
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: keil是一款常用的嵌入式开发工具,而J-Link是一种常用的仿真器设备。下面我将介绍如何使用keil和J-Link进行下载。 首先,在Keil软件打开你的工程项目,并确保你已经正确配置了目标芯片的选项。然后,点击“Project”菜单,选择“Options for Target”打开目标选项窗口。在这个窗口,你需要选择“Debug”选项卡,并将“Use”项设置为“J-Link/J-Trace”。这样,你已经启用了J-Link仿真器作为调试工具。 接下来,将J-Link仿真器与目标设备连接好,确保连接可靠。通常,J-Link需要通过USB接口与计算机连接,并通过其他接口(如JTAG、SWD等)与目标设备连接。在连接完毕后,你可以点击Keil软件菜单的“Debug”选项,选择“Start/Stop Debug Session”开始调试会话。 在调试会话,你可以点击Keil软件菜单的“Flash”选项,选择“Download”将编译好的二进制文件下载到目标设备Keil软件会自动将二进制文件通过J-Link仿真器发送给目标设备,并进行下载操作。下载完成后,你可以点击“Start/Stop Debug Session”按钮结束调试会话。 总结起来,使用Keil和J-Link进行下载的过程主要包括:配置目标选项、连接J-Link仿真器与目标设备、开始调试会话并下载二进制文件。希望以上步骤对你有所帮助。 ### 回答2: Keil是一种嵌入式开发软件,而J-Link是一种常用的支持多种芯片架构的调试下载工具。在使用Keil进行嵌入式开发时,可以通过J-Link下载程序到目标芯片。 首先,确保已经安装了Keil和J-Link的驱动程序。安装完成后,将J-Link连接到目标芯片的调试接口上,例如使用JTAG或SWD接口。 打开Keil软件,点击顶部菜单栏的"Project",选择"Options for Target",再点击"Debug"标签。 在"Debug"标签下的"Use"选项,选择"J-Link/J-Trace"作为调试器。然后在"Settings",根据实际连接方式选择J-Link的接口类型,例如选择"SWD"或"JTAG"。接下来,在"Device"选项选择目标芯片的型号。 点击"OK"保存设置后,Keil会自动识别J-Link,并在调试界面上显示相关信息。接下来,可以根据需要进行程序的编写和调试。 在进行下载操作之前,需要先新建或打开一个工程,在Keil的工程目录找到编译得到的可执行文件(通常为.hex或.bin类型),然后点击菜单栏的"Flash",选择"Download"。这样,Keil会将程序下载到目标芯片。 在下载过程Keil会将编译好的程序文件发送给J-Link,然后J-Link负责将程序写入目标芯片的闪存下载完成后,可以开始断点调试或运行程序。 总之,Keil使用J-Link下载程序非常简便。只需确保正确连接J-Link和目标芯片,设置好Keil调试选项,并将程序下载到目标芯片的闪存,就可以进行嵌入式开发和调试工作。 ### 回答3: Keil是一款常用的嵌入式软件开发工具,而J-Link是一种常用的调试与仿真工具,支持多种微处理器和微控制器。在使用Keil进行开发时,我们可以通过J-Link来将我们的程序下载到目标设备上。 首先,我们需要连接J-Link调试器与目标设备。J-Link调试器通常有USB接口,我们可以将其通过USB线与电脑连接。接着,我们需要用JTAG或SWD接口将J-Link调试器与目标设备连接起来。这通常需要用到一些导线和连接器,确保连接稳定。 接下来,我们需要在Keil进行一些配置。打开Keil软件后,点击“Project”菜单,并选择“Options for Target”选项。在出现的对话框,选择“Debug”选项卡,然后选择“Use JTAG or SW Device”选项。在“Settings”选择“J-Link”,并点击“OK”保存配置。 完成配置后,我们可以在Keil进行程序的编译。编译完成后,我们可以点击菜单的“Debug”选项,然后选择“Start/Stop Debug Session”来开始调试会话。 在调试会话开始后,我们可以通过点击菜单的“Flash”选项,然后选择“Download”来将程序下载到目标设备上。在弹出的对话框,我们可以选择J-Link作为下载设备,并选择正确的目标设备型号。然后,我们可以点击“Download”按钮开始下载程序下载完成后,我们就可以开始进行调试了。 总之,使用Keil进行嵌入式开发时,我们可以通过J-Link调试器将程序下载到目标设备上。这需要进行一些硬件连接和软件配置,然后就可以进行调试和仿真了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值