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.
大家好、我有一个关于将 volatile 与 CPU 和 CLA 之间共享的变量一同使用的编译器问题。 我已经构建了一个包含三个文件的简单示例:
cla_shared.c 声明两个浮点变量、一个在 CLA 到 CPU 消息 RAM 中、另一个在 CPU 到 CLA 消息 RAM 中:
// cla_shared.c // shared variables with cpu // in cpu2cla message RAM #pragma SET_DATA_SECTION("SCRATCH_CPU1TOCLA1") volatile float iir_input_cpu2cla=0; // in cla2cpu message RAM #pragma SET_DATA_SECTION("SCRATCH_CLA1TOCPU1") volatile float iir_output_cla2cpu;
clatasks.cla 具有 CLA 任务1代码。 CLA 任务采用 iir_input_cpu2cla、并将其传递给一个 IIR 滤波器、其输出为 iir_output_cla2cpu:
// clatasks.cla // shared variables with cpu // in cpu2cla message RAM extern volatile float iir_input_cpu2cla; // in cla2cpu message RAM extern volatile float iir_output_cla2cpu; // local variables for CLA only float IIR_SR[6]; float IIR_B[4]; float IIR_A[4]; // cla task 1 is triggered by ePWM interrupt interrupt void Cla1Task1(void) { iir_output_cla2cpu = iir_input_cpu2cla*IIR_B[0] + IIR_SR[5]; IIR_SR[4] = iir_input_cpu2cla*IIR_B[1] + iir_output_cla2cpu*IIR_A[1] + IIR_SR[3]; IIR_SR[5] = IIR_SR[4]; IIR_SR[2] = iir_input_cpu2cla*IIR_B[2] + iir_output_cla2cpu*IIR_A[2] + IIR_SR[1]; IIR_SR[3] = IIR_SR[2]; IIR_SR[0] = iir_input_cpu2cla*IIR_B[3] + iir_output_cla2cpu*IIR_A[3]; IIR_SR[1] = IIR_SR[0]; // trigger the CPU ISR CLA_forceSoftwareInterrupt(CLA1SOFT_IN_REGS, 1); }
cpuisr.c 具有 CPU ISR 代码。 它每次迭代都会更改 iir_input_cpu2cla (制作一个正弦波)、然后根据 iir_input_cpu2cla 和 iir_output_cla2cpu 的值执行某些函数:
// cpuisr.c // shared variables with cpu // in cpu2cla message RAM extern volatile float iir_input_cpu2cla; // in cla2cpu message RAM extern volatile float iir_output_cla2cpu; // cpu-only variables in GSRAM float time=0.0; // CPU ISR is triggered by CLA task 1, software force interrupt interrupt void CPU_ISR(void) { time+=1.0; iir_input_cpu2cla=sin(idx*2*3.14159/1000.0); if(iir_output_cla2cpu>0.5) { // stuff depending on iir_output_cla2cpu } if(iir_output_cla2cpu<-0.5) { // stuff depending on iir_output_cla2cpu } if(iir_input_cpu2cla>0.5) { // stuff depending on iir_input_cpu2cla } if(iir_input_cpu2cla<-0.5) { // stuff depending on iir_input_cpu2cla } // ack the pie PieCtrlRegs.PIEACK.all = PIEACK_GROUP11; }
CLA 任务是定期触发的(例如、由 ePWM 中断触发)。 在 CLA 任务的末尾,它通过 CLA_forceSoftwareInterrupt ()触发 CPU ISR。 因此、CLA 任务和 CPU ISR 以锁步方式执行。 我们假定 CPU ISR 一直在下一个 CLA 任务开始前返回、这意味着它们永远不会同时执行。
我的问题是、使共享变量 iir_input_cpu2cla 和 iir_output_cla2cpu volatile 是否必要/合适。 如果我知道任务/ISR 永远不会在另一个正在运行时执行、那么在两次访问之间不会有变量改变的风险。 但是、如果变量被 限定为 volatile、那么我担心性能会受到不必要的 RAM 访问的影响。 例如、ClaTask1只需要从 iir_input_cpu2cla 读取一次 并且只需要对 iir_output_cla2cpu 写入一次、但是易失性可能会导致生成的代码每读取一次额外的三倍。 类似地、CPU_ISR 应该只需要对 iir_input_cpu2cla 执行一次写入操作 、并需要对 iir_output_cla2cpu 执行一次读取操作、但是易失性可能会使每个读取操作额外读取两次。
但是、如果删除 volatile 限定符、是否存在根本无法读取这些限定符的风险?
此致、
迈克
有关 易失性 variable 时、编译器需要生成代码、该代码假设可以通过系统中的某些其他方式随时读取或写入该变量。 假设有一系列语句、您知道这是不可能的。 就在语句范围之前、复制 易失性 转换为正常的局部变量。 在该 RANGE 语句中、请改用普通局部变量。 在该语句范围之后、将该普通局部变量复制到 易失性 成正比。
谢谢。此致、
-乔治
您好、George、感谢您的快速响应。
我还考虑将消息 RAM 中的易失性变量复制到非易失性局部变量作为权变措施。 听起来是一种非常安全的方法、但还有其他方法吗? 在我的实际代码中、有很多共享变量、在开始和结束时复制所有这些变量的时间很长。ISR/任务。
此致、
迈克
也许这个想法使它实际... 将所有共享变量收集到一个结构中。 创建两个结构实例。 一个是易失性的、另一个不易失。 根据需要在它们之间复制。 使用简单的结构分配实现副本...
non_volatile_instance = volatile_instance;
依赖编译器优化该副本。
谢谢。此致、
-乔治