File : s-bbbosu-erc32.adb


   1 ------------------------------------------------------------------------------
   2 --                                                                          --
   3 --                  GNAT RUN-TIME LIBRARY (GNARL) COMPONENTS                --
   4 --                                                                          --
   5 --                S Y S T E M . B B . B O A R D _ S U P P O R T             --
   6 --                                                                          --
   7 --                                  B o d y                                 --
   8 --                                                                          --
   9 --        Copyright (C) 1999-2002 Universidad Politecnica de Madrid         --
  10 --             Copyright (C) 2003-2006 The European Space Agency            --
  11 --                     Copyright (C) 2003-2016, AdaCore                     --
  12 --                                                                          --
  13 -- GNARL is free software; you can  redistribute it  and/or modify it under --
  14 -- terms of the  GNU General Public License as published  by the Free Soft- --
  15 -- ware  Foundation;  either version 3,  or (at your option) any later ver- --
  16 -- sion. GNARL is distributed in the hope that it will be useful, but WITH- --
  17 -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
  18 -- or FITNESS FOR A PARTICULAR PURPOSE.                                     --
  19 --                                                                          --
  20 --                                                                          --
  21 --                                                                          --
  22 --                                                                          --
  23 --                                                                          --
  24 -- You should have received a copy of the GNU General Public License and    --
  25 -- a copy of the GCC Runtime Library Exception along with this program;     --
  26 -- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
  27 -- <http://www.gnu.org/licenses/>.                                          --
  28 --                                                                          --
  29 -- GNARL was developed by the GNARL team at Florida State University.       --
  30 -- Extensive contributions were provided by Ada Core Technologies, Inc.     --
  31 --                                                                          --
  32 -- The port of GNARL to bare board targets was initially developed by the   --
  33 -- Real-Time Systems Group at the Technical University of Madrid.           --
  34 --                                                                          --
  35 ------------------------------------------------------------------------------
  36 
  37 --  There are page numbers in the comments below, please provide the reference
  38 --  to the document (here in this header) to which these references apply ???
  39 
  40 pragma Restrictions (No_Elaboration_Code);
  41 
  42 with System.BB.Board_Support.ERC32;
  43 with System.BB.Parameters;
  44 
  45 package body System.BB.Board_Support is
  46    use type ERC32.Scaler_8;
  47    use type ERC32.Timers_Counter;
  48    use CPU_Primitives;
  49 
  50    package Registers renames ERC32;
  51 
  52    -----------------------
  53    -- Local Definitions --
  54    -----------------------
  55 
  56    Periodic_Scaler : constant := 0;
  57    --  In order to obtain the highest granularity of the clock we set the
  58    --  scaler to 0.
  59 
  60    Alarm_Scaler : constant := 0;
  61    --  In order to obtain the highest resolution of the alarm timer we set
  62    --  the scaler to 0.
  63 
  64    Periodic_Count : constant := Registers.Timers_Counter'Last - 1;
  65    --  Value to be loaded in the clock counter to accomplish the
  66    --  Clock_Interrupt_Period.
  67    --
  68    --  One is subtracted from Timers_Counter'Last because when the Scaler is
  69    --  set to 0, the timeout period will be the counter reload value  plus 1.
  70 
  71    --  Constants defining the external interrupts
  72 
  73    General_Purpose_Timer : constant System.BB.Interrupts.Interrupt_ID := 12;
  74 
  75    Timer_Control_Mirror : Registers.Timer_Control_Register;
  76    pragma Volatile (Timer_Control_Mirror);
  77    --  Timer_Control register cannot be read. So the following object holds a
  78    --  copy of the Timer_Control register value.
  79 
  80    ----------------------
  81    -- Local Procedures --
  82    ----------------------
  83 
  84    procedure Stop_Watch_Dog;
  85    pragma Inline (Stop_Watch_Dog);
  86    --  Stop the watch dog timer
  87 
  88    procedure Initialize_Memory;
  89    pragma Inline (Initialize_Memory);
  90    --  Initialize the memory on the board
  91 
  92    procedure Initialize_Clock;
  93    --  Perform all the initialization related to the clock
  94 
  95    ------------------------
  96    -- Alarm_Interrupt_ID --
  97    ------------------------
  98 
  99    function Alarm_Interrupt_ID return Interrupts.Interrupt_ID is
 100    begin
 101       return General_Purpose_Timer;
 102    end Alarm_Interrupt_ID;
 103 
 104    ---------------------------
 105    -- Clear_Alarm_Interrupt --
 106    ---------------------------
 107 
 108    procedure Clear_Alarm_Interrupt is
 109    begin
 110       --  From MEC Specification Document (MCD/SPC/0009/SE) page 35
 111 
 112       --  The MEC includes a specific register called Interrupt Pending
 113       --  Register, which reflects the pending interrupts.
 114 
 115       --  The interrupts in the IPR are cleared automatically when the
 116       --  interrupt is acknowledged. The MEC will sample the trap address in
 117       --  order to know which bit to clear. Therefore, this procedure has a
 118       --  null body for this target.
 119 
 120       null;
 121    end Clear_Alarm_Interrupt;
 122 
 123    -----------------------------
 124    -- Clear_Interrupt_Request --
 125    -----------------------------
 126 
 127    procedure Clear_Interrupt_Request
 128      (Interrupt : System.BB.Interrupts.Interrupt_ID)
 129    is
 130    begin
 131       --  Nothing to do for the IPIC
 132 
 133       null;
 134    end Clear_Interrupt_Request;
 135 
 136    --------------------------
 137    -- Clear_Poke_Interrupt --
 138    --------------------------
 139 
 140    procedure Clear_Poke_Interrupt is
 141    begin
 142       --  No Poke interrupt available for ERC32
 143 
 144       raise Program_Error;
 145    end Clear_Poke_Interrupt;
 146 
 147    ---------------------------
 148    -- Priority_Of_Interrupt --
 149    ---------------------------
 150 
 151    function Priority_Of_Interrupt
 152      (Interrupt : System.BB.Interrupts.Interrupt_ID) return System.Any_Priority
 153    is
 154    begin
 155       --  Assert that it is a real interrupt
 156 
 157       pragma Assert (Interrupt /= System.BB.Interrupts.No_Interrupt);
 158 
 159       return (Any_Priority (Interrupt) + Interrupt_Priority'First - 1);
 160    end Priority_Of_Interrupt;
 161 
 162    ----------------------
 163    -- Initialize_Board --
 164    ----------------------
 165 
 166    procedure Initialize_Board is
 167    begin
 168       --  The initialization of the ERC32 board consists on stopping the watch
 169       --  dog timer, initializing the memory, and initializing the clock in
 170       --  order to have the desired granularity and range.
 171 
 172       Stop_Watch_Dog;
 173       Initialize_Memory;
 174       Initialize_Clock;
 175    end Initialize_Board;
 176 
 177    ----------------------
 178    -- Initialize_Clock --
 179    ----------------------
 180 
 181    procedure Initialize_Clock is
 182       Real_Time_Clock_Scaler_Aux : Registers.Real_Time_Clock_Scaler_Register;
 183 
 184    begin
 185       --  Set the scaler for the clock
 186 
 187       Real_Time_Clock_Scaler_Aux       := Registers.Real_Time_Clock_Scaler;
 188       Real_Time_Clock_Scaler_Aux.RTCS  := Periodic_Scaler;
 189       Registers.Real_Time_Clock_Scaler := Real_Time_Clock_Scaler_Aux;
 190 
 191       --  Load the counter for the clock
 192 
 193       Registers.Real_Time_Clock_Counter := Periodic_Count;
 194 
 195       --  Set the proper bits in mirrored Timer Control Register. The timer
 196       --  used for the clock is programmed in periodic mode.
 197 
 198       --  From MEC Specification Document (MCD/SPC/0009/SE) page 50
 199 
 200       --  NOTE: All reserved bits have to be written with zeros in order to
 201       --  avoid parity error resulting in a MEC internal error.
 202 
 203       Timer_Control_Mirror.Reserved4  := (others => False);
 204       Timer_Control_Mirror.Reserved20 := (others => False);
 205 
 206       Timer_Control_Mirror.RTCCR := True;
 207       Timer_Control_Mirror.RTCCL := True;
 208       Timer_Control_Mirror.RTCSL := True;
 209       Timer_Control_Mirror.RTCSE := True;
 210 
 211       --  Do not modify General Purpose Timer downcounter
 212 
 213       Timer_Control_Mirror.GCL := False;
 214       Timer_Control_Mirror.GSL := False;
 215 
 216       --  Write MEC Timer Control Register
 217 
 218       Registers.Timer_Control := Timer_Control_Mirror;
 219    end Initialize_Clock;
 220 
 221    -----------------------
 222    -- Initialize_Memory --
 223    -----------------------
 224 
 225    procedure Initialize_Memory is
 226    begin
 227       --  Nothing to be done for the ERC32
 228 
 229       null;
 230    end Initialize_Memory;
 231 
 232    ------------------------
 233    -- Max_Timer_Interval --
 234    ------------------------
 235 
 236    function Max_Timer_Interval return Timer_Interval is
 237    begin
 238       return Timer_Interval'Last;
 239    end Max_Timer_Interval;
 240 
 241    -----------------------
 242    -- Poke_Interrupt_ID --
 243    -----------------------
 244 
 245    function Poke_Interrupt_ID return Interrupts.Interrupt_ID is
 246    begin
 247       --  No Poke interrupt available for ERC32
 248 
 249       raise Program_Error;
 250 
 251       --  Unreachable code
 252 
 253       return Interrupts.Interrupt_ID'First;
 254    end Poke_Interrupt_ID;
 255 
 256    ---------------------------
 257    -- Get_Interrupt_Request --
 258    ---------------------------
 259 
 260    function Get_Interrupt_Request
 261      (Vector : CPU_Primitives.Vector_Id)
 262       return System.BB.Interrupts.Interrupt_ID
 263    is
 264    begin
 265       --  The range corresponding to asynchronous traps is in 16#11# .. 16#1F#
 266 
 267       pragma Assert (Vector in 16#11# .. 16#1F#);
 268 
 269       return System.BB.Interrupts.Interrupt_ID (Vector - 16#10#);
 270    end Get_Interrupt_Request;
 271 
 272    -------------------------------
 273    -- Install_Interrupt_Handler --
 274    -------------------------------
 275 
 276    procedure Install_Interrupt_Handler
 277      (Handler   : Address;
 278       Interrupt : Interrupts.Interrupt_ID;
 279       Prio      : Interrupt_Priority)
 280    is
 281       pragma Unreferenced (Prio);
 282    begin
 283       CPU_Primitives.Install_Trap_Handler
 284         (Handler, CPU_Primitives.Vector_Id (Interrupt + 16#10#));
 285    end Install_Interrupt_Handler;
 286 
 287    ----------------
 288    -- Read_Clock --
 289    ----------------
 290 
 291    function Read_Clock return Timer_Interval is
 292    begin
 293       return
 294         Timer_Interval (Periodic_Count - Registers.Real_Time_Clock_Counter);
 295    end Read_Clock;
 296 
 297    ---------------
 298    -- Set_Alarm --
 299    ---------------
 300 
 301    procedure Set_Alarm (Ticks : Timer_Interval) is
 302       General_Purpose_Timer_Scaler_Aux :
 303         Registers.General_Purpose_Timer_Scaler_Register;
 304 
 305       Interrupt_Mask_Aux : Registers.Interrupt_Mask_Register;
 306 
 307    begin
 308       --  Alarm Clock downcount will reach 0 in Ticks. The granularity of
 309       --  time intervals is equal to Clock Period.
 310 
 311       --  Set the scaler
 312 
 313       General_Purpose_Timer_Scaler_Aux :=
 314         Registers.General_Purpose_Timer_Scaler;
 315       General_Purpose_Timer_Scaler_Aux.GPTS := Alarm_Scaler;
 316       Registers.General_Purpose_Timer_Scaler :=
 317         General_Purpose_Timer_Scaler_Aux;
 318 
 319       --  Load the counter
 320 
 321       Registers.General_Purpose_Timer_Counter :=
 322         Registers.Timers_Counter (Ticks);
 323 
 324       --  Set the proper bits in mirrored Timer Control Register.
 325       --  General Purpose Timer is used in one-shot mode.
 326 
 327       Timer_Control_Mirror.GCR := False;
 328 
 329       Timer_Control_Mirror.GCL := True;
 330       Timer_Control_Mirror.GSE := True;
 331       Timer_Control_Mirror.GSL := True;
 332 
 333       --  Do not modify Timer downcount
 334 
 335       Timer_Control_Mirror.RTCCL := False;
 336       Timer_Control_Mirror.RTCSL := False;
 337 
 338       --  From MEC Specification Document (MCD/SPC/0009/SE) page 50
 339 
 340       --  NOTE: All reserved bits have to be written with zeros in order to
 341       --  avoid parity error resulting in a MEC internal error.
 342 
 343       Timer_Control_Mirror.Reserved4 := (others => False);
 344       Timer_Control_Mirror.Reserved20 := (others => False);
 345 
 346       --  Write MEC Timer Control Register
 347 
 348       Registers.Timer_Control := Timer_Control_Mirror;
 349 
 350       --  Enable GPT Interrupts
 351 
 352       Interrupt_Mask_Aux := Registers.Interrupt_Mask;
 353       Interrupt_Mask_Aux.General_Purpose_Timer := False;
 354       Registers.Interrupt_Mask := Interrupt_Mask_Aux;
 355    end Set_Alarm;
 356 
 357    --------------------------
 358    -- Set_Current_Priority --
 359    --------------------------
 360 
 361    procedure Set_Current_Priority (Priority : Integer) is
 362    begin
 363       null; --  No board-specific actions necessary
 364    end Set_Current_Priority;
 365 
 366    --------------------
 367    -- Stop_Watch_Dog --
 368    --------------------
 369 
 370    procedure Stop_Watch_Dog is
 371    begin
 372       --  From MEC Specification Document (MCD/SPC/0009/SE) page 39
 373 
 374       --  After system reset or processor reset, the watch dog timer is enabled
 375       --  and starts running. By writing to the Trap Door Set after system
 376       --  reset, the timer can be disabled.
 377 
 378       Registers.Watchdog_Trap_Door_Set := 0;
 379    end Stop_Watch_Dog;
 380 
 381    ----------------------
 382    -- Ticks_Per_Second --
 383    ----------------------
 384 
 385    function Ticks_Per_Second return Natural is
 386    begin
 387       --  The prescaler is clocked by the system clock. When it underflows, it
 388       --  is reloaded from the prescaler reload register and a timer tick is
 389       --  generated. The effective division rate is therefore equal to the
 390       --  prescaler reload register value plus 1.
 391 
 392       return Parameters.Clock_Frequency / (Periodic_Scaler + 1);
 393    end Ticks_Per_Second;
 394 
 395 end System.BB.Board_Support;