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.

RTC / Idle Modes



All,

I wrote some code for the eZdsp C5505 stick. This code should toggle GP21 every second. I find that once I try to enter IDLE3 mode I stop receiving the RTC interrupt. If I do not disable the PLL it seems to work. Can someone please let me know what I am doing wrong?

Cheers!

 

#include <stdio.h>
#include <tistdtypes.h>
#include "csl_intc.h"

#define USE_EVAL_STICK (1)


extern void VECSTART(void); // CSL asm file

volatile ioport Uint16 * ICR =     (volatile Uint16 *) 0x0001;

volatile ioport Uint16 * TCR0 =    (volatile Uint16 *) 0x1810;

volatile ioport Uint16 * RTCPMGT = (volatile Uint16 *) 0x1930;

volatile ioport Uint16 * EBSR =    (volatile Uint16 *) 0x1C00;
volatile ioport Uint16 * PCGCR1 =  (volatile Uint16 *) 0x1C02;
volatile ioport Uint16 * PCGCR2 =  (volatile Uint16 *) 0x1C03;
volatile ioport Uint16 * PSRCR =   (volatile Uint16 *) 0x1C04;
volatile ioport Uint16 * PRCR =    (volatile Uint16 *) 0x1C05;

volatile ioport Uint16 * USBSCR =  (volatile Uint16 *) 0x1C32;
volatile ioport Uint16 * CLKSTOP = (volatile Uint16 *) 0x1C3A;


volatile ioport Uint16 * CGCR1 =    (volatile Uint16 *) 0x1C20;
volatile ioport Uint16 * CGCR2 =    (volatile Uint16 *) 0x1C21;
volatile ioport Uint16 * CGCR3 =    (volatile Uint16 *) 0x1C22;
volatile ioport Uint16 * CGCR4 =    (volatile Uint16 *) 0x1C23;

volatile ioport Uint16 * CCR2 =     (volatile Uint16 *) 0x1C1F;

volatile ioport Uint16 * IODIR1 =     (volatile Uint16 *) 0x1C06;
volatile ioport Uint16 * IODATAOUT1 = (volatile Uint16 *) 0x1C0A;
volatile ioport Uint16 * IOINTEN1 =   (volatile Uint16 *) 0x1C0E;
volatile ioport Uint16 * IODIR2 =     (volatile Uint16 *) 0x1C07;
volatile ioport Uint16 * IODATAOUT2 = (volatile Uint16 *) 0x1C0B;
volatile ioport Uint16 * IOINTEN2 =   (volatile Uint16 *) 0x1C0F;

volatile ioport Uint16 * RTCINTEN  = (volatile Uint16 *) 0x1900;
volatile ioport Uint16 * RTCUPDATE = (volatile Uint16 *) 0x1901;
volatile ioport Uint16 * RTCMIL    = (volatile Uint16 *) 0x1904;
volatile ioport Uint16 * RTCSEC    = (volatile Uint16 *) 0x1908;
volatile ioport Uint16 * RTCMIN    = (volatile Uint16 *) 0x190C;
volatile ioport Uint16 * RTCHOUR   = (volatile Uint16 *) 0x1910;
volatile ioport Uint16 * RTCDAY    = (volatile Uint16 *) 0x1914;
volatile ioport Uint16 * RTCMONTH  = (volatile Uint16 *) 0x1918;
volatile ioport Uint16 * RTCYEAR   = (volatile Uint16 *) 0x191C;
volatile ioport Uint16 * RTCINTFL  = (volatile Uint16 *) 0x1920;
volatile ioport Uint16 * RTCINTREG = (volatile Uint16 *) 0x1924;



// borrowed from CSL

#define CSL_SYS_CGCR1_RESETVAL           (0x1000u)
#define CSL_SYS_CGICR_RESETVAL           (0x0000u)
#define CSL_SYS_CGOCR_RESETVAL           (0x0000u)
#define CSL_SYS_CGCR2_RESETVAL           (0x0806u)

static Uint8 bPllBypass = 0;

void configure_pll(void)
{
    Uint16 timeout = 1000;
   
    // Bypass the PLL
    *CCR2 = 0x0000;
   
    // Reset PLL register
    *CGCR1 = CSL_SYS_CGCR1_RESETVAL;
    *CGCR2 = CSL_SYS_CGICR_RESETVAL;
    *CGCR4 = CSL_SYS_CGOCR_RESETVAL;
    *CGCR3 = CSL_SYS_CGCR2_RESETVAL;

    // Set CLR_CTRL = 0 in CGCR1
    *CGCR1 &= 0x7FFF;
   
    *CGCR2 = 0x8000;
    *CGCR4 = 0x0000;
    *CGCR3 = 0x0806;

    // Set PLL_PWRDN = 0, PLL_STANDBY = 0, CLR_CNTL = 1 and program MH in CGCR1
    // according to your required settings
    *CGCR1 = 0x8BE8;

    while (!(*CGCR3&0x0008) && timeout--)
    {
       
    }

    // Select pll
    *CCR2 = 0x0001;
   
    return;
}

void configure_io_toogle(void)
{
  #ifdef USE_EVAL_STICK    
    // Toggle GPIO21
    // Set GP21 instead of A[15]
    *EBSR |= 0x0001;
   
    // disable interrupt
    // set IO high and enable as output
    *IOINTEN2 &= 0xFFDF;
    *IODATAOUT2 |= 0x0020;
    *IODIR2 |= 0x0020;
  #else
      // toggle GPIO14
     
      // disable interrupt
    // set IO high and enable as output
    *IOINTEN1 &= 0xBFFF;
    *IODATAOUT1 |= 0x4000;
    *IODIR1 |= 0x4000;
  #endif
}

void toggle_io(void)
{
    static Uint8 setval = 1;

    if ( setval )
    {
      #ifdef USE_EVAL_STICK
        *IODATAOUT2 &= 0xFFDF;
      #else
          *IODATAOUT1 &= 0xBFFF;
      #endif 
        setval = 0;     
    }
    else
    {
      #ifdef USE_EVAL_STICK
        *IODATAOUT2 |= 0x0020;
      #else
          *IODATAOUT1 |= 0x4000;
      #endif
           
        setval = 1;
    }
  
}

interrupt void rtc_isr(void)
{
    Uint16 delay ;
   
    if ( bPllBypass )
    {
        *ICR = 0x00E0; // enable idle on all domains
        asm("  nop");
        asm("  idle");
        asm("  nop");
       
        // enable the pll again
        configure_pll();
       
        *RTCINTFL = *RTCINTFL;   
        bPllBypass = 0;
    }
    else
    {
        // clear interrupt flag register to all for interrupts to fire again
        *RTCINTFL = *RTCINTFL;   
    }
}

void configure_rtc(void)
{
    Uint8 timeOut = 1000;
   
    // Configure and enable the RTC interrupts using INTC module
    IRQ_globalDisable();

    // Clear any pending interrupts
    IRQ_clearAll();

    // Disable all the interrupts
    IRQ_disableAll();

    IRQ_setVecs((Uint32)&VECSTART);
   
    IRQ_plug (RTC_EVENT, &rtc_isr);

    IRQ_enable(RTC_EVENT);
    IRQ_globalEnable();
      
    // before writing the time to RTC Registers clear time update bit
    *RTCUPDATE = 0;

    // set time registers
    *RTCMIL   = 0;
    *RTCSEC   = 0;
    *RTCMIN   = 0;
    *RTCHOUR  = 0;
    *RTCDAY   = 0;
    *RTCMONTH = 0;
    *RTCYEAR  = 0;
   
    // Time updates enabled
    *RTCUPDATE |= 0x8000;
    while( (*RTCUPDATE & 0x8000) && (--timeOut != 0));

    // set interrupt register
    *RTCINTREG = 0x0002;  
   
    // enable interrupts
    *RTCINTEN = 0x0001;
   
}

void main(void)
{
    Uint16 i;

    // disable idle on all domains
    *ICR = 0x000E;
    asm("  idle");
    asm("  nop");
    asm("  nop");
    asm("  nop");
   
    // Configure PLL
    configure_pll();
   
    *PCGCR1 &= 0x7FFF;
    *PCGCR2 &= 0x007F;

    // Idle Setup
    // Reset peripherals
    *PSRCR = 0x0020;
    *PRCR  = 0x00BF;
    for(i=0; i<0xff; i++)
    {
        asm("   nop");
    }
   
    // We need to active the EMIF clock so it can ACK our request
    // Activate EMIF Clock
    // Proably should activate USB and UART's clocks also, but that seems
    // to be done by bootloader
    *PCGCR1 = 0x0000;
    *PCGCR2 = 0x0000;

    // Configure IO for toggling
    configure_io_toogle();
   
    // configure RTC Second Alarm
    configure_rtc();
   
    // disable TMR0
    *TCR0 = 0;

    // disable USB OSC
    *USBSCR = 0x804C;

    // Need to request from UART / USB / EMIF if we can disable clocks
    *CLKSTOP = 0x0015;
   
    // need to check to make sure all of the above ack before disabling clocks
    while(0x3F != *CLKSTOP)
    {
        asm("   nop");
    }

    // Disable all clocks but SYSCLK
    *PCGCR2 = 0x007F;
    *PCGCR1 = 0x7FFF;
  
    while(1)
    {
        // wait for ISR to fire
       
        bPllBypass = 1;
        // Disable & Powerdown the PLL
        *CCR2 = 0x0000;
        *CGCR1 &= 0xEFFF;
          
        // Configure for Idle, enable idle on all domains
        *ICR = 0x03EF; // enable idle on all domains
        asm("  nop");
        asm("  nop");
        asm("  idle");
        asm("  nop");
        asm("  nop");
       
        toggle_io();         

    }
}
   

  • Has anyone been able to reproduce the RTC interrupt issue with this code?

    Cheers!

  • Hi,

    I am not an expert but here are my two cents... 

    While on PLL bypass/Power down the CPU is running at (a very slow) 32.77kHz. You should try to keep your rtc_isr() cycles to a minimum. Try the following...

    • interrupt void rtc_isr(void)
    • {
    • Uint16 delay;
    • // PLL power up
    • *CGCR1 &= 0xEFFF;
    • for(delay=0;delay<500;delay++); 
    • // PLL bypass
    •     *CCR2 = 0x0001;
    •     for(delay=0;delay<500;delay++);
    •     
    • // Clear RTC interrupt flags
    • *RTCINTFL = *RTCINTFL;    
    • }

    Also, change your while(1) as follows...

    • while(1)
    • {              
    •   // Bypass PLL
    •     *CCR2 = 0x0000;
    •         // PLL power down
    •        *CGCR1 |= 1u<<12;
    •               
    •         // Configure for Idle, enable idle on all domains
    •         *ICR = 0x03EF; // enable idle on all domains
    •         asm("  nop");
    •         asm("  nop");
    •         asm("  idle");
    •         asm("  nop");
    •         asm("  nop");
    •         
    •         toggle_io();          
    • }

    Let me know if this works for you.

  • Thanks for a response, I agree that the RTC isr should be as short as possible.

    What I am seeing though is that the RTC interrupt stops firing once the PLL is disabled.

    Is it possible for you to run this code and tell me if you see the IO line toggle?

    Cheers!

  • Hi, I was able to see the GPIO toggle every second with some modifications to your code. See the attached .c file.

    Let me know if it works for you. 

    7484.rtc_idle3.c

    Also, could you check the value of IF1 when the RTC interrupt stops firing?

  • Thanks for the file.

    I get this to work some of the times from the debugger. If I power cycle and reconnect to the board it will usually work the first time. But if I restart the program (instead of terminate the session), it will only work occasionally.

    Do you see similar behavior? If so, can you explain what that means?

    I am using CCS4.2.3.00004 and Codegen tools 4.3.9.

    Cheers!

  • You are welcome! And yes, this is the expected behavior. 

    Whenever you pause, breakpoint or restart your code the RTC keeps counting and your periodic interrupt is still being fired. Since your emulation is paused, this interrupt is not serviced by the rtc_isr(), and the interrupt flag is not cleared. Now, the next time you try to run the code the interrupt flag is ON (not cleared) and the ISR will not be executed until that interrupt is cleared and fired again. 

    You should be able to make the emulation "restart" work by first clearing and disabling all interrupts at the the very beginning of your code or changing your --entry_point to _reset_isr (as opposed to _c_int00) if you are clearing all the interrupts in the reset_isr in vector.asm.

  • Nelson,

    When I reduce the for loop delay below 175, I find this stops working.  According to all of the documentation the PLL should take 4 ms to lock. But with the delay set to 175 is about 61ms.  Are you able to get this to work with a 4 ms delay?

    Cheers!

  • Unfortunately the link to the file 7484.rtc_idle3.c is broken: http://e2e.ti.com/cfs-file.ashx/__key/CommunityServer-Discussions-Components-Files/110/7484.rtc_5F00_idle3.c


    Could sombebody please upload this file again?



  • Hi

    any chance the file  7484.rtc_idle3.c  can be restored?

    Best