This was introduced when STM32WL support was added. Using constexpr for
the END_OF_MODE_TABLE constant allows it to be initialized in the class
declaration, but this needs C++11. This moves the initialization out of
the class declaration to the .cpp file, which does not need constexpr.
It also lets STM32WLx::END_OF_MODE_TABLE define its value directly
(instead of aliasing Module::END_OF_MODE_TABLE) to prevent reduce
runtime overhead (see below).
The downside of this change is that the value of the END_OF_MODE_TABLE
is no longer visible in other compilation units and thus cannot be
inlined into the rfswitch_table (if used).
For example, on STM32, this means that instead of having a pre-cooked
rfswitch_table that lives in the .rodata section (so can be read
directly from flash), the table lives in RAM and is initialized at
runtime (the actual modes and pins are copied from flash to RAM by the
standard startup loop that copies all of the .data section, and the
END_OF_MODE_TABLE value is copied by a bit of new generated code). This
means a little more runtime overhead, but the cost is mostly in RAM size
(80 bytes for the SMT32WL sketches, 16 per mode plus 16 for the
END_OF_MODE_TABLE).
In a first attempt at this commit, STM32WLx::END_OF_MODE_TABLE was still
initialized using the Module::END_OF_MODE_TABLE value, but since the
latter is also not available at compiletime, this meant initialization
of the former also needed to happen at runtime, adding even more code
overhead (and possibly leading to ordering issues as well). To avoid
this, the STM32WLx::END_OF_MODE_TABLE initialization now just duplicates
that of Module::END_OF_MODE_TABLE.
On AVR, the impact is not so much: Since AVR cannot address flash
directly, the table was already copied from flash to RAM at startup, so
the extra RAM usage is just 4 bytes because END_OF_MODE_TABLE is now
also present in RAM, to be copied into rfswitch_table at startup.
Options for avoiding this overhead (not implemented in this commit)
could be (in no particular order):
1. Use a macro instead of a constant. Downside is that these cannot be
scoped inside the Module/STM32WLx classes like now, so this requires
changes to sketches that use a rfswitch_table (and reduced scoping
and using macros adds more opportunity for conflicts and weird
errors).
2. Apply the change in this commit only when C++11 is not available.
Downside is that the initialization value of these constants must be
duplicated in the .h and .cpp file for C++ and older versions
respectively.
3. Let sketches just use `{Module::MODE_END_OF_TABLE, {}}` explicitly
instead of `Module::END_OF_MODE_TABLE`. Downside of this is that this
requires sketches to be modified and that it lets the sketch encode
more of the table structure, potentially making future API changes
harder (but it probably does not really matter in practice).
4. Turn END_OF_MODE_TABLE into a static method, which *can* then be
defined in the class declaration and inlined. The method can then be
conditionally marked as constexpr, which allows C++11 compilers to
completely resolve the rfswitch_table value at compiletime, producing
a binary identical to before this commit. When constexpr is omitted
(e.g. on older compilers), some runtime overhead is added (pretty
much the same as the result from this commit). Downside is that
sketches must be modified, and the `END_OF_MODE_TABLE` "constant"
must now be called, e.g. `END_OF_MODE_TABLE()` which might be a bit
unexpected syntax.
This adds a build for the Nucleo WL55JC1 board, and ensures that
the STM32WLx examples are skipped on all other boards.
To slightly generalize the list of boards, this pushes the pnum option
for the black pill into the boards list, instead of setting it into the
options variable (even though it is technically a board option and not
the board itself, conceptually it is part of the selected board and
these values are just concatenated, so it can go in either place).
Co-Authored-By: jgromes <jan.gromes@gmail.com>
This checks for some system macros to be set, but also includes the
doxygen build to generate documentation.
This reuses the RADIOLIB_EXCLUDE_STM32WLX that the code already checks
for to prevent having to duplicate this macro check in four places.
To detect running inside doxygen, this configures doxygen to predefine
a DOXYGEN macro (it seems no such macros are defined by default by
doxygen).
Because this interrupt is not connected to a GPIO or even the EXTI unit,
but directly to the MCU NVIC, the regular attachInterrupt flow cannot be
used.
Instead, this lets STM32WLx override the setDio1Action() and
clearDio1Action() methods to register the radio IRQ directly. Note that
it would have been nicer to implement this by overriding attachInterrupt
in STM32WLx_Module, but that is never called for virtual pins (because
the STM32Duino digitalPinToInterrupt() macro does not work for virtual
pins).
In addition, because the NVIC is level-sensitive and the code expects
edge-sensitive interrupts (for GPIO, the EXTI module in front of the
NVIC makes the interrupts edge-sensitive), this adds some additional
handling around the user-registered interrupt callback. To prevent the
ISR from triggering over and over again (and also to not require SPI
transactions in the ISR to clear the IRQ flags inside the radio), the
interrupt is disabled in the NVIC whenever it is trigered. Then,
whenever the IRQ flags *are* cleared in the radio, the IRQ is enabled in
the NVIC again. This requires making the SX126x::clearIrqStatus() method
virtual so STM32WLx can override it.
This is a nearly complete implementation, except that the Dio1 interrupt
is not yet supported (this will be added in a subsequent commit to
simplify review).
This fixes#588.