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.

Question about RTC match of LM4F110E5QR

Other Parts Discussed in Thread: TM4C1231E6PM

Hello,

I'm implementing RTC match functionality on LM4F110E5QR platform.

Following shows my partial code about RTC match.

The functionality is working fine at beggining of operation.

However, the RTC match interrupt "IntRTCIntHandler()" would not be toggling after a period of operation time.

Could anyone tell me what's happen?

Thanks.

Main()
{
   SysCtlPeripheralEnable(SYSCTL_PERIPH_HIBERNATE);
   SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_HIBERNATE);
   SysCtlPeripheralDeepSleepEnable(SYSCTL_PERIPH_HIBERNATE);   

   xTaskCreate (MonitorTask, (signed portCHAR *)"MonitorTask", 240, NULL, 4 , NULL);

   while(1)  
   {        
   }
}

void MonitorTask( void *pvParameters )
{
    HibernateIntClear(HIBERNATE_INT_RTC_MATCH_0);
    HibernateIntClear(HIBERNATE_INT_RTC_MATCH_1);
    HibernateIntEnable(HIBERNATE_INT_RTC_MATCH_0);
    HibernateIntDisable(HIBERNATE_INT_RTC_MATCH_1);
    IntPrioritySet(INT_HIBERNATE, 6<<5); 
    HibernateIntRegister(IntRTCIntHandler);

    HibernateRTCMatch0Set(HibernateRTCGet() + 10); 
    HibernateIntEnable(HIBERNATE_INT_RTC_MATCH_0);

    g_xMonitorQueue = xQueueCreate( 4 , sizeof(tMonitorTrigSource ) );
    
    for(;;)
    {
        xQueueReceive( g_xMonitorQueue,  &MonitorTrigSource, portMAX_DELAY );
        if(MonitorTrigSource == Monitor_Trig_IntRTC)
        {
             HibernateRTCMatch0Set(HibernateRTCGet() + 10); 
             HibernateIntEnable(HIBERNATE_INT_RTC_MATCH_0);
        }
    }
}

void IntRTCIntHandler(void)
{
    unsigned long ulHibernateIntValue;
    signed portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;

    ulHibernateIntValue = HibernateIntStatus(true);

    if (ulHibernateIntValue & HIBERNATE_INT_RTC_MATCH_0)
    {
	tMonitorTrigSource MonitorTrigSource = Monitor_Trig_IntRTC;				
	HibernateIntDisable(HIBERNATE_INT_RTC_MATCH_0);
	HibernateRTCMatch0Set(0);

	xQueueSendFromISR( g_xMonitorQueue, ( void * ) &MonitorTrigSource, &xHigherPriorityTaskWoken );

	if (xHigherPriorityTaskWoken != pdFALSE ) 
	{
	     taskYIELD();
	}
		
	HibernateIntClear(HIBERNATE_INT_RTC_MATCH_0);
    }
    else if (ulHibernateIntValue & HIBERNATE_INT_RTC_MATCH_1)
    {
	HibernateIntDisable(HIBERNATE_INT_RTC_MATCH_1);
	HibernateRTCMatch1Set(0);
		
	HibernateIntClear(HIBERNATE_INT_RTC_MATCH_1);
    }
}

  • YuSheng,

    Are you entering hibernate mode somewhere else in the program? The errata HIB#04 could cause a missed RTC Match event when the match is close to the hibernation mode entry point.

  • Hi John,

    Thanks for your reply.

    We didn't use hibernate mode in our program, the RTC match event is still missed.

    I read the status of HIB_MIS when the RTC count exceed the match number, the value is zero.

    Are there something else we need to pay attention?

    Thanks.

  • YuSheng,

    Is the RTCALT0 bit in the HIB_RIS register also 0? How are you determining that the interrupts have stopped?

    I will see if I can do some testing on this tomorrow.

  • Hi,

         I am just comparing your code to the one at the Drivers Library Users Guide.

         Isn't it that you also need these lines of code below at your initialization?

    HibernateEnableExpClk(SysCtlClockGet());
    HibernateClockConfig(HIBERNATE_OSC_LOWDRIVE);
    HibernateRTCEnable();

    -kel

  • Hi John,

     

    The RTCALT0 bit in the HIB_RIS register is also 0 when we miss the RTC match event.

    We use another system timer to check whether RTC match event is work fine or not.

  • Hi Markel,

    Sorry, I omitted to insert it to this web page.

    I have added these lines you listed as below.

    HibernateClockSelect(HIBERNATE_CLOCK_SEL_RAW);  

    HibernateEnableExpClk(32768);

    HibernateRTCEnable();

  • Hi,

         I assume that what you are trying to do is "RTC Match Functionality (No Hibernation)". Based from the steps in the datasheet you are missing this step below.

    3. Write the required RTC load value to the HIBRTCLD register at offset 0x00C.

         Which translates to using this code line below.

    //
    // Set the RTC to an initial value.
    //
    HibernateRTCSet(0);

         Also, regarding your HibernateIntClear code lines. Using this code line would be more efficient. That is like hitting 4 birds with one stone.

    HibernateIntClear(HIBERNATE_INT_PIN_WAKE | HIBERNATE_INT_LOW_BAT |
    HIBERNATE_INT_RTC_MATCH_0 |
    HIBERNATE_INT_RTC_MATCH_1);

    I don't quite get why you need to use this code line below twice

    HibernateIntEnable(HIBERNATE_INT_RTC_MATCH_0);

    -kel

  • YuSheng,

    I misinterpreted your first post as stating that you were getting RTC events and then they were stopping at some point during program operation. As a result, I did not look close enough at your configuration code.

    As Markel pointed out, you are missing some configuration steps. You will need to call HibernateEnableExpClk() and HibernateClockConfig() when you configure the Hibernate module and HibernateRTCMatchSet() before you start the RTC with HibernateRTCEnable().

    The call to HibernateRTCSet(0) is not strictly necessary, but is recommended for resetting the count during debugging because the RTC value will not go back to 0 unless the power is removed.

    I removed the RTOS parts from your code and added these steps and I got RTC interrupts as expected.

  • Hi John,
     
    We have set these settings Markel pointed out. Following shows all related setting and code we used.
    Now we only use one task "MonitorTask", and we found the RTC interrupt event is still missed at random time.
    This appearance maybe appear in a few hours.
     
    int main(void)
    {
             //
    	// Configure the processor to run at 50 MHz.
    	//
    	SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ |SYSCTL_OSC_MAIN);
    
    	//Enable peripherals 
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_HIBERNATE);
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN0);
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); 
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    
    	SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_HIBERNATE);
    	SysCtlPeripheralDeepSleepEnable(SYSCTL_PERIPH_HIBERNATE);	
    	SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_CAN0);
    	SysCtlPeripheralDeepSleepEnable(SYSCTL_PERIPH_CAN0);	
    
             //Initialize CAN and register interrupt handler
    	UICANInit();
    
             // Initialize internal RTC
    	HibernateClockSelect(HIBERNATE_CLOCK_SEL_RAW);
    	HibernateEnableExpClk(32768);
    	HibernateRTCEnable();
             HibernateRTCSet(946684800);
    
             // Reset all task handles before creating them.
    	ResetTaskHandle();
    
             xTaskCreate (MonitorTask, 	(signed portCHAR *)"MonitorTask", 	240,  NULL, 4 , NULL);
    
             /* Start the scheduler so our tasks start executing. */
    	vTaskStartScheduler();
    
             while(1)
    	{
    	}
    
    }
    
    void UICANInit(void)
    {
        SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN0);
        SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_CAN0);
        SysCtlPeripheralDeepSleepEnable(SYSCTL_PERIPH_CAN0);
    	
        //
        // Configure CAN Pins
        //
        GPIOPinTypeCAN(GPIO_PORTB_BASE, GPIO_PIN_4 | GPIO_PIN_5);
        GPIOPinConfigure(GPIO_PB4_CAN0RX);       //Add this code to set CAN pin Tx and Rx
        GPIOPinConfigure(GPIO_PB5_CAN0TX);			
    
        //
        // Reset the state of all the message object and the state of the CAN
        // module to a known state.
        //
        CANInit(CAN0_BASE);
    
        //
        // Configure the bit rate for the CAN device, the clock rate to the CAN
        // controller is fixed at 8MHz for this class of device and the bit rate is
        // set to 250000.
        //
        //CANBitRateSet(CAN0_BASE, 8000000, 1000000); //Ching changed from 250000
        CANBitRateSet(CAN0_BASE, configCPU_CLOCK_HZ, 1000000); //Ching changed again for 5749
    
        //
        // Take the CAN1 device out of INIT state.
        //
        CANEnable(CAN0_BASE);
    
        //
        // Enable interrups from CAN controller.
        //
        CANIntEnable(CAN0_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);
        IntPrioritySet(INT_CAN0, 6<<5);
    
        //dynamically register CANIntHandler
        //Also Enable interrupts for the CAN in the NVIC.
        CANIntRegister(CAN0_BASE, CANIntHandler1);
    }
    
    void MonitorTask( void *pvParameters )
    {
         tMonitorTrigSource MonitorTrigSource;
    
         g_xRTCBroTimer = xTimerCreate("RTCBroTimer",        /* Just a text name, not used by the kernel. */
                  RTOS_DETECT_EXT_RTC_BRO_TIME1_MS/portTICK_RATE_MS,    /* The timer period in ticks. */
                  pdTRUE,         /* The timers will auto-reload themselves when they expire. */
                  ( void * ) RTOS_DETECT_EXT_RTC_BRO_TIMER_ID,   /* Assign each timer a unique id equal to its array index. */
                  RTCBroTimerCallback  /* Each timer calls the same callback when it expires. */
                  );
         if (g_xRTCBroTimer == 0) {
             // Failed to create the timer.
         }
    	
         g_xMonitorQueue = xQueueCreate( 4 , sizeof(tMonitorTrigSource) );
    
         HibernateIntClear(HIBERNATE_INT_RTC_MATCH_0 | HIBERNATE_INT_RTC_MATCH_1);
         HibernateIntEnable(HIBERNATE_INT_RTC_MATCH_0);
         HibernateIntDisable(HIBERNATE_INT_RTC_MATCH_1);
         IntPrioritySet(INT_HIBERNATE, 6<<5);
         HibernateIntRegister(IntRTCIntHandler);
    
         // Send this queue.
         MonitorTrigSource = Monitor_Trig_Self;
         xQueueSend( g_xMonitorQueue, ( void * ) &MonitorTrigSource, ( portTickType ) 0 );
    
         /* As per most tasks, this task is implemented in an infinite loop. */
         for(;;)
         {
    	xQueueReceive( g_xMonitorQueue,  &MonitorTrigSource, portMAX_DELAY );	
    
             if(MonitorTrigSource == Monitor_Trig_IntRTC || MonitorTrigSource == Monitor_Trig_Self)
    	{
    	    SendTestCANMsg(0xBBBBCCCC, 0x1);
    				
    	    HibernateRTCMatch0Set(HibernateRTCGet() + 10); 
    	    HibernateIntEnable(HIBERNATE_INT_RTC_MATCH_0);
    	    xTimerChangePeriod(g_xRTCBroTimer , RTOS_DETECT_EXT_RTC_BRO_TIME1_MS/portTICK_RATE_MS , 0);
    	    xTimerStart(g_xRTCBroTimer , 0);
    	}
    	else if(MonitorTrigSource == Monitor_Trig_Timer)
    	{
    	    SendTestCANMsg(0xCCCCDDDD, 0x1);
    	    xTimerChangePeriod(g_xRTCBroTimer , RTOS_DETECT_EXT_RTC_BRO_TIME1_MS/portTICK_RATE_MS , 0);
                 xTimerStart(g_xRTCBroTimer , 0);
    	}
        }
    }
    
    void RTCBroTimerCallback(xTimerHandle pxTimer)
    {
        tMonitorTrigSource MonitorTrigSource = Monitor_Trig_Timer;
    	
        xQueueSend( g_xMonitorQueue, ( void * ) &MonitorTrigSource, ( portTickType ) 0 );
    }
    
    void IntRTCIntHandler(void)
    {
        unsigned long ulHibernateIntValue;
        signed portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
    
        ulHibernateIntValue = HibernateIntStatus(true);
    
        if (ulHibernateIntValue & HIBERNATE_INT_RTC_MATCH_0)
        {
    	tMonitorTrigSource MonitorTrigSource = Monitor_Trig_IntRTC;		
    		
    	HibernateIntDisable(HIBERNATE_INT_RTC_MATCH_0);
    	HibernateRTCMatch0Set(0);
    
    	xQueueSendFromISR( g_xMonitorQueue, ( void * ) &MonitorTrigSource, &xHigherPriorityTaskWoken );
    
    	if (xHigherPriorityTaskWoken != pdFALSE ) 
    	{
    	    taskYIELD();
    	}
    		
    	HibernateIntClear(HIBERNATE_INT_RTC_MATCH_0);
        }
        else if (ulHibernateIntValue & HIBERNATE_INT_RTC_MATCH_1)
        {
    	HibernateIntDisable(HIBERNATE_INT_RTC_MATCH_1);
    	HibernateRTCMatch1Set(0);
    		
    	HibernateIntClear(HIBERNATE_INT_RTC_MATCH_1);
        }
    }

     

  • Hi,

        I am not an expert regarding RTOS. Does these code lines below, needs to be inside a task? As John said, he made his test code work without the RTOS part. I suspect your RTOS task routines is causing the interrupt miss.

    IntPrioritySet(INT_HIBERNATE, 6<<5);
    HibernateIntRegister(IntRTCIntHandler);


    -kel

  • YuSheng,

    It would be nice if you could test a simple implementation of your code without the RTOS running. I'm not familiar enough with FreeRTOS to know if your RTOS configuration is the problem or not.

    Also, the version of StellarisWare you are using should be updated to the latest TivaWare. When you update, you will see that there is no code for RTC Match 1 functionality on your part. Additionally, the HibernateClockSelect() function call is not necessary on the LM4F parts. These functions were for older parts, but are not present on your LM4F110E5QR (Tiva:TM4C1231E6PM).

    I do not believe this to be the source of your problem, but it certainly would be an issue if you tried to implement a RTC Match 1 interrupt and handler.