• 809查看
  • 0回复

[测试标定] 汽车标定技术--标定量与#pragma的趣事

[复制链接]


该用户从未签到

发表于 21-1-2024 10:26:22 | 显示全部楼层 |阅读模式

汽车零部件采购、销售通信录       填写你的培训需求,我们帮你找      招募汽车专业培训老师


目录
1. 不添加#pragma语句2. 添加#pragma语句3. 标定量只给flash空间,不给ram指定空间
4. 总结

在之前不会使用overlay机制的时候,我们想要做汽车标定,标定常量编译出来的地址一般都应该是ram的地址,而且在链接文件中都会指定一段区域来存放标定量和观测量。
那么为什么要提出这样奇怪的问题呢?起因是在向客户询问标定量存放在在ram的哪个位置时,客户说不需要指定特定的段。这就有点疑惑了,在标定中明确说了,标定过程会分为两页:workingpage和referencepage;WP:可以进行数据修改的页,通常是ram段;RP:不能修改的页,通常是flash段;在ETAS的文档里更明确的表示:
汽车标定技术--标定量与#pragma的趣事w1.jpg

所以不指定位置的话,标定数据会存放到哪里呢?那么我用#pragma来做了如下试验,分享给大家。

01


不添加#pragma不添加上述语句,则不指定标定数据具体会放在什么位置;
汽车标定技术--标定量与#pragma的趣事w2.jpg
经过编译(此时未给变量分配地址)、链接(分配地址)之后,结果如下:
汽车标定技术--标定量与#pragma的趣事w3.jpg

可以看到,编译器将变量放在了0xd0000840这个位置,结合ld文件
汽车标定技术--标定量与#pragma的趣事w4.jpg

发现它把变量放在了DMI_DSPR(ram)段;所以有理由来谈谈变量在MCU放的位置:
MCU能存放数据的地方有三处:register、rom、ram,涉及到预定义的:

.text段   :存放代码

.rodata段 :存放只读数据

.noinit段  :存放不需要初始化数据

.bss段   :存放默认初始化数据(一般为0)

.data段   :存放已初始化数据

CSTACK段 :栈

HEAP段   :堆

         下面来看一些变量的例子:

属性

位置

操作

举例

宏变量

预编译期间被汇编进.text段;

运行已不存在

汽车标定技术--标定量与#pragma的趣事w5.jpg

常量

放在.rodata段

程序访问在.rodata读取

汽车标定技术--标定量与#pragma的趣事w6.jpg

未初始化全局变量

放在.noinit段;一般在ram

在.noinit

_no_init uint32_t ni_global_var;   

默认0初始化全局变量

存放在.bss段;一般放在ram

启动时将bss清零;程序访问时在.bss段存取

汽车标定技术--标定量与#pragma的趣事w7.jpg


已初始化全局变量

初始化值存放在.data_init段,一般是ROM;变量本身是存在.data段,一般放在ram

启动时将初值从.data_init段复制到.data段;程序访问时均是在.data段存取

汽车标定技术--标定量与#pragma的趣事w8.jpg

  注:(1)观测量是放在.bss段的

汽车标定技术--标定量与#pragma的趣事w9.jpg

(2)标定量本身应该是放在.data段的

汽车标定技术--标定量与#pragma的趣事w10.jpg

可以看到,calibration1变量本身是放在ram里的,在程序上电但未运行时,ram里肯定是为0的,所以必须有一个从rom把值拷贝到ram指定位置的操作:
汽车标定技术--标定量与#pragma的趣事w11.jpg
根据链接文件里,可以看到,DMI_DSPR是从PFLASH1l里读取值,所以有理由相信,在未指定ram区域给标定量时,初始化值是存在PFLASH1,且变量本身是放在ram里,位置由链接文件指定。那么这个值是存在flash里的具体位置应该如何找:
汽车标定技术--标定量与#pragma的趣事w12.jpg

可以看到.data_start是从0x802a20a8开始,那么0x802a20a8肯定是calibra1的初始值:[1,1,1,1,1],查看hex文件里:
汽车标定技术--标定量与#pragma的趣事w13.jpg

02


添加#pragma语句在添加上述语句之后,正常情况下标定量和观测量是会放到我们指定的区间的,
汽车标定技术--标定量与#pragma的趣事w14.jpg

通过链接文件给标定量分别划分了ram区和flash区:
汽车标定技术--标定量与#pragma的趣事w15.jpg

在这里,给标定量划分的flash区间是:0Xaf004000,共80K;给标定量划分的RAM区间是:0x60000000,也是80k;
同时也给观测量划分了ram区间是:0x60015000,共4K。那么现在就看如何将标定量观测量放到指定区间了;首先看看结果:
汽车标定技术--标定量与#pragma的趣事w16.jpg

calibration1被放到了区域:.calDataOvc;这是一块什么区域呢?来看看链接文件进一步解释:
汽车标定技术--标定量与#pragma的趣事w17.jpg

可以看到,在单片机开始运行之后,单片机会把RP_CAL0中的值复制到WP_CAL0,并且是变量名和值是一一对应。此时我们来看hex文件,在AF004000处应该是calibration1的初值:[1,1,1,1,1]
汽车标定技术--标定量与#pragma的趣事w18.jpg

03



不指定ram空间
在链接文件这样写:
汽车标定技术--标定量与#pragma的趣事w19.jpg

因为没有指定映射到ram的具体地址,所以在map文件里会出现如下现象:
汽车标定技术--标定量与#pragma的趣事w20.jpg
对比加上>WP_CAL0 AT>RP_CAL0,


可以看到,这个变量本身是放在flash里的,也就起不到标定的作用了。而标定量初始值如下,没有变化:
汽车标定技术--标定量与#pragma的趣事w22.jpg

为了比较,不修改rpcal1,如下:
汽车标定技术--标定量与#pragma的趣事w23.jpg

在相应位置添加#pragma语句:
汽车标定技术--标定量与#pragma的趣事w24.jpg

编译之后,在map文件中,calibration4的位置在60001000;
汽车标定技术--标定量与#pragma的趣事w25.jpg

而在hex中,af005000能找到其初始值:
汽车标定技术--标定量与#pragma的趣事w26.jpg

也就是说,通过语句> WP_CAL1 AT > RP_CAL1,将标定量本身放在了ram里,标定量初始值放在了flash里,在程序上电运行后,通过CALINIT函数把flash的值拷贝到指定的ram区;当然也有直接在内核初始化的时候将flash的值copy到ram里(hightec的ld文件);这里就要修改链接文件,如下图:
汽车标定技术--标定量与#pragma的趣事w27.jpg

使用copy_table函数,将指定的flash段的数据拷贝至与之匹配的ram段;
Copy_table函数是在mcal的coreinit函数里;

汽车标定技术--标定量与#pragma的趣事w28.jpg

04



总结
从以上结果来看,如果只是给标定量确定了flash的位置和大小,而不确定ram的大小,那么编译器会直接把标定量本身以及值都会存放在指定的flash里面,并且无法映射到ram,因为没有做这个操作;所以需要给ram去指定一个区间存放变量名,把值放到flash;这样我们就能做标定操作了。




该用户从未签到

发表于 15-3-2025 13:38:00 | 显示全部楼层
您好,针对您提出的汽车标定技术问题,我作为汽车工程师对以下几点进行专业回复:

1. 不添加#pragma语句的情况下,标定常量通常会被存放在默认的内存区域。
2. 添加#pragma语句可以实现对特定内存区域的精确控制,便于标定过程的实施。
3. 在标定量只给flash空间而不给ram指定空间的情况下,需要通过其他机制来保证标定量在ram中的正确位置,如利用overlay机制或特定编程技巧。
4. 总结来说,汽车标定过程中标定量和观测量通常存放在特定的内存区域,以确保标定过程的正确进行。不指定特定段可能存在风险,需要通过其他方式确保数据存储的安全和可靠性。关于工作页和参考页的设置,工作页用于数据修改,确保实时性,而参考页则提供数据备份和参考。

希望以上回复对您有所帮助。
回复 支持 反对

使用道具 举报

快速发帖

您需要登录后才可以回帖 登录 | 注册

本版积分规则

QQ|手机版|小黑屋|Archiver|汽车工程师之家 ( 渝ICP备18012993号-1 )

GMT+8, 19-8-2025 12:31 , Processed in 0.417543 second(s), 35 queries .

Powered by Discuz! X3.5

© 2001-2013 Comsenz Inc.