MSPM0G3519: no interrupt from TIMG after STOP mode

Part Number: MSPM0G3519
Other Parts Discussed in Thread: SYSCONFIG

Tool/software:


after the STOP mode is finished i'm reiniting the timer with the function generated by the SYSCFG
                SYSCFG_DL_TIMER_1_init();
enabling the IRQ
                NVIC_EnableIRQ(TIMER_1_INST_INT_IRQN);
starting the timer itself
                DL_TimerG_startCounter(TIMER_1_INST);
but getting no interrupts from the timer. any missing points here?
thank you
  • Hi Mykhaylo,

    Have you enabled the sleep on exit function in your init code?

    Regards,

    Zoey

  • nope - i'm not. actually init code is same as wakeup one, with the difference that SYSCFG_DL_TIMER_1_init called from general SYSCFG_DL_init

  • Can you show me the whole project? I can help double check from my side.

    Regards,

    Zoey

  • #include "ti_msp_dl_config.h"
    
    #define wakeup_cmd 0x0033
    #define null_cmd 0x0000
    #define reset_cmd 0x1100    //0x0011
    #define standby_cmd 0x0022
    #define read_ID 0x00a0
    
    union ads131b04 {
        struct {
            int response: 24;
            int chan0 : 24;
            int chan1 : 24;
            int chan2 : 24;
            int chan3 : 24;
            int crc: 24;
        } __attribute__((packed)) chans;
        uint8_t raw[18];
    };
    
    union ads131b04_cmd {
        struct {
            uint16_t cmd;
            uint16_t crc;
            uint32_t zeros[3]; 
        } __attribute__((packed)) tx;
        uint8_t raw[16];
    };
    
    volatile union ads131b04_cmd command = {.tx.zeros = {0,0,0}};
    volatile union ads131b04 resp;
    volatile bool gCheckTimer, gCheckADC, gCheckSleep, wakeup_signal_present = true;
    volatile uint32_t debug_counter = 0, debug_counter2 =0, stop_latency_counter = 0, debug_counter3 = 0;
    volatile DL_MCAN_ProtocolStatus protocolStatus;
    
    #define SPI_PACKET_SIZE (16)
    
    volatile DL_MCAN_TxBufElement txMsg;
    volatile DL_MCAN_RxBufElement rxMsg;
    
    void init_can_msg(volatile DL_MCAN_TxBufElement *txMsg)
    {
        /* Identifier Value. */
        txMsg->id = ((uint32_t)(0x4)) << 18U;
        /* Transmit data frame. */
        txMsg->rtr = 0U;
        /* 11-bit standard identifier */
        txMsg->xtd = 0U;
        /* ESI bit in CAN FD format depends only on error passive flag. */
        txMsg->esi = 0U;
        /* Transmitting 8 bytes. */
        txMsg->dlc = 8U;
        /* CAN frames transmitted without bit rate switching. */
        txMsg->brs = 1U;
        /* Frame transmitted in classic CAN format. */
        txMsg->fdf = 1U;
        /* Store Tx events. */
        txMsg->efc = 0U;
        /* Message Marker. */
        txMsg->mm = 0xAAU;
        /* Data bytes. */
        //txMsg.data[0] = LED0_STATUS_ON;
    }
    
    static const DL_TimerG_TimerConfig gTIMER_WAKEUPTimerConfig = {
        .period     = TIMER_WAKEUP_INST_LOAD_VALUE,
        .timerMode  = DL_TIMER_TIMER_MODE_ONE_SHOT,
        .startTimer = DL_TIMER_STOP,
    };
    
    static const DL_MCAN_ClockConfig gMCAN0ClockConf = {
        .clockSel = DL_MCAN_FCLK_SYSPLLCLK1,
        .divider  = DL_MCAN_FCLK_DIV_1,
    };
    
    
    inline void delay(int cycles)
    {
        gCheckTimer = false;
        int counter;
        for (counter = 0; counter < cycles; counter++)
        {
            while (false == gCheckTimer) {
                __WFI();
                }
            counter++;
        }
    }
    
    int main(void)
    {
        SYSCFG_DL_init();
        NVIC_DisableIRQ(WAKEUP_PORT_INT_IRQN);
        // Enable NVIC interrupt
        NVIC_EnableIRQ(ADC12_0_INST_INT_IRQN);
        NVIC_EnableIRQ(TIMER_0_INST_INT_IRQN);
        NVIC_EnableIRQ(TIMER_WAKEUP_INST_INT_IRQN);
        //DL_MCAN_ProtocolStatus protocolStatus;
        DL_GPIO_clearPins(DBG_PORT, DBG_PIN_DBG_PIN);
        debug_counter = 0;
        const uint8_t to_be_transmitted =   sizeof(command.raw)/sizeof(uint8_t);
        const uint8_t to_be_read =          sizeof(command.raw)/sizeof(uint8_t);
    
        command.tx.cmd = null_cmd;
    
        init_can_msg(&txMsg);
        while (DL_MCAN_OPERATION_MODE_NORMAL != DL_MCAN_getOpMode(MCAN0_INST))
            ;
        gCheckTimer = true;
        DL_TimerG_startCounter(TIMER_0_INST);
        DL_ADC12_enableConversions(ADC12_0_INST);
        //DL_TimerG_initTimerMode(TIMER_WAKEUP_INST, (DL_TimerG_TimerConfig *) &gTIMER_WAKEUPTimerConfig);
        DL_TimerG_startCounter(TIMER_WAKEUP_INST);
    
        while (1) {
            uint8_t idx_w, idx_r;
    
            if (wakeup_signal_present)
            {   
                //DL_GPIO_setPins(DBG_PORT, DBG_PIN_DBG_PIN);      
                while (false == gCheckTimer) {
                    __WFE();
                }
                gCheckTimer = false;
    
                while (false == gCheckADC) {
                    __WFE();
                }
                gCheckADC = false;
    
                // send cmd and read response from external ADC
                idx_w = 0;
                idx_r = 0;
                do
                {
                    idx_w += DL_SPI_fillTXFIFO8(SPI_0_INST, &command.raw[idx_w], to_be_transmitted-idx_w);
                    idx_r += DL_SPI_drainRXFIFO8(SPI_0_INST,&resp.raw[idx_r], to_be_read-idx_r);
                }   while (to_be_transmitted > idx_w || to_be_read > idx_r);
    
                // read internal ADC results
                uint16_t v12redundant  = DL_ADC12_getMemResult(ADC12_0_INST, DL_ADC12_MEM_IDX_0);
                uint16_t v24redundant = DL_ADC12_getMemResult(ADC12_0_INST, DL_ADC12_MEM_IDX_1);
                uint16_t ref1v8 = DL_ADC12_getMemResult(ADC12_0_INST, DL_ADC12_MEM_IDX_2);
    
                txMsg.id = ((uint32_t)(0x7)) << 18U;
                txMsg.brs=1;
                uint32_t i=0;
    
                txMsg.data[i++] = (uint8_t)(resp.chans.chan0>>0 & 0xFF);// VBAT24
    
                txMsg.dlc=11;
                DL_MCAN_writeMsgRam(MCAN0_INST, DL_MCAN_MEM_TYPE_BUF, 0, &txMsg);
                DL_MCAN_TXBufAddReq(MCAN0_INST, 0);
    
            }
            else
            {
                DL_GPIO_clearPins(DBG_PORT, DBG_PIN_DBG_PIN); 
                if (stop_latency_counter == 0)
                {
                    stop_latency_counter++;
                    NVIC_DisableIRQ(TIMER_WAKEUP_INST_INT_IRQN);                
                    NVIC_DisableIRQ(ADC12_0_INST_INT_IRQN);
                    NVIC_DisableIRQ(TIMER_0_INST_INT_IRQN);
                    DL_TimerG_stopCounter(TIMER_0_INST);
                    DL_VREF_disableInternalRef(VREF);
                    DL_VREF_disablePower(VREF);
                    DL_ADC12_disableConversions(ADC12_0_INST);          
                    DL_ADC12_disablePower(ADC12_0_INST);
                    bool powerup_not_ok = true;
    
                        bool ackstatus;
                        uint32_t cancellation_status, retry_counter;
                        gCheckSleep = false;
                        DL_MCAN_txBufCancellationReq(MCAN0_INST, 0);
                        do {
                            cancellation_status = DL_MCAN_txBufCancellationStatus(MCAN0_INST);
                        }while((cancellation_status & 0x1) == 0);
                        //DL_MCAN_setOpMode(MCAN0_INST, DL_MCAN_OPERATION_MODE_SW_INIT);
                        DL_MCAN_addClockStopRequest(MCAN0_INST, true);//CSR
                        while (DL_MCAN_OPERATION_MODE_SW_INIT != DL_MCAN_getOpMode(MCAN0_INST));//INIT must be set to '1' by h/w
    
                        DL_MCAN_enableClockStopGateRequest(MCAN0_INST);//STOPREQ
                        while (DL_MCAN_isClockStopGateRequestEnabled(MCAN0_INST) == false);//STOPREQ
                        do {
                        {
                           ackstatus = DL_MCAN_getClockStopAcknowledgeStatus(MCAN0_INST); //ACKSTS
                        }
                        }while (ackstatus == false);
                        
                        //while(DL_MCAN_getClockStopAcknowledgeStatus(MCAN0_INST) == true);
    
                        DL_MCAN_disableModuleClock(MCAN0_INST);
                        DL_GPIO_setPins(CAN_STB_PORT, CAN_STB_PIN_0_PIN);
                        //DL_GPIO_clearPins(DBG_PORT, DBG_PIN_DBG_PIN);
    
                       // DL_TimerG_initTimerMode(TIMER_WAKEUP_INST, (DL_TimerG_TimerConfig *) &gTIMER_WAKEUPTimerConfig);
                       // DL_TimerG_startCounter(TIMER_WAKEUP_INST);
                        DL_SYSCTL_setPowerPolicySTOP2();
                        NVIC_EnableIRQ(WAKEUP_PORT_INT_IRQN);
                        if (!(SYSCTL->SOCLOCK.PMODECFG))
                        {
                            __WFI();
                        }
                        gCheckSleep = false;
                        NVIC_DisableIRQ(WAKEUP_PORT_INT_IRQN);
                        DL_SYSCTL_setPowerPolicyRUN0SLEEP0();
                        //SYSCFG_DL_init();
                        SYSCFG_DL_SPI_0_init();
                        DL_GPIO_clearPins(CAN_STB_PORT, CAN_STB_PIN_0_PIN);
                        DL_MCAN_enableModuleClock(MCAN0_INST);
                        DL_MCAN_disableClockStopGateRequest(MCAN0_INST);
                        while (DL_MCAN_isClockStopGateRequestEnabled(MCAN0_INST) == true);
                        DL_MCAN_addClockStopRequest(MCAN0_INST, false);
    
    
                        while(DL_MCAN_getClockStopAcknowledgeStatus(MCAN0_INST) == true);
    
                        gCheckTimer = false;
                        SYSCFG_DL_TIMER_0_init();
                        DL_TimerG_startCounter(TIMER_0_INST);
                        NVIC_EnableIRQ(TIMER_0_INST_INT_IRQN);
                    do
                    {
                        SYSCFG_DL_MCAN0_init();
                        //SYSCFG_DL_init();
                        //DL_GPIO_clearPins(DBG_PORT, DBG_PIN_DBG_PIN);
                        DL_MCAN_getProtocolStatus(MCAN0_INST, &protocolStatus);
                        if (protocolStatus.busOffStatus)
                        {
                            powerup_not_ok = true;
                            delay(1000);
                        }
                        else
                            powerup_not_ok = false;
    
                    } while(powerup_not_ok);
                    delay(1000);
                    DL_VREF_disablePower(VREF);
                    DL_VREF_enableInternalRef(VREF);
                    debug_counter3++;
                    DL_ADC12_enablePower(ADC12_0_INST);
                    DL_ADC12_enableConversions(ADC12_0_INST);
                    SYSCFG_DL_ADC12_0_init();
                    NVIC_EnableIRQ(ADC12_0_INST_INT_IRQN);
                    SYSCFG_DL_TIMER_WAKEUP_init();
                    NVIC_EnableIRQ(TIMER_WAKEUP_INST_INT_IRQN);
                    DL_GPIO_clearPins(DBG_PORT, DBG_PIN_DBG_PIN);
                    DL_TimerG_startCounter(TIMER_WAKEUP_INST);
                    __enable_irq();
    
    
                }
                else
                {
                    if (stop_latency_counter > 50)
                        stop_latency_counter = 0;
                    else
                        stop_latency_counter++;
                }
    
            }
        }  
    }
    
    void TIMER_0_INST_IRQHandler(void)
    {
        DL_GPIO_setPins(DBG_PORT, DBG_PIN_DBG_PIN);
        switch (DL_TimerG_getPendingInterrupt(TIMER_0_INST)) {
            case DL_TIMERG_INTERRUPT_ZERO_EVENT:
                gCheckTimer = true;
                //debug_counter++;
                break;
            default:
                break;
        }
    }
    
    void ADC12_0_INST_IRQHandler(void)
    {
        switch (DL_ADC12_getPendingInterrupt(ADC12_0_INST)) {
            case DL_ADC12_IIDX_MEM2_RESULT_LOADED:
                gCheckADC = true;
                //debug_counter2++;
                break;
            default:
                break;
        }
    }
    
    void TIMER_WAKEUP_INST_IRQHandler(void)
    {
        DL_MCAN_RxFIFOStatus fifoStatus = {0};
        debug_counter2++;
        //DL_GPIO_setPins(DBG_PORT, DBG_PIN_DBG_PIN);
        switch (DL_TimerG_getPendingInterrupt(TIMER_WAKEUP_INST)) {
            case DL_TIMERG_INTERRUPT_ZERO_EVENT:
                DL_MCAN_getRxFIFOStatus(MCAN0_INST, &fifoStatus);
                if (fifoStatus.fillLvl > 0)
                {
                    debug_counter++;
                    do
                    {
                        DL_MCAN_readMsgRam(MCAN0_INST, DL_MCAN_MEM_TYPE_FIFO, 0U, fifoStatus.num, &rxMsg);
                        DL_MCAN_writeRxFIFOAck(MCAN0_INST, fifoStatus.num, fifoStatus.getIdx);
                        DL_MCAN_getRxFIFOStatus(MCAN0_INST, &fifoStatus);
                    } while(fifoStatus.fillLvl > 0);
    
                    wakeup_signal_present = true;
                }
                else {
                    wakeup_signal_present = false;            
                }
                gCheckSleep = true;
                break;
            default:
                break;
        }
    
    }
    
    void GROUP1_IRQHandler(void)
    {
        //debug_counter3++;
        DL_GPIO_clearInterruptStatus(WAKEUP_PORT_PORT, WAKEUP_PORT_WAKEUP_PIN);
    }
    well... yeah - it's very small 

  • Since I can not see the sysconfig, just want to double check:

    1. Not enable sleep on exit

    2. Enable interrupt configuration

  • sure thing - no "Sleep on Exit"and the interrupt is enabled.

    after two fixes the interrupts appeared. first is obvious missing 

    wakeup_signal_present = true

    in GPIO interrupt handler.

    but the second one had completely flabbergasted me - i did substituted 

    NVIC_EnableIRQ(WAKEUP_PORT_INT_IRQN);
    with
    DL_GPIO_clearInterruptStatus(WAKEUP_PORT_PORT, WAKEUP_PORT_WAKEUP_PIN);
    DL_GPIO_enableInterrupt(WAKEUP_PORT_PORT, WAKEUP_PORT_WAKEUP_PIN);

    and reciprocal NVIC_DisableIRQ with  clearInterruptStatus+disableInterrupt

    (of course NVIC_EnableIRQ(WAKEUP_PORT_INT_IRQN); in main() must be set as well).
    i'm quite perplexed with this - I was under impression that main mechanism that controls interrupts is exactly NVIC_Enable/DisableIR
  • Hi,

    NVIC is used for control interrupt to tell the CPU

    And 

    DL_GPIO_clearInterruptStatus(WAKEUP_PORT_PORT, WAKEUP_PORT_WAKEUP_PIN);
    DL_GPIO_enableInterrupt(WAKEUP_PORT_PORT, WAKEUP_PORT_WAKEUP_PIN);
    Is used to enable GPIO interrupt.
    One is for CPU the other is peripheral
    Regards,
    Zoey
  • Hi Zoey, thank you for the reply. please elaborate on utilization of the mechanisms. I've been using them as following on other MCUs: the peripheral's interrupt switch is utilized only once in the init phase and never touched later; while the CPU's interrupt switch is constantly in use while toggling between interrupt on/off happens according to the application logic. same idea was implemented here but it backfired in .... completely different peripheral - the timer. could you tell - first if the process described above applicable to 3519 and why the effect observed.