在MSP430的RAM中调试程序的研究

发布者:独享留白1028最新更新时间:2018-05-04 来源: eefocus关键字:在MSP430  RAM  调试程序 手机看文章 扫描二维码
随时随地手机看文章

先说下我所使用的IDE及硬件,IDE为IAR集成开发环境,本人从学习单片机时就使用的IAR,CCS也用过,但觉得没IAR使用的顺手,如果是CCS爱好者请自己去研究下CCS中应该怎么设置才能在RAM中调试MSP430的程序,理论上也是很简单的。硬件为MSP-EXP430F5529LP,也就那块红色的MSP430F5529 LaunchPad 。至于为什么要在RAM中调试程序,自己去百度这样做的好处吧,我也懒得说了。


首先简单分析下MSP430F5529的启动过程,根据其官方数据手册所述,中断向量表如下:


可以看到中断向量表在0xFF80-0xFFFF,其中复位向量在0xFFFE-0xFFFF,一共两个字节,16位,系统上电或复位后从这里取出16数据作为PC的值,然后MCU开始执行“main”函数,其实并不是最先执行的main函数,而是执行IAR编译器定义的程序入口点__program_start函数,其又被编译器定义为cstart_begin函数,后面紧跟着的是cstart_call_main函数,此函数才会去调用main函数。口说无凭,实验为证。


使用IAR创建一个工程,在main.c中随便写几句代码,然后在工程选项的Debugger子选项卡中取消勾选Run to main,取消此勾选的原因是此选项会在调试中直接让单片机运行到main函数的第一行代码然后暂停。这样一来main函数之前的代码就无法看到了,我这里使用的是软件仿真,硬件仿真也会是一样的结果。


设置完后点击调试按钮出现反汇编窗口,如下图,可以看到,程序并没有停在左边的源代码窗口,而是停在了右边的反汇编窗口,并且当前程序的地址为0x4400,其具有两个标号,分别为cstart_begin和__program_start,此函数只有一句代码"MOV.W #0x4400,SP",不难看出这是在设置堆栈指针SP为0x4400(注意和当前的PC值不要搞混,虽然值是一样的),下面紧跟标号为cstart_call_main的函数,此函数第一句代码是调用的main函数,第二句调用exit函数,exit函数是编译器自动为我们定义的函数,这里不做说明。


然后再在Go to那里输入中断向量表的地址0xFFFE,结果如下图,红框处即为复位向量,其值为0x4400,后面是5529的参考手册中所说的仿真器指令中的一条,不做分析。于是验证了上面所说的MSP430F5529的启动过程。


既然已经知道了MSP430F5529的启动过程,那么接下来就是找链接器脚本了,不过IAR将其叫做XLINK configuration file(XLINK配置文件),其后缀名为.xcl,在工程选项的Linker子选项卡中有和链接器有关的选项,如下图


可以看到Linker configuration file选项一栏有Override default选项,将其勾选,然后就可以找到IAR默认使用的链接器脚本文件,其路径为X:\

Program Files (x86)\IAR Systems\Embedded Workbench 7.2\430\config\linker,这个文件夹里有许多xcl文件,找到对应单片机的即可。顺带

提一下在Linker configuration file选项下面有一个Override default program entr的选项,这里就有IAR自己定义的程序入口点的函数名称。


在分析MSP430F5529的xcl文件之前先分析下MSP430F5529的的内存映像,其数据手册中有一个Memory Organization的表格,如下图


从这个表格中可以看出F5529的主FLASH所在的地址空间为0x4400-0x243FF,总大小为128KB,RAM所在地址空间为0x2400-0x43FF,总大小为8KB,其他地址空间就暂且不看了,反正这里用不到。


接下里就是分析F5529的xcl文件了,F5529的xcl文件行数比较多,我就不贴出来了,只要关注其中几行即可。下面为RAM中所存的段(Segment),至于什么是段,我也不解释了,这个是嵌入式开发中关于链接器的知识,自己百度去吧。

// -----------------------------------------------  

// RAM memory  

//  

  

-Z(DATA)DATA16_I,DATA16_Z,DATA16_N,TLS16_I=2400-43FF  

-Z(DATA)DATA16_HEAP+_DATA16_HEAP_SIZE  

-Z(DATA)CODE_I  

-Z(DATA)DATA20_I,DATA20_Z,DATA20_N,DATA20_HEAP+_DATA20_HEAP_SIZE  

-Z(DATA)CSTACK+_STACK_SIZE#  

可以看出这里定义的RAM地址空间为0x2400-0x43FF,和数据手册中的RAM所在地址空间一致。

下面为主FLASH中所存的段

// -----------------------------------------------  

// Read-only memory  

//  

  

// -------------------------------------  

// Low memory 0-0FFFF  

//  

  

// ---------------------------  

// Constant data  

//  

  

-Z(CONST)DATA16_C,DATA16_ID,TLS16_ID,DIFUNCT,CHECKSUM=4400-FF7F  

  

// ---------------------------  

// Code  

//  

  

-Z(CODE)CSTART,ISR_CODE,CODE16=4400-FF7F  

  

  

// -------------------------------------  

// All memory 0-FFFFF  

//  

  

// ---------------------------  

// Code  

//  

  

-P(CODE)CODE=4400-FF7F,10000-243FF  

  

// ---------------------------  

// Constant data  

//  

  

-Z(CONST)DATA20_C,DATA20_ID,CODE_ID=4400-FF7F,10040-243FF  

  

  

// -------------------------------------  

// Interrupt vectors  

//  

  

-Z(CODE)INTVEC=FF80-FFFF  

-Z(CODE)RESET=FFFE-FFFF  

可以看出这里定义的主FALSH地址空间为0x4400-0xFF7F、0xFF80-0xFFFF和0x10000-0x243FF。其中貌似部分段的存放地址是从0x10040开始的,不过这并无大碍,反正都在主FLASH空间。


链接器脚本分析完了,接下来就是在RAM中调试程序了,在这里只需更改链接器脚本中的FLASH地址空间为RAM地址空间即可实现在RAM中调试程序,那么将RAM分为0x2400-0x33FF、0x3400-0x437F和0x4380-0x43FF三个部分,分别用作FLASH、RAM和中断向量表,至于为什么要将中断向量表放在0x4380-0x43FF处,后面在RAM中调试需要使用中断的程序时再做说明。xcl文件的改动部分如下

// -----------------------------------------------  

// RAM memory  

//  

  

-Z(DATA)DATA16_I,DATA16_Z,DATA16_N,TLS16_I=3400-437F  

-Z(DATA)DATA16_HEAP+_DATA16_HEAP_SIZE  

-Z(DATA)CODE_I  

-Z(DATA)DATA20_I,DATA20_Z,DATA20_N,DATA20_HEAP+_DATA20_HEAP_SIZE  

-Z(DATA)CSTACK+_STACK_SIZE#  

  

  

// -----------------------------------------------  

// Read-only memory  

//  

  

// -------------------------------------  

// Low memory 0-0FFFF  

//  

  

// ---------------------------  

// Constant data  

//  

  

-Z(CONST)DATA16_C,DATA16_ID,TLS16_ID,DIFUNCT,CHECKSUM=2400-33FF  

  

// ---------------------------  

// Code  

//  

  

-Z(CODE)CSTART,ISR_CODE,CODE16=2400-33FF  

  

  

// -------------------------------------  

// All memory 0-FFFFF  

//  

  

// ---------------------------  

// Code  

//  

  

-P(CODE)CODE=2400-33FF  

  

// ---------------------------  

// Constant data  

//  

  

-Z(CONST)DATA20_C,DATA20_ID,CODE_ID=2400-33FF  

  

  

// -------------------------------------  

// Interrupt vectors  

//  

  

-Z(CODE)INTVEC=4380-43FF  

-Z(CODE)RESET=43FE-43FF  

将改动后的xcl文件放在工程的根目录,其它目录也行,反正IAR可以改变链接器脚本文件所在的路径。然后在工程选项的Linker子选项卡中的Linker configuration file选项中的Override default选项勾上,然后填入更改后的xcl文件的路径,我这里是填是$PROJ_DIR$\lnk430f5529_ram.xcl,因为我将更改后的文件改名成lnk430f5529_ram.xcl然后放在工程的根目录了,也可以用右边的选择按钮选择绝对路径。





然后就是将调试器改为硬件仿真器然后下载调试了,进入调试状态后发现单片机没有停住,到反汇编窗口一看发现0xFFFE处的复位向量的值为0xFFFF,然后去看0x43FE处的值发现是正确的0x2400,如下图。



我在测试RAM调试之前先在FLASH中下载了一个P4.7每过1秒改变一次电平的程序,也即LaunchPad上绿灯闪烁的程序,当时调试时0xFFFE处的复位向量和上面软件仿真的一样,为0x4400,然而现在却不是了。理论上我将FLASH地址空间放到了RAM中是不会再去擦除FLASH的。但实际上仿真器却把FLASH给擦除了,于是我开始在工程选项的Debugger中寻找是否有与FLASH擦除的相关的选项,结果还真有


将这里的Flash erase选为Retain unchanged memory,这个选项是保留未改变内容的内存,其子选项中Compare with image on target和Compare with image cached on PC是差不多的选项,可以任选一个。这样的话就不会擦除原来的FLASH内容了。但是下载调试发现虽然FLASH中的程序没有被擦除,新的程序也被下载到RAM中,但是MCU还是运行的FLASH中的程序。


再次回顾MSP430F5529的启动过程发现其实原因在于原来的0xFFFE处的复位向量的值并未改成正确的0x2400,还是使用FLASH时的0x4400,所以运行的还是FLASH中的程序,于是乎想了两种解决办法:


1、将中断向量表仍然放在0xFF80-0xFFFF处,那样在下载程序时会更新0xFFFE处的复位向量,将其指向0x2400这个RAM地址,但却存在断电后再次上电,RAM中的程序消失后,MCU还是会去RAM中运行,而不是运行FLASH中的程序。


2、在使用默认的xcl文件下载FLASH的程序时,在FLASH程序的main函数之前加一个函数。此函数判断0x43FE处“复位向量”是否为0x2400,如果是,则跳转到0x2400处执行RAM中的程序,否则继续运行FLASH中的main函数。


显然,方法2更胜一筹,虽然需要在FLASH程序里多加一点内容。那么现在就是如何在main函数前加一个函数来判断了,通过在IAR的文档目录(X:\Program Files (x86)\IAR Systems\Embedded Workbench 7.2\430\doc)中寻找参考手册,发现了一个名为EW430_CompilerReference的pdf文件,在其书签的Part1.Using the compiler->The DLIB runtime environment->System startup and termination中找到了System Startup过程,如下图


我们所需关注的也就是被划红线的部分,这几部分主要说了系统在启动时会先去执行一个初始化序列,这个初始化序列在main函数之前执行,

初始化序列中有一个__low_level_init函数,这个函数如果用户定义了就会去执行,否则不会去执行这个函数,而处理启动和结束过程的代码在

IAR的目录X:\Program Files (x86)\IAR Systems\Embedded Workbench 7.2\430\src\lib这个目录里,而这个目录里貌似又有几个目录,通过筛

选,发现cstartup.s43和low_level_init.c在430\src\lib\430目录里,其中cstartup.s43为汇编文件,手册里说尽量不要修改这个文件,那么剩下的

就是low_level_init.c了,这个文件里只有一个__low_level_init函数,代码如下

#include  

  

int __low_level_init(void)  

{  

  /* Insert your low-level initializations here */  

  

  /* 

   * Return value: 

   * 

   *  1 - Perform data segment initialization. 

   *  0 - Skip data segment initialization. 

   */  

  

  return 1;  

}  

那么将此文件拷贝到工程根目录,然后再工程中添加此文件,然后将此函数修改为如下代码

#include  

  

#define RUN_IN_RAM 1  

#define NEW_RESET (*(volatile unsigned int*)0x43FE)  

  

int __low_level_init(void)  

{  

    if(NEW_RESET == 0x2400)  

    {  

        if(!RUN_IN_RAM)  

            asm("MOV #2400h, PC");  

    }       

  return 1;  

}  

这里定义RUN_IN_RAM这个宏的原因是,在编译即将在RAM中调试的代码时也会编译low_level_init.c这个文件,于是RAM中的代码也会含有__low_level_init函数,当FLASH中的__low_level_init函数检测到0x43FE处的值为0x2400时会跳到0x2400这个RAM地址处
继续执行代码,而接下来就是执行RAM中的__low_level_init代码了,如果不判断现在是不是在RAM中运行,程序又会跳转到0x2400处执行代码,如此一来就形成了死循环。所以当下载到FLASH中时RUN_IN_RAM为0,会跳转,而下载到RAM中时RUN_IN_RAM为1,不会跳转。这个函数跳转使用了汇编代码"MOV #2400h,  PC",也即将PC的值设置为0x2400,如果不懂汇编的话那就没法了,反正跳转基本得这么写因为C语言无法使用PC寄存器,只有汇编能使用。


然后就是编译下载了,先用默认的xcl文件在FLASH里下载一次,然后用修改后的xcl文件下载到RAM里面运行,但结果还是失败了,下载到RAM的程序仍然没有运行,还是运行的FLASH的程序。

经过调试,发现FLASH里的low_level_init函数在判断NEW_RESET(地址为0x43FE)是否为0x2400时的结果为否,然而用Go to跳转到0x43FE处却发现显示的值是正确的0x2400(PS:这里由于我看的是IAR的反汇编窗口,其内存刷新好像比较慢,所以还是显示的正确值,但其实已经被修改了),后来使用中间变量查看程序读取到的NEW_RESET值,发现是0。

      然后又调试了一会,突然一次调试的时候发现0x43FC处的值为0x4408,而0x4408正好是FLASH程序中调用low_level_init程序后的代码的地址,准确来说应该是0x004408,这样一来0x43FE处为0也就很好解释了,因为FLASH中的程序将堆栈指针SP设置在0x4400处,当调用low_level_init时MCU自动压栈,也即将下一句代码的地址0x004408存在0x43FC处,注意,这里存的是32位数据,所以如果按8位表示的话,0x43FC处存的是0x08,0x43FD处存的是0x44,0x43FE处存的0x00,0x43FF处存的是0x00,以小端模式存储。


既然知道了是因为压栈而导致的复位向量被覆盖,那么在编译FLASH的程序时将RAM空间定义为0x2400-0x437F即可成功避开RAM中的中断向量表,考虑到中断向量表的0x80-0xD0处并没有中断,那么将RAM的结尾定位0x43CF也没问题(PS:虽然0xD0和0xD1没有放数据,但还是不能将RAM结尾定为0x43D2,因为堆栈要4字节对齐,0x43D2并不满足4字节对齐的条件)。


修改默认的xcl文件中的RAM地址空间为0x2400-0x437F,然后将链接器配置文件选择为此文件,在FLASH中下载一遍,然后使用修改的适用于RAM的xcl文件再下载到RAM中,发现果然可以运行RAM中的程序了,不过要运行FLASH中的程序必须得断电几秒后再上电才能运行,按复位是没用的,还是会运行RAM中的程序,原因在于MSP430复位时并不会清空RAM,断电几秒的原因在于MSP430功耗太低,且工作电压最低可到1.8V,只有电压下降到1.8V以下RAM才会清空。


至于带有中断的程序,只需要在你的main函数的关闭看门狗的代码后加一句SYSCTL |= SYSRIVECT,SYSCTL寄存器的SYSRIVECT位的功能如下图所示:


红线处说明了SYSRIVECT位如果为1则使用RAM的顶端所存放的中断向量表,RAM顶端也即0x43FF处,向下减去中断向量表的长度0x7F后为0x4380,所以我上面才会把中断向量表的地址空间定为0x4380-0x43FF。是为了在RAM中调试时可以正常调试带有中断的程序。我测试了下IO口中断,可以正常识别。

关键字:在MSP430  RAM  调试程序 引用地址:在MSP430的RAM中调试程序的研究

上一篇:程序跑飞原因分析
下一篇:STM8L和MSP430的低功耗对比

推荐阅读最新更新时间:2024-03-16 16:01

不能只靠内存,三星半导体崛起之路还长
三十年河东,三十年河西——说的是世事盛衰兴替,变化无常。然而在全球 半导体 市场,领头羊的位置却鲜有变化。自1993年开始,英特尔一直是全球最大半导体厂商。直至2017年,后来居上的 三星 才打破了这一现象,成为全球最大的半导体厂商。   而就在近日,IC Insights发布了2018年上半年全球半导体供应商Top15榜单,三星继续领跑,位居第一位,英特尔 位居第二位。其他几家按照排名分别是SK海力士、台积电 、镁光、博通、高通 、东芝东芝内存、德州仪器 、英伟达、西数 闪迪、英飞凌、恩智浦、意法半导体和联发科。     从上半年的营收表现方面来看,除了站在人工智能“风口”英伟达之外,存储芯片相关企业营收增幅尤为明显,包括三
[嵌入式]
NAND Flash价格崩盘前夕,国内存储面临大考验!
据悉,在经过为期一年半的价格暴涨之后,部分存储芯片的价格突然急速下滑,之后三星电子发布了一份并不乐观的2017年业绩预期,这两件事情让那些押注芯片行业的投资人陷入了深深的不安,一些投资人曾经认为芯片行业的红火至少还将持续一年半的时间。 此前有新闻指出,被广泛用在智能手机上的闪存芯片的价格在2017年第四季度出现了下跌,跌幅将近5%左右。伴随着这样的消息,一些分析人士预期今年存储芯片的市场增幅只能达到30%,较去年下降一半以上。 受此消息影响,上周三星电子的股票价格暴跌7.5%,另外三星的竞争对手SK海力士的股价也出现了大幅下跌,跌幅达6.2%。但是在分析人士看来,存储芯片市场应该不会出现突然间的大跌,2018年应该会是相对
[嵌入式]
台湾力晶、茂德八寸芯片厂登陆内地可望获准
12月18日,据国外媒体报道,“台湾经济部”预计将在12月底前批准力晶和茂德的申请,允许它们将较旧的八寸晶圆厂技术移转至内地,两大内存芯片生产厂商将在内地特殊芯片市场寻找商机。 这项举措将为芯片业带来新的商机。由于中国内地市场薪资低廉,加上与客户相邻,芯片业多年来一直抱怨无法对大陆投资,已经让它们在面对全球龙头厂商--韩国三星电子和海力士(Hynix)半导体竞争时处于不利境地。 力晶和茂德期盼上述登陆申请获得放行,不过这两家专精于生产随机存取内存(DRAM)芯片的厂商,仍在我国台湾以最先进的12寸晶圆技术进行生产。 茂德公司发言人、行销业务本部副总曾邦助表示,“我们将不会(在大陆)制造DRAM,不过我们希望利用该技术生产一些具
[焦点新闻]
2018年DRAM芯片产值将突破1000亿美元!三星成最大赢家
内存芯片产值高,受益最高的就是韩国企业了,尤其是三星电子,三星在DRAM内存占据全球市场份额的45%,NAND闪存占37%。 本文引用地址:  http://www.21ic.com/news/ce/201808/809252.htm 这两年DRAM内存、NAND闪存行业的疯狂激荡大家都看在眼里。内存尤其夸张,价格持续飙升。闪存方面倒是基本稳定了,但市场需求持续异常旺盛。两大行业空前火热,从业者自然也是赚得盆满钵满。根据市调机构IC Insight的最新报告,2018年全球前DRAM内存芯片产业总价值预计将达1016亿美元,年增幅高达39%,继续稳居第一,占全年整个IC行业的多达24%。 同时,这也将是历史上第一次,单个领域的I
[嵌入式]
Microchip加倍LCD PIC18单片机闪存及RAM容量以降低成本
PIC18F85J90系列单片机可提供集成的LCD模块、32 KB闪存及内部电压控制器,瞄准成本敏感的嵌入式显示应用 全球领先的单片机和模拟半导体供应商——Microchip Technology Inc.(美国微芯科技公司)推出6款集成了液晶显示器(LCD)模块的8位PIC单片机系列新产品。PIC18F85J90系列的闪存及RAM存储器容量比现有的64及80引脚系列器件增加了1倍,适用于需要嵌入式控制的高成本效益的人机接口应用,包括恒温器、民用表具及医疗仪器。存储容量的增加有助于用户增加更多诸如语音回放的复杂功能,拥有更多的自编程存储器分配,同时利用3V PIC18 J系列的制造工艺技术节省了成本。 具有片上LCD模块的PI
[单片机]
永远640k内存的电脑,你能想象得到么?
  “电脑的内存不需要超过640k!”也许,20年前,此话一出还会引得学术界一阵讨论,如今,再也没有人愿意承认自己说过这句话了。   就在我们认为这些天方夜谭的故事只有通过科学家的手,才能一一变为现实时,德州仪器首席科学家方进(Gene Frantz)却说“创新是工程师的责任。” 德州仪器首席科学家方进(Gene Frantz)   科学家是想到问题解决方法并说出来的人。而工程师则尝试各种办法,直至找到正确的解决方案为止。现有产品的新应用、科幻书籍和电影、洗热水澡时的灵感,儿童和配偶的生活体验往往都是他们创新的源泉。   规律是用来打破的   于
[嵌入式]
永远640k<font color='red'>内存</font>的电脑,你能想象得到么?
全球首次使用超密51纳米技术 三星产16G闪存
4月30日消息,作为世界上规模最大的电脑内存制造商,韩国三星电子公司本周末宣布,已经开始了16G容量NAND闪存芯片的大规模生产,这也是全球范围首次使用超密51纳米技术。 据韩联社报道,去年8月份的时候,三星电子开始了8G容量的60纳米技术NAND闪存芯片大规模生产,而此次推出的16G版本NAND闪存,无论在容量还是速度上,都比之前的产品有很大程度的提高。
[焦点新闻]
美光量产HBM3E高带宽内存 用于英伟达H200二季度出货
美光近日宣布已开始量产其 HBM3E 高带宽内存解决方案。英伟达 H200 Tensor Core GPU 将采用美光 8 层堆叠的 24GB 容量 HBM3E 内存,并于 2024 年第二季度开始出货。 美光 HBM3E 引脚速率超过 9.2Gb/s,提供超过1.2TB/s的内存带宽,美光 HBM3E 功耗比竞品低约 30%,美光 HBM3E 目前提供 24 GB 容量,使数据中心能够无缝扩展其人工智能应用。 此外,美光将于 2024 年3月出样12层堆叠的 36GB 容量 HBM3E,提供超过 1.2TB/s 的性能。同时,美光将赞助 3 月 18 日开幕的英伟达 GTC 全球人工智能大会,届时将分享更多前沿 AI 内存产品系
[半导体设计/制造]
美光量产HBM3E高带宽<font color='red'>内存</font> 用于英伟达H200二季度出货
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved