- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# /space/home/slher/rel/Beken/v6_4_5/macsw/plf/refip/src/driver/time/nx_time.c

Go to the documentation of this file.

    00001
    00019 #include "rwnx_config.h"
    00020
    00021 #if NX_FULLY_HOSTED
    00022
    00023 #include "nx_time.h"
    00024 #include "reg_mac_core.h"
    00025
    00027 static uint32_t epoch_sec;
    00029 static uint32_t epoch_usec;
    00030
    00031 void time_init(uint32_t sec, uint32_t usec)
    00032 {
    00033     epoch_sec = sec;
    00034     epoch_usec = usec;
    00035 }
    00036
    00047 __INLINE void read_time(uint32_t *msb, uint32_t *lsb)
    00048 {
    00049     uint32_t _msb, _msb_r, _lsb;
    00050     _msb = nxmac_monotonic_counter_2_hi_get() & 0xffff;
    00051     _lsb = nxmac_monotonic_counter_2_lo_get();
    00052     _msb_r = nxmac_monotonic_counter_2_hi_get() & 0xffff;
    00053
    00054     if (_msb_r != _msb)
    00055     {
    00056         _lsb = nxmac_monotonic_counter_2_lo_get();
    00057     }
    00058     *msb = _msb_r;
    00059     *lsb = _lsb;
    00060 }
    00061
    00062 int get_time(enum time_origin_t origin, uint32_t *sec, uint32_t *usec)
    00063 {
    00064     uint32_t msb, lsb, _sec, _usec, tmp, fact;
    00065
    00066     if (origin > SINCE_EPOCH)
    00067         return -1;
    00068
    00069     read_time(&msb, &lsb);
    00070
    00071     /* Replace uint64_t / 1000000 (uint48_t in practice)
    00072        by 3 ~fmul (mul + shift).
    00073        Yes this is more complicated but also 20 times faster on cpu without div
    00074        instruction.
    00075        48bits time value is divided in 4 parts 0xAABBCCCCDDDD
    00076        First two parts (A ,B) are only 8bits to allow more bits in the factor
    00077        (merging this two parts with a 16 bits factor doesn't provide enough precision).
    00078        For the third part (C) a factor on 16bits is enough so part is also 16bits.
    00079        Fourth part (D) is always < 1000000 so no need to divide it.
    00080        factor = 0x8637bd = 1 / 1000000 in Q43 = ((1<<43) / 1000000) (truncated on 24bits)
    00081      */
    00082     fact = 0x8637bd;
    00083     tmp = (msb >> 8) * fact;
    00084     _sec = (tmp >> 3);
    00085     tmp = (msb & 0xff) * fact;
    00086     _sec += (tmp >> 11);
    00087     fact >>= 8;
    00088     tmp = (lsb >> 16) * fact;
    00089     _sec += (tmp >> 19);
    00090     _usec = lsb - (_sec * 1000000);
    00091
    00092     if (origin == SINCE_EPOCH)
    00093     {
    00094         _sec += epoch_sec;
    00095         _usec += epoch_usec;
    00096
    00097     }
    00098
    00099     /* Previous computation ensure that loop won't run more than 2 times */
    00100     while (_usec > 1000000)
    00101     {
    00102         _usec -= 1000000;
    00103         _sec ++;
    00104     }
    00105
    00106     *sec = _sec;
    00107     *usec = _usec;
    00108
    00109     return 0;
    00110 }
    00111
    00112 int get_time_us(enum time_origin_t origin, uint64_t *usec)
    00113 {
    00114     uint32_t msb, lsb;
    00115     uint64_t val;
    00116
    00117     if (origin > SINCE_EPOCH)
    00118         return -1;
    00119
    00120     read_time(&msb, &lsb);
    00121     val = ((uint64_t)msb << 32) + (uint64_t)lsb;
    00122
    00123     if (origin == SINCE_EPOCH)
    00124     {
    00125         val += (uint64_t)epoch_usec;
    00126         val += (uint64_t)(epoch_sec * 1000000);
    00127     }
    00128
    00129     *usec = val;
    00130     return 0;
    00131 }
    00132
    00133 #endif /* NX_FULLY_HOSTED */
    00134