Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
20 years ago

CYGNUM_HAL_RTC_CONSTANTS

Hi!

I am trying to use the RTC constants (in order to calculate time from ticks), and I've seen something strange with them.

In the file

altera\kits\nios2\components\ecos\ecos-2.0\packages\devs\sopc\altera_avalon_timer\v2_0\include\altera_avalon_timer.h

there are the current definitions:

# define ALT_SYS_CLK_PERIOD_MULT ((ALT_SYS_CLK_PERIOD_UNITS !=

ALT_AVALON_TIMER_PERIOD_UNITS_S) ?

((ALT_SYS_CLK_PERIOD_UNITS != ALT_AVALON_TIMER_PERIOD_UNITS_MS) ?

((ALT_SYS_CLK_PERIOD_UNITS != ALT_AVALON_TIMER_PERIOD_UNITS_US ) ?

1

: 1)

: 1000)

: 1000000)

# define ALT_SYS_CLK_PERIOD_DIV ((ALT_SYS_CLK_PERIOD_UNITS ==

ALT_AVALON_TIMER_PERIOD_UNITS_NS ) ? 1000 : 1)

/*

* Having extracted the timer constants, use these to contruct the real time clock constants

* required for eCos.

*/

# define CYGNUM_HAL_RTC_CONSTANTS (1)# define CYGNUM_HAL_RTC_NUMERATOR (1000000000)# define CYGNUM_HAL_RTC_DENOMINATOR (ALT_SYS_CLK_PERIOD * ALT_SYS_CLK_PERIOD_MULT

/ ALT_SYS_CLK_PERIOD_DIV)

From the ecos documentation:

"The NUMERATOR divided by the DENOMINATOR gives the number of nanoseconds per tick"

If the NUMERATOR is 10^9 (fixed), the DENOMINATOR should be the ticks per second. that is, the frequency of the timer we are using.

If we look at the denominator calculation, is ALT_SYS_CLK_PERIOD * ALT_SYS_CLK_PERIOD_MULT / ALT_SYS_CLK_PERIOD_DIV

then, the frequency of a timer should be calculated from FREQUENCY_OF_THE_UNITS / CLOCK_PERIOD. For a 100 Hz timer, or 10 ms period, this would be 1000 ms / 10 = 100 Hz.

If we now look at the calculation done in the altera file, it is ALT_SYS_CLK_PERIOD (10) * ALT_SYS_CLK_PERIOD_MULT (1000) = 10000, which I think is not correct.

Also note than when we have millisecs as units, the ALT_SYS_CLK_PERIOD_MULT definition is correct, but I think is incorrect with all the other units.

So... am I right? Or have I missed anything?

Alex Bueno

3 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I think you're right. It looks like these constants are back to front. I believe that what's given below is more correct (although I'll need to do some further testing to be sure):

    /*
     * Construct some intermediate defines that are used to extract the timer 
     * configuration from the auto-generated system.h header file.
     */
    # define ALT_AVALON_TIMER_PERIOD_UNITS_S      0# define ALT_AVALON_TIMER_PERIOD_UNITS_MS     1# define ALT_AVALON_TIMER_PERIOD_UNITS_US     2# define ALT_AVALON_TIMER_PERIOD_UNITS_CLOCKS 3
    # define __ALT_CLK_BASE(name) name##_BASE# define _ALT_CLK_BASE(name) __ALT_CLK_BASE(name)# define ALT_SYS_CLK_BASE _ALT_CLK_BASE(CYGHWR_HAL_SYSCLK_DEV)
    # define __ALT_CLK_IRQ(name) name##_IRQ# define _ALT_CLK_IRQ(name) __ALT_CLK_IRQ(name)# define ALT_SYS_CLK_IRQ _ALT_CLK_IRQ(CYGHWR_HAL_SYSCLK_DEV)
    # define __ALT_CLK_PERIOD(name) name##_PERIOD# define _ALT_CLK_PERIOD(name) __ALT_CLK_PERIOD(name)# define ALT_SYS_CLK_PERIOD _ALT_CLK_PERIOD(CYGHWR_HAL_SYSCLK_DEV)
    # define __ALT_CLK_PERIOD_UNITS(name) name##_ALT_AVALON_TIMER_PERIOD_UNITS# define _ALT_CLK_PERIOD_UNITS(name) __ALT_CLK_PERIOD_UNITS(name)# define ALT_SYS_CLK_PERIOD_UNITS _ALT_CLK_PERIOD_UNITS(CYGHWR_HAL_SYSCLK_DEV)
    # define __ALT_CLK_FREQ(name) name##_FREQ# define _ALT_CLK_FREQ(name) __ALT_CLK_FREQ(name)# define ALT_SYS_CLK_FREQ _ALT_CLK_FREQ(CYGHWR_HAL_SYSCLK_DEV)
    /*
     * Having extracted the timer constants, use these to contruct the real time clock constants
     * required for eCos.
     */
    # define CYGNUM_HAL_RTC_CONSTANTS (1)
    # define CYGNUM_HAL_RTC_NUMERATOR (1000000 *  ALT_SYS_CLK_PERIOD * 
               ((ALT_SYS_CLK_PERIOD_UNITS == ALT_AVALON_TIMER_PERIOD_UNITS_S ) ? 1000 : 1))# define CYGNUM_HAL_RTC_DENOMINATOR ((ALT_SYS_CLK_PERIOD_UNITS == ALT_AVALON_TIMER_PERIOD_UNITS_US ) ? 1000 : 
                                         (ALT_SYS_CLK_PERIOD_UNITS == ALT_AVALON_TIMER_PERIOD_UNITS_CLOCKS ) ?   
             (ALT_SYS_CLK_FREQ/1000) : 1)# define CYGNUM_HAL_RTC_PERIOD (ALT_SYS_CLK_FREQ / CYGNUM_HAL_RTC_DENOMINATOR / 
                                         ((ALT_SYS_CLK_PERIOD_UNITS != ALT_AVALON_TIMER_PERIOD_UNITS_S ) ? 1000 : 1))
    # define CYGNUM_HAL_INTERRUPT_RTC ALT_SYS_CLK_IRQ

    Thanks for pointing this out!
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hi!

    I've checked your solution, and I think it's OK. Only to comment that in almost all other eCos HALs, the definition of the RTC Constants follow always the same rule: 1000000000 for CYGNUM_HAL_RTC_NUMERATOR, and the frequency of the timer (times per second) for CYGNUM_HAL_RTC_DENOMINATOR. This is helpful because this way you only have to define one constant, and it's pretty straight.

    If we follow this rule, and extracting some of the code of the previous altera_avalon_timer.h and I got this:

    "# define ALT_SYS_CLK_PERIOD_MULT ((ALT_SYS_CLK_PERIOD_UNITS !=

    ALT_AVALON_TIMER_PERIOD_UNITS_S) ?

    ((ALT_SYS_CLK_PERIOD_UNITS != ALT_AVALON_TIMER_PERIOD_UNITS_MS) ?

    ((ALT_SYS_CLK_PERIOD_UNITS != ALT_AVALON_TIMER_PERIOD_UNITS_US ) ?

    1000000000

    : 1000000)

    : 1000)

    : 1)

    # define ALT_SYS_CLK_PERIOD_DIV (ALT_SYS_CLK_PERIOD)

    /*

    * Having extracted the timer constants, use these to contruct the real time clock constants

    * required for eCos.

    */

    # define CYGNUM_HAL_RTC_CONSTANTS (1)# define CYGNUM_HAL_RTC_NUMERATOR (1000000000)# define CYGNUM_HAL_RTC_DENOMINATOR (ALT_SYS_CLK_PERIOD_MULT

    / ALT_SYS_CLK_PERIOD_DIV)

    "

    I think this is working, except for the ALT_AVALON_TIMER_PERIOD_UNITS_CLOCKS case, which I haven't considered.

    Hope this will be in the next nios altera package.

    Thanx

    Alex