Hello;
I need to generate two timer outputs with my Beaglebone black. They are high-speed signals so I cannot do it toggling a GPIO input after the timer ISR, so I want to automatically toggle the timer pin on every overflow interrupt, removing any potential latency introduced by the GPIO instructions. I have selected TIMER4 and TIMER7 for this purpose and I perform all the DMtimer operations, ISR Configuration included, in my code (Register, Priority Set, Enable, Reset, Counter Set, Configure....). However, when running and checking with my oscilloscope, I observe that only TIMER4 is toggling the GPIO output, while the TIMER7 pin remains low. Only one works.
How can I do so both timers toggle their respective outputs?
Next, I attach my code.
#include "consoleUtils.h" #include "soc_AM335x.h" #include "beaglebone.h" #include "interrupt.h" #include "dmtimer.h" #include "error.h" #include "hw_control_AM335x.h" /* #include "cache.h" #include "mmu.h" #include "hw_cm_wkup.h" #include "hw_cm_per.h" #include "hw_types.h" */ /****************************************************************************** ** INTERNAL MACRO DEFINITIONS *******************************************************************************/ #define TIMER_INITIAL_COUNT_4 (0xFFFFFFFFu-1)//(0xFF000000u) #define TIMER_RLD_COUNT_4 (0xFFFFFFFFu-1) //(0xFF000000u) #define TIMER_INITIAL_COUNT_7 (0xFFFFFFFFu-1)//(0xFF000000u) #define TIMER_RLD_COUNT_7 (0xFFFFFFFFu-1) //(0xFF000000u) /* #define START_ADDR_DDR (0x80000000) #define START_ADDR_DEV (0x44000000) #define START_ADDR_OCMC (0x40300000) #define NUM_SECTIONS_DDR (512) #define NUM_SECTIONS_DEV (960) #define NUM_SECTIONS_OCMC (1) */ /****************************************************************************** ** INTERNAL FUNCTION PROTOTYPES *******************************************************************************/ static void DMTimerAintcConfigure(void); static void DMTimerSetUp(void); static void DMTimerIsr4(void); static void DMTimerIsr7(void); /****************************************************************************** ** MMU Config / Enable *******************************************************************************/ /* #ifdef __TMS470__ #pragma DATA_ALIGN(pageTable, 16384); static volatile unsigned int pageTable[4*1024]; #elif defined(__IAR_SYSTEMS_ICC__) #pragma data_alignment=16384 static volatile unsigned int pageTable[4*1024]; #else static volatile unsigned int pageTable[4*1024] __attribute__((aligned(16*1024))); #endif void MMUConfigAndEnable(void) { REGION regionDdr = { MMU_PGTYPE_SECTION, START_ADDR_DDR, NUM_SECTIONS_DDR, MMU_MEMTYPE_NORMAL_NON_SHAREABLE(MMU_CACHE_WT_NOWA, MMU_CACHE_WB_WA), MMU_REGION_NON_SECURE, MMU_AP_PRV_RW_USR_RW, (unsigned int*)pageTable }; REGION regionOcmc = { MMU_PGTYPE_SECTION, START_ADDR_OCMC, NUM_SECTIONS_OCMC, MMU_MEMTYPE_NORMAL_NON_SHAREABLE(MMU_CACHE_WT_NOWA, MMU_CACHE_WB_WA), MMU_REGION_NON_SECURE, MMU_AP_PRV_RW_USR_RW, (unsigned int*)pageTable }; REGION regionDev = { MMU_PGTYPE_SECTION, START_ADDR_DEV, NUM_SECTIONS_DEV, MMU_MEMTYPE_DEVICE_SHAREABLE, MMU_REGION_NON_SECURE, MMU_AP_PRV_RW_USR_RW | MMU_SECTION_EXEC_NEVER, (unsigned int*)pageTable }; MMUInit((unsigned int*)pageTable); MMUMemRegionMap(®ionDdr); MMUMemRegionMap(®ionOcmc); MMUMemRegionMap(®ionDev); MMUEnable((unsigned int*)pageTable); } */ /****************************************************************************** ** FUNCTION DEFINITIONS *******************************************************************************/ int main(void) { // MMUConfigAndEnable(); // CacheEnable(CACHE_ALL); /* This function will enable clocks for the DMTimer4 & DMTimer7 instance */ DMTimer4ModuleClkConfig(); DMTimer7ModuleClkConfig(); /* Configure pinmuxing */ HWREG(SOC_CONTROL_REGS + CONTROL_CONF_GPMC_ADVN_ALE) = CONTROL_CONF_MUXMODE(2); HWREG(SOC_CONTROL_REGS + CONTROL_CONF_GPMC_OEN_REN) = CONTROL_CONF_MUXMODE(2); /* Enable IRQ in CPSR */ IntMasterIRQEnable(); /* Register DMTimer4 & DMTimer7 interrupts on to AINTC */ DMTimerAintcConfigure(); /* Perform the necessary configurations for DMTimer */ DMTimerSetUp(); /* Enable the DMTimer interrupts */ DMTimerIntEnable(SOC_DMTIMER_4_REGS, DMTIMER_INT_OVF_EN_FLAG); DMTimerIntEnable(SOC_DMTIMER_7_REGS, DMTIMER_INT_OVF_EN_FLAG); /* Start the DMTimers */ DMTimerEnable(SOC_DMTIMER_4_REGS); DMTimerEnable(SOC_DMTIMER_7_REGS); /* Halt the program */ while(1); } /* ** Do the necessary DMTimer configurations on to AINTC. */ static void DMTimerAintcConfigure(void) { /* Initialize the ARM interrupt control */ IntAINTCInit(); /* Registering DMTimerIsr */ IntRegister(SYS_INT_TINT4, DMTimerIsr4); IntRegister(SYS_INT_TINT7, DMTimerIsr7); /* Set the priority */ IntPrioritySet(SYS_INT_TINT4, 0, AINTC_HOSTINT_ROUTE_IRQ); IntPrioritySet(SYS_INT_TINT7, 0, AINTC_HOSTINT_ROUTE_IRQ); /* Enable the system interrupt */ IntSystemEnable(SYS_INT_TINT4); IntSystemEnable(SYS_INT_TINT7); } /* ** Setup the timer for one-shot and compare mode. */ static void DMTimerSetUp(void) { DMTimerPreScalerClkDisable(SOC_DMTIMER_4_REGS); DMTimerPreScalerClkDisable(SOC_DMTIMER_7_REGS); DMTimerReset(SOC_DMTIMER_4_REGS); DMTimerReset(SOC_DMTIMER_7_REGS); /* Load the counter with the initial count value */ DMTimerCounterSet(SOC_DMTIMER_4_REGS, TIMER_INITIAL_COUNT_4); DMTimerCounterSet(SOC_DMTIMER_7_REGS, TIMER_INITIAL_COUNT_7); /* Load the load register with the reload count value */ DMTimerReloadSet(SOC_DMTIMER_4_REGS, TIMER_RLD_COUNT_4); DMTimerReloadSet(SOC_DMTIMER_7_REGS, TIMER_RLD_COUNT_7); /* Configure the DMTimer for Auto-reload and compare mode */ DMTimerModeConfigure(SOC_DMTIMER_4_REGS, DMTIMER_AUTORLD_NOCMP_ENABLE); DMTimerModeConfigure(SOC_DMTIMER_7_REGS, DMTIMER_AUTORLD_NOCMP_ENABLE); DMTimerPostedModeConfig(SOC_DMTIMER_4_REGS, DMTIMER_POSTED); DMTimerPostedModeConfig(SOC_DMTIMER_7_REGS, DMTIMER_POSTED); HWREG(SOC_DMTIMER_4_REGS + DMTIMER_TCLR) |= 0x00000400; // Trigger on overflow HWREG(SOC_DMTIMER_4_REGS + DMTIMER_TCLR) |= DMTIMER_TCLR_PT; // Toggle... HWREG(SOC_DMTIMER_7_REGS + DMTIMER_TCLR) |= 0x00000400; // Trigger on overflow HWREG(SOC_DMTIMER_7_REGS + DMTIMER_TCLR) |= DMTIMER_TCLR_PT; // Toggle... } /* ** DMTimer interrupt service routine. This will send a character to serial ** console. */ static void DMTimerIsr4(void) { /* Disable the DMTimer interrupts */ //DMTimerIntDisable(SOC_DMTIMER_4_REGS, DMTIMER_INT_OVF_EN_FLAG); /* Clear the status of the interrupt flags */ DMTimerIntStatusClear(SOC_DMTIMER_4_REGS, DMTIMER_INT_OVF_IT_FLAG); //flagIsr = 1; /* Enable the DMTimer interrupts */ //DMTimerIntEnable(SOC_DMTIMER_4_REGS, DMTIMER_INT_OVF_EN_FLAG); } /* ** DMTimer interrupt service routine. This will send a character to serial ** console. */ static void DMTimerIsr7(void) { /* Disable the DMTimer interrupts */ //DMTimerIntDisable(SOC_DMTIMER_7_REGS, DMTIMER_INT_OVF_EN_FLAG); /* Clear the status of the interrupt flags */ DMTimerIntStatusClear(SOC_DMTIMER_7_REGS, DMTIMER_INT_OVF_IT_FLAG); //flagIsr7 = 1; /* Enable the DMTimer interrupts */ //DMTimerIntEnable(SOC_DMTIMER_7_REGS, DMTIMER_INT_OVF_EN_FLAG); }