主题中讨论的其他部件:AM5728, BeagleBoard-X15, TM4C1294NCPDT, SEGGER
工具/软件:TI C/C++编译器
标题所说的。 根据ANSI C标准,所有静态变量都应初始化为零或空。 是的,我们正在使用EABI。
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
工具/软件:TI C/C++编译器
标题所说的。 根据ANSI C标准,所有静态变量都应初始化为零或空。 是的,我们正在使用EABI。
根据ANSI C标准,所有静态变量都应初始化为零或空。 [/QUOT]要在所有情况下都在嵌入式目标上工作,可能需要从引导加载程序执行一些操作。 尝试了解问题的一些问题:
1)如果Initialization Model链接器选项是--ROM_model,则C运行时库启动代码将零初始化全局变量。 如果 Initialization Model linker选项是--ram_model,则引导加载程序负责对全局变量进行零初始化。 使用哪个初始化模型选项?
2)线程标题显示“外部内存中的全局变量未初始化为零”。 内部存储器中的全局变量是否已正确初始化? 是否在加载程序之前初始化了外部存储器接口?
I sure therealthing a setting to control this but we says ways finding the dists of compiler and linker switches and options, and unfind thing.[/QUOT]我创建了以下程序来测试已初始化和未初始化的全局变量的行为:
#include <stdio.h>
#include <stdbool.h>
#define NUM_DATA_O词语32
int uninitialized_data[NUM_DATA_字数];
int initialized_data[NUM_DATA_字数]=
{
1,2,3,4,5, 6,7,8,9,10, 11,12,13,14,15,16, 17,18,19,20,21, 22,23,24,25,26, 27,28,29,30,31, 32
};
int main(void){
内部索引;
int num_Expected值;
num_Expected值= 0;
对于(index = 0;index < NUM_DATA_JESS;index++)
{
IF (未初始化的数据[index]== 0)
{
num_Expected值+;
}
}
printf ("num Expected uninitialized_values=%d\n",num_Expected _values);
num_Expected值= 0;
对于(index = 0;index < NUM_DATA_JESS;index++)
{
IF (initialized_data[index]==(index + 1))
{
num_Expected值+;
}
}
printf ("num Expected initialized_values=%d\n",num_Expected _values);
对于(index = 0;index < NUM_DATA_JESS;index++)
{
未初始化的_data[index]++;
initialized_data[index]+;
}
返回0;}
测试使用:
1)在AM5728的ARM Cortex-A15和C66内核中运行相同的程序。
2) BeagleBoard-X15,与Blackhawk USB560-M仿真器连接,20引脚JTAG电缆,用于下载程序。
3) CCS 7.2。0.0.0013万。
4)编译器TI v Cortex-A15程序的17.3 .0.STS。
5)编译器TI v 8.1 4,用于C66程序。
6)存储在AM572.8512万KB L3 OCMC SRAM1中的程序,即内部设备存储器。
结果是:
A)当Cortex-A15和C66程序设置为--ROM_MODEL时, 在 从CCS调试器加载或重新加载程序时,未初始化的数据[]和初始化的数据[]数组被设置为预期值。 使用 --rom_model意味着编译器运行时库中的代码启动零初始化具有静态持续时间且没有初始化程序的变量。
B)当 Cortex-A15和C66程序设置为--ram_model时, 当程序从CCS调试器加载或重新加载时,initialized_data[]数组被设置为预期值。 但是, 在 从CCS调试器加载或重新加载程序时,未初始化的数据[]未进行零初始化。 重新加载程序时 ,未初始化的数据[]数组的内容与上次运行的内容相同。 使用--ram_model意味着CCS调试器负责对 静态持续时间的变量进行零初始化,而这些变量在加载程序时没有初始化程序。
以C66为例,当使用--ram_model编译时,链接程序映射文件显示 未初始化的数据数组位于地址0x4030.842万:
远 40.3082万 403082e0.0001万c8 未初始化 40.3082万e0 00000140000000140 (.common:__TI_tmpnams) 40.3084万20 000000802万00080</s>0.008万 (.common:uninitialized_data) 40.3084万a0 00000008000000008 (.common:parmbuf)
查看TI链接器生成的ELF程序头,可以看到:
$ readelf.exe -l /cygdrive/C/users/MR_halfword_v7/AM5728_C66_global_vars/Debug/AM5728_C66_global_vars.out Elf5728 Elf文件类型为EXEC (可执行文件) 入口点0x4.0306万c20 有6个程序标头,从偏移18.9608万 开始程序标头: 类型 偏移VirtAddr PhysAddr FileSiz MemSiz Flg对齐 负载 0x0.004万 0x4030万 0x4030万 0x06f40 0x06f40 R E 0x20 负载 0x006f80 0x4.0306万f40 0x4.0306万f40 0x0万 0x0.1万 RW 0x8 负载 0x006f80 0x4.0307万f40 0x4.0307万f40 0x0039c 0x0.0568万 RW 0x8 负载 0x0.732万 0x40.3084万a8 0x40.3084万a8 0x0.0174万 0x0.0174万 R 0x8 负载 0x0.7498万 0x4030.862万 0x4030.862万 0x0万 0x0.012万 RW 0x8 负载 0x0.7498万 0x4030.874万 0x4030.874万 0x0.0038万 0x0.0038万 R 0x4 段到段映射: 段段段... 00 文本 01. .stack.sysmem 2 far .fardata 03. const 04 首席信息官 05. 开关
起始地址 为0x4.0307万f40的装载段的 FileSiz为 0x0039c,MemSiz为 0x0.0568万。 由于MemSiz比 FileSiz大,我的理解是,CCS调试器加载程序时,它应该为零,以填充(加载地址+ FileSiz)所覆盖的内存范围 。 (加载地址+ MemSiz -1),这是内存地址0x40.3082万dc .. 0x40.3084万a7,它包含未初始化的数据数组的位置。 因此,TI链接器已正确生成ELF程序标头,该标头应导致CCS调试器在 加载程序时对未初始化的数据数组执行零初始化。
因此,问题可能出在CCS调试器中,也可能出在 Blackhawk USB560-M仿真器的驱动程序中。
附加了示例程序。
----这也是我的结论,调试器或仿真器驱动程序。[/QUOT]创建了我的测试程序的一个版本,它在与Segger J-Link连接的TM4C1294NCPDT中运行。 该程序使用TI ARM 17.3 v.0编译,程序设置为使用--ram_model从SRAM执行。 选择此设备和调试探测器后,可以使用CCS和IAR调试程序加载相同的ELF .OUT文件。
使用CCS 7.2 调试器下载程序时 ,如果 从0.0.0013万 调试器加载或重新加载程序,则会将initialized_data[]数组设置为预期值。 但是, 在 从CCS调试器加载或重新加载程序时,未初始化的数据[]未进行零初始化。 重新加载程序时 ,未初始化的数据[]数组的内容与上次运行的内容相同。
当使用IAR嵌入式工作台IDE - ARM 8.11 2下载同一程序时, 加载或重新加载程序时,未初始化的数据[]和已初始化的数据[]数组被设置为预期值。
示例程序的ELF程序标题为:
$ readelf.exe -l /cygdrive/C/users/MR_halfword_v7/TM4C129_RAM_GLOBAL_vars/Debug/TM4C129_RAM_GLOBAL_vars.out Elf文件类型为EXEC (可执行文件) 入口点0x2万d47 有4个程序标头,从offset 7.8032万 程序标头: 类型 偏移VirtAddr PhysAddr FileSiz MemSiz Flg对齐 负载 0x0.0034万 0x0万 0x0万 0x0.0208万 0x0.0208万 R 0x4 加载 0x0.0023万c 0x2000万 0x2000万 0x0.108万 0x0.108万 R E 0x4 负载 0x0012bc 0x2000.108万 0x2000.108万 0x0万 0x0.02万 RW 0x4 负载 0x0012bc 0x2000.128万 0x2000.128万 0x000a0 0x0.012万 RW 0x4 段到段映射: 段段段... 00 intvecs .init_array 01 text .const 02 堆栈 03. 数据.bss
使用CCS 7.2 调试器下载程序时,Segger J-Link控制面板报告以下内存写入:
T1410 5175:057 JLINK_WriteMem(0x0万000000,0万,0x0208字节,...) 数据:80 12 00 20 47 0D 00 20 ... -闪存 T1410 5175:058 JLINK_WriteMem(0x2000万, 0x1080字节,...) -数据:0E B5 02 92 01 91 00 90 ... T1410 5175:211 JLINK_WriteMem (0x2000.128万,0x00A0字节...) 数据:01 00 00 02 00 00 00 ...
使用IAR调试器下载程序时,Segger J-Link控制面板报告以下内存写入:
T1B9万:435 JLINK_WriteMem(0x0万,0x0208字节,...) 数据:80 12 00 20 47 0D 00 20 ... -闪存 T1B9万:435 JLINK_WriteMem(0x2000万, 0x13A0 bytes,...) -数据:0E B5 02 92 01 91 00 90 ...
比较ELF程序标头和写入目标的内存可以看出:
a) IAR调试器正在正确写入MemSiz字段指定的内存区域大小,因此该字段对.bss段进行零初始化。
B) CCS 7.2 调试器错误地只写入“FileSiz”字段指定的内存区域大小,因此不能对“MemSiz”字段大于“FileSiz”字段的任何内存区域进行零初始化。
使用的示例附于 e2e.ti.com/.../TM4C129_5F00_RAM_5F00_global_5F00_vars.zip
我还测试了CCS 6.01 和CCS 6.2 ,它们的行为方式与CCS 7.2 相同。Chester Gillon 说:b) CCS 7.2 调试器错误地只写入FileSiz字段指定的内存区域大小, 因此,不会对MemSiz字段大于FileSiz字段的任何内存区域进行零初始化。
对于使用--ram_model的程序,一个变通方法是在链接程序命令文件中为包含未初始化变量的部分显式填充零。 例如,对于C66示例程序:
远 > OCMC_RAM1,Fill = 0
此变通方法不会更改目标上的内存使用情况,但ELF .OUT文件的大小会随未初始化部分的大小而增加。
当CCS调试器的加载程序不能按照ELF规范进行零初始化的问题最初出现在几年前时,加载程序被更改为按照规范所说的那样。 这种更改产生了意外后果,导致某些客户的性能严重下降。 决定保留ELF标准行为,但不作为默认行为。 这种感觉是,很少有情况会依赖调试器对嵌入式程序的加载行为,因为生成的软件可能无法在实时系统中工作。
虽然可以通过GEL启用非默认零填充行为。 在适当的Gel回调(例如启动)中执行"GEL_EnableZeroFill(1)"将启用它。