Blog » Timer interrupt with QuickStart
Timer interrupt with QuickStart
I've discussed LED blinking using GPIO and software delay in my previous post. Today I'd like to show how to quickly configure cascaded timer interrupt using QuickStart. The purpose of this post is not to describe how timers work but to show how easily the configuration with QuickStart is. Timers and interrupt controller will be discussed deeply in some of next posts.
You can see block diagram of what we will try to do now. We want to execute interrupt every 1 second using cascaded connection of two timers. Each timer is able to create up to 128 * 65536 division ratio of its input. Start creating a new QuickStart project as described in previous post.
Block diagram of timer connection
Lets do our configuration. Timer 0 will have its input connected to system bus clock which is 32MHz when using MC56F8006, 40MHz when using MC56F81xx or 60MHz when using MC56F83xx. The input prescaler is set to 1/32 - this will create 1MHz on timer input (MC56F8006). The timer will count up until compare, then will reinitialize to load value (0) and toggle output flag (OFLAG). Timer 0 has 1kHz on its output (output flag toggle frequency). Don't forget to check QT_0 checkbox to enable timer 0. See configuration screenshot below.
Timer 0 configuration
Timer 1 input will be connected to timer 0 output and will count up on output flag toggle up to compare value, then will reinitialize to load value (0) and generate interrupt. Fill in ISR name the function name of interrupt routine. See configuration below.
Timer 1 configuration
The next step is to enable peripheral clock to Timer 0 and Timer 1 in system module. See picture.
Peripheral clock enable
Continue enabling GPIO for LED as outputs (same configuration as in my previous post). See configuration.
The final step is to check interrupt controller ISR setup. There should be ISR function name you've entered in timer 1 configuration in "26. Timer 1 Compare/Overflow/Edge" edit box. Finish by clicking Save icon and closing configuration dialog.
Interrupt controller ISR config
We can change source code at this point. We should call all peripheral configuration routines and create ISR function. See source code snippet below:
/* clear compare flag */
ioctl(QTIMER_1, QT_CLEAR_FLAG, QT_COMPARE_FLAG);
/* toggle bit3 */
ioctl(GPIO_A, GPIO_TOGGLE_PIN, BIT_3 | BIT_4 | BIT_5);
void main (void)
/* initialize SYS module */
ioctl(SYS, SYS_INIT, NULL);
/* configure COP module */
ioctl(COP, COP_INIT, NULL);
/* configure all GPIO modules */
ioctl(GPIO, GPIO_INIT_ALL, NULL);
/* configure timer 0 */
ioctl(QTIMER_0, QT_INIT, NULL);
/* configure timer 0 */
ioctl(QTIMER_1, QT_INIT, NULL);
/* initialize interrupt controller and enable interrupts */
ioctl(WINTC, WINTC_INIT, NULL);
/* enable interrupts */
/* feed the watchdog periodically */
ioctl(COP, COP_CLEAR_COUNTER, NULL);
#pragma interrupt keyword is a signal for compiler that the function is interrupt subroutine (ISR). Compiler will add instructions for saving registers at function start, restoring registers and RTI instruction at function end.
Your LED should now change its state in 1Hz period after application launch. You can try to add brakpoint to your subroutine by cliking to "-" symbol at begin of each line in debug mode or by pressing F9. You can also switch editor view to assembler or mixed mode. A compiled code of ISR routine is on picture below. You can see the power of QuickStart - ioctl(GPIO_A, GPIO_TOGGLE_PIN, BIT_3 | BIT_4 | BIT_5); was compiled to single instruction. As I said before QuickStart is mostly a set of macros so the compilation is very effective.
Mixed view of source code
I personally do not use QuickStart and this is the last post where I use it. I think it is very important to understand how architecture and peripherals work. Deep description is the primary aim of these posts. I will start probably with GPIO and Interrupt controller.