|
DataMuseum.dkPresents historical artifacts from the history of: Rational R1000/400 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Rational R1000/400 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 17408 (0x4400) Types: Ada Source Notes: 03_class, FILE, R1k_Segment, e3_tag, package body V_Timer_Support, seg_057f7c
└─⟦8527c1e9b⟧ Bits:30000544 8mm tape, Rational 1000, Arrival backup of disks in PAM's R1000 └─⟦cfc2e13cd⟧ »Space Info Vol 2« └─⟦this⟧
with Machine_Code; with System; use System; with Unchecked_Conversion; with V_Krn_Conf_I; use V_Krn_Conf_I; with Krn_Defs; with V_Bits; with V_I_Types; with V_I_Timeop; with V_Cpu_Conf; with Link_Block; with Grp_Table; with Machine_Types; with V_Ada_Info; package body V_Timer_Support is use V_I_Types; use V_I_Timeop; use Machine_Types; -- COUNT_DOWN.TIM (MUST BE CONFIGURED FOR BOARD) -- -- This package body contains the timer support subprograms implementing -- the single count down timer model. A count down timer is setup to -- generate a timer interrupt after a variable number of seconds (duration -- units). A single timer is used for both maintaining the current time -- and scheduling alarms. -- -- Refer to the following package bodies in BOARD_SUPPORT -- directory for templates of support routines implemented using different -- timer models: -- STUB.TIM - null, stubbed routines -- PERIODIC.TIM - uses single timer that interrupts at a fixed -- periodic rate -- -- To use a different model, simply delete the source for this -- V_TIMER_SUPPORT package body from this file and include one of the -- above files. One_Msec : constant Duration := 0.001; Next_Interrupt_Time : Time_T := (Day => 0, Sec => 0.0); -- Time of next timer interrupt Alarm_Flag : Boolean := False; -- Set if an alarm has been scheduled Next_Alarm_Time : Time_T := (Day => 0, Sec => 0.0); -- Time of next alarm -- ************************************************************* -- -- THE FOLLOWING TYPES AND CONSTANTS ARE TO BE CONFIGURED -- FOR YOUR BOARD -- -- ************************************************************* --&&&&&&&&&&&& SUPPRIMER Counter_T du commentaire &&&&&&&&&& -- type Counter_T is range 0 .. 255; -- for Counter_T'Size use 8; --&&&&&&&&&&&& SUPPRIMER Counter_T du commentaire &&&&&&&&&& -- Board specific counter type. -- ONLY UPDATE the range and size. Counts_Per_Msec : constant := 12; -- machine 2,4576Mhz and Timer in delay mode = 200 prescaler -- This is the number of ticks per millisecond Max_Count : constant := 255; -- This is the maximum count that the timer can be set to -- The corresponding maximum duration. Where, Max_Duration : constant := (Max_Count / Counts_Per_Msec) * 0.001; -- Note: maximum duration allowed is 12 hours. Min_Count : constant := 1; -- This represents the minimum count between timer interrupts -- The corresponding minimum duration. Where, Min_Duration : constant := (Min_Count / Counts_Per_Msec) * 0.001; -- ************************************************************* -- -- THE FOLLOWING SUBPROGRAMS ARE TO BE CONFIGURED FOR YOUR BOARD -- -- ************************************************************* function Get_Interrupt_Vector_Number return System.Address is begin return System.To_Address (2#1000_1101#); end Get_Interrupt_Vector_Number; procedure Init_Timer is use V_Bits; -- Initializes the timer device hardware registers -- MC68155 PICU Register Register_R0 : Byte; -- pointer registers CR1/CR6 Register_R1 : Byte; -- Register_R3 : Byte; -- local interrupt mask register Register_R5 : Byte; -- system bus interrupt mask register for Register_R0 use at System.To_Address (16#0301_0020#); for Register_R1 use at System.To_Address (16#0301_0022#); for Register_R3 use at System.To_Address (16#0301_0026#); for Register_R5 use at System.To_Address (16#0301_002A#); -- MC68901 Timer register Register_Vr : Byte; -- Vector register Register_Iera : Byte; -- Interrupt enable register A Register_Imra : Byte; -- Interrupt mask register A for Register_Vr use at System.To_Address (16#0301_000B#); for Register_Iera use at System.To_Address (16#0301_0003#); for Register_Imra use at System.To_Address (16#0301_0009#); begin -- Interrupt handler configuration Register_R3 := Machine_Types.Byte (Bit_Or (Machine_Types.Byte'Pos (Register_R3), 2#0000_0100#)); Register_R5 := Machine_Types.Byte (Bit_Or (Machine_Types.Byte'Pos (Register_R5), 2#0000_0000#)); Register_R0 := 2#0000_0010#; Register_R1 := 2#0000_0000#; -- Interrupt Timer configuration Register_Vr := 2#1000_0000#; -- define the most signicant bits of IVR Register_Iera := Machine_Types.Byte (Bit_Or (Machine_Types.Byte'Pos (Register_Iera), 2#0010_0000#)); Register_Imra := Machine_Types.Byte (Bit_Or (Machine_Types.Byte'Pos (Register_Imra), 2#0010_0000#)); end Init_Timer; procedure Set_Timer (Count : Counter_T) is -- Sets the timer to generate an interrupt after count ticks Register_Tadr : Byte; -- Timer A data register Register_Tacr : Byte; -- Timer A control register for Register_Tadr use at System.To_Address (16#0301_000F#); for Register_Tacr use at System.To_Address (16#0301_000C#); begin Register_Tacr := 2#0000_0000#; -- Stop timer Register_Tadr := Byte (Count); -- load the count Register_Tacr := 2#0000_0111#; -- restore the timer end Set_Timer; procedure Read_Timer (Count : out Counter_T) is -- Reads the remaining timer count until the next interrupt Register_Tadr : Byte; -- Timer A data register for Register_Tadr use at System.To_Address (16#0301_000F#); begin Count := Counter_T (Register_Tadr); end Read_Timer; procedure Clear_Timer_Interrupt is -- Clears current timer interrupt Register_Iera : Byte; -- Interrupt enable register A Register_Tacr : Byte; -- Timer A control register for Register_Tacr use at System.To_Address (16#0301_000C#); for Register_Iera use at System.To_Address (16#0301_0003#); use V_Bits; begin Register_Tacr := 2#0000_0000#; -- Stop timer Register_Iera := Machine_Types.Byte (Bit_And (Machine_Types.Byte'Pos (Register_Iera), 2#1101_1111#)); Register_Iera := Machine_Types.Byte (Bit_Or (Machine_Types.Byte'Pos (Register_Iera), 2#0010_0000#)); end Clear_Timer_Interrupt; pragma Inline_Only (Clear_Timer_Interrupt); -- ************************************************************* -- -- END OF BOARD SPECIFIC CONFIGURATION -- -- ************************************************************* function Duration_To_Count (Sec : Duration) return Counter_T is -- Converts duration seconds into timer tick counts begin return Counter_T (Sec / One_Msec) * Counts_Per_Msec; end Duration_To_Count; pragma Inline_Only (Duration_To_Count); procedure Init is -- Resets the clock's current time. Initializes the timer device. -- This procedure is called during kernel startup. begin Next_Interrupt_Time := (Day => 0, Sec => Max_Duration); Alarm_Flag := False; -- Initialize timer hardware registers Init_Timer; -- Get timer counting down Set_Timer (Max_Count); end Init; procedure Set_Time (Day : Day_T; Sec : Duration; Timer_Support_Arg : Address := No_Addr) is -- Resets the clock's current time with the input parameter. -- Cancels active alarm which will be rescheduled later. Intr_Status : V_Krn_Conf_I.Intr_Status_T; begin -- Disable interrupts to inhibit potential interaction with -- timer interrupt handler V_Krn_Conf_I.Interrupts_Disable (Intr_Status); Next_Interrupt_Time := (Day => Day, Sec => Sec) + (Day => 0, Sec => Max_Duration); Alarm_Flag := False; -- Get timer counting down Set_Timer (Max_Count); V_Krn_Conf_I.Interrupts_Restore (Intr_Status); end Set_Time; procedure Get_Current_Time (Day : out Day_T; Sec : out Duration) is -- Gets the clock's current time. The returned time is -- normalized so that its seconds component is less than a day. -- This function is called both by the kernel for -- calculating a time to pass to schedule_alarm and by -- CALENDAR package which traps to kernel to get current time. Count : Counter_T; Intr_Status : V_Krn_Conf_I.Intr_Status_T; Time : Time_T; begin -- Disable interrupts to inhibit potential interaction with -- timer interrupt handler V_Krn_Conf_I.Interrupts_Disable (Intr_Status); -- Current time is the time at the next interrupt minus -- the time represented by the remaining ticks to be counted down Read_Timer (Count); Time := Next_Interrupt_Time - (Day => 0, Sec => Integer (Count / Counts_Per_Msec) * One_Msec); V_Krn_Conf_I.Interrupts_Restore (Intr_Status); Day := Time.Day; Sec := Time.Sec; end Get_Current_Time; procedure Schedule_Alarm (Alarm_Day : Day_T; Alarm_Sec : Duration) is -- Schedules an alarm to be posted some time in the future. -- -- This procedure is called by the kernel whenever a future timing event -- must occur. The kernel passes in an absolute (not relative) time in the -- future when an alarm should occur. The kernel computes this time by -- adding some amount onto the value returned by GET_CURRENT_TIME. -- Examples are the expiration of a delay or the end of the time slice. -- -- SCHEDULE_ALARM is always called with the time of the earliest alarm. -- -- When the current time reaches alarm_time, -- V_KRN_CONF_I.POST_ALARM should be called to post the alarm. Intr_Status : V_Krn_Conf_I.Intr_Status_T; Alarm : Time_T; Current_Time : Time_T; Next_Minus_Min : Time_T; Current_Plus_Min : Time_T; Alarm_Time : Time_T := (Day => Alarm_Day, Sec => Alarm_Sec); begin -- Disable interrupts to inhibit potential interaction with -- timer interrupt handler V_Krn_Conf_I.Interrupts_Disable (Intr_Status); Next_Minus_Min := Next_Interrupt_Time - (Day => 0, Sec => Min_Duration); if Alarm_Time <= Next_Minus_Min then Get_Current_Time (Current_Time.Day, Current_Time.Sec); Current_Plus_Min := Current_Time + (Day => 0, Sec => Min_Duration); -- reset timer for new interval inserted before current -- interval would expire if Alarm_Time < Current_Plus_Min then Alarm := Current_Plus_Min; else Alarm := Alarm_Time; end if; if Alarm < Next_Minus_Min then Next_Interrupt_Time := Alarm; Set_Timer (Duration_To_Count ("-" (Alarm, Current_Time).Sec)); end if; end if; Alarm_Flag := True; Next_Alarm_Time := Alarm_Time; V_Krn_Conf_I.Interrupts_Restore (Intr_Status); end Schedule_Alarm; -- Cancels a previously scheduled alarm. procedure Cancel_Alarm is begin Alarm_Flag := False; end Cancel_Alarm; procedure Process_Timer_Interrupt is -- Processes the timer interrupt by advancing the current time and -- checking if the time for the next alarm has been reached. Delta_Duration : Duration := Max_Duration; Delta_Count : Counter_T := Max_Count; Delta_Alarm : Time_T; Intr_Status : V_Krn_Conf_I.Intr_Status_T; Post_Flag : Boolean := False; begin -- Clears current timer interrupt Clear_Timer_Interrupt; -- Disable interrupts to inhibit potential interaction with -- other handlers that may want to read the current time V_Krn_Conf_I.Interrupts_Disable (Intr_Status); if Alarm_Flag then if Next_Alarm_Time <= Next_Interrupt_Time then Alarm_Flag := False; Post_Flag := True; else Delta_Alarm := Next_Alarm_Time - Next_Interrupt_Time; if Delta_Alarm.Day /= 0 or Delta_Alarm.Sec >= Max_Duration * 2 then null; elsif Delta_Alarm.Sec < Min_Duration then Delta_Duration := Min_Duration; Delta_Count := Min_Count; elsif Delta_Alarm.Sec <= Max_Duration then Delta_Duration := Delta_Alarm.Sec; Delta_Count := Duration_To_Count (Delta_Duration); else Delta_Duration := Delta_Alarm.Sec / 2; Delta_Count := Duration_To_Count (Delta_Duration); end if; end if; end if; Next_Interrupt_Time := Next_Interrupt_Time + (Day => 0, Sec => Delta_Duration); Set_Timer (Delta_Count); V_Krn_Conf_I.Interrupts_Restore (Intr_Status); if Post_Flag then V_Krn_Conf_I.Post_Alarm; end if; end Process_Timer_Interrupt; end V_Timer_Support;
nblk1=10 nid=c hdr6=1e [0x00] rec0=22 rec1=00 rec2=01 rec3=02a [0x01] rec0=1a rec1=00 rec2=04 rec3=050 [0x02] rec0=1a rec1=00 rec2=10 rec3=088 [0x03] rec0=18 rec1=00 rec2=02 rec3=014 [0x04] rec0=17 rec1=00 rec2=03 rec3=020 [0x05] rec0=18 rec1=00 rec2=0d rec3=00a [0x06] rec0=18 rec1=00 rec2=0b rec3=076 [0x07] rec0=09 rec1=00 rec2=0a rec3=044 [0x08] rec0=1c rec1=00 rec2=05 rec3=018 [0x09] rec0=18 rec1=00 rec2=06 rec3=022 [0x0a] rec0=14 rec1=00 rec2=07 rec3=036 [0x0b] rec0=16 rec1=00 rec2=0f rec3=012 [0x0c] rec0=1e rec1=00 rec2=08 rec3=022 [0x0d] rec0=18 rec1=00 rec2=0e rec3=01c [0x0e] rec0=19 rec1=00 rec2=09 rec3=000 [0x0f] rec0=19 rec1=00 rec2=09 rec3=000 tail 0x2176547ae87da833ef640 0x42a00088462060003 Free Block Chain: 0xc: 0000 00 00 00 04 80 01 49 01 02 03 04 73 74 65 72 5f ┆ I ster_┆