打印
[应用相关]

STM32-Keil软件仿真和硬件仿真 在线仿真_stlink仿真器能使程序运行在ram里面么

[复制链接]
834|47
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
tpgf|  楼主 | 2024-10-30 15:35 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
一、软件仿真
1.1 仿真配置
首先确定仿真的硬件环境。点击魔术棒,,在Target项确认一下仿真的芯片型号无误,然后选择外部时钟源频率(因为STM32一般使用外部时钟),一般是8MHz。



然后按照如下勾选,这里使用软件仿真就勾选Use Simulator。勾选Run to main(),表示仿真时跳过汇编代码,直接跳转到 main 函数开始仿真。然后Dialog DLL和Parameter分别按照自己的型号进行修改,比如如果你是用的是STM32F103ZE××,就把-pSTM32F103VB改为-pSTM32F103ZE便可,这里是设置支持所选型号的芯片的软硬件仿真,设置好后仿真的时候就可以通过 Peripherals 选择对应外设的对话框观察仿真结果(非常实用,后边详述)。



1.2 操作方法
点击 开始仿真。



这里的DEBUG工具条是比较常用,其中作为一般的使用者或者说入门的使用者来说,最常使用的还是下面加黑的几个。

复位:其功能等同于硬件上按复位按钮。相当于实现了一次硬复位。按下该按钮之后,代码会重新从头开始执行。
执行到断点处:该按钮用来快速执行到断点处,有时候你并不需要观看每步是怎么执行的,而是想快速的执行到程序的某个地方看结果,这个按钮就可以实现这样的功能,前提是你在查看的地方设置了断点。
挂起:此按钮在程序一直执行的时候会变为有效,通过按该按钮,就可以使程序停止下来,进入到单步调试状态。
执行进去:该按钮用来实现执行到某个函数里面去的功能,在没有函数的情况下,是等同于执行过去按钮的。
执行过去:在碰到有函数的地方,通过该按钮就可以单步执行过这个函数,而不进入这个函数单步执行。
执行出去:该按钮是在进入了函数单步调试的时候,有时候你可能不必再执行该函数的剩余部分了,通过该按钮就直接一步执行完函数余下的部分,并跳出函数,回到函数被调用的位置。
执行到光标处:该按钮可以迅速的使程序运行到光标处,其实是挺像执行到断点处按钮功能,但是两者是有区别的,断点可以有多个,但是光标所在处只有一个。
汇编窗口:通过该按钮,就可以查看汇编代码,这对分析程序很有用。
堆栈局部变量窗口:该按钮按下,会弹出一个显示变量的窗口,在里面可以查看各种你想要看的变量值,也是很常用的一个调试窗口。
Watch窗口:可以用来查看全局变量。
串口打印窗口:该按钮按下,会弹出一个类似串口调试助手界面的窗口,用来显示从串口打印出来的内容。需要注意的是在硬件调试时无法使用,只能从硬件上获取串口信息。
内存查看窗口:该按钮按下,会弹出一个内存查看窗口,可以在里面输入你要查看的内存地址,然后观察这一片内存的变化情况。是很常用的一个调试窗口。
性能分析窗口(没标的那个):按下该按钮,会弹出一个观看各个函数执行时间和所占百分比的窗口,用来分析函数的性能是比较有用的。
逻辑分析窗口:按下该按钮会弹出一个逻辑分析窗口,通过 SETUP 按钮新建一些 IO 口,就可以观察这些 IO 口的电平变化情况,以多种形式显示出来,比较直观。
关于执行到某处以及设置/清除断点 等这些常规操作不在赘述。

逻辑分析窗口
点击选择逻辑分析仪(Logic Analyzer),



点击左上角SETUP



然后输入要查看的引脚,选择显示类型为Bit,最后Close(另外显示颜色可以自由选择)。这里的引脚名有一定的格式,比如这个是表示GPIOC13引脚,PORTC这里可以理解为GPIOC引脚状态寄存器,(PORTC & 0x00002000)表示取其GPIOC13的状态(bit),然后右移13位是把该值移到最低位(可以简记为pin号是几就右移几位)。



如果不知道怎么确定“&”的数应该是多少,可以参考下面各pin号的值:

#define GPIO_Pin_0                 ((uint16_t)0x0001)  /*!< Pin 0 selected */
#define GPIO_Pin_1                 ((uint16_t)0x0002)  /*!< Pin 1 selected */
#define GPIO_Pin_2                 ((uint16_t)0x0004)  /*!< Pin 2 selected */
#define GPIO_Pin_3                 ((uint16_t)0x0008)  /*!< Pin 3 selected */
#define GPIO_Pin_4                 ((uint16_t)0x0010)  /*!< Pin 4 selected */
#define GPIO_Pin_5                 ((uint16_t)0x0020)  /*!< Pin 5 selected */
#define GPIO_Pin_6                 ((uint16_t)0x0040)  /*!< Pin 6 selected */
#define GPIO_Pin_7                 ((uint16_t)0x0080)  /*!< Pin 7 selected */
#define GPIO_Pin_8                 ((uint16_t)0x0100)  /*!< Pin 8 selected */
#define GPIO_Pin_9                 ((uint16_t)0x0200)  /*!< Pin 9 selected */
#define GPIO_Pin_10                ((uint16_t)0x0400)  /*!< Pin 10 selected */
#define GPIO_Pin_11                ((uint16_t)0x0800)  /*!< Pin 11 selected */
#define GPIO_Pin_12                ((uint16_t)0x1000)  /*!< Pin 12 selected */
#define GPIO_Pin_13                ((uint16_t)0x2000)  /*!< Pin 13 selected */
#define GPIO_Pin_14                ((uint16_t)0x4000)  /*!< Pin 14 selected */
#define GPIO_Pin_15                ((uint16_t)0x8000)  /*!< Pin 15 selected */



比如,如果你需要查看PA11的引脚,就写为(PORTA & 0x00000800)>> 11(0x00000800可以写为0x0800)。因为为PA11,所以写PORTA,从上宏定义可知,因为11脚对应的是0x0800,所以就&0x0800,因为是11脚就右移11位。

设置好引脚之后,在View下勾选上更新窗口,这样的话仿真时各种数据会实时更新,逻辑分析仪也就可以看到实时波形。



设置好之后点击运行,就可以在逻辑分析仪窗口看到该引脚的状态实时波形。



Watch窗口
Watch创口可以用来观察全局变量,只要将需要观察的全局变量复制到下面的窗口中,运行之后就可以看到数据的变化。



比如这里是观察一个结构体数组变量的情况,那个数据的值是多少、是什么类型一目了然。



当然,这里没法看局部变量,要看局部变量的话还是要用堆栈局部变量窗口。

堆栈局部变量窗口
你可能会问,什么是堆、栈?点这!

什么是堆栈?

内存分配方式有三种:

[1]从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。

[2]在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。

[3]从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由程序员决定,使用非常灵活,但如果在堆上分配了空间,就有责任回收它,否则运行的程序会出现内存泄漏,频繁地分配和释放不同大小的堆空间将会产生堆内碎块。

简言之,我们可以通过这个串口观察申请在堆栈区的变量,另外实测发现静态变量也是可以看的。总之,通过Watch窗口和堆栈窗口我们可以查看几乎所有的变量。

Peripherals窗口
它是用来仿真时观察和修改芯片的在外设寄存器用的,第一个System Viewer可以通过箭头所指的地方直接查看。

            

但是! 这是一个通用的选项,即涵盖了所有的外设,这上边可以查看的外设在我们的芯片型号上不一定有。比如我选用的是STM32VBT6只有3个串口,而这里可以看5个串口!而SyetemViwer下边的是外设是根据前文配置仿真时配置的Dialog DLL和Parameter决定的,所以要使用这个功能,必须要把Dialog DLL和Parameter配置为你要仿真的芯片型号。

另外两者的界面也有一些差别,看一哈

     

左图是System Viwer的界面,直接显示了改外设的所有寄存器极其每个位的值。右图是另一个界面,可以相对前者比较直观一些。

二、硬件/在线仿真
2.1 仿真器通信协议/接口
目前主流的协议是JTAG协议和SWD协议,一般常用的仿真器也是同时支持这两种协议/接口的。

JTAG协议/接口
JTAG(Joint Test Action Group,联合测试行动小组)是一种国际标准测试协议(IEEE 1149.1兼容),主要用于芯片内部测试。现在多数的高级器件都支持JTAG协议,如ARM、DSP、FPGA器件等。JTAG的工作原理可以归结为:在器件内部定义一个TAP(Test Access Port,测试访问口),通过专用的JTAG测试工具对内部节点进行测试和调试。一个含有JTAG Debug接口模块的CPU,只要时钟正常,就可以通过JTAG接口访问CPU的内部寄存器、挂在CPU总线上的设备以及内置模块的寄存器。

JTAG有5根线与目标CPU相连,TMS、TCK、TDI、TDO、NTRST:

TMS:测试模式选择,TMS用来设置JTAG接口处于某种特定的测试模式;
TCK:测试时钟输入;
TDI:测试数据输入,数据通过TDI引脚输入JTAG接口;
TDO:测试数据输出,数据通过TDO引 脚从JTAG接口输出;
NTRST:JTAG模块复位
其中在引脚紧缺的时候NTRST复位引脚可以不用。

SWD协议/接口
SWD全称Serial Wire Debug,是ARM为嵌入式设备推出的一种简单的调试接口,这种接口通过一条双向数据线和一条时钟线实现对于ARM核心的调试。

SWD需要3根线与目标MCU相连,SWDIO,SWDCLK和GND。

SWDIO 为双向Data口,主机到目标的数据传送。
SWDCLK 为时钟口,主机驱动。
GND  GND脚。
关于SWD的协议的具体内容,可以参考这篇文章。还不满足的话可以参考这篇硕士论《WD协议的研究及ARM程序下载器的设计》。

RDI协议/接口
远程调试接口(Remote Debug Interface),是ARM公司提出的标准调试接口,主要用于ARM芯片的仿真,由于各个IDE厂商使用的调试接口各自独立,硬件无法进行跨平台的调试。现在众多的IDE厂家都逐步采用标准RDI作为ARM仿真器的调试接口,因此使跨平台的硬件调试成为可能。EasyJTAG由于使用标准RDI调试接口,因此在任何使用标准RDI接口的IDE调试环境中都可以使用,例如ARM公司的ADS1.2/IAR公司的EWARM 3.30 。

2.2 常见仿真器
Jlink
J-Link是德国SEGGER公司推出基于JTAG的仿真器。简单地说,是一个JTAG协议转换盒,即一个小型USB到JTAG的转换盒,其连接到计算机用的是USB接口,而到目标板内部用的还是jtag协议。它完成了USB接口和JTAG接口的转换工作。JLINK是一个通用的开发工具,可以用于KEIL、IAR、ADS 等平台。速度,效率,功能都很好,据说是众多仿真器里最强悍的。



STlink
ST-LINK是专门针对意法半导体STM8和STM32系列芯片的仿真器。ST-LINK /V2指定的SWIM标准接口和JTAG / SWD标准接口。



————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/2401_87555332/article/details/143242668

使用特权

评论回复
沙发
kkzz| | 2024-11-7 20:23 | 只看该作者
软件仿真是指没有硬件参与的仿真,完全通过模拟实现。它主要用于软件问题的排查,如寄存器配置等

使用特权

评论回复
板凳
minzisc| | 2024-11-7 20:36 | 只看该作者
需要实际的硬件设备,可以在电脑上模拟STM32的各种外设和运行环境

使用特权

评论回复
地板
ingramward| | 2024-11-7 20:59 | 只看该作者
可以在Keil的配置中设置程序的ROM和RAM空间,但这只是为了仿真目的,并不直接反映到实际的硬件上。

使用特权

评论回复
5
cemaj| | 2024-11-8 08:58 | 只看该作者
STLink仿真器为STM32开发者提供了一个强大的在线仿真环境,使得程序能够在RAM中运行,从而简化了开发流程并提高了调试效率。

使用特权

评论回复
6
mollylawrence| | 2024-11-8 10:37 | 只看该作者
可以在不连接实际硬件的情况下进行调试,节省时间和成本。

使用特权

评论回复
7
linfelix| | 2024-11-8 14:11 | 只看该作者
STM32的RAM大小是有限的,因此需要确保程序的大小不会超过可用的RAM空间。

使用特权

评论回复
8
youtome| | 2024-11-8 17:17 | 只看该作者
支持在RAM中运行程序。              

使用特权

评论回复
9
hudi008| | 2024-11-8 20:30 | 只看该作者
在 Keil 等开发环境中,可以进行相关的配置来使程序运行在 RAM 中。

使用特权

评论回复
10
robertesth| | 2024-11-8 22:31 | 只看该作者
某些对程序运行稳定性要求较高的调试阶段,在 RAM 中运行可以避免 Flash 写入次数过多导致的寿命问题(Flash 有写入寿命限制)。

使用特权

评论回复
11
bestwell| | 2024-11-9 09:46 | 只看该作者
使用ST-Link仿真器时,可以选择将程序下载到RAM中运行。

使用特权

评论回复
12
janewood| | 2024-11-9 12:30 | 只看该作者
使用STLink仿真器,确实可以让程序运行在STM32的RAM中。

使用特权

评论回复
13
51xlf| | 2024-11-9 16:29 | 只看该作者
需要考虑硬件资源、固件版本、开发环境和配置设置等多个因素。

使用特权

评论回复
14
vivilyly| | 2024-11-9 19:29 | 只看该作者
STM32微控制器必须具备足够的RAM空间来存储程序和数据

使用特权

评论回复
15
albertaabbot| | 2024-11-9 21:43 | 只看该作者
STLINK仿真器确实可以使STM32程序在RAM中运行,但需要注意上述的限制和问题。

使用特权

评论回复
16
maudlu| | 2024-11-10 09:57 | 只看该作者
程序是存储在 Flash 中运行的,因为 Flash 具有非易失性,断电后数据不会丢失。但是在某些特殊的调试场景下,也可以将程序加载到 RAM 中运行。

使用特权

评论回复
17
averyleigh| | 2024-11-10 11:40 | 只看该作者
为了确保程序能够在RAM中运行,需要为程序分配足够的RAM空间。这通常是在Keil的链接脚本(Linker Script)中完成的。

使用特权

评论回复
18
plsbackup| | 2024-11-10 17:02 | 只看该作者
硬件仿真则是将程序下载到STM32的实际硬件中运行。在这个过程中,STLINK仿真器起到了关键作用。它允许开发者将编译后的程序下载到STM32的FLASH或RAM中,并在硬件上实现仿真。

使用特权

评论回复
19
averyleigh| | 2024-11-10 21:20 | 只看该作者
可以设置断点、单步执行、查看和修改变量等,这些操作都是在实际的硬件环境中进行的。

使用特权

评论回复
20
jonas222| | 2024-11-11 10:45 | 只看该作者
因为中断向量表通常位于FLASH中,而在RAM调试模式下,中断向量表可能没有被正确映射到RAM中。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1931

主题

15650

帖子

12

粉丝