如何将数据添加到闪存中的段中会弄乱程序的时间?

时间:2020-03-06 14:41:19  来源:igfitidea点击:

我有一个实时嵌入式应用程序,其主要周期以10KHz运行。它在配置为从闪存引导的TI TMS320C上运行。我最近在源文件中添加了一个初始化的数组,突然之间计时被搞砸了(以太复杂的方式无法很好地说明串行端口写不再按时完成)。

令我困惑的事情是:

  • 我什至没有访问新数据,只是声明了一个初始化数组。
  • 它取决于大小-仅当数组> 40个字时才会出现问题。
  • 我知道我不会在链接图中溢出任何数据段。
  • 没有数据缓存,因此不是由于破坏缓存一致性。

关于增加Flash中.cinit段的大小如何影响代码时序的任何想法?

添加信息:
我认为代码可能已经移动了,但是与数据完全分开了。我通过内存映射验证了在错误前后,所有代码段都具有相同的地址。我还验证了没有一个段是完整的。映射中唯一更改的地址是.cinit节中的少数几个。该部分包含用于初始化ram中变量的数据值(如我的数组)。在调用main()之后永远都不应访问它。

解决方案

我的怀疑可能指向数据/代码与底层媒体/内存之间的对齐方式发生了变化。添加到数据将更改堆中的内存位置(取决于内存模型),并且可能使代码跨越闪存设备的"页面"边界,从而导致以前没有的延迟。

初始化可以覆盖另一个相邻的代码吗?
是否有使用该数组的结构或者变量,这些结构或者变量现在更大并且可能导致堆栈溢出?

也可能是银行或者页面冲突。也许我们有两个经常被调用的例程(大约是中断处理程序),它们都位于同一页面上,现在又分成了两个页面。

也许新的静态分配的数组将现有数据推入较慢的内存区域,从而导致对该数据的访问更慢?

如果数组是地址空间中的最后一块,问题是否会再次出现?如果不是,请查看地图,尝试移动数组声明,以便将放置在它之后的内容一一拖曳到它之前。这样,我们可以查明相关对象并开始弄清楚为什么移动它会导致延迟。

我冒着自我风险,声称我们在这里没有性能问题,而是某种形式的内存损坏,这些症状表现为性能问题。将数组添加到可执行文件中以更改内存图片。因此,我的猜测是内存损坏几乎无害(即覆盖未使用的内存部分),并且将内存移位超过40个字节会导致内​​存损坏带来更大的问题。哪个是真正的问题

经过一天多的盯着痕迹并生成了程序集,我想我已经解决了。
根本原因问题原来是一个设计问题,仅当启动串行端口写的ISR与更高优先级的ISR发生冲突时,才会引起故障。刚好计时了一下,只需要在一条循环中添加一些额外的指令就可以使两个中断发生冲突。

因此,问题就变成了:如何在闪存中存储而不访问其他数据,如何执行其他指令?

答案似乎与Frosty和Frederico的建议有关,但并不完全相同。新数组确实会移动一些现有变量,但不会跨页面边界或者移动到较慢的区域(在此板上,所有区域的访问时间应相同)。但是它的确改变了一些经常访问的结构的偏移量,这导致优化器发出稍有不同的指令序列来访问它们。一种数据对齐方式可能会导致一个周期的管道停顿,而另一种情况则不会。而且,这几条指令将时序转移得足够多,足以暴露出潜在的问题。