Skip to content

Add LoRa Basics Modem radio drivers and LoRaWAN stack #77495

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

Salamandar
Copy link
Contributor

@Salamandar Salamandar commented Aug 23, 2024

This pull request adds support for the Semtech transceivers with the "radio drivers", and for the LoRaWAN stack, both provided by the LoRa Basics Modem project (https://github.com/Lora-net/SWL2001)

This PR adds:

  • A new external module, the repository SWL2001 from Semtech
  • Duplicated drivers for LR11xx and SX126x LoRa transceivers -> I postfixed the compatible with -new, but what's the guideline on that ?
    • The drivers don't expose any API as the LBM repository provides one and the LBM stack uses the "RAL" "Radio Abstraction Layer". We might need to create an ad-hoc API for Zephyr.
  • The LoRaWAN subsystem based on the LBM stack
    • The subsys actually only contains the Kconfig and the source for the "main stack thread". The rest of the code and bindings lives in the module.
    • I named the drivers lora_lbm and subsys lorawan_lbm, to differentiate from the loramac-node implementations.
  • Samples: driver samples written from scratch and LBM "examples" ported from the SWL2001 repository.
    • Those ported examples come with the app_helpers code in modules/lora_basics_modem for portability purpose, but this should be cleaned up.

EDIT: I splitted this PR in half : this PR contains only code that was written with zephyr in mind. The samples that still need porting are in https://github.com/salamandar/zephyr/tree/lbm_samples

@zephyrbot zephyrbot added area: Samples Samples area: Shields Shields (add-on boards) labels Aug 23, 2024
@Salamandar Salamandar changed the title Add LoRa Basics Modem radio drivers and LoRaWAN stack Draft: Add LoRa Basics Modem radio drivers and LoRaWAN stack Aug 23, 2024
@zephyrbot
Copy link
Collaborator

zephyrbot commented Aug 23, 2024

The following west manifest projects have changed revision in this Pull Request:

Name Old Revision New Revision Diff
lora_basics_modem 🆕 N/A (Added) Lora-net/SWL2001@v4.8.0 N/A

DNM label due to: 1 added project

Note: This message is automatically posted and updated by the Manifest GitHub Action.

@zephyrbot zephyrbot added manifest manifest-lora_basics_modem DNM This PR should not be merged (Do Not Merge) labels Aug 23, 2024
@zafersn
Copy link
Contributor

zafersn commented Aug 26, 2024

Hi, @Salamandar, did you have chance to test this with CONFIG_PM?

When I enable it, join requests always fail. still investigating this issue...

Any idea what the issue could be?

P.S.
I was also working on porting this basic lib to zephyr and finished it just couple of days ago. and just noticed your implementation now :)

@Salamandar Salamandar force-pushed the lora_basics_modem branch 2 times, most recently from d74b021 to abbb834 Compare August 26, 2024 11:35
@zafersn
Copy link
Contributor

zafersn commented Aug 26, 2024

Hi @Salamandar I’m not sure if this is the best place to discuss build failures, but I wanted to share these with you. If there’s a more appropriate forum or person for this, please let me know.

here are errors: when I build your pull request:

Probably you know, but anyway:

disable wdt:
CONFIG_WATCHDOG=n

got error:

zephyr/modules/lora_basics_modem/app_helpers/smtc_hal_zephyr/smtc_hal_watchdog.c:57: undefined reference to `__device_dts_ord_115'

workaround for now.

void hal_watchdog_reload(void)
{
#ifdef CONFIG_WATCHDOG
	 wdt_feed(prv_wdt_dev, prv_wdt_channel_id);
#endif
}

disabling all region supports:
CONFIG_LORA_BASICS_MODEM_ENABLE_ALL_REGIONS=n

compiling is ok but

*** Booting Zephyr OS build v3.7.0-rc3-124-gabbb8340c2af ***
[00:00:00.000,000] <inf> smtc_modem: Periodical uplink (60 sec) example is starting
[00:00:00.000,000] <inf> smtc_modem: Modem Initialization
[00:00:00.203,000] <inf> smtc_modem: Use soft secure element for cryptographic functionalities
[00:00:00.203,000] <inf> smtc_modem_hal: Opened flash area of size 65536
[00:00:00.203,000] <err> smtc_modem: Invalid Region 0x01
[00:00:00.203,000] <err> smtc_modem: Region (0x1) in nvm context not supported
[00:00:00.203,000] <wrn> smtc_modem: No valid lr1mac context --> Factory reset
[00:00:00.261,000] <inf> smtc_modem: stack_id 0
[00:00:00.261,000] <inf> smtc_modem: DevNonce = 0
[00:00:00.261,000] <inf> smtc_modem: JoinNonce = 0xff ff ff, NetID = 0xff ff ff
[00:00:00.261,000] <inf> smtc_modem: Region = CN470
[00:00:00.261,000] <inf> smtc_modem: LoRaWAN Certification is disabled on stack 0
[00:00:00.261,000] <inf> smtc_modem: lorawan_alcsync_services_init task_id 7, service_id 0, CURRENT_STACK:0
[00:00:00.261,000] <wrn> smtc_modem: stream_services_init
[00:00:00.261,000] <wrn> smtc_modem: lfu_services_init
[00:00:00.290,000] <inf> smtc_modem: Modem event callback
[00:00:00.290,000] <inf> smtc_modem: Event received: RESET
[00:00:00.290,000] <err> smtc_modem: Invalid Region 0x01
[00:00:00.291,000] <err> smtc_modem: In WEST_TOPDIR/wsc/periodical_uplink_semtec/src/main_periodical_uplink.c - modem_event_callback (line 373): SMTC_MODEM_RC_INVALID
[00:00:00.291,000] <inf> smtc_modem: smtc_modem_join_network
[00:00:00.291,000] <inf> smtc_modem: Start a new join sequence in 3 seconds on stack 0
[00:00:00.291,000] <inf> smtc_modem: Starting loop...
[00:00:00.291,000] <inf> smtc_modem: Sleeping for 3000ms
[00:00:03.291,000] <inf> smtc_modem: Sleeping for 0ms
[00:00:03.291,000] <inf> smtc_modem: Sleeping for 10000ms
[00:00:06.859,000] <inf> smtc_modem: modem_tpm_radio_busy_lbt
[00:00:06.859,000] <inf> smtc_modem: Sleeping for 10000ms

Ill share the quick workaround solution shortly

@Salamandar Salamandar force-pushed the lora_basics_modem branch 8 times, most recently from bcb80a0 to 16fdee2 Compare August 26, 2024 19:40
@erwango erwango removed their request for review February 4, 2025 14:24
@fabiobaltieri fabiobaltieri added DNM (manifest) This PR should not be merged (controlled by action-manifest) and removed DNM This PR should not be merged (Do Not Merge) labels Feb 4, 2025
@Salamandar
Copy link
Contributor Author

@Salamandar Is that still actually a Draft work ?

It is still a work in progress but, indeed, not a draft anymore.

I expect a lot of comments, and requests for changes, that's a bit why I named it a "draft". But you're right, that is misleading on the state of the code.

@Salamandar Salamandar changed the title Draft: Add LoRa Basics Modem radio drivers and LoRaWAN stack Add LoRa Basics Modem radio drivers and LoRaWAN stack Feb 4, 2025
@Salamandar
Copy link
Contributor Author

FYI the compliance checks fail on something where clang-format and Checkpatch disagree, see #83374.

@martinjaeger
Copy link
Member

As a general comment: We try to avoid having multiple implementation for the same thing in the Zephyr tree. This means that the new LoRa Basics Modem will finally have to replace the "old" LoRaMAC-node stack. If it's not feasible to replace the entire stack at once, we can have a transition phase with both options in parallel (implementation selectable via Kconfig). But we should ideally try to use the same user-facing API for both.

I suggest to split this PR into several smaller chunks which make it easier to review:

  • If that makes sense, we could update just the LoRa driver first and the entire LoRaWAN stack in a follow-up PR?
  • New boards/shields/samples should be added in a follow-up PR once the driver and LoRaWAN stack updates are merged.

Existing devicetree bindings should be reused (and changed/extended, if required).

Do you think we can (mostly) re-use the existing APIs in include/zephyr/drivers/lora.h and include/zephyr/lorawan/lorawan.h with the new stack?

@wietsedv
Copy link

Semtech appears to have written an out-of-tree LBM Zephyr driver themselves. It would probably be a good idea to compare these two implementations.

@kartben
Copy link
Collaborator

kartben commented Feb 25, 2025

Semtech appears to have written an out-of-tree LBM Zephyr driver themselves. It would probably be a good idea to compare these two implementations.

@wietsedv well this PR is from Semtech, so basically the same code (or a subset of it, at least) :)

This module provides:
* The cmake files for LoRa Basics Modem
* The "HAL" described here:
  https://github.com/Lora-net/SWL2001/blob/master/lbm_lib/PORTING_GUIDE.md
* Reimplementations of the logging functions in smtc_modem_hal_dbg_trace.h

Signed-off-by: Félix Piédallu <felix@piedallu.me>
Those drivers are actually device tree bindings, and HAL/BSP as described
in https://github.com/Lora-net/SWL2001/blob/master/lbm_lib/PORTING_GUIDE.md

Signed-off-by: Félix Piédallu <felix@piedallu.me>
Those shields are sold by Semtech and are arduino compatible.

Signed-off-by: Félix Piédallu <felix@piedallu.me>
This stack is based on the lora_basics_modem external module.

It provides configuration for LBM as well as a standalone
"main" LBM thread that needs to be manually started.

Signed-off-by: Félix Piédallu <felix@piedallu.me>
Copy link

This pull request has been marked as stale because it has been open (more than) 60 days with no activity. Remove the stale label or add a comment saying that you would like to have the label removed otherwise this pull request will automatically be closed in 14 days. Note, that you can always re-open a closed pull request at any time.

@github-actions github-actions bot added the Stale label Apr 27, 2025
@JordanYates
Copy link
Collaborator

I am planning to start looking at this in the near future.
Since this PR is quite large, I think a better process is going to be building up support in-tree in smaller chunks, starting with just the basic LoRa API (packet send/receive).
This will let us get the infrastructure (repo fork, build system etc) in place without an overwhelming diff.
We can then look at the LoRaWAN integration, new boards, etc in follow-on PRs.

@github-actions github-actions bot removed the Stale label Apr 28, 2025
@martinjaeger
Copy link
Member

martinjaeger commented Apr 28, 2025

@JordanYates FYI: Unfortunately, Semtech decided not to continue funding the upstreaming process of the LoRa Basics Modem stack to Zephyr and leave it to the community. Before you spend much time into reviewing the PR, we should check with @Salamandar if he will be able to continue working on this PR.

@kartben kartben requested a review from Copilot April 28, 2025 12:53
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces support for Semtech transceivers by adding a new external module from the LoRa Basics Modem repository, duplicated LoRa transceiver drivers, and a LoRaWAN subsystem built on top of the LBM stack.

  • Added Salamandar as a maintainer and updated file globs for new drivers and bindings.
  • Introduced a new West project for lora_basics_modem support.
Files not reviewed (19)
  • boards/shields/semtech_lr11xxmb1xxs/Kconfig.shield: Language not supported
  • boards/shields/semtech_lr11xxmb1xxs/doc/index.rst: Language not supported
  • boards/shields/semtech_lr11xxmb1xxs/semtech_lr1110mb1xxs.overlay: Language not supported
  • boards/shields/semtech_lr11xxmb1xxs/semtech_lr1120mb1xxs.overlay: Language not supported
  • boards/shields/semtech_lr11xxmb1xxs/semtech_lr1121mb1xxs.overlay: Language not supported
  • boards/shields/semtech_lr11xxmb1xxs/semtech_lr11xxmb1xxs_common.dtsi: Language not supported
  • boards/shields/semtech_sx126xmb2xxs/Kconfig.shield: Language not supported
  • boards/shields/semtech_sx126xmb2xxs/doc/index.rst: Language not supported
  • boards/shields/semtech_sx126xmb2xxs/semtech_sx1261mb1bas.overlay: Language not supported
  • boards/shields/semtech_sx126xmb2xxs/semtech_sx1261mb1cas.overlay: Language not supported
  • boards/shields/semtech_sx126xmb2xxs/semtech_sx1261mb2bas.overlay: Language not supported
  • boards/shields/semtech_sx126xmb2xxs/semtech_sx1262mb1cas.overlay: Language not supported
  • boards/shields/semtech_sx126xmb2xxs/semtech_sx1262mb1cbs.overlay: Language not supported
  • boards/shields/semtech_sx126xmb2xxs/semtech_sx1262mb1das.overlay: Language not supported
  • boards/shields/semtech_sx126xmb2xxs/semtech_sx1262mb1pas.overlay: Language not supported
  • boards/shields/semtech_sx126xmb2xxs/semtech_sx1262mb2cas.overlay: Language not supported
  • boards/shields/semtech_sx126xmb2xxs/semtech_sx1268mb1gas.overlay: Language not supported
  • boards/shields/semtech_sx126xmb2xxs/semtech_sx126xmb1xxs_common.dtsi: Language not supported
  • boards/shields/semtech_sx126xmb2xxs/semtech_sx126xmb2xxs_common.dtsi: Language not supported
Comments suppressed due to low confidence (1)

MAINTAINERS.yml:2677

  • The glob pattern 'semtech_sx12*' may be ambiguous given the reference to SX126x transceivers in the PR description. Please verify if this pattern should be updated to 'semtech_sx126*' to accurately match the target board files.
    - boards/shields/semtech_sx12*/

@fmoessbauer
Copy link
Contributor

As I just stumbled upon the shortcomings of the loramac-node driver, I'm scratching my head around the following questions:

  • Is the sx1276 chip supported (can't find any reference in this PR, but upstream supports it). The Lilygo T-Beam has it which is widely used for LoRa HAM operations.
  • Is it possible to set the LoRa sync_word to a user-provided value? The RAL supports this, but it is crucial to also expose this API in Zephyr. This is currently a showstopper of porting Meshcom or Meshtastic to Zephyr. For details, see this discussion.

@JordanYates
Copy link
Collaborator

Is the sx1276 chip supported

It is not supported in this PR, but I have it working to some extent with LBM, which will be part of my initial transition PR.

Is it possible to set the LoRa sync_word to a user-provided value?

Not with the current Zephyr LoRa API. There is nothing stopping us from extending the API to support this, although I am a bit confused since the RAL abstraction only takes a uint8_t, but the loramac-node defines differ in size (and value) between the sx126x and sx127x drivers.

// SX1272.h
#define LORA_MAC_PRIVATE_SYNCWORD                   0x12
// SX126x.h
#define LORA_MAC_PRIVATE_SYNCWORD                   0x1424

@fmoessbauer
Copy link
Contributor

I am a bit confused since the RAL abstraction only takes a uint8_t, but the loramac-node defines differ in size (and value) between the sx126x and sx127x drivers.

The LoRa sync words are complicated. It's not simply that nodes can communicate if the sync words match. Instead, a transmission only reliably works if certain conditions between the sender and receiver syncword match. That's why there are different syncwords between SX1272 (2-byte) and SX126x (4-byte) for the same network.

The chosen values also have an effect on the likelyhood of a successful transmission (it's not just a deterministic criterion). Further, not all sync words are valid at all. Unfortunately all that is undocumented territory. The probably best analysis is found in this blog post: https://blog.classycode.com/lora-sync-word-compatibility-between-sx127x-and-sx126x-460324d1787a

TL;DR:
This technically means, we need two sync words (one 2-byte, one 4-byte) in the abstraction layer, as we don't know the hardware below. The driver can then just pick the corresponding one. As these sync words cannot easily be derived from each other, both must be user-provided. This is also how Meshtastic and Meshcom currently handle it: Provide both and #ifdef based on chip (which would be done in the driver part then).

@fmoessbauer
Copy link
Contributor

I just stumbled upon a derivation function for the sync word in RadioLib: https://github.com/jgromes/RadioLib/blob/c570b44dc35f3d2cddf326926b17b1ea91e32328/src/modules/SX128x/SX128x.cpp#L1020

uint8_t data[2] = {(uint8_t)((syncWord & 0xF0) | ((controlBits & 0xF0) >> 4)),
                   (uint8_t)(((syncWord & 0x0F) << 4) | (controlBits & 0x0F))};

This means the sync word is just 2 bytes and then another 2 bytes of control bits are mixed in, which are simply 0x44 (per default). If this is just a coincidence or a rule remains unclear. At least in case of Meshcom this is not true, as they use 0x2b and 0x2b24 (but it is even unclear if this works due to coincidence or by design).

@JordanYates
Copy link
Collaborator

The equation you came across looks quite similar to the conversion in LoRa Basics Modem to convert the uint8_t in the RAL API to the 2 byte sync word for the SX126x

https://github.com/Lora-net/SWL2001/blob/9a14f6772c1d6e303bacb2d594c8063bb804b6ee/lbm_lib/smtc_modem_core/radio_drivers/sx126x_driver/src/sx126x.c#L1310-L1325

@fmoessbauer
Copy link
Contributor

Indeed, but there they just read the sync word from the modem (SX126X_REG_LR_SYNCWORD) to get the control bits and then mix the 2-byte sync word in. Is that even a valid call-chain according to the datasheet of the sx126x, in case no sync word was set before?

If there only would be documentation...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: LoRa area: Process area: Samples Samples area: Shields Shields (add-on boards) DNM (manifest) This PR should not be merged (controlled by action-manifest) manifest manifest-lora_basics_modem
Projects
None yet
Development

Successfully merging this pull request may close these issues.