Hello,
I'm using a MC9S12XF521 microcontroller.
I want to create a function (timer_1_ms) which configure a timer and enable to counte the timer. After the timer has finished to count-down, an interrupt while set a semaphore in order to go out to the timer_1_ms() function. My problem is about using an IRQ. I don't know my code doesn't work.
/*******************************************************************************/
/* Timer 1 ms */
/*******************************************************************************/
void timer_1_ms(void)
{
/* with Clock_Settings(), the bus' speed is 40MHz */
blink_led(LED5_MASK); /* LED5 for indicate that we are in the function */
PITCE_PITCE0 = 0; /* Le timer0 is disable, so doesn't count */
timer_1_ms_flag = 0; /* semaphore used to speak between timer_1_ms() function and the IRQ */
PITCSTP &= ~BIT0_MASK; /* The timer0 wont wait a bit set of PITFLT register to count again after an overflow */
PITMTLD0 = 200; /* Load of the timer0 8bits at 200 => increment of the 16bits timer0 each 5us */
PITLD0 = 200; /* Load of the timer0 16bits at 200 => flag each 1ms */
PITTF_PITTF0 = 1; /* interrupt flag is clear (just in case) */
PITINTE_PITINTE0 = 1; /* Interrup of the timer0 is enable */
PITCE_PITCE0 = 1; /* The timer 0 is enable to count */
PITCFLMT_PITE = 1; /* The PIT module si enable */
while (timer_1_ms_flag != 1){
LED1 = 0; /* LED1 ON to show that we are in the loop */
}
blink_led(LED2_MASK); /* LED2 ON to show that we are out of the loop */
}
/*******************************************************************************/
/* Timer Interrupt Service Routine */
/*******************************************************************************/
#pragma CODE_SEG __NEAR_SEG NON_BANKED
void interrupt Timer_Isr(void)
{
blink_led(LED4_MASK); /* LED4 ON to show that we are in the timer interrupt routine*/
if(PITTF_PITTF0 == 1){
PITCE_PITCE0 = 0; /* Disable the timer0 */
PITTF_PITTF0 = 1; /* Clear the flag */
blink_led(LED3_MASK); /* LED3 ON to show that we are in the subroutine*/
timer_1_ms_flag = 1; /* semaphore at 1 */
}
}
#pragma CODE_SEG TIMER_ISR_CODE
/*******************************************************************************/
Thank you,
Pierre
Thank you RadekS !
Your last comment will be very usefull for a beginner as me.
The community is quite good !
Have a great day,
Pierre
Hi Pierre,
I am glad that it works now.
About interrupt vector numbers)
You may look at mc9s12xf512.h file and you will find this definition:
#define VectorNumber_Vpit0 66U
So, you could directly define interrupt routine as:
interrupt VectorNumber_Vpit0 void Timer_Isr(void)
or as
interrupt 66 void Timer_Isr(void)
In such case, you don’t need vector table.
The next option is definition this vector number in prm linker file.
The interrupt number 0 presents POR reset vector, 1 is CM reset, 2 is COP reset, ... , 119 is Spurious Interrupt (63 in the case of S12 core).
Interrupt number = (0xFE-Vector Address)/2. See Table Interrupt Vector Locations at RM.
For Example: Interrupt number of SCI0 = (0xFE-D6)/2 = 0x14 = 20.
I hope it helps you.
Have a great day,
RadekS
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
EDIT: fixed Spurious Interrupt vector number.
Hi RadekS,
Thank you for your answere.
Before your comment, I did not know the PIT interrupt. I worked in this way and I found a solution to my problem.
See after (in case it could help someone) my new code :
In Interrupts.c :
/*******************************************************************************/
/* Timer Interrupt Service Routine */
#pragma CODE_SEG __NEAR_SEG NON_BANKED
void interrupt Timer_Isr(void)
{
if(PITTF_PITTF0 == 1){
PITCE_PITCE0 = 0; /* Disable the timer0 */
PITTF_PITTF0 = 1; /* Clear the flag */
timer_1_ms_flag = 1; /* semaphore at 1 */
}
}
#pragma CODE_SEG TIMER_ISR_CODE
/*******************************************************************************/
In Vector.c :
/* Interrupt vectors table */
typedef void (*near tIsrFunc)(void);
const tIsrFunc _InterruptVectorTable[] @0xFF10 = {
/* ISR name No. Address Pri XGATE Name
Timer_Isr, /* 0x3D 0xFF7A 1 no ivVpit0
/*******************************************************************************/
It was really hard to me to find the good vector in the vectors table. There is any document which talk about the interrupt and their vector ?
Thank you,
Pierre
Hi Pierre,
The most important question is what do you want to do?
Do you want to have periodic interrupt every 1ms? Or do you want to generate 1ms interval?
In the first case, PIT or RTI is correct choice (PIT is more precise, but RTI could run in pseudo STOP mode). They are designed for generating periodic interrupts.
In the second case, the ECT timer will better choice. You don’t need to take care about divider, disable and enable module again….
The example codes are here:
https://community.freescale.com/docs/DOC-95116
For example: XEP100 - ECT 500us interval - CW47, XEP100 - ECT 500us period - CW47, XS128 - PIT - CW47, ...
And here:
https://community.freescale.com/docs/DOC-329209
Note: Be careful with commands like "PITTF_PITTF0 = 1; /* Clear the flag */". This is read/modify/write command and it will clear all pending flags in PITTF register. Please use rather commands like PITTF=0x01; or PITTF=PITTF_PITTF0_MASK; for clearing specific flag. This is important in all cases where the register contains at least two flags which are cleared by writing log.1 = general rule.
I hope it helps you.
Have a great day,
RadekS
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
I found a little trick to solve this problem ( I call an other function in the RTI_isr) but I'm afraid with using this for the future.
If you have a suitable idea, please do not hesitate!
Thank you (again),
Pierre
After some investigation, I found the problem's source but not its solution...
The function timer_1_ms() works but when the timer finish to count-down, this is the rti_isr which is called by the interruption.
I use an project example to go faster in my development.
The new question is : How to call the good interrupt routine after an overflow of a timer ?
Thank you