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.

TMS320F280039C: Abnormal highest priority ePWM interrupt under BIOS system

Part Number: TMS320F280039C
Other Parts Discussed in Thread: SYSBIOS

Tool/software:

The code for the BIOS system is shown below. The EPWM waveform (blue) and the interrupt waveform (yellow, toggling once each time the EPWM interrupt is entered) are shown in Figure 1. As can be seen from the figure, the toggling position of the interrupt does not occur at the midpoint of the EPWM waveform (i.e., the PRD position). Moreover, an interrupt anomaly occurs at a fixed interval (1 ms).

BIOS.cpuFreq.lo = 120000000;

Load.hwiEnabled = true;
Load.swiEnabled = true;

var task0Params = new Task.Params();
task0Params.instance.name = "task0";
task0Params.priority = 12;
task0Params.stackSize = 512;
Program.global.task0 = Task.create("&TaskParameterInit", task0Params);
var task1Params = new Task.Params();
task1Params.instance.name = "task1";
task1Params.priority = 8;
task1Params.stackSize = 512;
Program.global.task1 = Task.create("&TaskBasicControl", task1Params);
// task2
var task2Params = new Task.Params();
task2Params.instance.name = "task2";
task2Params.priority = 7;
task2Params.stackSize = 768;
Program.global.task2 = Task.create("&TaskMonitorControl", task2Params);

var ti_sysbios_hal_Hwi0Params = new ti_sysbios_hal_Hwi.Params();
ti_sysbios_hal_Hwi0Params.instance.name = "hwi_pwm";
ti_sysbios_hal_Hwi0Params.priority = 15;
ti_sysbios_hal_Hwi0Params.eventId = -1;
Program.global.hwi_pwm = ti_sysbios_hal_Hwi.create(52, "&HwiPwmISR", ti_sysbios_hal_Hwi0Params);
// hwi1
var ti_sysbios_hal_Hwi1Params = new ti_sysbios_hal_Hwi.Params();
ti_sysbios_hal_Hwi1Params.instance.name = "hwi_sciarx";
ti_sysbios_hal_Hwi1Params.priority = 9;
Program.global.hwi_sciarx = ti_sysbios_hal_Hwi.create(96, "&HwiSciaRX", ti_sysbios_hal_Hwi1Params);
// hwi2
var ti_sysbios_hal_Hwi2Params = new ti_sysbios_hal_Hwi.Params();
ti_sysbios_hal_Hwi2Params.instance.name = "hwi_sciatx";
ti_sysbios_hal_Hwi2Params.priority = 8;
Program.global.hwi_sciatx = ti_sysbios_hal_Hwi.create(97, "&HwiSciaTX", ti_sysbios_hal_Hwi2Params);

void EPWM5_Init(void)
{
EALLOW;
CpuSysRegs.PCLKCR2.bit.EPWM5 = 1; // 开启EPWM1时钟
EDIS;
//EALLOW;
//EPwm5Regs.TZSEL.bit.OSHT4 = 1; // 使能单次触发(One-Shot)保护
//EPwm5Regs.TZEINT.bit.OST = 1;
//EDIS;
EALLOW;
GpioCtrlRegs.GPAPUD.bit.GPIO8 = 1; // Disable pull-up on GPIO0 (EPWM1A)
GpioCtrlRegs.GPAPUD.bit.GPIO9 = 1; // Disable pull-up on GPIO1 (EPWM1B)
GpioCtrlRegs.GPAMUX1.bit.GPIO8 = 1; // Configure GPIO0 as EPWM1A
GpioCtrlRegs.GPAMUX1.bit.GPIO9 = 1; // Configure GPIO1 as EPWM1B
EDIS;
EPwm5Regs.TBCTL.bit.PHSEN = TB_ENABLE; //相位加载使能
EPwm5Regs.TBPHS.bit.TBPHS = 0; //相位值为0
EPwm5Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; //高速预分频
EPwm5Regs.TBCTL.bit.CLKDIV = TB_DIV1; //时基预分频 DIV1意思不分频
EPwm5Regs.TBPRD = 1000; // 设置周期值(决定PWM频率)
EPwm5Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // 向上-向下计数模式
EPwm5Regs.TBCTL.bit.PRDLD = TB_SHADOW; // 影子寄存器模式
EPwm5Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; //CMPA使用影子寄存器
EPwm5Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW; //CMPB使用影子寄存器
EPwm5Regs.CMPCTL.bit.LOADAMODE = 2; //重要,关乎合适加载占空比
EPwm5Regs.CMPCTL.bit.LOADBMODE = 2; //重要,关乎合适加载占空比
EPwm5Regs.CMPA.bit.CMPA = 0; // // 初始化CMPA值
EPwm5Regs.CMPB.bit.CMPB = 1000; // // 初始化CMPA值
EPwm5Regs.AQCTLA.bit.CAU = AQ_CLEAR; // 当计数器=比较值A且计数方向向上(UP)时,清除PWM1A(拉低)
EPwm5Regs.AQCTLA.bit.CAD = AQ_SET; // 当计数器=比较值A且计数方向向下(DOWN)时,置位PWM1A(拉高)
EPwm5Regs.AQCTLB.bit.CBU = AQ_SET; // 当计数器=比较值A且计数方向向上(UP)时,清除PWM1A(拉低)
EPwm5Regs.AQCTLB.bit.CBD = AQ_CLEAR; // 当计数器=比较值A且计数方向向下(DOWN)时,置位PWM1A(拉高)
EPwm5Regs.ETSEL.bit.INTSEL = ET_CTR_PRD;
EPwm5Regs.ETSEL.bit.INTEN = 1; // 使能ePWM1中断
EPwm5Regs.ETPS.bit.INTPRD = 1; // 每个事件都触发中断(无分频)
}

void HwiPwmISR(void)
{
LED16_TOGGLE;
LED17_TOGGLE;
EPwm5Regs.ETCLR.bit.INT = 1;
}


The code for the non-BIOS system is shown below. The EPWM (blue) waveform and the interrupt (yellow, toggling once each time the EPWM interrupt is entered) waveform are shown in Figure 2. As can be seen from the figure, the interrupt toggling occurs precisely at the midpoint of the EPWM waveform and remains stable without any anomalies.

void EPWM5_Init(void)
{
EALLOW;
CpuSysRegs.PCLKCR2.bit.EPWM5 = 1; // 开启EPWM1时钟
EDIS;
EALLOW;
PieVectTable.EPWM5_INT = &epwm1_timer_isr;//提供中断服务程序入口
EDIS;
// EALLOW;
// EPwm5Regs.TZSEL.bit.OSHT4 = 1; // 使能单次触发(One-Shot)保护
//EPwm5Regs.TZEINT.bit.OST = 1;
//EDIS;
EALLOW;
GpioCtrlRegs.GPAPUD.bit.GPIO8 = 1; // Disable pull-up on GPIO0 (EPWM1A)
GpioCtrlRegs.GPAPUD.bit.GPIO9 = 1; // Disable pull-up on GPIO1 (EPWM1B)
GpioCtrlRegs.GPAMUX1.bit.GPIO8 = 1; // Configure GPIO0 as EPWM1A
GpioCtrlRegs.GPAMUX1.bit.GPIO9 = 1; // Configure GPIO1 as EPWM1B
EDIS;
EPwm5Regs.TBCTL.bit.PHSEN = TB_ENABLE;//相位加载使能
EPwm5Regs.TBPHS.bit.TBPHS =0 ; //相位值为0
EPwm5Regs.TBCTL.bit.HSPCLKDIV=TB_DIV1; //高速预分频
EPwm5Regs.TBCTL.bit.CLKDIV=TB_DIV1; //时基预分频 DIV1意思不分频
EPwm5Regs.TBPRD = 1000; // 设置周期值(决定PWM频率)
EPwm5Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // 向上-向下计数模式
EPwm5Regs.TBCTL.bit.PRDLD = TB_SHADOW; // 影子寄存器模式
EPwm5Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; //CMPA使用影子寄存器
EPwm5Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW; //CMPB使用影子寄存器
EPwm5Regs.CMPCTL.bit.LOADAMODE = 2; //重要,关乎合适加载占空比
EPwm5Regs.CMPCTL.bit.LOADBMODE = 2; //重要,关乎合适加载占空比
EPwm5Regs.CMPA.bit.CMPA = 500; // // 初始化CMPA值
EPwm5Regs.CMPB.bit.CMPB = 500; // // 初始化CMPA值
EPwm5Regs.AQCTLA.bit.CAU = AQ_CLEAR;// 当计数器=比较值A且计数方向向上(UP)时,清除PWM1A(拉低)
EPwm5Regs.AQCTLA.bit.CAD = AQ_SET; // 当计数器=比较值A且计数方向向下(DOWN)时,置位PWM1A(拉高)
EPwm5Regs.AQCTLB.bit.CBU = AQ_SET;// 当计数器=比较值A且计数方向向上(UP)时,清除PWM1A(拉低)
EPwm5Regs.AQCTLB.bit.CBD = AQ_CLEAR; // 当计数器=比较值A且计数方向向下(DOWN)时,置位PWM1A(拉高)
EPwm5Regs.ETSEL.bit.INTSEL =ET_CTR_PRD;
EPwm5Regs.ETSEL.bit.INTEN = 1; // 使能ePWM1中断
EPwm5Regs.ETPS.bit.INTPRD = 1; // 每个事件都触发中断(无分频)
EALLOW;
PieCtrlRegs.PIEIER3.bit.INTx5 = 1; //EPWM1中断
IER |= M_INT3; //使能CPU中断3
EDIS;
EALLOW;
CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1; // 同步启动所有ePWM时基计数器
EDIS;
EINT; // 开启全局中
ERTM; // 允许实时调试中断
}

__interrupt void epwm1_timer_isr(void)
{
LED16_TOGGLE;
LED17_TOGGLE;
EPwm1Regs.ETCLR.bit.INT = 1;
PieCtrlRegs.PIEACK.bit.ACK3 = 1;
}

  • Hello,

    Skip in pulses could happen because of change in Action qualifier set-up, do you change your AQ during code?

  • During program execution, AQ, CMP, and TBPRD remain unchanged, and the EPWM waveform (the blue waveform in Figure 1) shows no anomalies. However, the timing of entering the interrupt (represented by the yellow waveform in the diagram, which toggles each time the EPWM interrupt is triggered) is incorrect.

    The initialization configurations for Figure 1 and Figure 2 are essentially identical, except that the system in Figure 1 runs on a BIOS-based system, where the EPWM interrupt is configured in the .cfg file, as shown in the code below.
    var ti_sysbios_hal_Hwi = xdc.useModule('ti.sysbios.hal.Hwi');
    var ti_sysbios_hal_Hwi0Params = new ti_sysbios_hal_Hwi.Params();
    ti_sysbios_hal_Hwi0Params.instance.name = "hwi_pwm";
    ti_sysbios_hal_Hwi0Params.priority = 15;
    ti_sysbios_hal_Hwi0Params.eventId = -1;
    Program.global.hwi_pwm = ti_sysbios_hal_Hwi.create(52, "&HwiPwmISR", ti_sysbios_hal_Hwi0Params);

    In contrast, Figure 2 runs on a non-BIOS system, with the interrupt configured during initialization, and the timing of entering the interrupt (represented by the yellow waveform, which toggles each time the EPWM interrupt is triggered) is normal, as shown in the code below.
    EALLOW;
    PieVectTable.EPWM5_INT = &epwm1_timer_isr;
    EDIS;
    EPwm5Regs.ETSEL.bit.INTSEL =ET_CTR_PRD;
    EPwm5Regs.ETSEL.bit.INTEN = 1;
    EPwm5Regs.ETPS.bit.INTPRD = 1;
    EALLOW;
    PieCtrlRegs.PIEIER3.bit.INTx5 = 1;
    IER |= M_INT3;
    EDIS;

    I would like to know whether this issue is caused by scheduling in the BIOS system, which leads to abnormal timing of entering the EPWM interrupt. If so, how can it be optimized and improved?

  • During program execution, AQ, CMP, and TBPRD remain unchanged, and the EPWM waveform (the blue waveform in Figure 1) shows no anomalies. However, the timing of entering the interrupt (represented by the yellow waveform in the diagram, which toggles each time the EPWM interrupt is triggered) is incorrect.

    The initialization configurations for Figure 1 and Figure 2 are essentially identical, except that the system in Figure 1 runs on a BIOS-based system, where the EPWM interrupt is configured in the .cfg file, as shown in the code below.
    var ti_sysbios_hal_Hwi = xdc.useModule('ti.sysbios.hal.Hwi');
    var ti_sysbios_hal_Hwi0Params = new ti_sysbios_hal_Hwi.Params();
    ti_sysbios_hal_Hwi0Params.instance.name = "hwi_pwm";
    ti_sysbios_hal_Hwi0Params.priority = 15;
    ti_sysbios_hal_Hwi0Params.eventId = -1;
    Program.global.hwi_pwm = ti_sysbios_hal_Hwi.create(52, "&HwiPwmISR", ti_sysbios_hal_Hwi0Params);

    In contrast, Figure 2 runs on a non-BIOS system, with the interrupt configured during initialization, and the timing of entering the interrupt (represented by the yellow waveform, which toggles each time the EPWM interrupt is triggered) is normal, as shown in the code below.
    EALLOW;
    PieVectTable.EPWM5_INT = &epwm1_timer_isr;
    EDIS;
    EPwm5Regs.ETSEL.bit.INTSEL =ET_CTR_PRD;
    EPwm5Regs.ETSEL.bit.INTEN = 1;
    EPwm5Regs.ETPS.bit.INTPRD = 1;
    EALLOW;
    PieCtrlRegs.PIEIER3.bit.INTx5 = 1;
    IER |= M_INT3;
    EDIS;

    I would like to know whether this issue is caused by scheduling in the BIOS system, which leads to abnormal timing of entering the EPWM interrupt. If so, how can it be optimized and improved?

  • Hello, thanks for your patience. Are you still experiencing this issue? Interrupts aren't nested by default, so if there's some other interrupt occasionally being triggered shortly before the EPWM interrupt is triggered, that could prevent it from running until the earlier interrupt completes. Do you have other interrupt enabled in this system? At the very least, the SYSBIOS Clock module by default sets up a Hwi for one of the Timer interrupts on the device, so that could be one possible factor.

    Also keep in mind that with SYSBIOS, latency to reach your Hwi function is longer than a regular non-BIOS interrupt because of the time it takes to run the Hwi dispatcher. See timing benchmarks here:

    https://software-dl.ti.com/dsps/dsps_public_sw/sdo_sb/targetcontent/bios/sysbios/6_83_00_18/exports/bios_6_83_00_18/packages/ti/sysbios/benchmarks/doc-files/benchmarks.html

    There are some tips at the thread below on nesting and using "zero latency" interrupts if required:

     [FAQ] Are there any C28 device specific items with TI-RTOS (SYS/BIOS)? 

    Note that SYS/BIOS is no longer being supported. I can offer some ideas, but support will be limited. If you're still able to, I recommend migrating to another option like FreeRTOS.

    Whitney