Answered by:
Hardware Timer

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.comFriday, 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.comFriday, 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;
}
--- MisbahSenior 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.comWednesday, 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