This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Two timer output toggling does not work (only one)

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(&regionDdr);
    MMUMemRegionMap(&regionOcmc);
    MMUMemRegionMap(&regionDev);
    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);
}