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.

[参考译文] TMS320F280049C:外设挂起时触发奇怪的行为

Guru**** 2544420 points


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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1420653/tms320f280049c-can-peripheral-hanging-triggers-strange-behavior

器件型号:TMS320F280049C

工具与软件:

您好!

这是一个奇怪的行为,我们观察到,并希望得到一些帮助,以了解正在发生什么,为什么它正在发生。

我们正在为我们的一款产品设置 CAN 外设。 我们按如下方式设置 CAN 和 ISR:

void setup_can(void)
{
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_CANA);

    // Initialize the CAN controller
    CAN_initModule(CANA_BASE);

    //
    // setup Auto Bus On and delay time (in clock cycles - default is 0h)
    //
    CAN_setAutoBusOnTime(CANA_BASE, 0UL);
    CAN_enableAutoBusOn(CANA_BASE);

    // Set up the CAN bus bit rate depending on CAN_SPEED_UC digital input; 0 = 250kBits/s / 1 = 500kBits/s
    if (0u == GpioDataRegs.GPADAT.bit.GPIO11)
    {
        CAN_setBitRate(CANA_BASE, DEVICE_SYSCLK_FREQ, 250000, 16);
    }
    else
    {
        CAN_setBitRate(CANA_BASE, DEVICE_SYSCLK_FREQ, 500000, 25);
    }

    // Enable interrupts on the CAN peripheral.
    CAN_enableInterrupt(CANA_BASE, CAN_INT_IE0 | CAN_INT_ERROR);

    CAN_enableRetry(CANA_BASE);

    // Start CAN module operations
    CAN_startModule(CANA_BASE);
}

__interrupt void can_isr(void)
{
#define CAN_ERROR_COUNT                 25

    uint32_t status_ui32, status2_ui32;
    uint16_t can_msg_frame_type[1];

    //Allow ADC1/SCIB_TX/Timer0/Timer1/SCIB_Rx to pre-empt ISR
    IER |= (M_INT1|M_INT9|M_INT13);
    IER &= (M_INT1|M_INT9|M_INT13);

    // Enable PIE interrupt group 1 - Interrupt 1 (ADCA1)
    // Enable PIE interrupt group 1 - Interrupt 3 (ADCC1)
    // Enable PIE interrupt group 1 - Interrupt 7 (TIMER0)
    // Enable PIE interrupt group 9 - Interrupt 4 (SCIB_TX)
    // Enable PIE interrupt group 9 - Interrupt 3 (SCIB_RX)
    // Enable PIE interrupt group 9 - Interrupt 4 (SCIB_TX)
    PieCtrlRegs.PIEIER1.bit.INTx1 = 1;
    PieCtrlRegs.PIEIER1.bit.INTx3 = 1;
    PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
    PieCtrlRegs.PIEIER9.bit.INTx3 = 1;
    PieCtrlRegs.PIEIER9.bit.INTx4 = 1;

    // Clear ACK to allow group 1 INT
    // Clear ACK to allow group 9 INT
    PieCtrlRegs.PIEACK.bit.ACK1 = 1;
    PieCtrlRegs.PIEACK.bit.ACK9 = 1;

    // Wait one cycle as per errata
    asm("       NOP");
    EINT;

    // Read the CAN interrupt status to find the cause of the interrupt
    status_ui32 = CAN_getInterruptCause(can_base_ui16);

    // If the cause is a controller status interrupt, then get the status

    if (status_ui32 < RX_MSG_OBJ_ID_END)
    {
        can_msg_count_ui32++;

        // TX interrupt occurred on message object and the message TX is complete
        if(status_ui32 <= TX_MSG_OBJ_ID_END)
        {
            //Clear the message object interrupt
            CAN_clearInterruptStatus(can_base_ui16, status_ui32);
        }
        // RX interrupt occurred on message object and the message RX is complete
        else
        {
            // Get the received message
            CAN_readMessageWithID(can_base_ui16, status_ui32, can_msg_frame_type, (uint32_t *)can_rx_msg_identifer29_ui32, can_rx_msg_data_buffer_ui16);

            // CAN bus message receive data parser
            can_rx_msg_parser(status_ui32);

            //Clear the message object interrupt
            CAN_clearInterruptStatus(can_base_ui16, status_ui32);
        }
    }
    else
    {
        // Spurious interrupt handling can go here.
    }

    // Clear the global interrupt flag for the CAN interrupt line
    CAN_clearGlobalInterruptStatus(can_base_ui16, CAN_GLOBAL_INT_CANINT0);

    // Acknowledge the PIE interrupt
    PieCtrlRegs.PIEACK.bit.ACK9 = 1;

    DINT;
}

我们观察到的是在客户系统启动期间、CAN 总线上除节点之外的所有节点都存在初始噪声、导致所有 TX 消息都不存在 ACK。 期望是节点进入被动错误状态、直到系统节点否定确认消息、但我们注意到的是、微控制器会由于看门狗复位而复位、我们认为这是导致在我们尝试按照 TX 调度程序发送更多消息时尝试重新发送消息的原因。 这是预期结果吗?

此外、这种行为还会导致互补 PWM 信号发生跨导、从而导致单元故障。

 我在这里捕获了一些图:

  

绿色信号=应用开始时设置 Testpin

红色和蓝色信号=互补的 PWM 信号

您可以清楚地看到 PWM 的跨导和测试引脚的未知切换就在看门狗复位之前。  

我们的问题是、为什么 PWM 和测试引脚会因 CAN 挂起而受到影响?

我们能够使用 can_getStatus (can_base_ui16)在 ISR 中读取错误和状态寄存器来解决复位问题;这仅供您参考、但我们仍想知道为何观察到这种奇怪的行为、以及它是否会与其他类型的错误有关。

此致、

Harsha.

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

    嗨、 Harsha、

    通道3和4看起来不像互补 PWM。 通道1的信号是什么? 哪个通道是复位信号? 您在哪里以及何时处理看门狗?

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

    尊敬的 QJ Wang:

    前2个波形表示跨导、这就是它看起来不是互补的原因、下面是应该看起来像正常的样子;

    在此快照中、通道1和2是互补 PWM。 以下是其设置方法:

    void setup_pwm_llc_bridge(void)
    {
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EPWM1);
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EPWM2);
    
        SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
    
        //Generates the sync out pulse from EPWM1
        EPWM_setSyncOutPulseMode(EPWM1_BASE, EPWM_SYNC_OUT_PULSE_ON_COUNTER_ZERO);
    
        // Set-up TBCLK
        // Set up period of 25Khz, 4000 x 10ns
        // Phase shift 0
        // Reset Counter
        // Counter count up
        // Dont load phase shift from shadow
        EPWM_setTimeBasePeriod(EPWM1_BASE, PWM1_PERIOD_INITIAL);
        EPWM_setPhaseShift(EPWM1_BASE, PWM1_PHASESHIFT_INITIAL);
        EPWM_setTimeBaseCounter(EPWM1_BASE, 0U);
        EPWM_setTimeBaseCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_UP);
        EPWM_disablePhaseShiftLoad(EPWM1_BASE);
    
        // Set up start-of-conversion event on ePWM1A using timer event C
        EPWM_disableADCTrigger(EPWM1_BASE, EPWM_SOC_A);
        EPWM_setADCTriggerSource(EPWM1_BASE, EPWM_SOC_A, EPWM_SOC_TBCTR_U_CMPC);
        EPWM_setADCTriggerEventPrescale(EPWM1_BASE, EPWM_SOC_A, 1);
    
        // Set ePWM clock pre-scaler PWM CLK = SYS CLK
        EPWM_setClockPrescaler(EPWM1_BASE, EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1);
    
        // Set up shadowing, compare A value will be loaded on start of period
        EPWM_setCounterCompareShadowLoadMode(EPWM1_BASE, EPWM_COUNTER_COMPARE_A, EPWM_COMP_LOAD_ON_CNTR_ZERO);
        EPWM_setCounterCompareShadowLoadMode(EPWM1_BASE, EPWM_COUNTER_COMPARE_C, EPWM_COMP_LOAD_ON_CNTR_ZERO);
    
        // Set-up compare value
        EPWM_setCounterCompareValue(EPWM1_BASE, EPWM_COUNTER_COMPARE_A, PWM1_DUTY_INITIAL);
        // Set - up compare value for trigger of SOC at 50 duty
        EPWM_setCounterCompareValue(EPWM1_BASE, EPWM_COUNTER_COMPARE_C, (PWM1_DUTY_INITIAL >> 1));
    
    //    EPwm1Regs.ETPS.bit.INTPRD = 1;
    //    EPwm1Regs.ETPS.bit.SOCAPRD = 1;
    
        // Set actions, PWM_A high on 0 and low when compare match
        EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A,EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
        EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
    
    //    EPWM_setADCTriggerSource(EPWM1_BASE, EPWM_SOC_A, EPWM_SOC_TBCTR_U_CMPC);
        EPWM_enableADCTrigger(EPWM1_BASE, EPWM_SOC_A);
    
        // Deadband 10 x 10ns = 100ns
        EPWM_setRisingEdgeDelayCount(EPWM1_BASE,PWM1_DEADTIME_INITIAL);
        EPWM_setFallingEdgeDelayCount(EPWM1_BASE,PWM1_DEADTIME_INITIAL);
        // Deadband applied on rising and falling edge for the complimentary signals
        EPWM_setDeadBandDelayMode(EPWM1_BASE, EPWM_DB_RED, true);
        EPWM_setDeadBandDelayMode(EPWM1_BASE, EPWM_DB_FED, true);
    
        EPWM_setDeadBandDelayPolarity(EPWM1_BASE, EPWM_DB_RED, EPWM_DB_POLARITY_ACTIVE_HIGH);
        // EPWM_B generated as complimentary using Deadband module
        EPWM_setDeadBandDelayPolarity(EPWM1_BASE, EPWM_DB_FED, EPWM_DB_POLARITY_ACTIVE_LOW);
    
        //Enable PWM on GPIO
        GPIO_setPadConfig(0, GPIO_PIN_TYPE_STD);
        GPIO_setPinConfig(GPIO_0_EPWM1A);
    
        GPIO_setPadConfig(1, GPIO_PIN_TYPE_STD);
        GPIO_setPinConfig(GPIO_1_EPWM1B);

    当看门狗复位时、控制进入引导加载程序、我在引导加载程序中有一个 TEST 引脚切换、这由我在前一条消息中共享的波形的通道1指示。 因此、 在我之前在通道1切换时分享的波形中、这意味着控制功能位于引导加载程序中、而通道1停止切换且通道2设置为高电平时、这意味着它处于与 PWM 一起应用中。 那么、这是我如何跟踪看门狗触发复位的时间和地点。 我尝试了在中断模式下设置看门狗、然后调用 SYSCTL_resetDevice ();以进行复位、但由于某种原因、复位函数无法正常工作。

    此外、每个测试引脚仅在相应的模式下设置、即在应用程序中未设置引导加载程序测试引脚、而在引导加载程序中未设置应用测试引脚。

    如果您需要其他信息、请告诉我。

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

    您好!

    我注意到在 CAN ISR 中启用了中断:为什么在 CAN ISR 中启用这些中断(SCI、计时器、ADC)?

    ==================================

    //允许 ADC1/SCIB_TX/Timer0/Timer1/SCIB_Rx 挤占 ISR
    IER |=(M_INT1|M_INT9|M_INT13);
    IER 且=(M_INT1|M_INT9|M_INT13);

    //启用 PIE 中断组1—中断1 (ADCA1)
    //启用 PIE 中断组1 -中断3 (ADCC1)
    //启用 PIE 中断组1 -中断7 (TIMER0)
    //启用 PIE 中断组9 -中断4 (SCIB_TX)
    //启用 PIE 中断组9 -中断3 (SCIB_RX)
    //启用 PIE 中断组9 -中断4 (SCIB_TX)
    PieCtrlRegs.PIEIER1.bit.INTx1 = 1;
    PieCtrlRegs.PIEIER1.bit.INTx3 = 1;
    PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
    PieCtrlRegs.PIEIER9.bit.INTx3 = 1;
    PieCtrlRegs.PIEIER9.bit.INTx4 = 1;

    //清除 ACK 以允许组1 INT
    //清除 ACK 以允许组9 INT
    PieCtrlRegs.PIEACK.bit.ACK1 = 1;
    PieCtrlRegs.PIEACK.bit.ACK9 = 1;

    //根据勘误表等待一个周期
    asm (" NOP");
    EINT;

    ================================

     CAN 传输不应影响 ePWM 输出。  

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

    您好!

    我们使用这段代码 是为了允许中断占先、基本上可以将中断具有低优先级。 我们尝试找出 EPWM 表现这种方式的根本原因(如果您注意到波形、即使测试引脚在不应有的情况下进行切换)、我们复制此故障的唯一方法是在 CAN 上强制出现 ACK 错误、这就是我们认为 CAN 外设的错误行为会导致 ePWM 输出行为错误的原因。

    此致、

    Harsha.  

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

    嗨、 Harsha、

    您能否检查如果禁用嵌套中断、您是否获得相同的中断 ePWM 信号波形?