📄 clock.cxx
字号:
// The alarms are in ascending trigger order. When we // find an alarm that is later than us, we go in front of // it. if( list_alarm->trigger > alarm->trigger ) break; else alarm_list_ptr = &list_alarm->next; }#endif // Insert the new alarm at *alarm_list_ptr alarm->next = *alarm_list_ptr; *alarm_list_ptr = alarm; Cyg_Scheduler::unlock(); }}// -------------------------------------------------------------------------// Remove an alarm from this countervoid Cyg_Counter::rem_alarm( Cyg_Alarm *alarm ){ CYG_REPORT_FUNCTION(); CYG_ASSERTCLASS( this, "Bad counter object" ); CYG_ASSERTCLASS( alarm, "Bad alarm passed" ); Cyg_Alarm **alarm_list_ptr; // pointer to list#if defined(CYGIMP_KERNEL_COUNTERS_SINGLE_LIST) alarm_list_ptr = &alarm_list;#elif defined(CYGIMP_KERNEL_COUNTERS_MULTI_LIST) alarm_list_ptr = &(alarm_list[ ((alarm->trigger+increment-1)/increment) % CYGNUM_KERNEL_COUNTERS_MULTI_LIST_SIZE ] ); #else#error "No CYGIMP_KERNEL_COUNTERS_x_LIST config"#endif // Now that we have the list pointer, we can use common code for // both list organizations. Cyg_Scheduler::lock(); CYG_INSTRUMENT_ALARM( REM, this, alarm ); while( *alarm_list_ptr != NULL ) { Cyg_Alarm *list_alarm = *alarm_list_ptr; CYG_ASSERTCLASS(list_alarm, "Bad alarm in counter list" ); if( list_alarm == alarm ) break; else alarm_list_ptr = &list_alarm->next; } // If the alarm was found, remove it from the list. if( *alarm_list_ptr != NULL ) { *alarm_list_ptr = alarm->next; alarm->enabled = false; } Cyg_Scheduler::unlock(); }//==========================================================================// Constructor for clock objectCyg_Clock::Cyg_Clock( cyg_resolution res ){ CYG_REPORT_FUNCTION(); resolution = res;}// -------------------------------------------------------------------------// Destructor for Clock objectsCyg_Clock::~Cyg_Clock(){ CYG_REPORT_FUNCTION();}// -------------------------------------------------------------------------// #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//==========================================================================// 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;}#ifdef HAL_CLOCK_LATENCYcyg_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// -------------------------------------------------------------------------cyg_uint32 Cyg_RealTimeClock::isr(cyg_vector vector, CYG_ADDRWORD data){// CYG_REPORT_FUNCTION();#ifdef 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); return Cyg_Interrupt::CALL_DSR;}// -------------------------------------------------------------------------void Cyg_RealTimeClock::dsr(cyg_vector vector, cyg_ucount32 count, CYG_ADDRWORD data){// CYG_REPORT_FUNCTION(); 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 + -