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
}
Solved! Go to Solution.
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
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!!!
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 -
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 -
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
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
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
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.
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
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
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.
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?