Other Parts Discussed in Thread: TMS320F28374S
器件型号: TMS320F28374S
在 TMS320F28374S 的 CCS 工程中、添加或删除把手(理论上这不会影响 ADC 采样或控制环路执行,甚至在运行时也不会调用)会导致充电模块的实际输出电流出现固定偏置。 这是在严格的条件下发生的、即只有代码已更新、而完全没有对硬件进行任何更改->这可能是什么原因?
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.
Other Parts Discussed in Thread: TMS320F28374S
器件型号: TMS320F28374S
在 TMS320F28374S 的 CCS 工程中、添加或删除把手(理论上这不会影响 ADC 采样或控制环路执行,甚至在运行时也不会调用)会导致充电模块的实际输出电流出现固定偏置。 这是在严格的条件下发生的、即只有代码已更新、而完全没有对硬件进行任何更改->这可能是什么原因?
您好 Liu、
该问题 不 是由句柄的逻辑引起的、这是由于 在添加或删除任何代码时编译器和链接器重新组织存储器布局导致的、这会损坏或移动关键控制循环变量。
在 TMS320F28374S 上、当您添加或删除代码(甚至是死代码)时、链接器会为所有未显式固定到特定位置的变量重新分配存储器地址。 这可能导致:
存储器分配冲突 — ADC 采样或电流控制循环中使用的变量会重定位到与其他存储器操作(例如,DMA、CLA 或栈活动)重叠或被其他存储器操作损坏的地址 1.
执行时序移位 — 如果控制循环从闪存运行,则代码重组会更改对齐和缓存 /预取行为、从而更改 ADC 到 PWM 的延迟。 在快速电流环路中、即使是亚微秒级的时序变化也表现为一致的输出偏置 2.闪存段需要 128 位对齐、任何代码大小变化都可能在关键功能相对于闪存组边界和等待状态边界 3的填充位置发生移位。
与优化相关的变量损坏 —同一器件 (TMS320F28374S) 上的直接类似情况表明、添加/删除函数会导致计数器变量行为异常(范围从 0–0x7F 到 0–4 折叠)、这完全是由于链接器存储器重新分配所致。 该问题对优化级别敏感、并在将变量显式分配给存储器段 1 时消失。
| 行动 | 安全 |
|---|---|
#pragma DATA_SECTION(variable, "section_name") 用于所有关键控制环路和 ADC 相关变量 |
防止链接器在代码更改时重定位它们 |
将时间关键型控制功能分配给 .TI.ramfunc 部分 |
消除了闪存等待状态/对齐时序灵敏度 |
启用 -w 链接器选项并将所有段显式放置在 .cmd 文件中 |
防止默认分配算法产生不可预测的放置 4. |
比较 .map 两个版本之间的文件 |
准确标识移动了哪些变量/函数的地址 |
.map 为这两个构建(使用和不使用句柄)生成链接器文件并对它们进行比较。 在与电流基准、PI 控制器状态、ADC 结果缓冲区或校准偏移相关的变量中查找地址变化。 地址移入有问题区域的变量是固定偏置的来源。
后续: 您是否 .map 在两个编译版本之间比较了链接器文件、以确定哪些特定控制循环变量或函数更改了存储器地址?
谢谢
Srikanth
嗨、Liu、
没错、当添加/删除代码时、链接器会移动 几乎所有内容。 关键不是查找移动了哪些变量(它们都移动了)、而是查找哪些变量移动 到了存在访问冲突或时序问题的存储器区域。 以下是如何系统地缩小范围:
在.map 文件 diff 中、忽略与控制循环无关的变量。 仅关注 以下类别:
| 可变类别 | 水平 |
|---|---|
| ADC 结果缓冲器 | 原始 ADC 读数、平均样本 |
| 电流/电压基准 | IREF、Vref、设定点 |
| PI/PID 控制器状态 | 积分累加器、误差项、输出 |
| 校准偏移 | ADC 偏移、增益校正值 |
| PWM 占空比变量 | 占空比输出、比较值 |
对于上面的每个变量、检查其新地址是否跨越到 有问题的区域 1:
不要通过数百个地址更改来寻找、而是 固定您的关键变量并确认修复:
// Pin ADC and control-loop variables to a dedicated section
#pragma DATA_SECTION(adcResult, "ctrl_data")
#pragma DATA_SECTION(piIntegral, "ctrl_data")
#pragma DATA_SECTION(currentRef, "ctrl_data")
#pragma DATA_SECTION(dutyOutput, "ctrl_data")
// In your .cmd file, assign this section to a fixed, conflict-free RAM block:
SECTIONS
{
ctrl_data : > RAMGS4, PAGE = 1 // Use a GS RAM block NOT used by DMA
}
然后再次添加/删除手柄。 如果偏置消失、您已确认根本原因。 如果仍然存在、还要将控制 ISR 函数移至 RAM:
#pragma CODE_SECTION(controlLoopISR, ".TI.ramfunc")
这消除了在快速电流环路中导致一致偏置的闪存对齐/等待状态时序偏移 1.
您不需要确定 移动到坏区域的确切变量。 实际方法是:
#pragma DATA_SECTION.TI.ramfunc这是类似 TMS320F28374S 情况的确切分辨率、在这种情况下、变量行为完全由于链接器重新分配而发生变化 1.
此致、
Zackary Fleenor
您好 Liu、
您的发现确认了根本原因。 即使您的 ISR 本身位于 RAM 中、它 调用的函数 仍然位于闪存中。 当 CPU 从 RAM 分支到闪存中的 ISR 时、会导致等待状态损失、从而在控制循环中引入固定时序偏差 1.
在快速电流环路中、实际中断延迟的总和为:触发延迟+ ADC 采样+硬件响应+上下文保存+ ISR 内的所有代码执行 1.添加或删除代码(甚至是死代码)时、链接器会移位该嵌套函数在闪存中的位置。 这会更改其相对于 128 位闪存组边界和预取/缓存行边界的对齐 2.结果是每次 ISR 执行时,等待状态周期的数量不同但一致,这会将 ADC 到 PWM 的更新时间移动固定的量,表现为恒定电流偏置。

移动被调用函数可以 .TI.ramfunc 完全消除 ISR 执行路径中的闪存访问。 RAM 具有零等待状态、因此无论工程中其他地方的代码如何更改、时序都是确定性的 2.
确保 任何时间关键型 ISR 中的整个调用链都位于 RAM 中、而不仅仅是顶层 ISR 函数。 从 ISR 调用的任何函数(以及这些调用的任何函数) 也必须放置在中 .TI.ramfunc:
#pragma CODE_SECTION(controlLoopISR, ".TI.ramfunc")
#pragma CODE_SECTION(nestedFunction, ".TI.ramfunc")
// Include ALL functions in the ISR call tree
这可以使控制循环在添加或删除代码时不受链接器引起的闪存对齐变化的影响。
此致、
Zackary Fleenor