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.

Enable clock divider/prescaler for DMTimer

Genius 5820 points

Hi,

I try to configure DMTimer2 as simple permanent counter but fail to configure the clock divider/prescaler, it is always running and counting with full 24 MHz. This is my code:

// first part is taken from DMTimer example...
DMTimer2ModuleClkConfig();
DMTimerReset(SOC_DMTIMER_2_REGS);
DMTimerCounterSet(SOC_DMTIMER_2_REGS,0);
DMTimerReloadSet(SOC_DMTIMER_2_REGS,0);
DMTimerModeConfigure(SOC_DMTIMER_2_REGS,DMTIMER_AUTORLD_NOCMP_ENABLE);

// then registers are written to make use of clock prescaler
HWREG(SOC_DMTIMER_2_REGS + DMTIMER_TCLR)&=~DMTIMER_TCLR_PTV; // clear current prescale-counter values
HWREG(SOC_DMTIMER_2_REGS + DMTIMER_TCLR)|=0x18;              // set prescaler to 6 which is equal to a divider by 128
HWREG(SOC_DMTIMER_2_REGS + DMTIMER_TCLR)|=DMTIMER_TCLR_PRE;  // enable prescaler

// and start the timer
HWREG(SOC_DMTIMER_2_REGS + DMTIMER_TCLR) |= DMTIMER_TCLR_ST;

No IRQ or something like that is involved, I just want it to count up. With the code above the prescaler value is ignored - any idea why?

  • qxc,

    I'm not sure which release you are using, but will base some feedback on the Processor SDK package for AM335x.

    If you look at the DMTIMERPrescalerClkEnable API located in the Processor SDK package under C:\ti\pdk_am335x_1_0_0\packages\ti\starterware\dal\dmtimer.c, there are some "wait" steps. Could this be the issue?

    void DMTIMERPrescalerClkEnable(uint32_t baseAddr, uint32_t dividerRatio)
    {
        uint32_t regVal = 0;
        /* Wait for previous write to complete */
        DMTIMER_WAIT_FOR_WRITE(baseAddr, DMTIMER_POSTED_WRITE_STS_TCLR);
    
        /* Clear the dividerRatio field of TCLR */
        regVal = HW_RD_REG32(baseAddr + DMTIMER_TCLR);
        /* this is a 3 bit field having no field definitions */
        regVal &= ~DMTIMER_TCLR_PTV_MASK;
        HW_WR_REG32((baseAddr + DMTIMER_TCLR), regVal);
    
        /* Wait for previous write to complete */
        DMTIMER_WAIT_FOR_WRITE(baseAddr, DMTIMER_POSTED_WRITE_STS_TCLR );
    
        /* Set the dividerRatio field and enable the pre-scaler clock */
        regVal = HW_RD_REG32(baseAddr + DMTIMER_TCLR);
        /* Set the prescaler enable bit */
        HW_SET_FIELD(regVal, DMTIMER_TCLR_PRE, DMTIMER_TCLR_PRE_ENABLE);
        /* Move the prescaler clock divider ratio */
        regVal |= (dividerRatio << DMTIMER_TCLR_PTV_SHIFT);
        HW_WR_REG32((baseAddr + DMTIMER_TCLR), regVal);
    
    }

    To test that the prescaler can be enabled and manipulated, I tried the example at C:\ti\pdk_am335x_1_0_0\packages\ti\starterware\examples\dmtimer\countdown_time. In dmtimerAppCdt_t (countdown_timer_app_main.c), you can enable the prescaler and the ratio. This affected the timing in the example.

    0x1U,  /* isClockPrescalerEnabled */
    0x2U,  /* ClockPrescalerRatio */

    Hope this helps.

    Lali

  • This does not seem to be the reason. When I use this function DMTIMERPrescalerClkEnable() (as well as the "old" StarterWare function DMTimerPreScalerClkEnable()) instead of my own initialisations, the result is the same.
  • qxc,

    Do you see anything get set at register location 0x48040038 (DMTIMER2 TCLR) bits 2-4 or 5?

    Lali
  • This was a part of thereason but not the whole story:

    First it contained 0x1A, means PRE-bit was not set. So I modified DMTimerPreScalerClkEnable() this way:

        /* Set the PTV field and enable the pre-scaler clock */
        HWREG(baseAdd + DMTIMER_TCLR) |= (ptv & DMTIMER_TCLR_PTV);
        DMTimerWaitForWrite(DMTIMER_WRITE_POST_TCLR, baseAdd);
    
        HWREG(baseAdd + DMTIMER_TCLR) |=DMTIMER_TCLR_PRE;
    }

    Now the register contains 0x3A - but it still does not make use of prescaler. What else could be missing?


    Thanks!

  • OK, I found it: after setting PRE bit, a wait is required too:

    /* Set the PTV field and enable the pre-scaler clock */
    HWREG(baseAdd + DMTIMER_TCLR) |= (ptv & DMTIMER_TCLR_PTV);
    DMTimerWaitForWrite(DMTIMER_WRITE_POST_TCLR, baseAdd);

    HWREG(baseAdd + DMTIMER_TCLR) |=DMTIMER_TCLR_PRE;
    DMTimerWaitForWrite(DMTIMER_WRITE_POST_TCLR, baseAdd);