Hi all,
I'm trying some bare-metal (no OS) programming on my BeagleBone (rev A6) with the aid of StarterWare on CCS v5.3. I'm trying to build a project, based on the DM timer counter example provided with StarterWare, that configures a timer and toggles the LED on the board every time the timer interrupt fires.
My problem is that the timer interrupt (for timer 2) does not seem to fire. The code within the timer interrupt does not seem to execute, and a breakpoint that is placed within the ISR I defined never pauses execution. When I manually pause the execution and check the appropriate register location I see the timer counter value changing, so it seems apparent to me that the timer was configured and set up properly. However, it looks like something prevented my ISR setup from working. I find this especially strange because I don't have any additional code after setting up the timer interrupts that could have mangled the configuration.
Code follows, thanks in advance for any advice or suggestions.
/*
* main.c
*/
// Timer reference: dmTimerCounter.c example code file.
// See page 116 (PDF page 119) of the StarterWare users guide.
#include "dmtimer.h"
#include "interrupt.h"
#include "gpio_v2.h"
#include "soc_AM335x.h"
#include "beaglebone.h"
static void hardware_init();
static void timer_init();
static void timer_config(unsigned long, unsigned long);
static void isr_timer2();
int main(void) {
// Set up hardware and peripherals.
hardware_init();
// Configure timer settings
timer_config(0xF0000000u, 0xF0000000u);
timer_init();
// XXX: Turn on LED
GPIOPinWrite(SOC_GPIO_1_REGS, (23), GPIO_PIN_HIGH);
// Enable timer interrupt
DMTimerIntEnable(SOC_DMTIMER_2_REGS, DMTIMER_INT_OVF_EN_FLAG);
// Turn on actual timer
DMTimerEnable(SOC_DMTIMER_2_REGS);
// Loop forever- all work takes place in ISRs.
while(1) ;
}
static void hardware_init() {
// Configure GPIO/LED
GPIO1ModuleClkConfig();
GPIO1Pin23PinMuxSetup();
GPIOModuleEnable(SOC_GPIO_1_REGS);
GPIOModuleReset(SOC_GPIO_1_REGS);
/* Set GPIO 1.23 as output */
GPIODirModeSet(SOC_GPIO_1_REGS, (23), GPIO_DIR_OUTPUT);
}
static void timer_init() {
// Set up the configuration for the hardware timer.
/* Enable clocks for DMTimer2 */
DMTimer2ModuleClkConfig();
/* Initialize ARM interrupt controller (AINTC) */
IntAINTCInit();
/* Register our ISR to DMTimer2's interrupt. */
IntRegister(SYS_INT_TINT2, isr_timer2);
/* Set the DMTimer2's interrupt priority to 0. */
IntPrioritySet(SYS_INT_TINT2, 0, AINTC_HOSTINT_ROUTE_IRQ);
/* Enable the DMTimer2 interrupt. */
IntSystemEnable(SYS_INT_TINT2);
/* Enable IRQ in CPSR (ARM program status register) */
IntMasterIRQEnable();
}
static void timer_config(unsigned long initial, unsigned long reload) {
// Configure timer
// Note that instead of doing a count from 0 to some compare value, we are
// preloading the timer with a given value and watching for it to overflow,
// which is functionally identical.
/* Configure the timer mode. */
// Modes: autoreload (selected) versus one-shot mode. Does the timer automatically reset itself?
// compare versus overflow (selected) mode. Does the timer ISR trip on equality to a value, or on overflow?
DMTimerModeConfigure(SOC_DMTIMER_2_REGS, DMTIMER_AUTORLD_NOCMP_ENABLE);
/* Load initial counter value into timer. */
DMTimerCounterSet(SOC_DMTIMER_2_REGS, initial);
/* Load reload counter value into timer, the value the timer gets every time it is reset. */
DMTimerReloadSet(SOC_DMTIMER_2_REGS, reload);
}
// Interrupt vector for BeagleBone timer
static void isr_timer2() {
static short int mode = 0;
/* Disable the DMTimer interrupt */
DMTimerIntDisable(SOC_DMTIMER_2_REGS, DMTIMER_INT_OVF_EN_FLAG);
/* Clear the interrupt flags (IF) status */
DMTimerIntStatusClear(SOC_DMTIMER_2_REGS, DMTIMER_INT_OVF_IT_FLAG);
/* *********** ISR TASKS BEGIN *********** */
if (mode == 0) {
// Turn on LED
GPIOPinWrite(SOC_GPIO_1_REGS, (23), GPIO_PIN_HIGH);
mode = 1;
} else {
// Turn off LED
GPIOPinWrite(SOC_GPIO_1_REGS, (23), GPIO_PIN_LOW);
mode = 0;
}
/* *********** ISR TASKS END *********** */
/* Re-enable the DMTimer interrupt */
DMTimerIntEnable(SOC_DMTIMER_2_REGS, DMTIMER_INT_OVF_EN_FLAG);
}