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.

uart interrupt not triggered

Part Number: MSPM0G3507
Other Parts Discussed in Thread: MSPM0G3507, SYSCONFIG, LP-MSPM0G3507

Tool/software:

Hi all,
I'm reaching out with a question regarding the UART on the MSPM0G3507. I'm using it for debugging purposes, but I've encountered an issue with the UART interrupt when receiving data.
The problem is that the interrupt works correctly the first time the program runs, and it successfully prints the received data. However, on subsequent receptions, the interrupt is not triggered to send back the data. I've tried to troubleshoot the issue, but I couldn't find the root cause. I just attached the Irq handler of my code to for your consideration.
static void ManageUsartIrqHandler(UART_Regs *UsartPeriph , UsartCircBuffer_str *UsartCircBuffPtr)
{
  
     uint32_t intMask;
    
     DL_UART_Main_getEnabledInterruptStatus(UsartPeriph,intMask);
  
  
    /* RX Not Empty interrupt management */
    switch(DL_UART_Main_getPendingInterrupt(UsartPeriph))
    {
    case DL_UART_MAIN_IIDX_RX:
      
        (void)CircBuffer_WriteData(&UsartCircBuffPtr->Rx , DL_UART_Main_receiveData(UsartPeriph));
        //DL_UART_Main_transmitData(UsartPeriph,DL_UART_Main_receiveData(UsartPeriph));
        //DL_UART_Main_transmitData(UsartPeriph, 0x06); // ACK byte
        //(void)CircBuffer_WriteData(&UsartCircBuffPtr->Tx, 'A');
        
        break;
       

       
    bool transmissionComplete = false; 
     
    case DL_UART_MAIN_IIDX_TX:
      {
        uint8_t Data;
        
    
        if(CircBuffer_ReadData(&UsartCircBuffPtr->Tx , &Data))
        {   
            //DL_UART_Main_transmitData(UsartPeriph, 'T'); // Transmitting data
            DL_UART_Main_transmitData(UsartPeriph,Data);
            transmissionComplete = false;
        }
        
        else
        {
            //DL_UART_Main_disableInterrupt(UsartPeriph,DL_UART_MAIN_IIDX_TX);
            transmissionComplete = true;
        } 
        
        if(transmissionComplete)
        {
            (void)CircBuffer_WriteData(&UsartCircBuffPtr->Tx, 'A'); // Refill transmit buffer
            transmissionComplete = false;
        }
        
        
      }
      break;
    default:
      return;
    }
}

Could you please help me understand what might be causing this issue?
  • Do the echo examples work OK?

    Have you tried toggling the LED in your interrupt handler to see if the uart is getting triggered or there is an error in your circular buffer routine?

  • In addition to Keith's debugging points I'd like to ask:

    Do you mean that the interrupt only fires for the first received UART character, or do you mean that the interrupt fires the first time you program the device, but after resetting / power cycling it wont fire? 

    Trying the UART examples first and reporting back would help to diagnose the issue. 

    Finally, is this using a launchpad or custom hardware?

  • Check your (Rx) FIFO settings, either via sysconfig or the debugger.

    As I read this code, you're reading one byte for each RX interrupt. The FIFO works on a threshold (crossing), not a level [Ref TRM (SLAU846A) Sec 16.2.7.1]. If you don't decrease the level below the threshold, you won't get another  interrupt as it refills. This invites races and gradual skewing. When I did this (with the SPI) my policy was to always empty the Rx FIFO on any (Rx) interrupt.

    A simple remedy might be to disable the Rx FIFO. Alternatively, change your code to always empty it.

  • the Circular buffer works correctly and I tested the echo example, for the first echo it works and then it never trig the interrupt.

  • I mean that the interrupt fires the first time I program and for example it send back the received message (Echo) but just one time during program execution and then if I received other data it never get trigged and of course no echo back. I'm using LP-MSPM0G3507 board in IAR environment. 

  • That could be my problem but could you please let me know how to decrease the level below the threshold and how  to disable the Rx FIFO ? in the meanwhile I will try to check the refrence you mentiond. thanks  

  • Using sysconfig, under the relevant "Communications->UART", the "Advanced Configuration" includes a checkbox for "Enable FIFOs".

    Emptying the FIFO could look something like

    uint8_t rxbyte;
    while (DL_UART_receiveDataCheck(UsartPeriph, &rxbyte))
    {
        (void)CircBuffer_WriteData(&UsartCircBuffPtr->Rx , rxbyte);
    }

    I expect this code will work whether or not the FIFOs are enabled.

  • And you enable/disable The FIFO in sysconfig here:

  • I played with FIFO config a little and It's my init function for the UART. now with this config (make FIFO disable) , the RX interrupt fires correctrly for example when I send a char from TeraTerm to board it receive and put it in my circular buffer but the the TX interrupt no longer fires.

    static void InitUsartController(const UsartDevData_str *UsartDevData)
    {
        IRQn_Type IRQnType;
        DL_UART_Main_ClockConfig gUART_0ClockConfig = {UsartDevData->clockSel, UsartDevData->divideRatio};
        static const DL_UART_Main_Config gUART_0Config = 
        {
            .mode        = DL_UART_MAIN_MODE_NORMAL,
            .direction   = DL_UART_MAIN_DIRECTION_TX_RX,
            .flowControl = DL_UART_MAIN_FLOW_CONTROL_NONE,
            .parity      = DL_UART_MAIN_PARITY_NONE,
            .wordLength  = DL_UART_MAIN_WORD_LENGTH_8_BITS,
            .stopBits    = DL_UART_MAIN_STOP_BITS_ONE
        };
            
        /* Get Periph Id */
         UART_Regs *UsartPeriph = UsartDevData->Periph;
         
         /* Reset UART device */
         DL_UART_Main_reset      (UsartPeriph);
         DL_UART_Main_enablePower(UsartPeriph);
         
        /* USART Periph Configuration */
        {
            DL_UART_Main_setClockConfig    (UsartPeriph,(DL_UART_Main_ClockConfig *)&gUART_0ClockConfig);
            DL_UART_Main_init              (UsartPeriph, (DL_UART_Main_Config *) &gUART_0Config);
            DL_UART_Main_setOversampling   (UsartPeriph, USART_OVERSAMPLING);
            
    //        /* Configure FIFOs */
    //        DL_UART_Main_enableFIFOs(UsartPeriph);
    //        DL_UART_Main_setRXFIFOThreshold(UsartPeriph, DL_UART_RX_FIFO_LEVEL_ONE_ENTRY);
    //        DL_UART_Main_setTXFIFOThreshold(UsartPeriph, DL_UART_TX_FIFO_LEVEL_3_4_EMPTY);
            
            DL_UART_Main_setBaudRateDivisor(UsartPeriph, UsartDevData->ibrd, UsartDevData->fbrd);
            DL_UART_Main_enableInterrupt   (UsartPeriph, DL_UART_MAIN_INTERRUPT_RX);
            DL_UART_Main_enable            (UsartPeriph);
        }
        
        /* USART Irq Configuration */
        {
            IRQnType = UsartDevData->usart_irq_n;
            NVIC_ClearPendingIRQ(IRQnType);
            NVIC_EnableIRQ      (IRQnType);
        }
        
        /* USART Enable Section */
        DL_UART_Main_enable(UsartPeriph);
    }

    here are also Read and Write functions that I use : 

    static uint32_t WriteUsartBuffer(UART_Regs *UsartPeriph , UsartCircBuffer_str *UsartCircBuffPtr , uint8_t *BuffPtr , uint16_t BuffSize)
    {
        
        uint32_t WriteData;
        
        /* Copy "Data To Send" in circular buffer [with interrupt disabled] */
        
        DL_UART_Main_disableInterrupt(UsartPeriph,DL_UART_MAIN_INTERRUPT_TX); __DSB(); __ISB();
        
        WriteData = CircBuffer_WriteBuffer(&UsartCircBuffPtr->Tx , BuffPtr , BuffSize);
        
        DL_UART_Main_enableInterrupt(UsartPeriph,DL_UART_MAIN_INTERRUPT_TX);
        
        return(WriteData);
       
    }
    
    
    
    
    static uint32_t ReadUsartBuffer(UART_Regs *UsartPeriph, UsartCircBuffer_str *UsartCircBuffPtr, uint8_t *BuffPtr , uint16_t BuffSize)
    {
    
        uint32_t ReadData;
        
        /* Get RX Circular Buffer Ptr */
        CircBuffer_str *CircBufPtr = &UsartCircBuffPtr->Rx;
        
        /* Check if Buffer Data Len is not 0 */
        if(CircBuffer_GetDataLen(CircBufPtr) > 0)
        {
        	/* Read Data From Circular Buffer [with interrupt disabled] */
            DL_UART_Main_disableInterrupt(UsartPeriph,DL_UART_MAIN_INTERRUPT_RX); __DSB(); __ISB();
            ReadData = CircBuffer_ReadBuffer(CircBufPtr , BuffPtr , BuffSize);
    	    DL_UART_Main_enableInterrupt(UsartPeriph,DL_UART_MAIN_INTERRUPT_RX);
    
    	    return(ReadData); 
        }
    
        return(0U);   
    }

  • If you are depending on the interrupt to supply more TX data, you have a deadlock because the FIFO can't get full enough to set the interrupt. I say use either the FIFO or your ring buffer, but not both.