locked
Hardware Timer RRS feed

  • Question

  • Hello,

    I am working with an OMAP3530 Device running on WinCE 6 R3 / TI_ARM_A8 BSP.  After reading all the posts here, I feel I need a hardware timer to enable my application to read data from the ADC every millisecond sharp.  Would anyone please give me some timer driver source code for reference?

    I appreciate your help very much,

    Luan


    Luan Le

    Thursday, May 10, 2012 12:52 AM

Answers

  • I don't know how to change the interrupt priority so I tried to implement Misbah's idea and it works.  The interrupt intervals are all closed to 2ms now.  In my way, I used Compare Interrupt and set a new compare value at each interrupt as below

        #define MSEC_TO_TICK(msec)  (((msec) << 12)/125 + 1)  // msec * 32.768
       
        compareVal = INREG32(&pDevice->pGPT->TCRR) + MSEC_TO_TICK(2);
        OUTREG32(&pDevice->pGPT->TMAR, compareVal);

    I don't see any wrong with this way but for some reason it causes jitter in the timing.  Following Misbah's example, in the initialization I set the Reload Register TLDR and Count Register TCRR to  (0xFFFFFFFF - (32 * 1024 * 2)), enable Overflow Interrupt, and start the timer.  I don't have to load any register in the IST.

    It is working for me now.  Thank you all for your help.


    Luan Le

    • Proposed as answer by Misbah Khan Thursday, May 31, 2012 5:04 AM
    • Unproposed as answer by Misbah Khan Thursday, May 31, 2012 5:07 AM
    • Marked as answer by LuanLe Thursday, August 2, 2012 4:26 PM
    Wednesday, May 30, 2012 10:22 PM

All replies

  • I doubt anyone will give you driver source... Why don't you try it yourself and if you run into problems ask specific questions here? There are enough example drivers available to you; just check the other BSPs in the PLATFORM folder (see also the COMMON\src\SOC folder).

    Good luck,

    Michel Verhagen, eMVP
    Check out my blog: http://guruce.com/blog

    GuruCE
    Microsoft Embedded Partner
    http://guruce.com
    Consultancy, training and development services.

    Thursday, May 10, 2012 1:32 AM
  • I cannot give you the whole source code, as it is my companies property, but will definitely help you to write for your own.

    Read the GPTimer module of omap3530 first, decide upon which timer you would use considering the available timers in your case.

    plan your driver (stream interface) with respect to interface and API's . Do your home work  first, then i would be in a position to help you and you would also be in a position to understand better.

    --- Misbah


    Senior Design Engineer T.E.S Electroni Solutions (Bangalore-India) www.tes-dst.com email-misbah.khan@tes-dst.com

    • Proposed as answer by Misbah Khan Thursday, May 31, 2012 5:13 AM
    Friday, May 11, 2012 7:36 AM
  • Hello,

    I add a hardware timer driver to the BSP so that I can run a thread within my application exactly every 2ms.  For now, the stream driver is
    hardcoded to use only one timer.  Since Timer 1 is used as the system timer and Timer 2 for Profiler, I am using Timer 3.  I set it up as
    a free running timer in compare mode of 2ms with match interrupt enabled.  I don't know how to set the source clock for the timer but it seems
    to me that the source clock is the same as for Timer 1, which is 32.768 KHz.

    My IST does nothing except toggling a GPIO pin, set a new compare value, and then clear the interrupt.  The timing on my scope shows the interrupt
    intervals vary between 2ms to 2.5ms.  The timer registers initialization is below:

        // stop timer
        OUTREG32(&pDevice->pGPT->TCLR, 0);

        // Soft reset GPTIMER
        OUTREG32(&pDevice->pGPT->TIOCP, SYSCONFIG_SOFTRESET);

        // Set smart idle
        OUTREG32(pDevice,
       &pDevice->pGPT->TIOCP,
                SYSCONFIG_SMARTIDLE|SYSCONFIG_ENAWAKEUP|
                SYSCONFIG_AUTOIDLE
            );

        // Disable posted mode
        OUTREG32(pDevice, &pDevice->pGPT->TSICR, 0);  // Also did try in posted mode with same result

        // Set match register to avoid unwanted interrupt
        OUTREG32(&pDevice->pGPT->TMAR, 0xFFFFFFFF);

        // Enable match interrupt
        OUTREG32(&pDevice->pGPT->TIER, GPTIMER_TIER_MATCH);

        // Enable match wakeup
        OUTREG32(&pDevice->pGPT->TWER, GPTIMER_TWER_MATCH);

        // Enable timer in auto-reload and compare mode
        OUTREG32(&pDevice->pGPT->TCLR, GPTIMER_TCLR_CE|GPTIMER_TCLR_AR|GPTIMER_TCLR_ST);

        OUTREG32(&pDevice->pGPT->TLDR, 0);


    The match register is updated at the start and also in the IST as below:

        #define MSEC_TO_TICK(msec)  (((msec) << 12)/125 + 1)  // msec * 32.768
       
        compareVal = INREG32(&pDevice->pGPT->TCRR) + MSEC_TO_TICK(2);
        OUTREG32(&pDevice->pGPT->TMAR);


    I don't know why my timer period is not consistent.  Would you please tell me what could be the cause or I am missing something?

    Thanks for your help,

    Luan


    Luan Le

    Friday, May 25, 2012 4:43 PM
  • sounds like you need to look at your thread priority and interrupt priority.

    Keep in mind that anything that runs on your system between the interrupt and setting the new match value will affect your timer period.


    Bruce Eitman (eMVP)
    Senior Engineer
    Bruce.Eitman AT Eurotech DOT com
    My BLOG http://geekswithblogs.net/bruceeitman

    Eurotech Inc.
    www.Eurotech.com

    Friday, May 25, 2012 5:18 PM
  • Thanks Bruce for your advice.  I need your help on how to look at the interrupt priority but I did try setting my timer thread priority to 0.  I also tried using different available timers and did not see any change on the timing.

    Luan


    Luan Le

    Friday, May 25, 2012 5:47 PM
  • Interrupt priority is either determined by the CPU itself or by your IST.  You know your hardware better than I do.


    Bruce Eitman (eMVP)
    Senior Engineer
    Bruce.Eitman AT Eurotech DOT com
    My BLOG http://geekswithblogs.net/bruceeitman

    Eurotech Inc.
    www.Eurotech.com

    Friday, May 25, 2012 6:10 PM
  • I found out that the interrupt priority is set by the CPU and it is not changable.  It is IRQ_39.

    Has anyone else written a timer driver for OMAP35/3730?  I would also appreciate your inputs very much.

    Luan


    Luan Le

    Friday, May 25, 2012 8:44 PM
  • Your Timer Initialization may not be correct, Refer the below code and do it accordingly ... The example is not for timer 3, so make the changes accordingly ...
    ------------------------------------------------------------------


    #define GPT_FCLK                        0x48005000     /* FCLK reg */
    #define GPT_ICLK                        0x48005010    /* ICLK reg */
    #define GPT_CLK_SOURCE                    0x48005040    /* CLK source */

    #define THREAD_PRIORITY                    5
    /* No of times polling the H/W register */
    #define MAX_POLL_REG_VALUE                10

    /* Freq in MZ */
    #define FREQ_12_MZ                        12000000
    #define FREQ_13_MZ                        13000000
    #define FREQ_19_2_MZ                    19200000
    #define FREQ_38_4_HZ                    38400000

    static int OMAP_Timer_Init(void)
    {
        PULONG pFclk,pIclk;
        PULONG pClock;

        /* Timer 4 register map */
        PHYSICAL_ADDRESS timer4reg;
        timer4reg.LowPart = OMAP_GPTIMER4_REGS_PA;
        timer4reg.HighPart = 0;

        /* FCLK access */
        PHYSICAL_ADDRESS fclk;
        fclk.LowPart = GPT_FCLK;
        fclk.HighPart = 0;

        /* ICLK access */
        PHYSICAL_ADDRESS iclk;
        iclk.LowPart = GPT_ICLK;
        iclk.HighPart = 0;

        /* Clock Source */
        PHYSICAL_ADDRESS clocks;
        clocks.LowPart      = GPT_CLK_SOURCE;
        clocks.HighPart     = 0;

        RETAILMSG(ZONE_FUNCTION, (L"++ In OMAP_Timer_Init() \n"));

        /* Config FCLK */
        pFclk = (PULONG)MmMapIoSpace(fclk,4,FALSE);
        OUTREG32(pFclk, INREG32(pFclk) | (1<<5));
        MmUnmapIoSpace(pFclk ,4);

        /* Config ICLK */
        pIclk = (PULONG )MmMapIoSpace(iclk,4,FALSE);
        OUTREG32(pIclk, INREG32(pIclk) | (1<<5));
        MmUnmapIoSpace(pIclk ,4);

        Sleep(100);
        /* Select source clock */
        pClock = (PULONG )MmMapIoSpace(clocks,4,FALSE);
        //OUTREG32(pClock, INREG32(pClock) | (1<<2));
        /* Taking 32 k hz as clock source now ( Misbah <30-June-09> ) */
        OUTREG32(pClock, INREG32(pClock) | (0<<2));
        MmUnmapIoSpace(pClock ,4);

        /* Map the timer 4 configuration register to virtual address space */
        g_pTimerRegs = (OMAP_GPTIMER_REGS*)MmMapIoSpace(timer4reg, \
            sizeof(OMAP_GPTIMER_REGS), FALSE);

        RETAILMSG(ZONE_FUNCTION,(L" + OMAP_Timer_Init \n"));

        return TRUE;

    }

    --- Misbah

    Senior Design Engineer T.E.S Electroni Solutions (Bangalore-India) www.tes-dst.com email-misbah.khan@tes-dst.com

    • Proposed as answer by Misbah Khan Thursday, May 31, 2012 5:09 AM
    Monday, May 28, 2012 2:24 PM
  • you may have to play with thread quantum along with thread priority of your IST. See this blog, it may show some lights on getting the real time performance for your timer driver.

    http://vinoth-vinothblog.blogspot.in/2011/11/handling-real-time-tasks-in-windows-ce.html


    Vinoth.R http://vinoth-vinothblog.blogspot.com http://www.e-consystems.com

    Tuesday, May 29, 2012 8:51 AM
  • Hello Misbah,

    Thanks a lot.  Unfortunately, I am still struggling in getting the timer period stable.  I used your code in the Initialization and also tried the thread priority of both 0 and 5 but the problem is still there - the period between interrupts is ranging from 2.1ms to 2.4ms.  One thing I also don't understand is that if I set the clock source to 32K_FCLK, I am getting interrupts.  However, if I set the clock source to SYS_CLK, I do not getting any interrupts.  Do you know the reason why?  Do I have to do anything else to use SYS_CLK.  I want to try this out because I see the OALPerformanceTimer uses SYS_CLK instead of 32K_FCLK.

    Hi Vinoth,

    I appreciate you help.  I also added your suggestion by calling CeSetThreadQuantum() with parameter 0 after setting thread priority but it does not make a difference in this case.

    Please let me know if you can think of anything else that you want me to try.

    Luan


    Luan Le

    Tuesday, May 29, 2012 8:34 PM
  • In my opinion thread priority and thread quantum optimization is not related to this issue. The issue is related to configuration and accessing the GP Timer.

    its good news that your driver is functional to a certain level. Lets go step by step to resolve it.

    Are you using the timer in single shot or continues mode? Configure it for single shot and try once. 

    How are you calculating the timer expire period ? If that is having error your timer measurement will be effected.  Use "GetTickCount()" insted when you are running the timer and in IST, then print the difference.

    If SYS_CLK is not working then it might be that it is not enabled for timer 3 in your case. Why dont you try timer 4 once?

    Clock source may not be an issue related to interrupt accuracy in the order of ms for an over flow to occur.

    Is your timer load value correct , just verify it against following eg:

    time_in_ms = 2000; //2ms

    uSourceFreq = (32*1024);

                time_in_ms = ((uSourceFreq * time_in_ms) / 1000);

                //printf("GPT_IOControl: time config %ld \n",time_in_ms);

                time_in_ms = (0xffffffff - time_in_ms);

    OUTREG32((PULONG)&g_pTimerRegs->TLDR, time_in_ms);

    ---- mISBAH


    Senior Design Engineer T.E.S Electroni Solutions (Bangalore-India) www.tes-dst.com email-misbah.khan@tes-dst.com

    • Proposed as answer by Misbah Khan Thursday, May 31, 2012 5:07 AM
    Wednesday, May 30, 2012 6:10 AM
  • IRQ_39 is the interrupt hardware ID - and wouldn't be changable, no.  

    But is it also the priority?   The priority determines the order that interrupts are handled.   If there are other interrupts handled prior to your timer, then it would explain some jitter in the timing.


    Bruce Eitman (eMVP)
    Senior Engineer
    Bruce.Eitman AT Eurotech DOT com
    My BLOG http://geekswithblogs.net/bruceeitman

    Eurotech Inc.
    www.Eurotech.com

    Wednesday, May 30, 2012 12:40 PM
  • I don't know how to change the interrupt priority so I tried to implement Misbah's idea and it works.  The interrupt intervals are all closed to 2ms now.  In my way, I used Compare Interrupt and set a new compare value at each interrupt as below

        #define MSEC_TO_TICK(msec)  (((msec) << 12)/125 + 1)  // msec * 32.768
       
        compareVal = INREG32(&pDevice->pGPT->TCRR) + MSEC_TO_TICK(2);
        OUTREG32(&pDevice->pGPT->TMAR, compareVal);

    I don't see any wrong with this way but for some reason it causes jitter in the timing.  Following Misbah's example, in the initialization I set the Reload Register TLDR and Count Register TCRR to  (0xFFFFFFFF - (32 * 1024 * 2)), enable Overflow Interrupt, and start the timer.  I don't have to load any register in the IST.

    It is working for me now.  Thank you all for your help.


    Luan Le

    • Proposed as answer by Misbah Khan Thursday, May 31, 2012 5:04 AM
    • Unproposed as answer by Misbah Khan Thursday, May 31, 2012 5:07 AM
    • Marked as answer by LuanLe Thursday, August 2, 2012 4:26 PM
    Wednesday, May 30, 2012 10:22 PM
  • Hello again,

    I was a little too quick in my testing.  I thought everything is OK but it is not quite.  However, it is differrent from before.  In my original implementation, I got the timing constantly changing from one interrupt to the next ranging from 2ms to 2.5ms.  In the new implementation with Misbah's idea, the timing is more 2ms but 2.3 and 2.4 are still happening; 2.3ms or greater can be captured at least once every 1/2 second and 2.4ms occurs about once every 4 seconds.

    At this time, I do not think it is anything wrong with the configuration but I don't know what is the next step.

    I am gratefull for any other idea that you can give me.

    Luan


    Luan Le

    Thursday, May 31, 2012 12:17 AM
  • I forget your mail id. can you mail me.


    Senior Design Engineer T.E.S Electroni Solutions (Bangalore-India) www.tes-dst.com email-misbah.khan@tes-dst.com

    Thursday, May 31, 2012 5:38 AM
  • Hi Misbah,

    My email is LNLUAN@yahoo.com.

    Thanks.


    Luan Le

    Thursday, May 31, 2012 2:26 PM