|
|
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_┆