ich benutze mittlerweile auch viel C++ und sehe darin keinen Nachteil.
Dazu Mbed-os, das ebenfalls sehr konsequent C++ nutzt und auch das API
bietet alles in Klassen an.
Die Interrupts kann man da auch bequem im Usercode abarbeiten:
Im RAM ist ein Bereich für die Kopie der Interrupt Vektoren reserviert.
Die ISR kann fest in die Tabelle wenn sie zur Kompilierzeit bekannt ist,
kann aber zur Laufzeit einfach mit
1 | void NVIC_SetVector(IRQn_Type IRQn, uint32_t vector);
|
umgebogen werden.
Für den Fall das man eine Methode als ISR nutzen möchte gibt es einen
Helfer names CThunk. Das ist eine Trampolin Funktion die sich einen
Callback merkt und als ISR arbeitet. Kostet zusätzliche indirekte calls,
aber die nehme ich für den Luxus in Kauf. Dafür spare ich mir die lange
universelle Behandlung in der HAL ISR.
Der Vorteil ist, das ich meine Komponente schön kapseln kann und die bei
Bedarf den ISR Kram implizit behandelt. Es muss keine ISR im Core vorab
reserviert werden (Arduino) oder eine unübersichtliche 'ich kann alle
Ints' (HAL) implementiert werden.
Benutzt habe ich das z.B. in einer Timerklasse. Der gebe ich den
gewünschten Callback mit und intern wird die Interruptbehandlung
gemacht.
Auszugsweise sieht das so aus, Timerkram weggelassen:
1 | class HWTimer {
|
2 | public:
|
3 | HWTimer(int id, chrono::microseconds period, Callback<void()> cb, bool onePulseMode);
|
4 |
|
5 | ~HWTimer();
|
6 | void start(chrono::microseconds period = 0us);
|
7 | void stop();
|
8 |
|
9 | private:
|
10 | void callTimerFn();
|
11 |
|
12 | private:
|
13 | int _id;
|
14 | bool _onePulseMode;
|
15 | Callback<void()> _cb; // user callback on timeout
|
16 | CThunk<HWTimer> _irq; // helper for setting static irq member function
|
17 | void *_pConfig; // generic pointer, used for implementation dependent structures
|
18 | };
|
19 |
|
20 |
|
21 | HWTimer::HWTimer(int id, chrono::microseconds us_period, Callback<void()> cb, bool onePulseMode) :
|
22 | _id(id),
|
23 | _onePulseMode(onePulseMode),
|
24 | _cb(cb),
|
25 | _irq(this)
|
26 | {
|
27 | // set IRQ ISR, use CThunk to handle member function call from static
|
28 | _irq.callback(&HWTimer::callTimerFn);
|
29 |
|
30 | // activate IRQ in NVIC
|
31 | NVIC_SetVector(TimIRQTab[id], (uint32_t)_irq);
|
32 | NVIC_EnableIRQ(TimIRQTab[id]);
|
33 | }
|
34 |
|
35 | void HWTimer::callTimerFn()
|
36 | {
|
37 | if (__HAL_TIM_GET_FLAG((TIM_HandleTypeDef*)_pConfig, TIM_FLAG_UPDATE) == SET) {
|
38 | __HAL_TIM_CLEAR_FLAG((TIM_HandleTypeDef*)_pConfig, TIM_FLAG_UPDATE);
|
39 |
|
40 | _cb();
|
41 | }
|
42 | }
|
Den CThunk könnte man auch aus dem OS rausoperieren, der setzt nichts OS
spezifisches vorraus. Aber da habe ich keine Ambitionen, das OS hat ja
noch mehr zu bieten das ich benutzen möchte.