rp2040_hal_2.2.1_dd57b8f8/src/interrupts/bb_runtimes/rp-timer-interrupts.adb

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
--
--  Copyright 2021 (C) Jeremy Grosser
--
--  SPDX-License-Identifier: BSD-3-Clause
--
with RP2040_SVD.TIMER;     use RP2040_SVD.TIMER;
with Ada.Interrupts.Names; use Ada.Interrupts.Names;

package body RP.Timer.Interrupts is

   --------------------------
   -- Alarm_Handler (spec) --
   --------------------------

   protected Alarm_Handler is

      entry Wait_For_Alarm;

   private

      procedure IRQ_Handler
        with Attach_Handler => TIMER_IRQ_2_Interrupt_CPU_1;

      Alarm_Triggered : Boolean := False;

   end Alarm_Handler;

   --------------------------
   -- Alarm_Handler (body) --
   --------------------------

   protected body Alarm_Handler is

      entry Wait_For_Alarm
         when Alarm_Triggered
      is
      begin
         Alarm_Triggered := False;
      end Wait_For_Alarm;

      procedure IRQ_Handler is
      begin
         TIMER_Periph.INTR.ALARM_2 := True;
         Alarm_Triggered           := True;
      end IRQ_Handler;

   end Alarm_Handler;

   ------------
   -- Enable --
   ------------

   procedure Enable
      (This : in out Delays)
   is
   begin
      TIMER_Periph.INTE.ALARM_2 := True;
      RP.Timer.Set_Debug_Pause (False, False);
   end Enable;

   -------------
   -- Disable --
   -------------

   procedure Disable
      (This : in out Delays)
   is
   begin
      TIMER_Periph.INTE.ALARM_2 := False;
   end Disable;

   -------------
   -- Enabled --
   -------------

   function Enabled
      (This : Delays)
      return Boolean
   is (TIMER_Periph.INTE.ALARM_2);

   -----------------
   -- Delay_Until --
   -----------------

   procedure Delay_Until
      (This : in out Delays;
       T    : Time)
   is
   begin
      if T <= Clock then
         return;
      end if;
      TIMER_Periph.ALARM2 := UInt32 (T and 16#FFFFFFFF#);
      loop
         Alarm_Handler.Wait_For_Alarm;
         if Clock >= T then
            return;
         elsif TIMER_Periph.INTS.ALARM_2 then
            --  If the high byte of the timer rolled over but we still haven't
            --  reached the target time, reset the alarm and go again
            TIMER_Periph.ALARM2 := UInt32 (T and 16#FFFFFFFF#);
         end if;
      end loop;
   end Delay_Until;

   ------------------------
   -- Delay_Microseconds --
   ------------------------

   overriding
   procedure Delay_Microseconds
      (This : in out Delays;
       Us   : Integer)
   is
      Deadline : constant UInt64 := UInt64 (Clock) + UInt64 (Us);
   begin
      if Us > 0 then
         while UInt64 (Clock) < Deadline loop
            null;
         end loop;
      end if;
   end Delay_Microseconds;

   ------------------------
   -- Delay_Milliseconds --
   ------------------------

   overriding
   procedure Delay_Milliseconds
      (This : in out Delays;
       Ms   : Integer)
   is
   begin
      Delay_Until (This, Clock + (1_000 * Time (Ms)));
   end Delay_Milliseconds;

   -------------------
   -- Delay_Seconds --
   -------------------

   overriding
   procedure Delay_Seconds
      (This : in out Delays;
       S    : Integer)
   is
   begin
      Delay_Until (This, Clock + (1_000_000 * Time (S)));
   end Delay_Seconds;

end RP.Timer.Interrupts;