12 namespace irq = satcat5::irq;
13 namespace util = satcat5::util;
21 static u8* stack_ref = 0;
25 static const u32 USER_CONTEXT = 0x40000000u;
26 static const u32 INTERRUPT_CONTEXT = 0x80000000u;
33 static u32 g_lock_count = 0;
48 if (g_lock_count) {g_lock_count = 0; ok =
false;}
49 if (g_irq_list) {g_irq_list = 0; ok =
false;}
50 if (g_timer) {g_timer = 0; ok =
false;}
51 if (g_irq_ctrl) {g_irq_ctrl = 0; ok =
false;}
55 #if SATCAT5_ALLOW_DELETION
56 irq::Controller::~Controller() {
69 if (g_lock_count < USER_CONTEXT)
return;
73 while (g_irq_ctrl && ptr) {
74 if (ptr->
m_irq_idx >= 0) irq_unregister(ptr);
80 g_lock_count -= USER_CONTEXT;
98 g_timer = timer ? timer : SATCAT5_CLOCK;
99 stack_ref = (u8*)__builtin_frame_address(0);
104 g_lock_count = USER_CONTEXT;
108 return (g_lock_count >= USER_CONTEXT);
112 return (g_lock_count >= INTERRUPT_CONTEXT);
116 return (g_lock_count > USER_CONTEXT);
127 unsigned elapsed = 0;
131 g_lock_count += INTERRUPT_CONTEXT;
138 if (SATCAT5_IRQ_STATS) tstart = g_timer->
now();
143 #if SATCAT5_IRQ_STATS
152 unsigned stack_now = (unsigned)(stack_ref - (u8*)__builtin_frame_address(0));
157 g_lock_count -= INTERRUPT_CONTEXT;
186 if (g_lock_count >= USER_CONTEXT)
191 #if SATCAT5_ALLOW_DELETION
192 irq::Handler::~Handler() {
196 if (m_irq_idx < 0)
return;
199 if (g_lock_count >= USER_CONTEXT)
208 : irq::Handler(lbl, irq)
214 #if SATCAT5_ALLOW_DELETION
215 irq::Adapter::~Adapter() {
221 m_obj->request_poll();
224 irq::Shared::Shared(
const char* lbl,
int irq)
230 #if SATCAT5_ALLOW_DELETION
231 irq::Shared::~Shared() {
251 if (g_lock_count++ == USER_CONTEXT) {
256 if (SATCAT5_IRQ_STATS && g_timer)
257 m_tstart = g_timer->
now();
260 irq::AtomicLock::~AtomicLock() {
268 #if SATCAT5_IRQ_STATS
275 if (--g_lock_count == USER_CONTEXT) {
Driver for the ConfigBus timer.
void irq_event() override
Method called whenever an interrupt is triggered.
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.
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.
ControllerNull(satcat5::util::TimeRef *timer=0)
Constructor accepts an optional Timer pointer, if available.
void service_all()
User should call one of the "service" methods whenever a SatCat5-related interrupt occurs.
Parent object for receiving interrupt-handler callbacks.
Handler(const char *lbl, int irq)
Only children should create or destroy base class.
virtual void irq_event()=0
Method called whenever an interrupt is triggered.
const char *const m_label
Human-readable label, for debugging.
u32 m_max_irqtime
Statistics tracking for time consumed by this interrupt.
const int m_irq_idx
IRQ index for this interrupt handler.
void irq_event() override
Method called whenever an interrupt is triggered.
An "OnDemand" object is polled only on request.
void suggest_clock(satcat5::util::TimeRef *timer)
Compare the provided reference to the current TimeRef, and keep whichever is "better" by an internal ...
static void remove(T *&list, T *item)
Remove the designated item from the list.
static void add(T *&list, T *item)
Add new item to front or back, whichever is simpler.
static T * next(const T *item)
Fetch pointer to the next item.
Running maximum with label tracking.
void update(const char *lbl, u32 value)
Update stats if new value exceeds previous record.
The TimeRef API provides access to a monotonic time-counter.
TimeVal now()
Create a TimeVal object using the tick-count from raw().
Templated functions for manipulating singly-linked lists.
Core event-processing loop for SatCat5 software.
Platform-agnostic API for interrupt management.
satcat5::util::RunningMax worst_irq
Statistics tracking for critical sections.
satcat5::util::RunningMax worst_stack
Statistics tracking for critical sections.
bool pre_test_reset()
Hard-reset of global variables at the start of each unit test.
satcat5::util::RunningMax worst_lock
Statistics tracking for critical sections.
Timestamp for measuring elapsed time.
unsigned elapsed_tick() const
Measure elapsed time in ticks.
Miscellaneous mathematical utility functions.