Skip to content

drivers/sx1276: LoRa transceiver phy driver proposal#6002

Closed
Cr0s wants to merge 19 commits intoRIOT-OS:masterfrom
Cr0s:sx1276-radio-driver
Closed

drivers/sx1276: LoRa transceiver phy driver proposal#6002
Cr0s wants to merge 19 commits intoRIOT-OS:masterfrom
Cr0s:sx1276-radio-driver

Conversation

@Cr0s
Copy link
Copy Markdown

@Cr0s Cr0s commented Oct 27, 2016

Hello to RIOT folks!

I'd like to propose this initial implementation of LoRa physical layer driver.

  • Driver is basically a port of Semtech's LoRaMAC's physical layer implementation.
  • Driver is working well and tested on 868 MHz band
  • Driver is able to do LoRa RX and TX

Features that are considered as "done":

  • Reading / Writing SPI registers
  • Chip version/revision check as a communication test
  • Setting up the LoRa modem configuration: SF, BW, CR, frequency
  • Setting up other parameters such as TX power and sensitivity tweaks according to ERRATA
  • SX1276 random number generator
  • Working with DIO interrupt lines. RxDone and TxDone events working asynchronously
  • Working with SX1276's FIFO
  • RX and TX timeout timers
  • Events callback to the upper layers code
  • Testing app: rx, tx, random, different modulation parameters. Very fun to see on the SDR's waterfall!

What will be done to make this driver complete (by me or someone else who wish and could):

  • FSK modulation
  • Make sure that CAD is working properly
  • Adaptation to the netdev2 interface
  • Proper time-on-air calculation formula
  • Polishing the code and documentation to the it's perfect possible form
  • Chip built-in temperature sensor
  • More testing/example applications

I appreciate any feedback, fix proposals and related points!

Best regards,
Cr0s

@OlegHahm OlegHahm added Area: network Area: Networking Area: drivers Area: Device drivers labels Oct 27, 2016
@OlegHahm OlegHahm added this to the Release 2017.01 milestone Oct 27, 2016
@Cr0s Cr0s changed the title [sx1276] LoRa transceiver phy driver proposal drivers/sx1276: LoRa transceiver phy driver proposal Oct 27, 2016
@jia200x
Copy link
Copy Markdown
Member

jia200x commented Oct 28, 2016

It's working for us. We were able to send and receive data.
We are starting the netdev2 adoption. I will let you know when we make the PR.

Cheers!

@@ -0,0 +1,450 @@
/*
* Copyright (C) 2016 Cr0s
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It's usually preferred to provide an e-mail address - either here or in the doxygen @author line.

@kaspar030
Copy link
Copy Markdown
Contributor

also a real name.

-----Original Message-----
From: Oleg Hahm [email protected]
To: RIOT-OS/RIOT [email protected]
Sent: Fr., 28 Okt. 2016 17:44
Subject: Re: [RIOT-OS/RIOT] drivers/sx1276: LoRa transceiver phy driver proposal (#6002)

OlegHahm commented on this pull request.

@@ -0,0 +1,450 @@
+/*

  • * Copyright (C) 2016 Cr0s

It's usually preferred to provide an e-mail address - either here or in the doxygen @author line.

You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
#6002 (review)

sx1276_reg_write(dev,
SX1276_REG_DIOMAPPING1,
(sx1276_reg_read(dev, SX1276_REG_DIOMAPPING1)
& SX1276_RF_LORA_DIOMAPPING1_DIO0_MASK) | SX1276_RF_LORA_DIOMAPPING1_DIO0_00);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not sure why the SX1276_RF_LORA_DIOMAPPING1_DIO0_MASK) | SX1276_RF_LORA_DIOMAPPING1_DIO0_00 are "DIO0", if you are in lora mode, shouldn't both the mask and the mode be for "DIO3"? so to make sure "DIO3" generates de CADDONE ISR. Cheers.

Copy link
Copy Markdown
Author

@Cr0s Cr0s Nov 1, 2016

Choose a reason for hiding this comment

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

Well spotted. Since CAD mode didn't tested, this obvious copy-paste mistake was not seen before.

Gonna fix it asap.

P.S.: the actual error present in the original Semtech's code:
https://github.com/Lora-net/LoRaMac-node/blob/master/src/radio/sx1276/sx1276.c#L1164
so it was inherited as it is.

* Radio driver supported modems.
*/
typedef enum {
SX1276_MODEM_FSK = 0, SX1276_MODEM_LORA,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please spit into multiple lines.

* Radio driver internal state machine states definition.
*/
typedef enum {
SX1276_RF_IDLE = 0, SX1276_RF_RX_RUNNING, SX1276_RF_TX_RUNNING, SX1276_RF_CAD,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Multiple lines here again.

@OlegHahm
Copy link
Copy Markdown
Member

OlegHahm commented Nov 2, 2016

drivers/include/sx1276.h
Binary file not shown.

Huh?

(void) arg;
}

void *dio_polling_thread(void *arg)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hi!, I'm not sure why would you choose to use threads over pin interrupts? Doesn't this make packet loss more likely? Plus doesn't this implement a pooling system witch is cpu and energy intensive? Also, is it really needed since you are using stack memory and other resources. Cheers

Copy link
Copy Markdown
Author

@Cr0s Cr0s Nov 2, 2016

Choose a reason for hiding this comment

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

Hi! I'll try to clarify reasons why I did that.

The main point is to not doing complex stuff inside DIO's ISRs and do it in separate thread instead.

Doesn't this make packet loss more likely?

I think no, the RX handling is pretty straightforward and doesn't involve complex mechanisms such as packet queues which may overflow or something like that.

Plus doesn't this implement a pooling system witch is cpu and energy intensive?

The dio_polling_thread doesn't poll a DIO pins as busy-waiting one. The major part of a time this thread is blocked on awaiting messages that comes from DIO interrupt handlers.

As this thread is awaiting for messages in blocked state, it's not CPU-intensive at all.

Also, is it really needed since you are using stack memory and other resources

This thread is needed since the handler of DIO interrupt might be pretty heavy in matter of stack usage. For example, consider the DIO0 interrupt on RX. After the RX event occurs, if we just call the event handler's callback and If we put some stack-heavy MAC logic into that callback, the ISR stack will definitely be overflowed than if we will do event callback from the separate thread.

The stack space is allocated for this thread only.

Another solution I came up with is to force user to create a thread to handle messages from the driver, but it's seems to me a clear violation of implementation hiding principle and that will lead to more ways to do something wrong.

I hope I made the rationale clear for you.

Cheers.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Hi @Cr0s!

Just read this discussion.
Netdev2 allows a similar flow without the need of another thread on the driver side. For instance, the enc28j60 driver calls netdev->event_callback with NETDEV2_ISR_EVENT and this is translated to a message to the gnrc_netdev2 thread. In the end, the isr function of the driver is called (as shown here).

In this case the dio_polling_thread could be the isr function of the driver (note the isr function is not in ISR context, the name is a bit tricky :P). Probably it would need some flags to identify which interrupt occured.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Hello, @jia200x.

Getting rid of a separate thread could be made as a part of the netdev2 interface adaption.


static inline void send_event(sx1276_t *dev, sx1276_event_type_t event_type)
{
if (dev->sx1276_event_cb != NULL) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Couldn't we use an assert here instead?

spi_release(dev->spi);

if (res < 0) {
printf("sx1276: error initializing SPI_%i device (code %i)\n",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please change all printfs to DEBUG.


/* Check presence of SX1276 */
if (!sx1276_test(dev)) {
DEBUG("init_radio: test failed");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Missing \n.

sx1276_set_channel(dev, dev->settings.channel);

/* Create DIO event lines handler */
kernel_pid_t pid = thread_create((char *) dev->_internal.dio_polling_thread_stack, sizeof(dev->_internal.dio_polling_thread_stack), THREAD_PRIORITY_MAIN,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Line is too long.

/* Set radio in continuous reception */
sx1276_set_op_mode(dev, SX1276_RF_OPMODE_RECEIVER);

for (i = 0; i < 32; i++) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why 32? Please use a macro/constant here.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

32 is the number of random bits that we will get from the transceiver and then we will put them into 32 bit integer.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

@OlegHahm Any update on this? Should I add macro or leave it as is?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Replaced by macro.

| SX1276_RF_IMAGECAL_IMAGECAL_START);

while ((sx1276_reg_read(dev, SX1276_REG_IMAGECAL) & SX1276_RF_IMAGECAL_IMAGECAL_RUNNING)
== SX1276_RF_IMAGECAL_IMAGECAL_RUNNING) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@PeterKietzmann, @haukepetersen, how do we handle this in general? Didn't we agree on a failsafe counter for these kind of loops to avoid infinitely trying?

Copy link
Copy Markdown
Author

@Cr0s Cr0s Nov 3, 2016

Choose a reason for hiding this comment

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

Yes, it's better to replace that with some timeout-based polling to avoid infinite loops in bad cases. I've seen lot of similar loops in RIOT's peripheral drivers. Example.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

@OlegHahm Any update on this? Should I leave it as is or add timeout counters?

@jia200x
Copy link
Copy Markdown
Member

jia200x commented Jan 18, 2017

Hi you all.
Here's the netdev2 adoption. It has been tested with LoRaWAN and works with no known issues.

Cheers
[1]:https://github.com/Inria-Chile/RIOT/tree/sx1276-netdev2/drivers/sx1276

@Cr0s
Copy link
Copy Markdown
Author

Cr0s commented Jan 21, 2017

@emmanuelsearch anything stated as "working" in description is actually working fine, it can be merged at the moment.

@aabadie
Copy link
Copy Markdown
Contributor

aabadie commented Jan 21, 2017

I have a couple of Semtech SX1272 devices that should be compatible with SX1276 : they only covers bands from 850MHz to 1GHz and can be configured with 3 bandwidths (500KHz, 250KHz and 125KHz).
I read a bit the PR and the default parameters should be fine with what I have, so I wish I can give a try next week.

@PeterKietzmann PeterKietzmann modified the milestones: Release 2017.01, Release 2017.04 Jan 26, 2017
@jia200x jia200x mentioned this pull request Feb 23, 2017
5 tasks
@aabadie
Copy link
Copy Markdown
Contributor

aabadie commented Mar 17, 2017

@Cr0s any update on your side with this one ?
It seems that this PR is still using the old SPI api. As I said above, I have a couple of ST Nucleo LoRa Kit that I'd like to try with.

@aabadie
Copy link
Copy Markdown
Contributor

aabadie commented Mar 23, 2017

ping @Cr0s, are planning to continue your work on this PR ?

@PeterKietzmann
Copy link
Copy Markdown
Member

@Cr0s which board and which radio device did you use for testing?

@PeterKietzmann
Copy link
Copy Markdown
Member

Do you know if the sx1272 radio is with your sx1276 driver?

@aabadie
Copy link
Copy Markdown
Contributor

aabadie commented Mar 27, 2017

@PeterKietzmann, I started to work on adapting this work (mainly #6645) to SX1272 and SX1276. Still work in progress but in a better shape that those ones.

@dylad
Copy link
Copy Markdown
Member

dylad commented Mar 27, 2017

@PeterKietzmann I don't think this driver can be used for sx1272 without some work.

@PeterKietzmann
Copy link
Copy Markdown
Member

Thanks for both your quick responses! @aabadie where can I find your work, is it already visible for the public?

@aabadie
Copy link
Copy Markdown
Contributor

aabadie commented Mar 27, 2017

@PeterKietzmann, yes. here : https://github.com/aabadie/RIOT/tree/driver_sx127x

(Something I did without hardware yesterday) I quickly tested it this morning on sx1272 but it didn't work. I'm wondering if SPI works on Nucleo boards.

@dylad
Copy link
Copy Markdown
Member

dylad commented Mar 27, 2017

@aabadie
I'm not sure about the others, but nucleo-l1 SPI works (if you remove the LED pin init at startup)
I have 2 SX1272 and one SX1276. I'll try to test your PR later.

@aabadie
Copy link
Copy Markdown
Contributor

aabadie commented Mar 27, 2017

if you remove the LED pin init at startup

is it mandatory ?

@PeterKietzmann
Copy link
Copy Markdown
Member

@aabadie do I understand it correctly that your work is based on #6645? @aabadie, @dylad which radio devices (talking about external SPI devices) are you using?

@aabadie
Copy link
Copy Markdown
Contributor

aabadie commented Mar 27, 2017

@aabadie do I understand it correctly that your work is based on #6645?

More or less. I have to admit that I had to largely adapt it to fit the coding style of RIOT.

@dylad
Copy link
Copy Markdown
Member

dylad commented Mar 27, 2017

Yes, the GPIO definition seems to prevail on the SPI definition.
More information at #6501
As I said I have 2 SX1272 (SX1272RF1 board) and one SX1276 (SX1276MB1MAS board)

@aabadie
Copy link
Copy Markdown
Contributor

aabadie commented Mar 27, 2017

@dylad, @PeterKietzmann, I opened a PR with my rework : #6797

miri64 added a commit that referenced this pull request Jun 30, 2017
drivers/sx127x: rework of implementations from #6645 and #6002
@aabadie
Copy link
Copy Markdown
Contributor

aabadie commented Jun 30, 2017

Closing since #6797 is merged.

@aabadie aabadie closed this Jun 30, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: drivers Area: Device drivers Area: network Area: Networking CI: needs squashing Commits in this PR need to be squashed; If set, CI systems will mark this PR as unmergable

Projects

None yet

Development

Successfully merging this pull request may close these issues.