keil程序在外部RAM中调试的问题总结(个人的一点经验总结)

keil程序在内部RAM调试的基本步骤网上已经有很多了,我就不再赘述,大家可以在网上搜到很多。

但是有些时候内部RAM并不够用,这就需要将程序装入外部RAM中调试,而在这个过程中可能会出现各种各样的问题,在这里我将会把我遇到过的一些问题和需要注意的地方总结一下,希望能够对大家有所帮助。

有错误的地方也希望大神们能够不吝赐教,提前表示感谢···

转载请注明出处:waitig‘s blog

先介绍下我项目使用的硬件,芯片是LPC1788,外部RAM是MT48LC4M32B2,大小为16M(128Mb X32 SDRAM),之前用的是MT48LC2M32B2,大小为8M,后来发现东西太多,8M不够用了,所以换成了16M的。

在换RAM时也遇到过一些问题,这个在下文中会有介绍。

  • 在外部RAM中调试程序,程序中一定不能有操作外部RAM的代码!

在外部RAM中调试,程序中不要有操作外部RAM的代码,初始化也不要有,包括对RAM相关引脚的操作。

RAM的初始化和引脚的初始化要放到jlink的下载配置文件中,主要是对LPC的寄存器进行相关配置,不要忘了RAM中的读取算法配置。

把我的配置文件贴出来供大家参考一下。

FUNC void PinSel(int p1, int n1, int f1)
{
    _WDWORD(0x4002C000 + (p1 * 32 + n1) * 4, 0x8 | f1);
}

FUNC void InitSDRAM(void)
{
    int i;

    PinSel(2,16,1);
    PinSel(2,17,1);
    PinSel(2,18,1);
    PinSel(2,20,1);
    PinSel(2,24,1);
    PinSel(2,28,1);
    PinSel(2,29,1);
    PinSel(2,30,1);
    PinSel(2,31,1);

    for(i = 0; i < 32; i++)
        PinSel(3,i,1);

    for(i = 0; i < 21; i++)
        PinSel(4,i,1);

    PinSel(4,24,1);
    PinSel(4,25,1);
    PinSel(4,30,1);
    PinSel(4,31,1);

    /* PCONP |= 1 << 11 */
    _WDWORD(0x400FC0C4, 0x04288FDE);    // Power On EMC

    /* EMCCONTROL |= 1 */
    _WDWORD(0x2009C000, 0x00000001);    // Enable EMC

    /* EMCDLYCTL */
    _WDWORD(0x400FC1DC, 0x00081818);    // Config data read delay

    /* EMCCONFIG */
    _WDWORD(0x2009C008, 0x00000000);    // Little endian mode

    /* DYNAMICCONTROL */
    _WDWORD(0x2009C020, 0x00000003);    // Set normal self refresh mode, normal power mode
                                        // CE always HI
                                        // Enable clock out
                                        // Clock do not stop during idle

    /* DYNAMICREFRESH */
    _WDWORD(0x2009C024, 0x0000001F);    // refresh timing 

    /* DYNAMICREADCONFIG */
    _WDWORD(0x2009C028, 0x00000001);    // read timing 

    /* DYNAMICRP */
    _WDWORD(0x2009C030, 0x00000002);    // tRP

    /* DYNAMICRAS */
    _WDWORD(0x2009C034, 0x00000003);    // tRAS

    /* DYNAMICSREX */
    _WDWORD(0x2009C038, 0x00000005);    // tSREX

    /* DYNAMICAPR */
    _WDWORD(0x2009C03C, 0x00000001);    // tAPR

    /* DYNAMICDAL */
    _WDWORD(0x2009C040, 0x00000005);    // tDAL

    /* DYNAMICWR */
    _WDWORD(0x2009C044, 0x00000003);    // tWR

    /* DYNAMICRC */
    _WDWORD(0x2009C048, 0x00000004);    // tRC

    /* DYNAMICRFC */
    _WDWORD(0x2009C04C, 0x00000004);    // tRFC

    /* DYNAMICXSR */
    _WDWORD(0x2009C050, 0x00000005);    // tXSR

    /* DYNAMICRRD */
    _WDWORD(0x2009C054, 0x00000001);    // tRRD

    /* DYNAMICMRD */
    _WDWORD(0x2009C058, 0x00000003);    // tMRD

    /* DYNAMICCASRAS0 */
    _WDWORD(0x2009C104, 0x00000303);    // RAS/CAS Latency

    /* DYNAMICCONFIG0 */
    _WDWORD(0x2009C100, 0x00004500);    // Config device type as SDRAM
                                        // Config address mapping

    _sleep_(100);                       // Wait 100 ms

    /* DYNAMICCONTROL */
    _WDWORD(0x2009C020, 0x00000183);    // nop command

    _sleep_(100);                       // Wait 100 ms

    /* DYNAMICCONTROL */
    _WDWORD(0x2009C020, 0x00000103);    // pre-charge command

//    /* DYNAMICREFRESH */
//    _WDWORD(0x2009C024, 0x00000002);    // refresh timing 

    _sleep_(100);                       // Wait 100 ms

    /* DYNAMICREFRESH */
    _WDWORD(0x2009C024, 0x0000001F);    // refresh timing 

    /* DYNAMICCONTROL */
    _WDWORD(0x2009C020, 0x00000083);    // mode command
    _RDWORD(0xA0000000 | (0x32 << (2 + 2 + 8)));

    _sleep_(100);                       // Wait 100 ms

    /* DYNAMICCONTROL */
    _WDWORD(0x2009C020, 0x00000003);    // noamal command

    /* DYNAMICCONFIG0 */
    _WDWORD(0x2009C100, 0x00084500);    // enable buffer

    _sleep_(100);                       // Wait 100 ms
}

以上是外部RAM的初始化部分,不要忘了其中的RAM本身的寄存器,在本例中的地址是0xA0000000,寄存器中的各个位数的作用如下图:

(截图自MT48LC4M32B2的datasheet)

其中数据要配置正确,RAM才能正确工作。接下来是对内存保护单元(MPU)的配置,两者结合,就是Jlink对RAM的初始化和配置。

RAM_Debug.ini 的文件如下所示:

INCLUDE MT48LC4M32LFB5.ini

InitSDRAM();                                // Initialize memory

LOAD ..\SDRAM_obj\uc1788.axf INCREMENTAL    // Download program

/* RNR */
_WDWORD(0xE000ED98, 0x00000000);            // Use No.0 MPU

/* RBAR */
_WDWORD(0xE000ED9C, 0xA0000000);            // Set MPU base addr

/* RASR */
_WDWORD(0xE000EDA0, 0x03000031);            // Set MPU size and permission

/* SHCSR */
// _WDWORD(0xE000ED24, 0x00000100);            // Enable memory managemeng fault

/* MPU_CONTROL */
_WDWORD(0xE000ED94, 0x00000005);            // Enable MPU

/* VTOR */
_WDWORD(0xE000ED08, 0x10000000);            // Set vector table offset

SP = _RDWORD(0x10000000);                   // Set stack pointer
PC = _RDWORD(0x10000004);                   // Set program counter

这样就能像在FLASH中调试一样来在RAM中调试了。

但是,程序中不要出现任何操作RAM的代码!一定记住!

  • 程序装入RAM中起始地址出错

所谓起始地址,就是指程序刚装入RAM中,还没有运行的那个pc地址。

正常情况下,这个地址是指向芯片启动代码的systemiInit()这个函数所在的地址的,但是有些时候这个地址会出错,跑到一个不知道什么地址的地方去。

如下图所示:

我分析出现这个现象的原因是在jlink对RAM的配置方面有问题,也就是对RAM没有配置成功,导致程序没有成功存入RAM中,或者是储存成功,但是读取失败,或者储存读取都有问题。

解决方案就是查看内存中的数据,看是否正确。或者对设备重新上电,对jlink复位后重新调试。

这个问题在我这里偶尔会出现,但重新调试又会消失,所以到目前我也没弄清楚这个问题出现的原因。

  • 程序跑入HardFault_Handler

HardFault_Handler是指指令错误中断,一般是因为程序代码翻译成的汇编代码中出现了错误的指令。

解决这个问题的方法一般是找出错误指令的地址,如果地址是在当前分配的代码段的最开始位置(比如我在分散加载里面将这段代码放在0xA0001000-0XA0002000之间,然后出错指令出现在0xA0001010这个位置);

或者在上个代码段的结束位置(比如我将这段代码放在0xA0001000位置处,上段代码在0xA0000900结束,而出错指令在0xA0000920这个位置);

一般情况下是内存不够用导致的,而且出错的语句一般是向全局变量赋值的语句。因为内存不够用,但是jlink在向RAM中写数据的时候并不知道内存不够,导致后来溢出的数据折返回代码段起始地址,将以前的内容覆盖所导致的。(内存覆盖)

解决这个问题的方法就是换一个大的RAM。

还有一种可能,就是在程序中有操作RAM的代码,这也会导致RAM中内容被修改,出现错误的指令。

  • 程序中途跑飞

上一条中的问题也有可能导致程序中途跑飞,此外还有一种可能就是指针问题。

指针没有正确初始化,使用了未初始化的指针,或者是指针没有正确回收,导致出现野指针,是最常见的,也是最容易导致程序跑飞的原因。出现问题应最先考虑此因素。

排除了以上的因素后,可以根据那些常规方法,比如查看LR寄存器的值,找到出现问题的语句等方法来查找具体原因。

  • 更换新外部RAM时要注意的问题

更换新RAM之前先看RAM的手册和芯片的手册,看清楚使用的芯片支持不支持新的RAM,我就因为没看清楚手册导致买了芯片不支持的RAM,既费钱又费力。。。。

芯片user manul上一般都有一个表,表中就是它所支持的所有RAM的类型。如下图:

先查清楚再买芯片,血淋淋的教训。。。

不同的RAM读写规则有些会有所不同,配置也不尽相同,所以在更换新RAM时要仔细读懂RAM的datasheet,对其清楚掌握。

基本上需要配置的最主要参数有以下几个:页大小,外部总线地址映射(行,列,bank),空间大小,位数,读写的算法(在RAM自己的寄存器中配置);

外部总线地址映射要与芯片对应,然后通过上表来确定配置寄存器的值。(程序在RAM中调试要修改jlink的ini文件)

  • 结语:暂时就想到了这些,以上的问题都是我在实际项目中碰到的问题,和一些经验介绍。由于我自己也学艺不精,能力有限,所以难免有错误的地方,希望路过的大神可以帮忙指正。同时声明,仅供参考。

转载请注明出处:waitig‘s blog

keil程序在外部RAM中调试的问题总结(个人的一点经验总结),布布扣,bubuko.com

时间: 2024-10-25 02:33:06

keil程序在外部RAM中调试的问题总结(个人的一点经验总结)的相关文章

下面调用函数f 处理外部RAM中的数

Ptr=NULL; //NULL在文件stdio.h中定义过. Ptr=(unsigned int *)malloc(N*sizeof(int)); //注意一定是要开辟N个int型的字节长度,不然编译会出错. //printf("%ld\n",Ptr); for(i=0;i { *(Ptr+i)=i; } for(i=0;i { Buf[i] = *(Ptr+i); } //下面调用函数f 处理外部RAM中的数 f((float *)(Ptr)); //请问:这样调用函数有问题吗?

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,才能把程

在SRAM、FLASH中调试代码的配置方法(附详细步骤)

因为STM32的FLASH擦写次数有限(大概为1万次),所以为了延长FLASH的使用时间,我们平时调试时可以选择在SRAM中进行硬件调试.除此之外,SRAM 存储器的写入速度比在内部 FLASH 中要快得多,所以下载程序到SRAM中的速度较快. 所以我们很有必要建立两个版本的工程配置,在SRAM中调试程序完毕后,再把代码下载到FLASH中即可.这篇笔记主要分享在keil5中配置FLASH调试与SRAM调试的详细配置方法及如何切换两种配置. 本篇笔记以STM32F103ZET6为例.其FLASH大

keil将程序装入外部FLASH详解

在实际项目中,经常出现芯片的内部FLASH空间不够的情况,这就需要将程序分一部分装到外部FLASH中. 为了让大家能少走些弯路,在这里把我在这其中遇到的一些问题和经验教训给大家分享一下. 仅供参考,如果有错误的地方欢迎指正,提前表示感谢! 转载请注明出处:blog.csdn.net/waitig1992 硬件环境介绍 芯片是LPC1788,外部FLASH是SST39VF1601(NORFLASH). 这个norflash在我的版本的keil(v4.0)中没有烧写算法,需要自己手动编写烧写算法,具

在keil中调试汇编程序

1.新建工程的过程不变,选对芯片,只不过是在新建文件的时候是.asm后缀 2.编写汇编程序完成后,将其放到文件夹中,然后再工程上右击,生成Hex文件 3.然后按debug按钮 4.单步执行(step按钮),可以在右侧看到psw,r0-r7,a,b,pc等的变化,可以选择右下角的memory选项卡,在address中输入你希望看到的存储空间,即可看到其中的内容变化,输入address时的规则是: 在Memory窗口中输入址值,得到的结果是程序代码区的内容,由于51是采用的是哈佛结构,程序指令存储和

在iis中调试asp.net程序

第一步,在iis中新建一个网站,名称为Langben,“物理路径”选择你的程序的根目录,端口你可以随便设置一个数,我这里设置为8888(后面要用到哦). 第二步,应用程序池设置一下 第三步,接下来,在你要调试的网站或者项目上右击,选择“属性”. 第四步,打开Web选项卡,服务器选择“本地IIS”,还记住第一步建网站的那个ip地址和端口吗?对,“项目URL”就是你第一步建的网站的url,图片中的localhost表示本地服务器的意思. 第五步,直接按F5试试吧,是不是So easy! 再也不用担心

在Chrome+Visual Studio中调试asp.net程序很慢的问题(Firefox也有类似问题)

在Chrome+Visual Studio中调试asp.net程序很慢的问题(Firefox也有类似问题) 今天开始起在Chrome中调试,发现问题主要出在菜单栏(layout文件)中,google了一番,查到很多原因,不过最终解决方法倒是很简单,特此分享一下: 在C:/Windows/System32/drivers/etc里边有一个hosts文件,用记事本打开,里边最后几行原来是: # localhost name resolution is handled within DNS itsel

在 NetBeans IDE 中调试 PHP 源代码

目录 准备工作 如何在 NetBeans IDE 中使用 XDebug 进行 PHP 调试 调试选项 使用工具栏和编辑器 调试器窗口 调试会话 样例调试会话 使用其他监视 PHP 和 HTML 混合用例 路径映射.调试器代理以及在定制 URL 上启动调试会话 要学习本教程,您需要具备以下软件和资源. 软件或资源 要求的版本 NetBeans IDE PHP 下载包 PHP 引擎 版本 5 Web 服务器 推荐使用 Apache HTTP Server 2.2. PHP 调试器 XDebug 2.

keil c51的内部RAM(idata)动态内存管理程序(转)

源:keil c51的内部RAM(idata)动态内存管理程序 程序比较简单,但感觉比较有意思,个人认为有一定应用价值,希望大家有更好的思路和方法,互相促进. 程序的基本思路是:在CPU堆栈指针SP以上的RAM区域,通过把堆栈指针SP上移若干个字节,把空出的RAM区域供用户使用,当用户在使用完后又可以把该RAM区域释放. 头文件dmalloc51.h /* **********************************************************************