RTC interrupts on MC12311 IC (with embedded MC9S08QE32 MCU))

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

RTC interrupts on MC12311 IC (with embedded MC9S08QE32 MCU))

Jump to solution
1,545 Views
koehler916
Contributor II

Hello!

 

I am experimenting with RTC interrupts and I am having trouble setting them set up. 

 

I have the following: 

     Hardware: X-1231X-MRB (with MC12311 IC (with embedded MC9S08QE32 MCU)) attached to a X-RF-TWR

     Compiler: CodeWarrior for MCU Version: 10.1 Build Id:110726

 

I am trying to get an RTC to trigger and enter an ISR to wake up a sleeping MCU (Stop2) mode.

However, I need to get the RTC working before I experiment with sleeping & waking.

I am following the code example presented in the MC9s08qe32 data sheet with no luck.

I do not know the syntax and/or necessary initializations to for interrupt vectors.

This is my first project on freescale products....

 

My code and understanding is as follows:

---------------------------------------------------------

void RTC_ISR(void)     //Is this the right prototype? I am guessing not.. the datasheet says Vrtc is the vector name

 

//Anything else I need to do here first?? Any MCU ports that muct be defined? Global interrupt enable??

 

void main(void)

{

     RTCMOD= 0x00;   //setting the counter value

     RTCSC=0x1F;       //enabling the interrupt and configuring the clock source

      for( ; ; )

      {

          //wait for RTC interrupt

      }

}

 

#pragma TRAP_PROC //Any idea what this is and/or what it is used for?

void RTC_ISR(void)       //Again.. is this the right syntax?

{

     RTCSC=0x80;          //Reset the interrupt flag

     //future - wake up MCU

     //future - check something

     //future - put mcu back to sleep

}

Labels (1)
0 Kudos
1 Solution
801 Views
bigmac
Specialist III

Hello,

 

I can see no reason for a syntax error associated with your ISR code.

 

1)  Using the vector number method, you should not need a prototype because the function is not called by any other function within the program.  With the alternative vector table method, it is possible that you may require a function prototypw for the benefit of creating the vector table, an array of function pointers.

 

2)  The name of the ISR function is quite arbitrary, as is the naming of any other function.  It would only become "ambiguous" should more than one function have the same name.

 

3)

RTCSC = RTCSC | 0x80;

What this means to read the RTCSC register, to set bit-7 using the mask value 0x80, and to write the result back to the register.  This process is intended to clear the RTIF flag, and should work in this case.  However, be aware that if the same approach were used on a register that contained two or more flags, there would be potential problems with more than the one flag being simultaneously cleared.  A  more direct approach would be better.

#define RTCSCval = 0x1F  // RTC clock ~1 Hz, using 1 kHz oscillator

...

RTCSC = RTCSCval | 0x80;

 

If you are using the CW device header file, this would be equivalent to the following, which is a little clearer in its intent.

RTCSC = RTCSCval | mRTCSC_RTIF;  // Write 1 to clear RTIF flag

 

4)  Because of the presence of the flag, with its special clearing procedure, you should not use read-modify-write processes to handle single bits within the RTCSC register.  All bits of the register should be simultaneously written with their required value.

 

5.  I am not familar with the mSETUP_PORT_A; etc. macros, and whether you have correctly applied them.

 

Regards,

Mac

 

View solution in original post

0 Kudos
10 Replies
801 Views
koehler916
Contributor II

UPDATE -----

 

The above code is for illistration purposes. I have code that works on the hardware now. The intterrupt function is never entered, but I can tell the RTC is doing something because all of the LEDs flash for a very very short time every second.

 

Here is the complete code that I am using. Again, any help with this is greatly appreciated!!!

 

CODE:

------------------------------------------------------

#include <hidef.h>/* for EnableInterrupts macro */

#include "Crt0.h"

#include "FunctionLib.h"

#include "PLM_config.h"

#include "SMAC_Interface.h"

#include "LED_Interface.h"

#include "CommonHeader.h"

#include "UART_Interface.h"

#include "icg.h"

#include "IrqControlLib.h"

 

void RTC_ISR(void); //Is this the right prototype? I am guessing not.. the datasheet says Vrtc is the vector name

void WaitNms(int n);

void Wait1ms(void);

 

bool_t Tick = FALSE;

 

void main(void)

{

  IrqControlLib_DisableAllIrqs();

  mSETUP_PORT_A // Setup port A

  mSETUP_PORT_B // Setup Port B

  mSETUP_PORT_C // Setup port C

  mSETUP_PORT_D // Setup port D

  mSETUP_PORT_E // Setup port E

  IrqControlLib_EnableAllIrqs();

  RTCMOD = 0x00; //setting the counter value

  RTCSC = 0x1F; //enabling the interrupt and configuring the clock source

  Led_OffAll();

  for( ; ; )

  {

    if(Tick == TRUE)

     {

      Led_TurnOnLed(15); WaitNms(750); //Turn on all LEDs and wait

      Led_TurnOffLed(15); WaitNms(250); //Turn off all LEDs

      Tick = FALSE;

     }

    else

    {

      Led_TurnOnLed(1); WaitNms(250); //Turn on 1 LEDs

      Led_TurnOffLed(1); WaitNms(250); //Turn off 1 LEDs

    }

  }

}

 

#pragma TRAP_PROC //Any idea what this is and/or what it is used for?

 

void RTC_ISR(void) //Again.. is this the right syntax?

{

  RTCSC=0x80; //Reset the interrupt flag

  Tick = TRUE;  //future - wake up MCU//future - check something//future - put mcu back to sleep

}

 

void Wait1ms(void)

{

  unsigned char i;

  for(i=0;i<255;i++)  {}

}

 

voidWaitNms(intn)

{

  int i;

  for(i=1;i<=n;i++)

  {

  Wait1ms();

  }

}

------------------------------------------------------------

 

Thanks in advance!!!

0 Kudos
801 Views
bigmac
Specialist III

Hello,

 

There are some alternative methods of entering ISR functions.  Some of these are covered within the FAQ section of AN2616.

 

An ISR function differs from a normal function in the following respects -

  1. The function must terminate with a RTI instruction, rather than a RTS instruction.  These are assembly instructions.
  2. It is mandatory to save the H-register to the stack, which is not automatically done by the interrupt entry process.
  3. The vector associated with the interrupt must contain the address of the ISR function.

The first two requirements are accomplished by using the pragma prior to the function code -

#pragma TRAP_PROC 

void RTC_ISR(void)

{

   ... 

}

 

An alternative approach is to use the special __interrupt keyword.  The keyword interrupt is an alias, and could be used instead.

__interrupt void RTC_ISR(void)

{

   ... 

}

 

The entry at the appropriate vector location can be achieved by -

  1. Specifying the vector number: __interrupt <vector_number> void RTC_ISR( void);or
  2. Creating a vector table, or
  3. Specifying the vector address within the PRM file.

 

Since your code uses the pragma method, you will have either a vector table present within your code, or the PRM file will include the interrupt vectors.  I hope this clarifies the requirements for the coding of interrupts.

 

Regards,

Mac

 

0 Kudos
801 Views
koehler916
Contributor II

UPDATE:

 

I read through the AN2616 document and experimented with several code combinations and got the RTC working.
Although the code compiles, runs, and the interrupts works now, I think the syntax may still be wrong because CodeWarrior still underlines my code and says there is a syntax error (see attached photo).

 

I did some research and the information for the vector is as follows: (according to the MCU datasheet)

 

Description --- Real-Time interrupt
Vector Name -- Vrtc
Vector Number --- 24
Address --- 0xFFCE/0xFFCF
Source --- RTIF
Enable --- RTIE

 

Right now, the only "interrupt-related" code that was added was this:

 

interrupt 24 void RTC_ISR(void)
{
  RTCSC = RTCSC|0x80;
  Tick = TRUE;
}

 

//**********MY CODE*****************

#include <hidef.h>                    /* for EnableInterrupts macro */
#include "Crt0.h"
#include "FunctionLib.h"
#include "PLM_config.h"
#include "SMAC_Interface.h"
#include "LED_Interface.h"
#include "CommonHeader.h"
#include "UART_Interface.h"
#include "icg.h"
#include "IrqControlLib.h"

 

//function definitions
void WaitNms(int n);
void Wait1ms(void);

 

//memory declarations
bool_t Tick = FALSE;

 

//interrupt functions
interrupt 24 void RTC_ISR(void)
{
  RTCSC = RTCSC|0x80;
  Tick = TRUE;
}

 

void main(void)
{
  IrqControlLib_DisableAllIrqs();
  mSETUP_PORT_A                     // Setup port A
  mSETUP_PORT_B                     // Setup Port B
  mSETUP_PORT_C                     // Setup port C
  mSETUP_PORT_D                     // Setup port D  
  mSETUP_PORT_E                     // Setup port E
  RTCMOD = 0x00;   //setting the counter value
  RTCSC = 0x1F;    //enabling the interrupt and configuring the clock source
  IrqControlLib_EnableAllIrqs();
  Led_OffAll();
  for( ; ; )
  {
    if (Tick == TRUE)
    {
      //RTCMOD = 0x00;//Re-setting the counter value
      //RTCSC = 0x1F; //Re-enabling the interrupt re-configuring the clock source
      Led_TurnOnLed(8);  WaitNms(100); //Turn on all LEDs and wait
      Led_TurnOffLed(8); WaitNms(100); //Turn off all LEDs
      Tick = FALSE;
    }
    else
    {
      Led_TurnOnLed(1);  WaitNms(100); //Turn on 1 LEDs
      Led_TurnOffLed(1); //Turn off 1 LEDs
    }

  }
}

 

void Wait1ms(void)
{
  unsigned char i;
  for(i=0;i<255;i++) {}
}

 

void WaitNms(int n)
{
  int i;
  for(i=1;i<=n;i++)
  {
    Wait1ms();
  }
}

 

I now have some questions:

 

1) Does the interrupt require any special prototype other than what I have written?
2) Is the name "RTC_ISR" ambiguous or is this name defined in some other file? (If so, which file?)
3) What does the | symbol do in the statement -->  RTCSC = RTCSC|0x80;
4) Is there any syntax to access a single bit inside a register?? (for example, simply remove the interrupt flag inside of the RTCSC register. Maybe something like RTCSC.7=0;?)
5) I am not sure what mSETUP_PORT_A does exactly. Is this a good programming practice to use this or should I define each register individually?
6) Do you have any code sugestions or pointers?

 

(Sorry for so many questions)

 

Thanks in advance,

Kevin

0 Kudos
802 Views
bigmac
Specialist III

Hello,

 

I can see no reason for a syntax error associated with your ISR code.

 

1)  Using the vector number method, you should not need a prototype because the function is not called by any other function within the program.  With the alternative vector table method, it is possible that you may require a function prototypw for the benefit of creating the vector table, an array of function pointers.

 

2)  The name of the ISR function is quite arbitrary, as is the naming of any other function.  It would only become "ambiguous" should more than one function have the same name.

 

3)

RTCSC = RTCSC | 0x80;

What this means to read the RTCSC register, to set bit-7 using the mask value 0x80, and to write the result back to the register.  This process is intended to clear the RTIF flag, and should work in this case.  However, be aware that if the same approach were used on a register that contained two or more flags, there would be potential problems with more than the one flag being simultaneously cleared.  A  more direct approach would be better.

#define RTCSCval = 0x1F  // RTC clock ~1 Hz, using 1 kHz oscillator

...

RTCSC = RTCSCval | 0x80;

 

If you are using the CW device header file, this would be equivalent to the following, which is a little clearer in its intent.

RTCSC = RTCSCval | mRTCSC_RTIF;  // Write 1 to clear RTIF flag

 

4)  Because of the presence of the flag, with its special clearing procedure, you should not use read-modify-write processes to handle single bits within the RTCSC register.  All bits of the register should be simultaneously written with their required value.

 

5.  I am not familar with the mSETUP_PORT_A; etc. macros, and whether you have correctly applied them.

 

Regards,

Mac

 

0 Kudos
801 Views
tonyp
Senior Contributor II

Just a minor note: Regarding the RTCSC flag clearing, actually just a "RTCSC = RTCSC" should be enough (unless compiler optimization eliminates it).  The flag is cleared by writing a 1, which is already set at the time we need to clear the flag.  So, just copying the register back to itself should clear the flag without any side effects to the current settings.


0 Kudos
801 Views
koehler916
Contributor II

I have the RTC interrupt code working now, and I have the MCU going to sleep, and waking up again from the RTC interrupt. Thank you for all of your help!

 

I do have one more question: If I define my interrupt like this...

 

  #pragma TRAP_PROC

  void RTC_ISR(void)

  {

    RTCSC = RTCSC | 0x80;

    Tick = TRUE;

  }

 

...then how do I add the vector number/address into the .prm file?

 

the vector information is:

 

Vector Name -- Vrtc
Vector Number --- 24
Address --- 0xFFCE/0xFFCF

I found the prm file, but I am not sure how to make the entry. Can anyone advise on this? I attached a photo of .prm file's vector section as I am seeing it.

----------------------------------------------------------------------------------------

Also, I tried taking the working RTC code and placing it into my project code and I am experiancing more errors. I created a new thread for this. The project code uses radio communication and UART in addition to RTC interrupt. I am hoping that switching to this #prama TRAP_PROC style will fix the problem.. The thread can be found here:

https://community.freescale.com/thread/105400

 

 

0 Kudos
801 Views
bigmac
Specialist III

Hello,

 

Within the PRM file, you could add -

VECTOR 24 RTC_ISR

 

However, it will depend on whether there is a separate vector table within the existing code.  If so, this should be updated with the name of the ISR function instead.

 

Regards,

Mac

 

0 Kudos
801 Views
koehler916
Contributor II
bigmac,
 
Thank you for your quick reply. I think the document you pointed me to will contain some good information. I am going to experiment more with this today and I will get back to you as soon as results become available. 
 
Kind Regards
0 Kudos
801 Views
rocco
Senior Contributor II

Hi Koehler,

 

Why do you think the RTC service routine is not being entered?

 

As far as I can tell, the only way the LEDs would blink is if "Tick" were set to TRUE, and the only place that "Tick" can become true is in the RTC's ISR. I think your code is working.

0 Kudos
801 Views
koehler916
Contributor II

The reason I believe the service routine is not being entered is for three reasons:

 

1 - While using a hardware debugger, the program does not break when placing a breakpoint inside of "if {tick == true}". The program also does not break when placing a breakpoint inside of my ISR.

 

2 - All LEDs briefly turn on every second, however it is very brief, definitely several orders of magnitude shorter than what my code says.

 

3 - Changing the code to specify just one led to turn on (if tick == true) results in no visible changes. All LEDS still very briefly blink, rather than the one I specified.

 

 My vote: improper syntax for defining and setting up the routine. Any ideas?

0 Kudos