⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 clock.cxx

📁 eCos1.31版
💻 CXX
📖 第 1 页 / 共 2 页
字号:
#ifdef CYGDBG_USE_ASSERTSbool Cyg_Clock::check_this( cyg_assert_class_zeal zeal) const{    // check that we have a non-NULL pointer first    if( this == NULL ) return false;        switch( zeal )    {    case cyg_system_test:    case cyg_extreme:    case cyg_thorough:    case cyg_quick:    case cyg_trivial:    case cyg_none:    default:        break;    };    return true;}#endif// -------------------------------------------------------------------------// // Clock Converters: split a rational into 4 factors to try to prevent// overflow whilst retaining reasonable accuracy.// // typically we get numbers like 1,000,000 for ns_per and// 100 and 1,000,000,000 for the dividend and divisor.// So we want answers like 1/10 and 10/1 out of these routines.static void construct_converter( Cyg_Clock::converter *pcc,                                        cyg_uint64 m1, cyg_uint64 d1,                                        cyg_uint64 m2, cyg_uint64 d2 ){    cyg_uint64 upper, lower;    unsigned int i;    static cyg_uint16 primes[] = {        3,5,7,11,13,17,19,23,29,31,37,41,43,47,        53,59,61,67,71,73,79,83,89,97,        101,103,107,109,113,127,131,137,139,149,        151,157,163,167,173,179,181,191,193,197,199,        239,                            // for 1,111,111        541,                            // for 10,101,011        1667,                           // for 8,333,333    };    int rounding = 0;    // Here we assume that our workings will fit in a 64; the point is to    // allow calculations with a number of ticks that may be large.    upper = m1 * m2;    lower = d1 * d2;#ifdef CYGDBG_USE_ASSERTS    cyg_uint64 save_upper = upper;    cyg_uint64 save_lower = lower;#endif retry_rounding:    // First strip out common powers of 2    while ( (0 == (1 & upper)) && ( 0 == (1 & lower)) ) {        upper >>= 1;        lower >>= 1;    }    // then common factors - use lazy table above    for ( i = 0 ; i < (sizeof( primes )/sizeof( primes[0] )); i++ ) {        cyg_uint64 j, k, p = (cyg_uint64)(primes[i]);        j = upper / p;        while ( j * p == upper ) {            k = lower / p;            if ( k * p != lower )                break;            upper = j;            lower = k;            j = upper / p;        }    }    m1 = upper;    d1 = lower;    m2 = 1;    d2 = 1;    if ( m1 > 0x10000 ) {        // only bother if there are more than 16 bits consumed here        // now move powers of 2 from d1 to d2        // keeping them the same order of magnitude        while ( (0 == (1 & d1)) && (d2 < d1) ) {            d1 >>= 1;            d2 <<= 1;        }        // and factors from the table - go too far, if anything        int cont = (d2 < d1);        for ( i = 0 ; cont && (i < (sizeof( primes )/sizeof( primes[0] ))); i++ ) {            cyg_uint64 k, p = (cyg_uint64)(primes[i]);            k = d1 / p;            while ( cont && ((k * p) == d1) ) {                // we can extract a prime                d1 = k;                d2 *= p;                k = d1 / p;                cont = (d2 < d1);            }        }                // move powers of 2 from m1 to m2 so long as we do not go less than d1        while ( (0 == (1 & m1)) && (m2 < m1) && (m1 > (d1 << 5)) ) {            m1 >>= 1;            m2 <<= 1;            if ( m1 < 0x10000 )                break;        }                // and factors from the table - ensure m1 stays well larger than d1        cont = ((m2 < m1) && (m1 > (d1 << 4)) && (m1 > 0x10000));        for ( i = 0 ; cont && (i < (sizeof( primes )/sizeof( primes[0] ))); i++ ) {            cyg_uint64 k, p = (cyg_uint64)(primes[i]);            k = m1 / p;            cont = cont && (k > (d1 << 4) && (k > 0x10000));            while ( cont && ((k * p) == m1) ) {                // we can extract a prime                m1 = k;                m2 *= p;                k = m1 / p; // examine k for getting too small                cont = ((m2 < m1) && (k > (d1 << 4)) && (k > 0x10000));            }        }        // if, after all that, m1 odd and unchanged, and too large,        // decrement it just the once and try again: then try it        // incremented once.        if ( (m1 & 1) && (m1 == upper) && (m1 > 0x10000) && (rounding < 2) ) {            CYG_ASSERT( 1 == m2, "m2 should be 1 to try rounding" );            m1--;            upper = m1;            rounding++;            goto retry_rounding;        }        // likewise for d1 - each of the pair can be odd only once each        if ( (d1 & 1) && (d1 == lower) && (d1 > 0x10000) && (rounding < 2) ) {            CYG_ASSERT( 1 == d2, "d2 should be 1 to try rounding" );            d1--;            lower = d1;            rounding++;            goto retry_rounding;        }    }    CYG_ASSERT( 0 != m1, "m1 zero" );    CYG_ASSERT( 0 != m2, "m2 zero" );    CYG_ASSERT( 0 != d1, "d1 zero" );    CYG_ASSERT( 0 != d2, "d2 zero" );    CYG_ASSERT( rounding || save_upper/save_lower == (m1 * m2)/(d1 * d2),                "Unequal in forwards direction" );    CYG_ASSERT( rounding || save_lower/save_upper == (d1 * d2)/(m1 * m2),                "Unequal in reverse direction" );    pcc->mul1 = m1;    pcc->div1 = d1;    pcc->mul2 = m2;    pcc->div2 = d2;}// other to clocks is (other * ns_per * dividend / divisor)void Cyg_Clock::get_other_to_clock_converter(    cyg_uint64 ns_per_other_tick,    struct converter *pcc ){    construct_converter( pcc,                         ns_per_other_tick, 1,                         resolution.divisor, resolution.dividend );}// clocks to other is (ticks * divisor / dividend / ns_per)void Cyg_Clock::get_clock_to_other_converter(    cyg_uint64 ns_per_other_tick,    struct converter *pcc ){    construct_converter( pcc,                         1, ns_per_other_tick,                         resolution.dividend, resolution.divisor );}//==========================================================================// Constructor for alarm objectCyg_Alarm::Cyg_Alarm(        Cyg_Counter     *c,             // Attached to this counter        cyg_alarm_fn    *a,             // Call-back function        CYG_ADDRWORD    d               // Call-back data        ){    CYG_REPORT_FUNCTION();    counter     = c;    alarm       = a;    data        = d;    trigger     = 0;    interval    = 0;    enabled     = false;#if defined(CYGIMP_KERNEL_COUNTERS_SINGLE_LIST) || defined(CYGIMP_KERNEL_COUNTERS_MULTI_LIST)    next        = NULL;#endif    }Cyg_Alarm::Cyg_Alarm(){}// -------------------------------------------------------------------------// DestructorCyg_Alarm::~Cyg_Alarm(){    CYG_REPORT_FUNCTION();    disable();}// -------------------------------------------------------------------------// #ifdef CYGDBG_USE_ASSERTSbool Cyg_Alarm::check_this( cyg_assert_class_zeal zeal) const{    // check that we have a non-NULL pointer first    if( this == NULL ) return false;        switch( zeal )    {    case cyg_system_test:    case cyg_extreme:    case cyg_thorough:        if( trigger != 0 && !enabled ) return false;    case cyg_quick:    case cyg_trivial:    case cyg_none:    default:        break;    };    return true;}#endif// -------------------------------------------------------------------------// Initialize Alarm and enablevoid Cyg_Alarm::initialize(                    cyg_tick_count    t,                // Absolute trigger time    cyg_tick_count    i                 // Relative retrigger interval    ){    CYG_REPORT_FUNCTION();    // If already enabled, remove from counter        if( enabled ) counter->rem_alarm(this);    CYG_INSTRUMENT_ALARM( INIT,     this, 0 );    CYG_INSTRUMENT_ALARM( TRIGGER,                          ((cyg_uint32 *)&t)[0],                          ((cyg_uint32 *)&t)[1] );    CYG_INSTRUMENT_ALARM( INTERVAL,                          ((cyg_uint32 *)&i)[0],                          ((cyg_uint32 *)&i)[1] );     trigger = t;    interval = i;    counter->add_alarm(this);}// -------------------------------------------------------------------------// Synchronize with a past alarm stream that had been disabled,// bring past times into synch, and the like.voidCyg_Alarm::synchronize( void ){    if( interval != 0 ) {        // This expression sets the trigger to the next whole interval        // at or after the current time. This means that alarms will        // continue at the same intervals as if they had never been        // disabled. The alternative would be to just set trigger to        // (counter->counter + interval), but this is less satisfying        // than preserving the original intervals. That behaviour can        // always be obtained by using initialize() rather than        // enable(), while the current behaviour would be more        // difficult to achieve that way.        cyg_tick_count d;        d = counter->current_value() + interval - trigger;        if ( d > interval ) {            // then trigger was in the past, so resynchronize            trigger += interval * ((d - 1) / interval );        }        // otherwise, we were just set up, so no worries.    }}// -------------------------------------------------------------------------// Ensure alarm enabledvoid Cyg_Alarm::enable(){    if( !enabled )    {        // ensure the alarm time is in our future:        synchronize();        enabled = true;        counter->add_alarm(this);    }}//==========================================================================// System clock object#ifdef CYGVAR_KERNEL_COUNTERS_CLOCKclass Cyg_RealTimeClock    : public Cyg_Clock{    Cyg_Interrupt       interrupt;    static cyg_uint32 isr(cyg_vector vector, CYG_ADDRWORD data);    static void dsr(cyg_vector vector, cyg_ucount32 count, CYG_ADDRWORD data);    Cyg_RealTimeClock();    static Cyg_RealTimeClock rtc;};Cyg_Clock::cyg_resolution rtc_resolution = CYGNUM_KERNEL_COUNTERS_RTC_RESOLUTION;//Cyg_RealTimeClock Cyg_RealTimeClock::rtc __attribute__((init_priority (1)));Cyg_RealTimeClock Cyg_RealTimeClock::rtc CYG_INIT_PRIORITY( CLOCK );// -------------------------------------------------------------------------Cyg_RealTimeClock::Cyg_RealTimeClock()    : Cyg_Clock(rtc_resolution),      interrupt(CYGNUM_HAL_INTERRUPT_RTC, 1, (CYG_ADDRWORD)this, isr, dsr){    CYG_REPORT_FUNCTION();    HAL_CLOCK_INITIALIZE( CYGNUM_KERNEL_COUNTERS_RTC_PERIOD );        interrupt.attach();    interrupt.unmask_interrupt(CYGNUM_HAL_INTERRUPT_RTC);    Cyg_Clock::real_time_clock = this;}#if defined(CYGVAR_KERNEL_COUNTERS_CLOCK_LATENCY) && defined(HAL_CLOCK_LATENCY)cyg_tick_count total_clock_latency, total_clock_interrupts;cyg_int32 min_clock_latency = 0x7FFFFFFF;cyg_int32 max_clock_latency = 0;bool measure_clock_latency = false;#endif#if defined(CYGVAR_KERNEL_COUNTERS_CLOCK_DSR_LATENCY)cyg_tick_count total_clock_dsr_latency, total_clock_dsr_calls;cyg_int32 min_clock_dsr_latency = 0x7FFFFFFF;cyg_int32 max_clock_dsr_latency = 0;cyg_uint32 clock_dsr_start = 0;#endif// -------------------------------------------------------------------------cyg_uint32 Cyg_RealTimeClock::isr(cyg_vector vector, CYG_ADDRWORD data){//    CYG_REPORT_FUNCTION();#if defined(CYGVAR_KERNEL_COUNTERS_CLOCK_LATENCY) && defined(HAL_CLOCK_LATENCY)    if (measure_clock_latency) {        cyg_int32 delta;        HAL_CLOCK_LATENCY(&delta);        // Note: Ignore a latency of 0 when finding min_clock_latency.        if (delta > 0) {            // Valid delta measured            total_clock_latency += delta;            total_clock_interrupts++;            if (min_clock_latency > delta) min_clock_latency = delta;            if (max_clock_latency < delta) max_clock_latency = delta;        }    }#endif    CYG_INSTRUMENT_CLOCK( ISR, 0, 0);    HAL_CLOCK_RESET( CYGNUM_HAL_INTERRUPT_RTC, CYGNUM_KERNEL_COUNTERS_RTC_PERIOD );    Cyg_Interrupt::acknowledge_interrupt(CYGNUM_HAL_INTERRUPT_RTC);#if defined(CYGVAR_KERNEL_COUNTERS_CLOCK_DSR_LATENCY)    HAL_CLOCK_READ(&clock_dsr_start);#endif        return Cyg_Interrupt::CALL_DSR|Cyg_Interrupt::HANDLED;}// -------------------------------------------------------------------------void Cyg_RealTimeClock::dsr(cyg_vector vector, cyg_ucount32 count, CYG_ADDRWORD data){//    CYG_REPORT_FUNCTION();#if defined(CYGVAR_KERNEL_COUNTERS_CLOCK_DSR_LATENCY)    if (measure_clock_latency) {        cyg_uint32 delta;        HAL_CLOCK_READ(&delta);        delta -= clock_dsr_start;        // Note: Ignore a latency of <= 0 when finding min_clock_latency.        if (delta > 0 ) {            // Valid delta measured            total_clock_dsr_latency += delta;            total_clock_dsr_calls++;            if (min_clock_dsr_latency > delta) min_clock_dsr_latency = delta;            if (max_clock_dsr_latency < delta) max_clock_dsr_latency = delta;        }    }#endif        Cyg_RealTimeClock *rtc = (Cyg_RealTimeClock *)data;    CYG_INSTRUMENT_CLOCK( TICK_START,                          rtc->current_value_lo(),                          rtc->current_value_hi());                              rtc->tick( count );#ifdef CYGSEM_KERNEL_SCHED_TIMESLICE#if    0 == CYG_SCHED_UNIQUE_PRIORITIES    // If timeslicing is enabled, call the scheduler to    // handle it. But not if we have unique priorities.        Cyg_Scheduler::scheduler.timeslice();#endif#endif    CYG_INSTRUMENT_CLOCK( TICK_END,                          rtc->current_value_lo(),                          rtc->current_value_hi());    }#endif// -------------------------------------------------------------------------// EOF common/clock.cxx

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -