SatCat5
satcat5/interrupts.h
Go to the documentation of this file.
1 // Copyright 2021-2025 The Aerospace Corporation.
3 // This file is a part of SatCat5, licensed under CERN-OHL-W v2 or later.
37 
38 #pragma once
39 
40 #include <satcat5/list.h>
41 #include <satcat5/timeref.h>
42 #include <satcat5/types.h>
43 
44 // By default, time statistics are enabled.
45 #ifndef SATCAT5_IRQ_STATS
46 #define SATCAT5_IRQ_STATS 1
47 #endif
48 
49 namespace satcat5 {
50  namespace irq {
57  class AtomicLock final {
58  public:
60  explicit AtomicLock(const char* lbl);
61  ~AtomicLock();
62 
64  void release();
65 
66  private:
67  const char* const m_lbl;
68  satcat5::util::TimeVal m_tstart;
69  bool m_held;
70  };
71 
73  constexpr int IRQ_NONE = -1;
74 
83  class Controller {
84  public:
92  void init(satcat5::util::TimeRef* timer = 0);
93 
95  static bool is_initialized();
97  static bool is_irq_context();
99  static bool is_irq_or_locked();
100 
104  void stop();
105 
106  protected:
108  friend satcat5::irq::Handler;
109 
112  ~Controller() SATCAT5_OPTIONAL_DTOR;
113 
116  static void interrupt_static(satcat5::irq::Handler* obj);
117 
122  virtual void irq_pause() = 0;
123  virtual void irq_resume() = 0;
125 
128  virtual void irq_register(satcat5::irq::Handler* obj) = 0;
129 
132  virtual void irq_unregister(satcat5::irq::Handler* obj) = 0;
133 
136  virtual void irq_acknowledge(satcat5::irq::Handler* obj);
137  };
138 
145  class ControllerNull final
146  : public satcat5::irq::Controller {
147  public:
149  explicit ControllerNull(satcat5::util::TimeRef* timer = 0);
150  ~ControllerNull() {}
151 
154  void service_all();
155  inline void service_one(satcat5::irq::Handler* obj)
157 
158  protected:
159  // Empty hardware-abstraction overrides.
160  void irq_pause() override {}
161  void irq_resume() override {}
162  void irq_register(satcat5::irq::Handler* obj) override {}
163  void irq_unregister(satcat5::irq::Handler* obj) override {}
164  void irq_acknowledge(satcat5::irq::Handler* obj) override {}
165  };
166 
187  class Handler {
188  public:
190  const char* const m_label;
191 
193  const int m_irq_idx;
194 
195  protected:
197 
199  Handler(const char* lbl, int irq);
200  ~Handler() SATCAT5_OPTIONAL_DTOR;
201 
203  virtual void irq_event() = 0;
204 
206  u32 m_max_irqtime;
207 
208  private:
209  // Linked list of all Handler objects.
210  friend satcat5::irq::Shared;
211  friend satcat5::util::ListCore;
212  satcat5::irq::Handler* m_next;
213  };
214 
222  class Adapter : public satcat5::irq::Handler {
223  public:
224  Adapter(const char* lbl, int irq, satcat5::poll::OnDemand* obj);
225  ~Adapter() SATCAT5_OPTIONAL_DTOR;
226 
227  protected:
228  void irq_event() override;
229  satcat5::poll::OnDemand* const m_obj;
230  };
231 
235  class Shared final : public satcat5::irq::Handler {
236  public:
237  Shared(const char* lbl, int irq);
238  ~Shared() SATCAT5_OPTIONAL_DTOR;
239 
240  // Add a child to the list.
241  inline void add(satcat5::irq::Handler* child)
242  {m_list.add(child);}
243 
244  protected:
245  void irq_event() override;
246 
248  };
249 
256  bool pre_test_reset();
257 
266  #if SATCAT5_IRQ_STATS
269  #endif
271  }
272 }
Adapter connects a hardware interrupt to any OnDemand object.
Automatic lock or mutex.
AtomicLock(const char *lbl)
Creating this object starts a critical section.
void release()
Optionally release this lock before the destructor is called.
Platform-agnostic interrupt controller.
virtual void irq_resume()=0
Disable hardware interrupts.
virtual void irq_register(satcat5::irq::Handler *obj)=0
Re-enable hardware interrupts.
Controller()
Only children should create or destroy base class.
static bool is_irq_or_locked()
Are we currently in a critical-section?
virtual void irq_pause()=0
Prevent preemption from "pause" until "resume".
void init(satcat5::util::TimeRef *timer=0)
Start the interrupt controller.
virtual void irq_unregister(satcat5::irq::Handler *obj)=0
Un-register the callback for an interrupt handler.
static bool is_initialized()
Has init() been called?
void stop()
Unregister ALL interrupt handlers.
static bool is_irq_context()
Are we currently servicing an interrupt?
virtual void irq_acknowledge(satcat5::irq::Handler *obj)
Post-handler acknowledgement, notification, and cleanup.
static void interrupt_static(satcat5::irq::Handler *obj)
Static interrupt service routine.
A do-nothing placeholder implementation of irq::Controller .
void irq_unregister(satcat5::irq::Handler *obj) override
Un-register the callback for an interrupt handler.
void irq_acknowledge(satcat5::irq::Handler *obj) override
Post-handler acknowledgement, notification, and cleanup.
void irq_register(satcat5::irq::Handler *obj) override
Re-enable hardware interrupts.
void irq_resume() override
Disable hardware interrupts.
void irq_pause() override
Prevent preemption from "pause" until "resume".
Parent object for receiving interrupt-handler callbacks.
const char *const m_label
Human-readable label, for debugging.
const int m_irq_idx
IRQ index for this interrupt handler.
Shared interrupt handler calls all children for any parent event.
An "OnDemand" object is polled only on request.
Definition: polling.h:131
Running maximum with label tracking.
Definition: utils.h:389
The TimeRef API provides access to a monotonic time-counter.
Definition: timeref.h:142
Templated functions for manipulating singly-linked lists.
satcat5::util::RunningMax worst_irq
Statistics tracking for critical sections.
satcat5::util::RunningMax worst_stack
Statistics tracking for critical sections.
satcat5::util::RunningMax worst_lock
Statistics tracking for critical sections.
constexpr int IRQ_NONE
Special index "-1" indicates a disabled or unconnected interrupt.
Timestamp for measuring elapsed time.
Definition: timeref.h:48
TimeRef and TimeVal define the API for monotonic timers.
Basic type aliases and prototypes used throughout SatCat5.