You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The primary purpose of this PR is to fix#524, allowing the LMIC to run without disabling interrupts at all, and without requiring any changes to underlying BSPs. When configured for interrupts, interrupts simply cause the current time stamp to be captured. The secondary ISR is run as part of os_runloop_once(). This should also fix#503, and address #528, #558, #548, and others.
In addition, since we're updating the radio driver, I addressed #524.
In testing, I discovered a subtle bug with one of our applications that uses LMIC_sendAlive() -- there was a path when sending piggybacked MAC data with a poll that would result in trying to take the port 0 path instead. This caused problems with ChirpStack and TTN, at least. (This is #570.)
Finally, updated to use Arduino IDE 1.8.12 in test.
Version of library changes to v3.1.0.20.
- [Interrupts and Arduino system timing](#interrupts-and-arduino-system-timing)
88
90
-[Downlink data rate](#downlink-data-rate)
89
91
-[Encoding Utilities](#encoding-utilities)
90
92
- [sflt16](#sflt16)
@@ -290,7 +292,7 @@ Configures the library for use with an sx1276 transceiver.
290
292
291
293
`#define LMIC_USE_INTERRUPTS`
292
294
293
-
If defined, configures the library to use interrupts for detecting events from the transceiver. If left undefined, the library will poll for events from the transceiver. See [Timing](#timing) for more info.
295
+
If defined, configures the library to use interrupts for detecting events from the transceiver. If left undefined, the library will poll for events from the transceiver. See [Timing](#timing) for more info. Be aware that interrupts are not tested or supported on many platforms.
294
296
295
297
### Disabling PING
296
298
@@ -812,32 +814,36 @@ This library provides several examples.
812
814
813
815
The library is
814
816
responsible for keeping track of time of certain network events, and scheduling
815
-
other events relative to those events. In particular, the library must note
817
+
other events relative to those events. For Class A uplink transmissions, the library must note
816
818
when a packet finishes transmitting, so it can open up the RX1 and RX2
817
819
receive windows at a fixed time after the end of transmission. The library does this
818
820
by watching for rising edges on the DIO0 output of the SX127x, and noting the time.
819
821
820
822
The library observes and processes rising edges on the pins as part of `os_runloop()` processing.
821
823
This can be configured in one of two ways (see
822
-
[Controlling use of interrupts](#controlling-use-of-interrupts)).
824
+
[Controlling use of interrupts](#controlling-use-of-interrupts)). See [Interrupts and Arduino system timing](#interrupts-and-arduino-system-timing) for implementation details.
823
825
824
-
By default, the routine `hal_io_check()`
826
+
By default, the library
825
827
polls the enabled pins to determine whether an event has occurred. This approach
826
828
allows use of any CPU pin to sense the DIOs, and makes no assumptions about
827
829
interrupts. However, it means that the end-of-transmit event is not observed
828
-
(and time-stamped) until `os_runloop()` is called.
830
+
(and time-stamped) until `os_runloop_once()` is called.
829
831
830
832
Optionally, you can configure the LMIC library to use interrupts. The
831
833
interrupt handlers capture the time of
832
-
the event. Actual processing is done the next time that `os_runloop()`
834
+
the event. Actual processing is done the next time that `os_runloop_once()`
833
835
is called, using the captured time. However, this requires that the
834
-
DIO pins be wired to Arduino pins that support rising-edge interrupts.
836
+
DIO pins be wired to Arduino pins that support rising-edge interrupts,
837
+
and it may require custom initialization code on your platform to
838
+
hook up the interrupts.
835
839
836
-
Fortunately, LoRa is a fairly slow protocol and the timing of the
837
-
receive windows is not super critical. To synchronize transmitter and
838
-
receiver, a preamble is first transmitted. Using LoRaWAN, this preamble
839
-
consists of 8 symbols, of which the receiver needs to see 4 symbols to
840
-
lock on. The current implementation tries to enable the receiver for 6
840
+
### Controlling protocol timing
841
+
842
+
The timing of end-of-transmit interrupts is used to determine when to open the downlink receive window. Because of the considerations above, some inaccuracy in the time stamp for the end-of-transmit interrupt is inevitable.
843
+
844
+
Fortunately, the timing of the receive windows at the device need not be extremely accurate; the LMIC has to turn on the receiver early enough to capture a downlink
845
+
from the gateway and must leave the receiver on long enough to compensate for timing
846
+
errors due to various inaccuracies. To make it easier for the device to catch downlinks, the gateway first transmits a preamble consisting of 8 symbols. The SX127x receiver needs to see at least 4 symbols to detect a message. The Arduino LMIC tries to enable the receiver for 6
841
847
symbol times slightly before the start of the receive window.
842
848
843
849
The HAL bases all timing on the Arduino `micros()` timer, which has a platform-specific
@@ -886,6 +892,20 @@ For a variety of reasons, the LMIC normally ignores clock errors greater than 40
886
892
887
893
This clock error is not reset by `LMIC_reset()`.
888
894
895
+
### Interrupts and Arduino system timing
896
+
897
+
The IBM LMIC used as the basis for this code disables interrupts while the radio driver is active, to prevent reentrancy via `radio_irq_handler()` at unexpected moments. It uses `os_getTime()`, and assumes that `os_getTime()` still works when interrupts were disabled. This causes problems on Arduino platforms. Most board support packages use interrupts to advance `millis()` and `micros()`, and with these BSPs, `millis()` and `micros()` return incorrect values while interrupts are disabled. Although some BSPs (like the ones provided by MCCI) provide real time correctly while interrupts are disabled, this is not portable. It's not practical to make such changes in every BSP.
898
+
899
+
To avoid this, the LMIC processes events in several steps; these steps ensure that `radio_irq_handler_v2()` is only called at predictable times.
900
+
901
+
1. If interrupts are enabled via `LMIC_USE_INTERRUPTS`, hardware interrupts catch the time of the interrupt and record that the interrupt occurred. These routines rely on hardware edge-sensitive interrupts. If your hardware interrupts are level-sensitive, you must mask the interrupt somehow at the ISR. You can't use SPI routines to talk to the radio, because this may leave the SPI system and the radio in undefined states. In this configuration, `hal_io_pollIRQs()` exists but is a no-op.
902
+
903
+
2. If interrupts are not enabled via `LMIC_USE_INTERRUPTS`, the digital I/O lines are polled every so often by calling the routine `hal_io_pollIRQs()`. This routine watches for edges on the relevant digital I/O lines, and records the time of transition.
904
+
905
+
3. The LMIC `os_runloop_once()` routine calls `hal_processPendingIRQs()`. This routine uses the timestamps captured by the hardware ISRs and `hal_io_pollIRQs()` to invoke `radio_irq_hander_v2()` with the appropriate information. `hal_processPendingIRQs()` in turn calls `hal_io_pollIRQs()` (in case interrupts are not configured).
906
+
907
+
4. For compatibility with older versions of the Arduino LMIC, `hal_enableIRQs()` also calls `hal_io_pollIRQs()` when enabling interrupts. However, it does not dispatch the interrupts to `radio_irq_handler_v2()`; this must be done by a subsequent call to `hal_processPendingIRQs()`.
908
+
889
909
## Downlink data rate
890
910
891
911
Note that the data rate used for downlink packets in the RX2 window varies by region. Consult your network's manual for any divergences from the LoRaWAN Regional Parameters. This library assumes that the network follows the regional default.
@@ -1195,6 +1215,9 @@ function uflt12f(rawUflt12)
1195
1215
1196
1216
- HEAD has the following changes:
1197
1217
1218
+
-[#570](https://github.com/mcci-catena/arduino-lmic/issue/570) corrects handling of piggy-back MAC responses when sending an `LMIC_sendAlive()` (`OPMODE_POLL`) message.
1219
+
-[#524](https://github.com/mcci-catena/arduino-lmic/issue/524) corrects handling of interrupt disable, and slightly refactors the low-level interrupt handling wrappers for clarity. With this change, `radio_irq_handler_v2()` is never called except from the run loop, and so the radio driver need not (and does not) disable interrupts. Version is v3.1.0.20.
1220
+
-[#568](https://github.com/mcci-catena/arduino-lmic/issue/568) improves documentation for the radio driver.
1198
1221
-[#537](https://github.com/mcci-catena/arduino-lmic/pull/537) fixes a compile error in SX1272 support. (Thanks @ricaun.) Version is v3.1.0.10.
1199
1222
1200
1223
- v3.1.0 officially adopts the changes from v3.0.99. There were dozens of changes; check the GitHub issue logs and change logs. This was a breaking release (due to changes in data layout in the LMIC structure; the structure is accessed by apps).
0 commit comments