mirror of
https://github.com/apache/nuttx.git
synced 2026-09-24 08:45:04 +08:00
wireless/lpwan: add SX1301 LoRa concentrator driver
Character driver for the Semtech SX1301, the baseband processor of a LoRaWAN gateway, and the two SX125x radios it drives. Received packets come from read(), downlinks go to write(), and the channel plan, the start and the stop are ioctls. The interface is device independent, in nuttx/wireless/lpwan/lora_gw.h with the commands in the common WLIOC_GW_* space, so another concentrator driver can implement it and the same application drive it. Adds a lorawan_gw configuration for the Nucleo F746ZG with a shield of the LRWAN_GS_HF1 family. Off by default (LPWAN_SX1301). Assisted-by: Claude Code 4.8 Signed-off-by: Jorge Guzman <jorge.gzm@gmail.com>
This commit is contained in:
committed by
Alan C. Assis
parent
790a197ed0
commit
f37bc4546e
@@ -5,5 +5,6 @@ LPWAN
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
lora_gw.rst
|
||||
sx126x.rst
|
||||
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
.. _lora_gw:
|
||||
|
||||
================================
|
||||
LoRa gateway (concentrator) API
|
||||
================================
|
||||
|
||||
A LoRa gateway does not listen to one channel at a time as an end device
|
||||
does: a concentrator demodulates several channels at once, on two radio
|
||||
front-ends, and every packet arrives with its own frequency, spreading factor
|
||||
and coding rate. The commands that configure a radio, ``WLIOC_SETRADIOFREQ``
|
||||
and the ``WLIOC_LORA_x`` family, therefore have nothing to act upon on such a
|
||||
device, and what it needs instead is a channel plan, a way to be started and
|
||||
stopped, and the counter its timestamps are taken from.
|
||||
|
||||
This is the device independent interface those drivers implement, declared in
|
||||
``nuttx/wireless/lpwan/lora_gw.h``. An application drives a gateway through it
|
||||
and never names a chip.
|
||||
|
||||
Character device
|
||||
================
|
||||
|
||||
A driver of this class registers a character device, ``/dev/lora0`` by
|
||||
convention, on which:
|
||||
|
||||
* ``read`` returns whole multiples of ``struct lora_gw_rxpkt_s``, oldest
|
||||
first, as many as fit in the buffer. It blocks until at least one packet is
|
||||
available unless the file was opened with ``O_NONBLOCK``, and fails with
|
||||
``EINVAL`` if the buffer cannot hold one whole packet.
|
||||
|
||||
* ``write`` takes exactly one ``struct lora_gw_txpkt_s``. The packet carries
|
||||
its own frequency, power, modulation and, for a LoRaWAN downlink,
|
||||
``invert_pol``. It is sent immediately with ``LORA_GW_TX_IMMEDIATE`` or at a
|
||||
concentrator timestamp with ``LORA_GW_TX_TIMESTAMPED``.
|
||||
|
||||
Both structures follow the layout of the userspace HAL that Semtech publishes
|
||||
for this family of chips, which is what gateway software is written against
|
||||
on other systems, so that such an application ports by replacing its
|
||||
``lgw_receive`` with ``read`` and its ``lgw_send`` with ``write``. Two things
|
||||
deliberately differ:
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - Field
|
||||
- Unit
|
||||
* - ``rssi_dbm10``, ``snr_db10``
|
||||
- Tenths of a dBm or dB, as integers, so that no floating point is
|
||||
needed in a driver
|
||||
* - ``datarate``
|
||||
- The spreading factor as a plain number, 7 to 12, not a bit mask
|
||||
* - ``bandwidth``
|
||||
- ``LORA_GW_BW_125K``, ``_250K`` or ``_500K``
|
||||
* - ``coderate``
|
||||
- ``enum wlioc_lora_cr_e``, shared with the end device drivers
|
||||
* - ``status``
|
||||
- ``LORA_GW_STAT_CRC_OK``, ``_CRC_BAD`` or ``_NO_CRC``
|
||||
|
||||
A packet reported as ``LORA_GW_STAT_CRC_BAD`` must never be forwarded as if
|
||||
it were valid: those are mostly correlator false triggers.
|
||||
|
||||
IOCTL commands
|
||||
==============
|
||||
|
||||
See ``nuttx/wireless/ioctl.h`` : ``WLIOC_GW_x``.
|
||||
|
||||
* ``WLIOC_GW_START`` resets the chip, loads the firmware of its internal
|
||||
MCUs, calibrates it and starts receiving on the selected channel plan.
|
||||
``WLIOC_GW_STOP`` stops it and ``WLIOC_GW_RESET`` does both in sequence.
|
||||
|
||||
* ``WLIOC_GW_SETREGION`` selects a channel plan by name, for example
|
||||
``"AU915"``, while the concentrator is stopped. ``WLIOC_GW_GETREGION``
|
||||
takes a ``struct lora_gw_regionreq_s``: an ``index`` of -1 describes the
|
||||
active plan, and 0 upwards enumerates the supported ones until ``ENODEV``.
|
||||
The description that comes back lists the centre frequency of each radio
|
||||
and the frequency, radio and type of every channel.
|
||||
|
||||
* ``WLIOC_GW_GETSTATUS`` fills a ``struct lora_gw_status_s`` with the state
|
||||
of the concentrator and its counters, including the packets dropped
|
||||
because their CRC failed.
|
||||
|
||||
* ``WLIOC_GW_GETTRIGCNT`` reads the internal counter of the concentrator, in
|
||||
microseconds. This is the time base a LoRaWAN network server schedules
|
||||
downlinks against.
|
||||
|
||||
Whether the units of the packet should instead follow the ones of the end
|
||||
device commands, that is, bandwidth in Hz and levels scaled by a hundred as
|
||||
in ``struct wlioc_rx_hdr_s``, is a question for the common LoRa API rather
|
||||
than for one driver, and is left as it is until that API materialises.
|
||||
|
||||
SX1301 driver
|
||||
=============
|
||||
|
||||
The Semtech SX1301 is the baseband processor of a LoRaWAN gateway: eight
|
||||
multi-SF demodulators, one LoRa standard demodulator and one FSK
|
||||
demodulator, driven by two SX125x radio front-ends that are reached through
|
||||
an SPI bridge inside the SX1301 itself. It is the first implementation of the
|
||||
interface above and is enabled with ``CONFIG_LPWAN_SX1301``.
|
||||
|
||||
Options
|
||||
-------
|
||||
|
||||
* ``CONFIG_LPWAN_SX1301_SPIFREQ`` is the SPI clock, up to 10 MHz.
|
||||
|
||||
* ``CONFIG_LPWAN_SX1301_DEFAULT_REGION`` is the channel plan selected when
|
||||
the driver is registered: one of AU915, AU915-1, US915, US915-1, EU868,
|
||||
AS923, KR920 or IN866. AU915 and US915 default to the second sub-band,
|
||||
which is what The Things Network and the Brazilian deployments use.
|
||||
|
||||
* ``CONFIG_LPWAN_SX1301_PRIVATE_NETWORK`` switches the frame synchronisation
|
||||
word from the public LoRaWAN one to the private one.
|
||||
|
||||
* ``CONFIG_LPWAN_SX1301_RXBADCRC`` and ``CONFIG_LPWAN_SX1301_RXNOCRC``
|
||||
deliver the packets that a gateway normally drops, which is useful when
|
||||
bringing a shield up against an unknown transmitter.
|
||||
|
||||
Board implementation
|
||||
--------------------
|
||||
|
||||
The driver is registered with ``sx1301_register``, which takes the device
|
||||
path, an SPI bus and a ``struct sx1301_lower_s``. That structure carries the
|
||||
two things the chip needs from the board: a ``reset`` hook driving its reset
|
||||
line, and an optional ``band_select`` hook for the shields whose front-end
|
||||
filters are switched between 868 and 915 MHz by a pair of GPIOs. See
|
||||
``nuttx/wireless/lpwan/sx1301.h``.
|
||||
|
||||
A worked example, with the wiring of an LRWAN_GS_HF1 shield, the expected
|
||||
boot output and a gateway forwarding to a public network, is in the
|
||||
:ref:`Nucleo F746ZG <nucleo-f746zg>` page.
|
||||
@@ -1,9 +1,14 @@
|
||||
.. _nucleo-f746zg:
|
||||
|
||||
================
|
||||
ST Nucleo F746ZG
|
||||
================
|
||||
|
||||
.. tags:: chip:stm32, chip:stm32f7, chip:stm32f746
|
||||
|
||||
.. figure:: nucleo-f746zg.jpg
|
||||
:align: center
|
||||
|
||||
This page discusses issues unique to NuttX configurations for the STMicro
|
||||
Nucleo-144 board. See ST document STM32 Nucleo-144 boards (UM1974):
|
||||
|
||||
@@ -313,6 +318,40 @@ and connect it as follows::
|
||||
CD PC11 CN11-2
|
||||
|
||||
|
||||
LoRa Concentrator Shield
|
||||
------------------------
|
||||
|
||||
The board supports a LoRa gateway shield of the LRWAN_GS_HF1 family, such as
|
||||
the RisingHF RHF0M301, which carries a Semtech SX1301 baseband processor and
|
||||
two SX1257 radio front ends. The shield is wired to SPI4 on the morpho
|
||||
connector::
|
||||
|
||||
FUNCTION GPIO CONNECTOR
|
||||
------------ ---- ---------
|
||||
SPI4_SCK PE12 CN11-49
|
||||
SPI4_MISO PE13 CN11-47
|
||||
SPI4_MOSI PE14 CN11-45
|
||||
SPI4_CS PE11 CN11-53
|
||||
SX1301_RESET PE15 active high
|
||||
BAND_SET1 PD15 D9, front end filter select
|
||||
BAND_SET2 PE9 D6, front end filter select
|
||||
------------ ---- ---------
|
||||
|
||||
The chip select is driven as a plain output rather than by the hardware NSS,
|
||||
as the concentrator needs it held low for a whole burst. The two band
|
||||
selection lines drive the filter bank of the shield: 915 MHz uses SET1 low
|
||||
and SET2 high, 868 MHz the other way around.
|
||||
|
||||
With ``CONFIG_LPWAN_SX1301`` selected, the board registers the concentrator
|
||||
at ``/dev/lora0``, behind the device independent gateway interface. That
|
||||
interface, the configuration options of the driver and the channel plans it
|
||||
supports are documented in :ref:`lora_gw`.
|
||||
|
||||
The same shields usually carry a serial NOR flash on SPI5 (PF7 SCK, PF8
|
||||
MISO, PF9 MOSI, PF6 CS). The pins are defined in ``include/board.h`` and the
|
||||
chip select is handled by the board, but no MTD driver is registered for it
|
||||
yet.
|
||||
|
||||
Configurations
|
||||
==============
|
||||
|
||||
@@ -421,3 +460,68 @@ NOTES:
|
||||
|
||||
CONFIG_HOST_LINUX=y : Builds under Linux
|
||||
CONFIG_ARM_TOOLCHAIN_GNU_EABI=y : ARM GNU for Linux
|
||||
|
||||
lorawan_gw
|
||||
----------
|
||||
|
||||
Turns the board into a LoRaWAN gateway: the SX1301 concentrator on SPI4 and
|
||||
the Ethernet interface with DHCP and DNS. The console is the virtual COM port
|
||||
on USART3.
|
||||
|
||||
Selecting ``CONFIG_WIRELESS_LORA_PKT_FWD`` adds the Semtech UDP packet
|
||||
forwarder of ``apps/wireless/lora_pkt_fwd``, which is what turns the
|
||||
concentrator into a gateway and provides the ``lora`` command used below.
|
||||
|
||||
.. figure:: nucleo-f746zg-lora-sx1301.png
|
||||
:align: center
|
||||
|
||||
The board with an LRWAN_GS_HF1 shield mounted on the morpho headers.
|
||||
|
||||
Build and flash::
|
||||
|
||||
$ ./tools/configure.sh nucleo-f746zg:lorawan_gw
|
||||
$ make
|
||||
$ cp nuttx.bin /media/<user>/NODE_F746ZG/
|
||||
|
||||
The forwarder and the concentrator are driven by the ``lora`` command, which
|
||||
mirrors the AT command set of the vendor gateway firmwares::
|
||||
|
||||
nsh> lora # list the subcommands
|
||||
nsh> lora sys # identity, network and channel plan
|
||||
nsh> lora ch # show the channel plan
|
||||
nsh> lora ch EU868 # change region: AU915, AU915-1, US915,
|
||||
# US915-1, EU868, AS923, KR920, IN866
|
||||
nsh> lora server <host> [up] [down] # network server, name or address
|
||||
nsh> lora start # start the concentrator and forward
|
||||
nsh> lora status # counters of both sides
|
||||
nsh> lora stop
|
||||
nsh> lora tx 917200000 7 hello # transmit one packet, for bring-up
|
||||
|
||||
The last one exists to bring a gateway up without a network server: it
|
||||
sends a single packet with the polarity of an uplink, so any LoRa receiver
|
||||
tuned to the same frequency, spreading factor and 125 kHz bandwidth sees
|
||||
it.
|
||||
|
||||
The default region is the second sub-band of AU915 (channels 8 to 15 plus the
|
||||
500 kHz channel 65), which is what The Things Network and the Brazilian
|
||||
deployments use; ``AU915-1`` selects the first sub-band instead. The default
|
||||
server and the gateway identifier come from the configuration
|
||||
(``CONFIG_LORA_PKT_FWD_SERVER`` and ``CONFIG_LORA_PKT_FWD_EUI``) and both can
|
||||
be changed at runtime.
|
||||
|
||||
A working session looks like this::
|
||||
|
||||
nsh> lora start
|
||||
sx1301_reg_probe: SX1301 detected, version 0x67
|
||||
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_agc_start: AGC running, radio map 0xf0
|
||||
sx1301_start: Concentrator started, modems 0x0b
|
||||
lora: forwarding to au1.cloud.thethings.network (up 1700, down 1700)
|
||||
sx1301_receive: RX chain 0 SF10 915200000 Hz snr 14.0 dB size 23 status 0x10
|
||||
lora: forwarded 1 packet(s)
|
||||
|
||||
Note that the sync word has to match the devices: the driver configures the
|
||||
concentrator for a public LoRaWAN network, and
|
||||
``CONFIG_LPWAN_SX1301_PRIVATE_NETWORK`` switches it to a private one.
|
||||
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 519 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 59 KiB |
Reference in New Issue
Block a user