MicroBlaze MCS 嵌入式程序空间不足导致异常

项目场景:

        项目场景:在 FPGA 开发中需要对一系列的外部设备进行统一管理,使用到了 MicroBlaze MCS IP 核作为嵌入式系统实现需求。MicroBlaze MCS IP 核是一种轻量级的软核处理器,它的资源和性能相对有限。在 Xilinx SDK 中进行嵌入式程序开发的过程中需要注意空间大小的问题。


问题描述

        下面这段代码来自 Xilinx SDK 中编写的嵌入式程序,已知 SelfTest_SSX30D() 和 SelfTest_SSX0804() 函数中均没有对变量 GlbSelfTestRet 进行修改。在 Xilinx SDK 调试环境中,我单步跟踪发现上述两个函数的执行结果均为正确,也就是说 GlbSelfTestRet 的值没有被修改,仍然是 0。但是当进行 if 判断时,GlbSelfTestRet 的值不为 0,程序退出。

 注:如果没有使用过 Xilinx SDK 对嵌入式程序进行上板调试,可以参考我的另一篇播客Xilinx SDK 基于 MicroBlaze MCS IP 核的嵌入式开发与调试_kennencool的博客-CSDN博客

UINT8 GlbSelfTestRet = 0;

int main()
{
    // 其他部分

    GlbSelfTestRet = 0;

    if( (dwRet = SelfTest_SSX30D()) != SDF_OK )
   	    GlbSelfTestRet |= 2;
    if( (dwRet = SelfTest_SSX0804()) != SDF_OK )
	    GlbSelfTestRet |= 1;

    if(GlbSelfTestRet)
        return 0;

    // 其他部分
}

原因分析:

        首先我们需要注意到 GlbSelfTestRet 是一个全局变量,在 C 语言中,全局变量通常存放在数据段中。因此只有当程序中发生了内存越界访问(而非内存泄漏),即访问了超出分配内存空间的位置,才可能会导致数据段中变量 GlbSelfTestRet 的值被错误地修改。

注:内存泄漏通常不会直接导致数据段中的数据被修改。内存泄漏指的是在程序中动态分配了内存(通常是使用 malloc 或类似的函数),但在不再需要这些内存时没有正确地释放它们,导致这些内存无法被再次使用,从而造成内存资源的浪费。

使用 Xilinx SDK 中自带的 Memory Monitor 工具对变量 GlbSelfTestRet 的存储空间进行监控:

注:Xilinx SDK 中自带的 Memory Monitor 是一个内存监视工具,它可以帮助开发者查看嵌入式系统中内存的使用情况,并检测诸如内存越界访问,内存泄漏等问题。

一  监控全局变量 GlbSelfTestRet 的地址空间

1.1 执行 GlbSelfTestRet = 0; 

         将鼠标悬停在变量 GlbSelfTestRet 上,获取内存 Address: 0xc93c。

1.2 对变量 GlbSelfTestRet 的内存添加监控

①在 Xilinx SDK 的菜单栏,点击 Window -> show view -> other:

         在 Debug 目录下找到 Memory,点击 OK。

②点击 Memory 窗口下 Monitors 旁边的绿色加号,输入地址:

 此时数据段中的数据情况:

 1.3 执行 if( (dwRet = SelfTest_SSX30D()) != SDF_OK )

         可以看到出现了红色数据,说明出现了内存越界访问

4、执行 if( (dwRet = SelfTest_SSX0804()) != SDF_OK )

         不出所料,存放 GlbSelfTestRet 的地址空间中的值被隐式地修改了。

二  监控 Stack 空间、Heap 空间、数据段空间

2.1 在 Xilinx SDK 的项目下新增编译链接命令,查看变量 GlbSelfTestRet 存放在哪个数据段 

①右键项目点击 properties,依次点击 C/C++ Build -> Settings -> MicroBlaze gcc linker -> Inferred Options -> Software Platform,点击绿色加号添加参数 “-Wl,-Map=output.map”

注:在 .map 文件中(链接脚本生成的映射文件),可以找到全局变量的存放地址和所在段的信息。

 ②右键重新 Build 项目,在 src 下生成一个 output.map 文件。

        全局搜索发现变量 GlbSelfTestRet  在 bss 段。 

2.2 根据 .ld 链接文件获取 Stack、Heap 以及 bss 段的开始地址和结束地址标记

注:

①Stack 的地址空间标记

.stack (NOLOAD) : {
   _stack_end = .;
   . += _STACK_SIZE;
   . = ALIGN(8);
   _stack = .;
   __stack = _stack;
} > ilmb_cntlr_Mem_dlmb_cntlr_Mem

起始地址标记:__stack,结束地址标记:_stack_end。

②Heap 的地址空间标记

.heap (NOLOAD) : {
   . = ALIGN(8);
   _heap = .;
   _heap_start = .;
   . += _HEAP_SIZE;
   _heap_end = .;
} > ilmb_cntlr_Mem_dlmb_cntlr_Mem

起始地址标记:_heap_start,结束地址标记:_heap_end。

③bss 段的地址空间标记

.bss (NOLOAD) : {
   . = ALIGN(4);
   __bss_start = .;
   *(.bss)
   *(.bss.*)
   *(.gnu.linkonce.b.*)
   *(COMMON)
   . = ALIGN(4);
   __bss_end = .;
} > ilmb_cntlr_Mem_dlmb_cntlr_Mem

起始地址标记:__bss_start,结束地址标记:__bss_end。

2.3 在嵌入式程序中添加代码获取运行时各空间的实际地址

extern uint8_t _heap_start;
extern uint8_t _heap_end;
extern uint8_t __stack;
extern uint8_t _stack_end;
extern uint8_t __bss_start;
extern uint8_t __bss_end;

int main()
{
	// 其他操作

	uint8_t* heap_start_addr = &_heap_start;
	uint8_t* heap_end_addr = &_heap_end;
	uint8_t* stack_start_addr = &__stack;
	uint8_t* stack_end_addr = &_stack_end;
	uint8_t *__bss_start_addr = &__bss_start;
	uint8_t *__bss_end_addr = &__bss_end;
    
    // 其他操作
}

获取情况:

_heap_start:0xd040

_heap_end:0xd840

__stack:0xdc40

_stack_end:0xd840

__bss_start:0xc928

__bss_end:0xd040

画图表示:

注:箭头是内存使用时被分配的顺序,可以看出 bss 和 Heap 段都是从低位地址到高位地址分配空间,而 Stack 段是从高位地址向低位地址分配空间。

2.4 调试程序观察 Stack、Heap 以及 bss 段的使用情况

①依次将 bss、Heap、Stack 的地址空间添加到 Memory Monitor:

②调试进入到 main.c 函数:

        发现第一个局部变量 dwRet 的地址是 0xcc10,局部变量处于 bss 段中是异常现象

③ 继续执行 if( (dwRet = SelfTest_SSX30D()) != SDF_OK )

        bss 段中更多的地址空间被非法使用。

④继续执行 if( (dwRet = SelfTest_SSX0804()) != SDF_OK ) 

        变量 GlbSelfTestRet 所处的空间已经被错误数据覆盖。

        根据现象猜想:对于 Stack 空间,编译器通常会根据函数的复杂性、函数调用的层数、局部变量的大小等因素来估计 Stack 空间的使用情况并进行优化。如果 Stack 空间不足以容纳所有的局部变量和函数调用上下文,编译器可能会将一些局部临时变量存储在 bss 段或者数据段中,以减少栈空间的使用。


解决方案:

修改嵌入式程序的链接脚本(.ld 文件)中的 Heap Size 和 Stack Size

         在 Xilinx SDK 中创建嵌入式程序项目后会根据设备和硬件设计自动生成一个 .ld 文件,初始化的 Stack Size 为 0x400,Heap Size 为 0x800。将其增大(修改为 Stack Size :0x4000,Heap Size 为 0x2800) 后程序运行正常。

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Microblaze程序烧录是指将用户编写的Microblaze处理器程序存储到处理器的Flash存储器或RAM存储器中的过程。烧录时需要经过如下几个步骤: 第一步是生成可执行文件。程序员需要使用集成开发环境编写程序,并将其编译和链接,生成可执行文件。此可执行文件包含了Microblaze处理器所需的指令和数据。 第二步是将可执行文件转化到仿真器支持的格式。仿真器通常需要将可执行文件转换为特殊的格式,以便使用仿真器将程序加载到处理器中。这个步骤通常由库函数完成,程序员只需要调用相关函数即可。例如,Xilinx公司提供的Vivado开发套件中有mcsformat库函数,可以将可执行文件转换为仿真器支持的格式。 第三步是将可执行文件烧录到处理器的存储器中。这一步需要使用特定的工具,例如Xilinx公司的iMPACT工具。程序员需要将仿真器连接到处理器系统中,并使用iMPACT工具将程序烧录到处理器的Flash或RAM存储器中。 最后,程序员需要对烧录的程序进行测试和调试,确保程序正常运行。如果程序出现问题,需要进行调试,找到问题所在并解决它。 总之,Microblaze程序烧录是将可执行文件存储到处理器存储器中的过程。这个过程需要程序员使用特定的工具和库函数,以确保程序能够正常运行。 ### 回答2: MicroBlaze是Xilinx公司推出的一种可定制的软核处理器,具有灵活性强、可扩展性好、性能高的优点,广泛应用于嵌入式系统中。在使用MicroBlaze进行开发时,我们需要将编写好的程序烧录到MicroBlaze中,以使其能够执行我们的任务。 在进行MicroBlaze程序烧录的过程中,通常需要准备两个重要的文件:MHS(Microprocessor Hardware Specification)文件和BSP(Board Support Package)文件。MHS文件是一个XML格式的文件,用于定义MicroBlaze处理器所需要的硬件资源,例如时钟频率、内存大小和地址等。BSP文件是一种特定平台下的软件框架,其中包含了与特定硬件相关的驱动程序和库文件,以便MicroBlaze程序与底层硬件进行交互。 在完成MHS和BSP文件的设计和配置后,我们可以使用Xilinx提供的工具将编写好的程序烧录到MicroBlaze中。常用的烧录工具包括Xilinx SDK、Vivado tool和JTAG等,其中Xilinx SDK是最为常用的烧录工具。使用Xilinx SDK进行烧录时,我们需要连接计算机和目标板子,以便进行调试和下载。在连接好后,我们可以通过Xilinx SDK提供的Easy2Use界面选择所需的程序文件、将其加载到目标板子中,完成程序烧录。 总的来说,MicroBlaze程序烧录是开发MicroBlaze处理器所必需的方法,它允许我们将编写好的程序加载到目标板子中并运行,实现我们需要完成的任务。在进行MicroBlaze程序烧录时,需要正确配置并使用相应的工具,这将有助于加快开发的速度和提高项目的效率。 ### 回答3: MicroBlaze是Xilinx推出的一种高性能,可编程的软件处理器,能够被实现在FPGA中,拥有小型尺寸,低功耗,高度可定制化等优势。在使用MicroBlaze进行FPGA应用开发时,需要烧录给MicroBlaze程序,在实际操作中,MicroBlaze程序烧录有以下几个步骤: 1. 编写MicroBlaze程序:用户需要使用Vivado或Xilinx SDK等开发工具编写MicroBlaze程序,或者使用已经存在的程序。编写好的程序需要打包成.xclbin文件,这个文件可以包含多个可重定位的ELF文件。 2. 设计Vivado项目:用户需要使用Vivado创建新的工程或者打开现有的工程,选择合适的FPGA设备,添加所需的IP,然后将打包成.xclbin文件的程序加入project。 3. 设计并配置AXI接口:在这个步骤中,用户需要添加AXI接口IP到Vivado工程中,然后根据MicroBlaze程序的需要进行配置。 4. 通过AXI接口烧录:使用JTAG端口或网络端口烧录MicroBlaze程序。可以使用Xilinx SDK中集成的调试器(Xilinx Debugger)或者其他工具来完成这个步骤。 总的来说,MicroBlaze程序烧录相对于其他软件烧录可能会更加复杂,需要在多个环节上进行配置和调试。但是,与传统软件虚拟机相比,MicroBlaze的高度定制化和低功耗等优势,使得在特定场景下MicroBlaze可能是更好的方案。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kennencool

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值