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.

[参考译文] RTOS/TMS320F28075:允许来自 TI-RTOS 内的中断

Guru**** 2208740 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/663273/rtos-tms320f28075-allowing-interrupts-from-within-ti-rtos

器件型号:TMS320F28075

工具/软件:TI-RTOS

我试图理解为什么我会得到不一致的 ADC 中断。  ADC 由 PWM 时钟触发、然后在转换完成时中断 CPU。  中断以2500Hz 的速率触发、序列中每4或5个中断就会丢失一次(我有一个 GPIO 位为高电平和低电平切换、因此我可以看到它何时不触发)。  我已经排除了其他已知中断、但现在我想知道 TI-RTOS 运行过程中是否有时间能够在短时间内阻止中断。   

我不熟悉 TI-RTOS、但我知道当它运行时、它有时会在中断上下文中运行、因此会阻止或至少延迟其他中断。  是否有办法从 TI-RTOS 内部重新启用中断、以便在阻止或切换较长的任务之前中断这些任务?  … 或者通过其他方式更一致地触发 ADC 中断?

谢谢、

   Aaron

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、Aaron、

    您以多快的速度运行器件?

    SYS/BIOS (例如 TI-RTOS 内核)会在短时间内禁用中断。 在 SYS/BIOS 版本说明中查看基准测试部分。 您可以点击该按钮来查找最大中断延迟。 它还显示了运行 Hwi 的持续时间。

    我希望您使用时钟模块的默认设置、因此它使用每1ms 运行一次的计时器。 您可以将其设置为用户提供(或无时钟)以消除计时器。 当然、您将在内核中失去计时机制(例如、没有 Task_sleep 或带有超时的 Semaphore_pend)、但它会将计时器消除为一个问题。

    SYS/BIOS 中始终存在零延迟中断(内核会增加零延迟)。 ADC 中断不能由内核管理。 缺点是 ISR 无法进行可能影响调度的内核调用(例如、没有 Semaphore_post)。 它可以布置另一个 Hwi、但这可以进行内核调用。

    Todd
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    谢谢 Todd。

    我以120 MHz 的频率运行时钟、我认为是默认的时钟模块设置。

    我尝试在发送程序之外运行中断(使用 Hwi_plug ()),但我看到同样的问题。

    它听起来不像计时器会导致中断不触发、而是会被延迟。 我看到中断没有在大约五分之一的时间触发、因此我认为其他事情正在发生。 为了驱动时序、我使用 PWM 定期启动 ADC、然后 ADC 在转换结束时触发中断。 中断至少在大多数时间触发、ADC 值变为良好状态。 这是设置代码...

    此设置中是否有任何问题?


    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // PWM 设置
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    EALLOW;

    //将 PWM 设置为以2.5kHz 的频率运行

    //设置 TBCLK
    //
    EPwm7Regs.TBPRD = PWM_TIMER_TBPRD; //设置计时器周期
    EPwm7Regs.TBPHS.bit.TBPHS = 0x0000; //相位为0
    EPwm7Regs.TBCTR = 0x0000; //清除计数器

    //设置比较值
    //
    EPwm7Regs.CMPA.bit.CMPA = PWM_MIN_CMP; //设置比较 A 值

    //设置计数器模式
    //
    EPwm7Regs.TBCTL.bit.CTRMODE = TB_FREEZE; //立即冻结,但稍后设置为 TB_COUNT_UP
    EPwm7Regs.TBCTL.bit.PHSEN = TB_DISABLE; //禁用相位加载
    // TODO:显示时钟速率计算
    EPwm7Regs.TBCTL.bit.HSPCLKDIV = TB_DIV4; //时钟与 SYSCLKOUT 的比率
    EPwm7Regs.TBCTL.bit.CLKDIV = TB_DIV2;

    //设置隐藏
    //
    EPwm7Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
    EPwm7Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;//零负载

    //设置电机驱动器的操作
    //
    EPwm7Regs.AQCTLA.bit.ZRO = AQ_SET;
    EPwm7Regs.AQCTLA.bit.CAU = AQ_CLEAR;

    //设置每个周期开始时的 ADC 触发
    //
    EPwm7Regs.ETSEL.bit.SOCAEN = 0;//禁用组上的 SOC
    EPwm7Regs.ETSEL.bit.SOCASEL = ET_CTR_ZERO;//在计数器重新归零时选择 SOC (恰好在 PWM 变为高电平之后)
    EPwm7Regs.ETPS.bit.SOCAPRD = 1;//在发生第一个事件时生成脉冲

    EDIS;


    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // ADC 设置
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    EALLOW;

    //写入配置
    AdcaRegs.ADCCTL2.bit.prescale = 6;//将 ADCCLK 分频器设置为/4
    AdcSetMode (ADC_ADCA、ADC_resolution_12位、ADC_SIGNALMODE_SINGLE);

    AdcbRegs.ADCCTL2.bit.prescale = 6;//将 ADCCLK 分频器设置为/4
    AdcSetMode (ADC_ADCB、ADC_Resolution、12位、ADC_SIGNALMODE_SINGLE);

    //将脉冲位置设置为晚期
    AdcaRegs.ADCCTL1.bit.INTPULSEPOS=1;
    AdcbRegs.ADCCTL1.bit.INTPULSEPOS = 1;

    //为 ADC 加电
    AdcaRegs.ADCCTL1.bit.ADCPWDNZ = 1;
    AdcbRegs.ADCCTL1.bit.ADCPWDNZ = 1;

    //此时、延迟1ms 以允许 ADC 加电时间
    //然后再继续其他设置。 调用函数
    //必须确保这一点。 数据表要求至少500us。

    EDIS;

    (笑声)
    继续


    uint16 acqps;

    //设置最小采集窗口(在 SYSCLKS 中)
    acqps = 14;// 75ns 待定-需要验证

    //选择要转换的通道和相对计时。
    //两个 ADC 都将与驱动的 ADC A 并联工作
    //在最后一次转换结束时中断。
    //
    EALLOW;
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // ADC A
    AdcaRegs.ADCBURSTCTL.bit.BURSTEN = 1;
    AdcaRegs.ADCBURSTCTL.bit.BURSTTRIGSEL = BURSTTRIGSEL_EPWM7_ADCSOCA;
    AdcaRegs.ADCBURSTCTL.bit.BURSTSIZE = ADC_A_BURST_LENGTH;

    // SOC0
    AdcaRegs.ADCSOC0CTL.bit.CHSEL = 1;// FSR0
    AdcaRegs.ADCSOC0CTL.bit.ACQPS = acqps;
    // SOC1
    AdcaRegs.ADCSOC1CTL.bit.CHSEL = 2;// FSR1
    AdcaRegs.ADCSOC1CTL.bit.ACQPS = acqps;
    // SOC2
    AdcaRegs.ADCSOC2CTL.bit.CHSEL = 3;// FSR2
    AdcaRegs.ADCSOC2CTL.bit.ACQPS = acqps;
    // SOC3
    AdcaRegs.ADCSOC3CTL.bit.CHSEL = 4;// FSR3
    AdcaRegs.ADCSOC3CTL.bit.ACQPS = acqps;
    // SOC4
    AdcaRegs.ADCSOC4CTL.bit.CHSEL = 5;// AMOTOR
    AdcaRegs.ADCSOC4CTL.bit.ACQPS = acqps;
    // SOC5
    AdcaRegs.ADCSOC5CTL.bit.CHSEL = 15;// FSR6
    AdcaRegs.ADCSOC5CTL.bit.ACQPS = acqps;
    // SOC6
    AdcaRegs.ADCSOC6CTL.bit.CHSEL = 14;// FSR7
    AdcaRegs.ADCSOC6CTL.bit.ACQPS = acqps;

    AdcaRegs.ADCINTSEL1N2.bit.INT1SEL = ADC_A_EOCx_TRIGGER_ADCINT1;//设置:EOCx 为 ADCINT1的触发器
    AdcaRegs.ADCINTSEL1N2.bit.INT1E = 1;//启用标志
    AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;//清除标志

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // ADC B
    AdcbRegs.ADCBURSTCTL.bit.bURSTEN = 1;
    AdcbRegs.ADCBURSTCTL.bit.bURSTTRIGSEL = BURSTTRIGSEL__EPWM7_ADCSOCA;
    AdcbRegs.ADCBURSTCTL.bit.bURSTSIZE = ADC_B_BURST_LENGTH;

    // SOC0
    AdcbRegs.ADCSOC0CTL.bit.CHSEL = 0;// ADCINB0、JP1_PIN8
    AdcbRegs.ADCSOC0CTL.bit.ACQPS = acqps;
    // SOC1
    AdcbRegs.ADCSOC1CTL.bit.CHSEL = 1;// ADCINB1、JP1_pin9
    AdcbRegs.ADCSOC1CTL.bit.ACQPS = acqps;
    // SOC2
    AdcbRegs.ADCSOC2CTL.bit.CHSEL = 2;// ADCINB2、JP1_pin10
    AdcbRegs.ADCSOC2CTL.bit.ACQPS = acqps;
    // SOC3
    AdcbRegs.ADCSOC3CTL.bit.CHSEL = 3;// FSR5
    AdcbRegs.ADCSOC3CTL.bit.ACQPS = acqps;
    // SOC4
    AdcbRegs.ADCSOC4CTL.bit.CHSEL = 4;// FSR4
    AdcbRegs.ADCSOC4CTL.bit.ACQPS = acqps;
    // SOC5
    AdcbRegs.ADCSOC5CTL.bit.CHSEL = 5;// ADCINB5、U3_VPROPI
    AdcbRegs.ADCSOC5CTL.bit.ACQPS = acqps;

    // ADC B 没有中断设置,因为 ADC A 提供中断。

    EDIS;


    谢谢、
    Aaron
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    一些 适用于上述代码的#def。。

    #definePWM_TIMER_TBPRD 3000 //周期寄存器
    #definePWM_MIN_CMP 0

    //从 SPRUHM9D 表9-22.
    #defineBURSTTRIGSEL__EPWM7_ADCSOCA 0x11
    //从 SPRUHM9D 表9-28中删除
    #defineTRIGSEL__EPWM7_ADCSOCA 0x11
    //设置 ADC A,比总样本少一个
    #defineADC_A_BURST_LENGTH 6.
    #defineADC_A_EOCx_TRIGGER_ADCINT1 6.
    //设置 ADC B,比总样本少一个
    #defineADC_B_BURST_LENGTH 5.
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、Aaron、

    我在您的代码中看不到任何奇怪的东西。 您有其他中断吗? 您是否正在执行任何软件中断优先级划分/嵌套? 或者、您在原始帖子中说过您已将其排除为可能的原因吗?

    惠特尼
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Aaron、在这方面有什么进展?

    惠特尼
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    感谢您询问 Whitney。

    我在每个 ISR 期间设置和清除 GPIO 输出、然后在示波器上观察、从而排除了其他应用中断。 当 ADC 中断没有指示触发时(由第二个 GPIO 输出证明)、其他 ISR 似乎都不会在时间段内产生干扰。

    如果有一种方法可以在调度 ISR 中放置类似的检测(GPIO 输出)、则这是一种方法。 但是、TI_RTOS 似乎是为了在 ISR 触发后相对较快地启用中断、因此这似乎不是一个可能的问题。

    另一种方法是让我有选择地禁用系统中的所有其他代码、看看是否有任何变化、然后尝试将影响这一点的因素置零。 我必须就其他优先事项开展工作,因此还没有机会尝试这一做法。

    Aaron
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Aaron、

    我再看一下您的代码、我怀疑突发模式没有达到您所期望的效果。 每次接收到触发信号时、突发模式都会遍历 BURSTSIZE + 1个连续 SOC。 突发转换的 SOC 由循环指针确定-这意味着它不会每次从 SOC0开始。 由于您执行的是7次突发、总共有16个 SOC、因此您的中断间隔不一致。

    我怀疑您应该将所用 SOC 的所有 TRIGSEL 字段配置为同一个源。 它们仍会在单个触发器上逐个转换。 请告诉我、这是否能满足您的期望。

    惠特尼

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Aaron、

    您是否有机会了解我的上述理论? 祝你好运?

    谢谢、
    惠特尼
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Whitney、
    我基本上遵循了 SPRUHM9D 中的突发模式示例、但在 SOC6的转换结束时添加了中断触发器。 在示例中、16个通道的循环似乎不是问题。 显然、只有设置的通道才应该相关。
    如果 RRPOINTER 是一个问题、我还尝试在每个中断结束时将其清零、以便强制下一个触发器使用 SOC0开始转换、但这不会改变行为。

    但是、我采用了提示和放弃的突发模式。 为什么在 SOC6转换结束时突发模式不提供一致的触发、这毫无意义、但我让它处理下面的代码、这不使用突发模式。


    //从 SPRUHM9D 表9-22.
    #define BURSTTRIGSEL__EPWM7_ADCSOCA 0x11
    //从 SPRUHM9D 表9-28中删除
    #define TRIGSEL__EPWM7_ADCSOCA 0x11
    //设置 ADC A 以在 SOC6完成时触发
    #define ADC_A_EOCx_TRIGGER_ADCINT1 6.

    // ADC A
    //
    // SOC0
    AdcaRegs.ADCSOC0CTL.bit.CHSEL = 1;//
    AdcaRegs.ADCSOC0CTL.bit.TRIGSEL = BURSTTRIGSEL__EPWM7_ADCSOCA;
    AdcaRegs.ADCSOC0CTL.bit.ACQPS = acqps;
    // SOC1
    AdcaRegs.ADCSOC1CTL.bit.CHSEL = 2;//
    AdcaRegs.ADCSOC1CTL.bit.TRIGSEL = BURSTTRIGSEL__EPWM7_ADCSOCA;
    AdcaRegs.ADCSOC1CTL.bit.ACQPS = acqps;
    // SOC2
    AdcaRegs.ADCSOC2CTL.bit.CHSEL = 3;//
    AdcaRegs.ADCSOC2CTL.bit.TRIGSEL = BURSTTRIGSEL__EPWM7_ADCSOCA;
    AdcaRegs.ADCSOC2CTL.bit.ACQPS = acqps;
    // SOC3
    AdcaRegs.ADCSOC3CTL.bit.CHSEL = 4;//
    AdcaRegs.ADCSOC3CTL.bit.TRIGSEL = BURSTTRIGSEL__EPWM7_ADCSOCA;
    AdcaRegs.ADCSOC3CTL.bit.ACQPS = acqps;
    // SOC4
    AdcaRegs.ADCSOC4CTL.bit.CHSEL = 5;//
    AdcaRegs.ADCSOC4CTL.bit.TRIGSEL = BURSTTRIGSEL__EPWM7_ADCSOCA;
    AdcaRegs.ADCSOC4CTL.bit.ACQPS = acqps;
    // SOC5
    AdcaRegs.ADCSOC5CTL.bit.CHSEL = 15;//
    AdcaRegs.ADCSOC5CTL.bit.TRIGSEL = BURSTTRIGSEL__EPWM7_ADCSOCA;
    AdcaRegs.ADCSOC5CTL.bit.ACQPS = acqps;
    // SOC6
    AdcaRegs.ADCSOC6CTL.bit.CHSEL = 14;//
    AdcaRegs.ADCSOC6CTL.bit.TRIGSEL = BURSTTRIGSEL__EPWM7_ADCSOCA;
    AdcaRegs.ADCSOC6CTL.bit.ACQPS = acqps;

    AdcaRegs.ADCINTSEL1N2.bit.INT1SEL = ADC_A_EOCx_TRIGGER_ADCINT1;//设置:EOCx 为 ADCINT1的触发器
    AdcaRegs.ADCINTSEL1N2.bit.INT1E = 1;//启用标志
    AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;//清除标志

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // ADC B
    //
    // SOC0
    AdcbRegs.ADCSOC0CTL.bit.CHSEL = 0;//
    AdcbRegs.ADCSOC0CTL.bit.TRIGSEL = BURSTTRIGSEL__EPWM7_ADCSOCA;
    AdcbRegs.ADCSOC0CTL.bit.ACQPS = acqps;
    // SOC1
    AdcbRegs.ADCSOC1CTL.bit.CHSEL = 1;//
    AdcbRegs.ADCSOC1CTL.bit.TRIGSEL = BURSTTRIGSEL__EPWM7_ADCSOCA;
    AdcbRegs.ADCSOC1CTL.bit.ACQPS = acqps;
    // SOC2
    AdcbRegs.ADCSOC2CTL.bit.CHSEL = 2;//
    AdcbRegs.ADCSOC2CTL.bit.TRIGSEL = BURSTTRIGSEL__EPWM7_ADCSOCA;
    AdcbRegs.ADCSOC2CTL.bit.ACQPS = acqps;
    // SOC3
    AdcbRegs.ADCSOC3CTL.bit.CHSEL = 3;//
    AdcbRegs.ADCSOC3CTL.bit.TRIGSEL = BURSTTRIGSEL__EPWM7_ADCSOCA;
    AdcbRegs.ADCSOC3CTL.bit.ACQPS = acqps;
    // SOC4
    AdcbRegs.ADCSOC4CTL.bit.CHSEL = 4;//
    AdcbRegs.ADCSOC4CTL.bit.TRIGSEL = BURSTTRIGSEL__EPWM7_ADCSOCA;
    AdcbRegs.ADCSOC4CTL.bit.ACQPS = acqps;
    // SOC5
    AdcbRegs.ADCSOC5CTL.bit.CHSEL = 5;//
    AdcbRegs.ADCSOC5CTL.bit.TRIGSEL = BURSTTRIGSEL__EPWM7_ADCSOCA;
    AdcbRegs.ADCSOC5CTL.bit.ACQPS = acqps;

    // ADC B 没有中断设置,因为 ADC A 提供中断。