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.

How to read the global timer in OMAP 4430?

Other Parts Discussed in Thread: 4430

I am trying to read the global system timer for Cortex A9, OMAP 4430 architecture (pandaboard rev A6). I work directly on the board with Debian GNU/Linux 7 (wheezy) and 3.9.11-x5 kernel version.

In general, my aim is to read values of the main system counter, which Linux system call invokes (e.g. clock_gettime()). I know that there are several timers in OMAP 4430 and I have to figure out which exact timer and register is used by Linux system call. I used this OMAP 4430 TRM where is said that register of "global timer" has this base address 0x48240600 with offset 0x200. Is it correct address for system timer? Now when I try to map and read this addresses, I always get 0 and it seems to me that something is wrong. I also have already tried to maped and read each of 11 GPtimers registers and I received either zero or bus error or like in case of GPTimer1 just random constant value which is not incrementing.

Earlier I could managed the same issue with beaglebone board (AM335x architecture, Cortex A8). I concluded that this "main" system timer addresses to 24MHz clock and DMTimer2 register. As I understood, the Linux kernel already contains dmtimer driver, which allows using system time through accessing to this DMTimer2 register. I maped its address 0x48040000 with offset of 0x3c and simply get ticks value. So I hoped that the idea of reading the timer would be the same for Cortex A9, but so far I fail. That's way I am asking, may be there are some additional tricks of reading this register for OMAP 4430?

To be more precise, this is the way how I read counter:

#define MAP_SIZE 4096UL
#define MAP_MASK (MAP_SIZE - 1)
volatile unsigned char* gpt_regs;
constexpr uint32_t GPTimer = 0x48240600;
constexpr uint32_t offset = 0x200;
int32_t fd;
if ( (fd=open("/dev/mem", O_RDWR|O_SYNC) ) < 0)
{
perror("open");
exit(-1);
}
gpt_regs = (unsigned char*) mmap(0, MAP_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPTimer & ~MAP_MASK);
uint32_t counter1 = * (int32_t*) ( gpt_regs + offset);

I will appreciate any help.

  • Hello Irina,

    I confirm that when read register at 0x4824 0600 in Cortex A9 MPU TIMER, it returns 0x00000000. This address corresponds to lower 32-bit timer counter.

    Address 0x4824 0604 corresponds to the upper 32-bit timer counter, it returns omapconf read 0x48240604 - 0x000785F8

    More information you can find in http://infocenter.arm.com/help/index.jsp Cortex-A9 MPCore Technical Reference Manual (Global timer, private timers, and watchdog registers > Global timer registers > Global Timer Counter Registers, 0x00 and 0x04)

    See the steps for modifying or reading this register:

    To modify the register proceed as follows:

    1. Clear the timer enable bit in the Global Timer Control Register

    2. Write the lower 32-bit timer counter register

    3. Write the upper 32-bit timer counter register

    4. Set the timer enable bit.

    To get the value from the Global Timer Counter register proceed as follows:

    1. Read the upper 32-bit timer counter register

    2. Read the lower 32-bit timer counter register

    3. Read the upper 32-bit timer counter register again. If the value is different to the 32-bit upper value read previously, go back to step 2. Otherwise the 64-bit timer counter value is correct.

    To enable this Timer you must set bit 0 Timer enable in Global Timer Control Register. - Global timer, private timers, and watchdog registers > Global timer registers > Global Timer Control Register

    Please read address 0x48240608 - 0x00000005

    Bit 0 = 0x1 Timer is enabled and the counter increments normally

    You can use OMAPCONF tool to check register settings - https://github.com/omapconf/omapconf/wiki

    Best regards,

    Yanko

  • Hello Yanko,

    Thank you for your answer and sorry for the late respond.

    I accepted it, because it was really helpful and this OMAPCONF tool is great! Thanks!
    However looking again through the specification I found the following phrase:

    "The 32-kHz sync timer, which is reset only at power up, provides the operating system (OS) with a stable timing source that stores the relative time since the last power cycle of the product. Finally, 11 GP timers, which are useful simply as basic timers, are included to generate time-stamp-based interrupts to the system software or to use as a source of pulse-width modulation (PWM) signals."

    and indeed I can read the address of the 32-kHz timer without any problem. Btw, OMAPCONF also provides an option "to read 32kHZ register." So I conclude that for Linux system call none of GP-timer registers is used, but this 32-kHz timer.

    Best Regards,

    Irina

  • Hello Irina,

    In addition to your conclusion I suggest to see following link:

    https://gitorious.org/omap-audio/linux-audio/commit/1fe97c8f6a1de67a5f56e029a818903d5bed8017

    Current OMAP code supports couple of clocksource options based on compilation flag (CONFIG_OMAP_32K_TIMER). The 32KHz sync-timer and 
    a GPTIMER which can run on 32KHz or system clock (e.g 38.4 MHz). So there can be 3 options - 1. 32KHz sync-timer 2. Sys_clock based (e.g 13/19.2/26/38.4 MHz) gptimer 3. 32KHz based GPTIMER.

    http://lists.infradead.org/pipermail/linux-arm-kernel/2012-May/097532.html

    Best regards,
    Yanko