JorgeGzm opened a new pull request, #19675:
URL: https://github.com/apache/nuttx/pull/19675
## Summary
Adds a character driver for the Semtech SX1301, the baseband processor of a
LoRaWAN gateway, together with the two SX125x radio front ends that it drives
through its internal SPI bridge. The driver resets the chip, loads the three
MCU firmware images, runs the calibration pass and the AGC handshake, and
then
exposes the receive FIFO and the transmitter through `read()`, `write()` and
a
small set of ioctls. Eight channel plans are provided, from AU915 to IN866,
and
the firmware images are `const` so that they stay in flash instead of taking
24 KiB of RAM.
Two details of the Semtech reference HAL are easy to miss, and both were
found
on hardware:
- The bridge that reaches the radios needs time between the chip select pulse
and the read back register. A Linux host gets that for free from the cost
of
a spidev transaction; here the register writes are fast enough that the
radios always read back as zero, which looks exactly like a dead board.
- The frame synchronisation registers come up configured for a private
network. A gateway that leaves them alone never detects a single frame of a
public LoRaWAN device.
Board support is added for the Nucleo F746ZG carrying a shield of the
LRWAN_GS_HF1 family on SPI4, with a `lorawan_gw` configuration that brings up
Ethernet, DHCP and DNS along with the concentrator.
The SX127X driver gains what an SX1276 needs to talk to such a gateway, and
three defects found while making that work are fixed:
- **Frequency.** `SX127X_FSTEP` divided by a step truncated to 61 Hz, while a
step is `FXOSC/2**19`, about 61.035 Hz. The 0.06 per cent error puts a
915 MHz channel more than 500 kHz away from the requested frequency,
outside
its own bandwidth: frames were transmitted, but on the wrong channel and
undecodable by anything tuned correctly. Two NuttX radios still talked to
each other, since both were wrong by the same amount.
- **Band.** The high or low frequency front end is now selected from the
configured frequency instead of being left at the reset value.
- **Unused function.** `sx127x_rx_watchdog()` is only wired into the FSK and
OOK receive path, but was compiled whenever receive support was on. A LoRa
only configuration therefore failed to build with the flags of the CI. This
is not hypothetical: `nrf52840-dk:sx127x` is such a configuration and does
not build on master today (see Testing).
On STM32L0 the SYSCFG clock was never enabled, because the symbol that
guarded
it does not exist in Kconfig for this chip. The mapping of a pin to an EXTI
line lives in `SYSCFG_EXTICR`, so every write to it was dropped and the
mapping
stayed at its reset value: a GPIO interrupt on any port other than port A
silently never fired. `nucleo-l073rz` has DIO0 of its radio on PA10 and works
by accident, which is probably why this went unnoticed; the B-L072Z-LRWAN1
has
it on PB4, so a transmission never completed and the driver waited forever.
The same pattern is present in the STM32C0 and STM32G0 clock setup and was
left
alone, as no board was available to test them.
On the B-L072Z-LRWAN1 the TCXO that clocks the radio is now powered before
the
driver is registered, the user button is corrected to PB2 because PC13
carries
DIO3 of the radio on this board, and two configurations are added for use as
a
LoRa transmitter.
## Impact
<img width="434" height="800" alt="nucleo-f746zg-lora-sx1301"
src="https://github.com/user-attachments/assets/0ac6cfc7-ee86-4900-b265-44402ccc4b48"
/>
<img width="653" height="306" alt="b-l072z-lrwan1"
src="https://github.com/user-attachments/assets/01d46784-fe9a-4d72-9b0b-3754b64f3e80"
/>
New driver, new board support, and one fix per existing area:
- `drivers/wireless/lpwan/sx1301`: new, off by default (`LPWAN_SX1301`).
- `drivers/wireless/lpwan/sx127x`: the frequency and band fixes change the
frequency actually used on the air, in the direction of the requested one.
Anyone who compensated for the old error in an application will notice. The
three new Kconfig options keep the previous behaviour by default (sync word
0x12, 7.8 kHz bandwidth, spreading factor 7).
- `arch/arm/src/stm32l0`: one clock enable. Every STM32L0 board gains working
GPIO interrupts outside port A; nothing that worked before stops working.
- Boards: `nucleo-f746zg` gains SPI4 and SPI5 pin definitions and the
concentrator glue; `b-l072z-lrwan1` gains the TCXO line and the corrected
button pin.
- Documentation: both board pages.
## Testing
Host: Ubuntu 24.04.4 LTS, x86_64, Linux 7.0.0-28-generic
- arm-none-eabi-gcc 13.2.1 (Arm GNU Toolchain 13.2.rel1)
- xtensa-esp32-elf-gcc from the NuttX SDK, for the ESP32 board
Every build below uses the warning flags of the CI:
`make EXTRAFLAGS="-Wno-cpp -Werror"`.
### Build
| Configuration | text | data | bss |
|---|---|---|---|
| `nucleo-f746zg:lorawan_gw` (new) | 362536 | 1672 | 41496 |
| `nucleo-f746zg:nsh` | 140010 | 888 | 4952 |
| `b-l072z-lrwan1:lorawan_tx` (new) | 81500 | 1076 | 3416 |
| `b-l072z-lrwan1:lorawan_beacon` (new) | 88368 | 1076 | 3424 |
| `b-l072z-lrwan1:sx127x` | 82824 | 1076 | 3432 |
| `nucleo-l073rz:sx127x` | 80268 | 1076 | 3404 |
| `nucleo-f091rc:sx127x` | 80556 | 1076 | 3408 |
| `nrf52840-dk:sx127x` | 101052 | 1088 | 6044 |
| `heltec_wifi_lora32:sx1276` | 116324 | 21040 | 9096 |
All of them build with no warning and no error. The last five are the other
users of the SX127X driver in the tree, built to show that the driver changes
do not regress them.
`nrf52840-dk:sx127x` does not build on master, which is what the unused
function fix addresses:
```
$ make -j EXTRAFLAGS="-Wno-cpp -Werror"
wireless/lpwan/sx127x/sx127x.c:1291:13: error: 'sx127x_rx_watchdog' defined
but
not used [-Werror=unused-function]
```
`nxstyle` reports nothing on the 34 changed files, `refresh.sh` leaves every
touched configuration unchanged, and the two documentation pages build with
`sphinx -W`.
### Concentrator, on hardware
Nucleo F746ZG with a RisingHF RHF0M301 shield, `lorawan_gw`:
```
nsh> lora start
sx1301_reg_probe: SX1301 detected, version 0x67
sx1301_setup_radio: Radio A: SX125x version 0x21
sx1301_setup_radio: Radio A: PLL locked at 917100000 Hz
sx1301_setup_radio: Radio B: PLL locked at 917900000 Hz
sx1301_calibrate: Calibration done, status 0xbf
sx1301_start: Arbiter firmware version 1 (expected 1)
sx1301_agc_start: AGC running, radio map 0xf0
sx1301_start: Concentrator started, modems 0x0b
```
### Receiving a LoRaWAN device
An end device based on an SX1276 sending its join request, AU915 first
sub-band:
```
sx1301_receive: RX chain 0 SF10 915200000 Hz snr 14.0 dB size 23 status 0x10
sx1301_receive: RX chain 3 SF10 915800000 Hz snr 13.7 dB size 23 status 0x10
```
Status 0x10 is a valid CRC, and 23 bytes is the exact length of a join
request. Forwarded to a network server over the internet with the forwarder
of
the companion pull request in nuttx-apps:
```
lora: forwarding to au1.cloud.thethings.network (up 1700, down 1700)
lora: forwarded 1 packet(s)
RX OK: 1 RX FWD: 1 PUSH: 4 sent, 3 acked PULL: 19 sent, 18 acked
```
### Receiving an SX127X, which is what the SX127X fixes are for
B-L072Z-LRWAN1 running `lorawan_tx` and transmitting on 917.2 MHz with
`sx127x -m 0 -f 917200000 -t -p 0 -l 32`.
Before the frequency fix the frames arrived on the channel 600 kHz above the
requested one and never passed the CRC:
```
sx1301_receive: RX chain 5 SF7 917800000 Hz snr 0.2 dB size 32 status 0x11
sx1301_receive: RX chain 5 SF7 917800000 Hz snr -1.7 dB size 32 status 0x11
```
After it, on the requested channel and with a valid CRC:
```
sx1301_receive: RX chain 2 SF7 917200000 Hz snr 8.2 dB size 32 status 0x10
sx1301_receive: RX chain 2 SF7 917200000 Hz snr 8.5 dB size 32 status 0x10
```
Before the SYSCFG fix the same board sent one frame per reset and then
blocked
forever waiting for the transmit interrupt; after it, 509 frames in 30 s. The
mapping register, read from the running firmware, confirms why:
```
nsh> xd 0x4001000c 4 # SYSCFG_EXTICR2, holds EXTI line 4
0000: 00 00 00 00 # before: line 4 on port A, while DIO0 is PB4
0000: 01 00 00 00 # after: line 4 on port B
```
### Transmitting
The concentrator sends a packet with `lora tx 917200000 7 hello-from-gateway`
and two B-L072Z-LRWAN1 boards listening on that frequency receive it:
```
board A> Received: SNR = 6 RSSI = -29 len = 18
board B> Received: SNR = 7 RSSI = -30 len = 18
0x68 0x65 0x6c 0x6c 0x6f 0x2d 0x66 0x72 0x6f 0x6d
```
Five transmissions, five receptions on each board.
The Docker based CI lists were not run locally; they are left to the CI of
the
pull request.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]