Skip to content

drivers/cc110x: Complete rewrite from scratch#10340

Merged
PeterKietzmann merged 7 commits intoRIOT-OS:masterfrom
maribu:cc110x_rewrite
Aug 20, 2019
Merged

drivers/cc110x: Complete rewrite from scratch#10340
PeterKietzmann merged 7 commits intoRIOT-OS:masterfrom
maribu:cc110x_rewrite

Conversation

@maribu
Copy link
Copy Markdown
Member

@maribu maribu commented Nov 6, 2018

Contribution description

The cc110x driver has been re-written from scratch to overcome the limitations of the old driver. The main motivation of the rewrite was to achieve better maintainability by a detailed documentation, reduce the complexity and the overhead of the SPI communication with the device, and to allow to simultaneously use transceivers with different configuration regarding the used base band, the channel bandwidth, the modulation rate, and the channel map.

Features of this driver include:

  • Support for the CC1100, CC1101, and the CC1100e sub-gigahertz transceivers
  • Detailed documentation of every aspect of this driver
  • An easy to use configuration API that allows setting the transceiver configuration (modulation rate, channel bandwidth, base frequency) and the channel map
  • Fast channel hopping by pre-calibration of the channels during device configuration (so that no calibration is needed during hopping)
  • Simplified SPI communication: Only during start-up the MCU has to wait for the transceiver to be ready (for the power regulators and the crystal to stabilize). The old driver did this for every SPI transfer, which resulted in complex communication code. This driver will wait on start up for the transceiver to power up and then use RIOT's SPI API like every other driver. (Not only the data sheet states that this is fine, it also proved to be reliable in practise.)
  • Greatly reduced latency: The RTT on the old driver (@ 150 kbps data rate) was about 16ms, the new driver (@ 250 kbps data rate) has as RTT of 4.9ms to 5.4ms about 3ms with header compression enabled (depending on SPI clock and on CPU performance) (measure with ping6).
  • Increased reliability: The preamble size and the sync word size have been doubled compared to the old driver (preamble: 8 bytes instead of 4, sync word: 4 byte instead of 2). The new values are the ones recommended by the data sheet for reliable communication

Testing procedure

On the MSB-IoT

E.g. by using examples/gnrc_networking: Flash this on two MSB-IoTs and run ping6 <ADDR> on one device with being replaced by the address of the other. I could ask one of my co-workers to perform this test, as there are no MSB-IoT boards left except the ones in my office. (I also tested myself, but maybe it is better to check if this is reproducible on someone else's machine.)

On the MSB-A2

Same as MSB-IoT, but add

CFLAGS += -DCC110X_PARAM_L2ADDR=13

to the Makefile and change the address (the 13) before flashing it on the second MSB-A2. (The MSB-A2's MCU has no unique ID (no CPUID, no unique MAC address in the embedded (but not broken out) Ethernet controller, no unique address in the CAN controller, no nothing) to use to derive a unique layer 2 address from. The on-board FTDI TTL-USB adapter has a unique ID, but that is not accessible from the TTL side. One could hack the flash tool to read that ID via USB and modify the uploaded image to include that ID on some location in the flash, but this seems to be much effort and unrelated to this PR...)

On the bluepill / blackpill

Connect a CC1101 breakout board with 433 MHz base band (I could not fine breakout boards for other base bands, so any random breakout board will likely be fine) to the pill like this:

VCC  <---> 3.3V
GND  <---> GND
CSN  <---> A4
SCK  <---> A5
MISO <---> A6
MOSI <---> A7
GDO0 <---> B0
GDO2 <---> B1

Add to board/bluepill/include/board.h (or board/blackpill/include/board.h):

 #define CC110X_PARAM_CS            GPIO_PIN(PORT_A, 4)
 #define CC110X_PARAM_GDO0          GPIO_PIN(PORT_B, 0)
 #define CC110X_PARAM_GDO2          GPIO_PIN(PORT_B, 1)
 #define CC110X_PARAM_PATABLE       (&cc110x_patable_433mhz)
 #define CC110X_PARAM_CONFIG        (&cc110x_config_433mhz_250kbps_300khz)
 #define CC110X_PARAM_CHANNELS      (&cc110x_chanmap_433mhz_300khz)

Add USEMODULE += cc1101 to the Makefile and use the same steps as on the MSB-IoT


Edit 1: Removed trailing line break to improve readability
Edit 2: Added space between "@" and "250 kbps" so that github user "250" is not linked
Edit 3: Adapted testing on Bluepill/blackpill, as no default configuration will be provided anymore

Issues/PRs references

@maribu
Copy link
Copy Markdown
Member Author

maribu commented Nov 6, 2018

@PeterKietzmann: Would you mind reviewing this PR and test on the MSB-A2?
@Citrullin: Would you mind testing on the Blue Pill or the Black Pill?
@fesselk: Would you mind testing on the MSB-IoT?

@maribu maribu force-pushed the cc110x_rewrite branch 2 times, most recently from 7a856a3 to 0082028 Compare November 7, 2018 08:07
@RIOT-OS RIOT-OS deleted a comment Nov 7, 2018
@maribu
Copy link
Copy Markdown
Member Author

maribu commented Nov 8, 2018

I think it won't hurt if I already sqaush the last to fix commits into the first commit to make travis happy.

@Citrullin
Copy link
Copy Markdown
Contributor

Citrullin commented Nov 9, 2018

@maribu The gnrc_networking size with the CC1101 is too large for the bluepill.

/usr/bin/../lib/gcc/arm-none-eabi/7.3.1/../../../../arm-none-eabi/bin/ld: /home/citrullin/git/riot_libs/examples/gnrc_networking/bin/bluepill/gnrc_networking.elf section `.text' will not fit in region `rom'
/usr/bin/../lib/gcc/arm-none-eabi/7.3.1/../../../../arm-none-eabi/bin/ld: region `rom' overflowed by 14216 bytes
collect2: error: ld returned 1 exit status

I am going to remove some things and try it again.

@maribu
Copy link
Copy Markdown
Member Author

maribu commented Nov 9, 2018

@Citrullin: Thanks for the feedback. Let me rebase this PR against the current master, than the flash hack documented in section "Additional Flash" in the boards docu will work with this PR as well. Please keep in mind that "make flash" will still check the against the official flash size reported by the MCU, so this will fail without modification of the OpenOCD config. Maybe it will be easier to use the st-flash with the hack and flash manually, or flash over UART using stm32flash which (if I remember correctly) also does not verify the flash size.

@Citrullin
Copy link
Copy Markdown
Contributor

@maribu I just used now the gnrc_minimal version. At least it doesn't crash with the initialization and IP address. :) I hope that I have the time today to check if I can send a package. I will also check the flash hack then :)

@maribu
Copy link
Copy Markdown
Member Author

maribu commented Nov 9, 2018

BTW: If you have a second blue pill, you could convert that to a Black Magic Probe, which is super nice :-) You could that flash directly from GDB using "load" and that will also work for 128 KiB flash.

Quick start with Black Magic Probe: You can connect to the UART via make PORT=/dev/ttyACM1 term as the BMP brings an integrated TTL Adapter :-)

For debugging or flashing run arm-none-eabi-gdb bin/bluepill/gnrc_networking.elf and then type:

tar ext /dev/ttyACM0       # Use Black Magic probe at /dev/ttyACM0 to debug
mon swdp_scan              # Scan for device via SWD
attach 1                   # Attach to the first detected device
load                       # Upload RIOT
start                      # Start the just uploaded image
con                        # GDB will break in main, so we need to continue

A few hints:

  1. GDB will detect changes on the elf file to upload. Just type "load" again when the file has changed. It will also reload the symbol table
  2. When scanning you might get "stuck in WFI". This is when the MCU is in lowest power state. An easy way to wake it up is to write help in the RIOT-terminal. Listing the available commands via UART is enough time for the BMP to detect the device. Once detected, attaching should work reliable even in lowest power state.
  3. Do not reset the board via the reset button. The BMP will be confused by that

@maribu
Copy link
Copy Markdown
Member Author

maribu commented Nov 9, 2018

BMP integration into RIOT would be also super-super nice :-) I hope I can have a look at that some time soon.

@PeterKietzmann PeterKietzmann added Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation Area: drivers Area: Device drivers labels Nov 9, 2018
@PeterKietzmann
Copy link
Copy Markdown
Member

@PeterKietzmann: Would you mind reviewing this PR and test on the MSB-A2?

I don't think I'll find time for a proper review. But I could give it a try on the msba2 once you the code converges

@Citrullin
Copy link
Copy Markdown
Contributor

Citrullin commented Nov 9, 2018

BTW: If you have a second blue pill, you could convert that to a Black Magic Probe, which is super nice :-) You could that flash directly from GDB using "load" and that will also work for 128 KiB flash.

Ahh, thanks. Didn't know this. I bought 2 maple pies, because of the 64kb. Yes, I will try this hack then :)

@maribu
Copy link
Copy Markdown
Member Author

maribu commented Nov 9, 2018

I don't think I'll find time for a proper review.

Sure. This PR got surprisingly big...

@kaspar030: You already started to give valuable feedback. Do you mind to review this PR?

@maribu
Copy link
Copy Markdown
Member Author

maribu commented Nov 9, 2018

@Citrullin:

Ahh, thanks. Didn't know this. I bought 2 maple pies, because of the 64kb.

For reliable operation this might be a good choice. The BluePill's "secret additional 64kB" flash is not guaranteed to work and there are cases known when it didn't. (But I personally never hat any issues and the success rate seems to be something like 99%.)

@Citrullin
Copy link
Copy Markdown
Contributor

I flashed it on two boards and tried your example. There is some traffic on the 433 ISM band. As you can see in the screenshot. But the seconds board isn't responding to the ping. I also tried it on the other one. I take a look into it. Maybe I did something wrong.

@maribu Is that a wanted behavior that a ping is resulting only in one data transmission? Haven't checked it yet, but are all 3 pings sent at once?

@Citrullin
Copy link
Copy Markdown
Contributor

Here a screenshot about the ping6 result.

Node 1:

> ifconfig
Iface  7  HWaddr: 3F  Channel: 0 
          MTU:255  HL:64  RTR  
          Source address length: 1
          Link type: wireless
          inet6 addr: fe80::ff:fe00:3f  scope: local  VAL
          inet6 group: ff02::2
          inet6 group: ff02::1
          inet6 group: ff02::1:ff00:3f
          inet6 group: ff02::1a
          
           Protocol or device doesn't provide statistics.
          Statistics for IPv6
            RX packets 2562  bytes 143472
            TX packets 36 (Multicast: 24)  bytes 1962
            TX succeeded 36 errors 0

> 
> ping6 fe80::ff:fe00:8a
ping timeout
ping timeout
ping timeout
--- fe80::ff:fe00:8a ping statistics ---
3 packets transmitted, 0 received, 100% packet loss

Node 2:

> ifconfig
Iface  7  HWaddr: 8A  Channel: 0 
          MTU:255  HL:64  RTR  
          Source address length: 1
          Link type: wireless
          inet6 addr: fe80::ff:fe00:8a  scope: local  VAL
          inet6 group: ff02::2
          inet6 group: ff02::1
          inet6 group: ff02::1:ff00:8a
          inet6 group: ff02::1a
          
           Protocol or device doesn't provide statistics.
          Statistics for IPv6
            RX packets 0  bytes 0
            TX packets 40 (Multicast: 31)  bytes 2162
            TX succeeded 40 errors 0

> 
> ping6 fe80::ff:fe00:3f
ping timeout
ping timeout
ping timeout
--- fe80::ff:fe00:3f ping statistics ---
3 packets transmitted, 0 received, 100% packet loss

@maribu
Copy link
Copy Markdown
Member Author

maribu commented Nov 11, 2018

@Citrullin: Thanks for testing

@maribu Is that a wanted behavior that a ping is resulting only in one data transmission? Haven't checked it yet, but are all 3 pings sent at once?

No, they should be send out right away. Maybe the spectrum analyzer cannot listen on all channels at the same time and walks the channels up an down. When the transmission is done on one channel while the analyzer is tuned in to another, it would miss the transmission. Maybe that is what happens? Channel 0 for the default configuration on the blue pill would be at 433.225 MHz (center frequency) and should be about 300 kHz wide.

I hope this is not an instance of the "works on my machine"-syndrome where everything works just fine on the developers PC, but no where else :-D

I had some trouble myself with the cheapest 433 MHz breakout boards that use a "spiral" as antenna. For some reason the signal is not detected when the sender is less than about half a meter away, but as soon the distance is higher than half a meter it gets 100% reliable. I believe this to be an antenna issue...

Maybe you CC1101 breakout boards have the same antenna issue. Could you try if it works with some more distance? Could you check if your break out boards are intended for the 433 MHz band? Thank you very much!

@Citrullin
Copy link
Copy Markdown
Contributor

Citrullin commented Nov 11, 2018

@maribu It really was the distance. Interesting. Never had this issue in the 868 band with Lora. Good to know. Maybe a little thing we can put in some FAQ or something. Here some screenshots.
So, I also played a bit with the sampling rate and I just looked nearer to the frequencies. Thanks for giving me these information. There are three pings as expected. Works like expected from the ping perspective. I am going to write some code for it. But I am really sure that this will work just fine :) Good job! It's really simple to use. Okay, the bluepill hack could be a bit simpler, but that doesn't have to do something with this PR.

I recognized that there is some traffic on the 433 band on power on. So, the device is sending something after it woke up. Is the node advertising its IP address? Haven't looked into the network stack & driver so far.

@maribu
Copy link
Copy Markdown
Member Author

maribu commented Nov 11, 2018

I really should add the documentation about that anomaly with the range. I hoped that was just me having bad luck with the antennas, as all other modules did not had those issues. (But the other ones were all 868 MHz - maybe it is not the antenna but the base band. Maybe this even is an obvious thing which is to be expected for 433 MHz transceivers and I'm simple unaware, as I have pretty much zero knowledge about the physical layer.)

@Citrullin
Copy link
Copy Markdown
Contributor

Citrullin commented Nov 12, 2018

@maribu So, I ask somebody who is better in this topic. He told me that this is a result of the transmitting power. So, if the nodes are too near to each other, the nodes are receiving nearly the whole transmitting power of each other. Since the nodes are really sensitive in detecting the electromagnetic fields, it is just too much power for the receiver. So it reaches the maximum of its detecting capability. So the wave doesn't look like a sinus waveform anymore, more like rectangle. And this is simply an incorrect signal for the node. That's the whole story :)

@maribu
Copy link
Copy Markdown
Member Author

maribu commented Nov 12, 2018

I recognized that there is some traffic on the 433 band on power on. So, the device is sending something after it woke up. Is the node advertising its IP address? Haven't looked into the network stack & driver so far.

I think that RPL sends those packets.

@Citrullin
Copy link
Copy Markdown
Contributor

@maribu I see that there is a function to set the tx power. Which is really helpful, since the 433 band also has some restrictions. So, I wanted to know what you set in the driver as default value? I would think 1mW would be great, since there is no restriction on the 433 band in case of duty-cycle with 1mW.

@maribu
Copy link
Copy Markdown
Member Author

maribu commented Nov 12, 2018

@Citrullin: I can confirm that too high TX power prevents the communication when the devices are too close: Reducing TX power on both nodes to 0dBm solves the problem :-)

Regarding the default TX power value: This sounds like a good idea to allow setting it via cc110x_params_t.

@Citrullin
Copy link
Copy Markdown
Contributor

Citrullin commented Nov 12, 2018

@maribu Is it fine for you if I put everything in this PR? Or should it be another feature request instead?

@maribu
Copy link
Copy Markdown
Member Author

maribu commented Aug 20, 2019

OK, I missed some boards on the first try at blacklisting. I also previously added some boards to BOARD_INSUFFICIENT_MEMORY in the initial tests:Added test for cc110x driver commit. I updated that commit to come with any empty BOARD_INSUFFICIENT_MEMORY, so that every change to BOARD_INSUFFICIENT_MEMORY is now bundled into a single commit.

I squashed right away. The diff on the "force-pushed" link should only show updates to BOARD_INSUFFICIENT_MEMORY and BOARD_BLACKLIST (and does so).

@maribu
Copy link
Copy Markdown
Member Author

maribu commented Aug 20, 2019

And again, you can squash. Please ping me once you have sorted out all issues with the CI.

@PeterKietzmann: Ping :-)

@PeterKietzmann
Copy link
Copy Markdown
Member

@kaspar030, @kYc0o @miri64 I am about to merge this PR this afternoon / evening after I had a final look over the code and passed last tests. It has +4,100 −2,240 so of course not everything is perfectly reviewed but the code is in very good shape, it is well documented and even stressful tests passed -> it improves the current state by means! If you have any concerns, speak out now!

@kaspar030
Copy link
Copy Markdown
Contributor

it improves the current state by means!

+1 for merging!

@PeterKietzmann
Copy link
Copy Markdown
Member

So once again I ran tests/drivers_cc110x with ping6 -c 3600 -i 100 -s 1000 fe80::ff:fe00:99 and furthermore I've checked the netstats which look good.

# 3600 packets transmitted, 3552 packets received, 1% packet loss
# round-trip min/avg/max = 76.322/76.325/76.381 ms

@Citrullin from the hearts you gave our comments I interpret that everything still runs ok on your side?

@maribu I have only two things left before merging.
(i) Please add msba2 to BOARD_PROVIDES_NETIF in examples/default/Makefile and tests/netstats_l2 and immediately squash.
(ii) Please squash together all commits, at least a little. I don't think we need 13 commits here.

The following is just a proposal. Please note that I slightly changed the commit order.

pick 615e25f drivers: Removed driver for CC110x transceivers
pick 544adc6 drivers/cc110x: Rewrite of the cc110x driver
s f71c236 drivers/cc110x: Added diagnostics to init
s 3113b6b drivers/cc110x: Integrated TX power configuration
s 4c0333c boards: Added cc110x params for MSB-A2 & MSB-IoT
s 34a4be9 drivers/cc110x: Block on netdev_driver_t::send()
s cdc6016 drivers/cc1xxx_common: Added L2 netstats
s 61797e7 drivers/cc1xxx_common: gnrc_netif_hdr_set_netif
pick e99e2cb sys/auto_init/netif: Increased cc110x stack size
r 24570d5 tests: Added test for the cc110x driver
(-> tests/driver_cc110x: add test for transceiver driver)
s 5ff0781 testing/driver_cc110x: Access low level info
s ef7d09e tests/driver_cc110x: BOARD_INSUFFICIENT_MEMORY
s d61259f tests/driver_cc110x: Blacklisted msp430 boards

maribu added 5 commits August 20, 2019 16:32
The cc110x driver has been re-written from scratch to overcome the limitations
of the old driver. The main motivation of the rewrite was to achieve better
maintainability by a detailed documentation, reduce the complexity and the
overhead of the SPI communication with the device, and to allow to
simultaneously use transceivers with different configuration regarding the used
base band, the channel bandwidth, the modulation rate, and the channel map.

Features of this driver include:

- Support for the CC1100, CC1101, and the CC1100e sub-gigahertz transceivers.
- Detailed documentation of every aspect of this driver.
- An easy to use configuration API that allows setting the transceiver
  configuration (modulation rate, channel bandwidth, base frequency) and the
  channel map.
- Fast channel hopping by pre-calibration of the channels during device
  configuration (so that no calibration is needed during hopping).
- Simplified SPI communication: Only during start-up the MCU has to wait
  for the transceiver to be ready (for the power regulators and the crystal
  to stabilize). The old driver did this for every SPI transfer, which
  resulted in complex communication code. This driver will wait on start up
  for the transceiver to power up and then use RIOT's SPI API like every other
  driver. (Not only the data sheet states that this is fine, it also proved to
  be reliable in practise.)
- Greatly reduced latency: The RTT on the old driver (@150 kbps data rate) was
  about 16ms, the new driver (@250 kbps data rate) has as RTT of ~3ms
  (depending on SPI clock and on CPU performance) (measured with ping6).
- Increased reliability: The preamble size and the sync word size have been
  doubled compared to the old driver (preamble: 8 bytes instead of 4,
  sync word: 4 byte instead of 2). The new values are the once recommended by
  the data sheet for reliable communication.
- Basic diagnostic during driver initialization to detect common issues as
  SPI communication issues and GDO pin configuration/wiring issues.
- TX power configuration with netdev_driver_t::set() API-integration
- Calls to netdev_driver_t::send() block until the transmission has completed
  to ease the use of the API (implemented without busy waiting, so that the
  MCU can enter lower power states or other threads can be executed).
With the increase of the message queue size from 8 to 16 in
946b06e, the default stack became too small.
This changes the stack size to grow with the message queue size.
- Added required logic to provide correct L2 netstats when the module
  netstats_l2 is used.
- Refactored code to use gnrc_netif_hdr_set_netif() over manually setting the
  pid to ease future refactoring.
The test application provides:
- RIOT's basic network utilities such as `ping6`
- A custom `cc110x` shell command that can be used print the low level device
  and driver state. This is mostly useful for debugging.
@maribu
Copy link
Copy Markdown
Member Author

maribu commented Aug 20, 2019

@maribu I have only two things left before merging.
(i) Please add msba2 to BOARD_PROVIDES_NETIF in examples/default/Makefile and tests/netstats_l2 and immediately squash.
(ii) Please squash together all commits, at least a little. I don't think we need 13 commits here.

Done.

  1. I was so free to additionally change the way the BOARD_PROVIDES_NETIF is declared into a merge-friendly way. (Those variables are often updated and a lot of PRs are facing merge conflicts because of that. By having one board per lines the chances are high that auto-merging succeeds.)
  2. I squashed the commits changing the same module together.

@PeterKietzmann
Copy link
Copy Markdown
Member

@maribu thanks! However, changing the way BOARD_PROVIDES_NETIF is organized in existing applications should IMO not be part of this PR. So could you please revert the last commit and add the msba2 to the Makefiles as suggested above?

@maribu
Copy link
Copy Markdown
Member Author

maribu commented Aug 20, 2019

So could you please revert the last commit and add the msba2 to the Makefiles as suggested above?

done

@kYc0o
Copy link
Copy Markdown
Contributor

kYc0o commented Aug 20, 2019

It is ok for me in the actual state. I'll add my concerns on the tracking issue and so we can advance together on this. I'll try to make a PR asap.

Thanks a lot @maribu for your huge efforts!

@PeterKietzmann
Copy link
Copy Markdown
Member

Thanks. I ran a final test using tests/driver_cc110x on one, and examples/default on an other msba2 board. I changed the hwaddr on one board to 88 and set the channel to 3 on both boards. A plain L2 packet sent via txtsnd command was successfully transmitted.

@PeterKietzmann PeterKietzmann added Reviewed: 1-fundamentals The fundamentals of the PR were reviewed according to the maintainer guidelines Reviewed: 2-code-design The code design of the PR was reviewed according to the maintainer guidelines Reviewed: 3-testing The PR was tested according to the maintainer guidelines Reviewed: 4-code-style The adherence to coding conventions by the PR were reviewed according to the maintainer guidelines labels Aug 20, 2019
Copy link
Copy Markdown
Member

@PeterKietzmann PeterKietzmann left a comment

Choose a reason for hiding this comment

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

ACK. Test reports have been posted earlier. Thanks to all contributors!

@PeterKietzmann PeterKietzmann merged commit 11b4bab into RIOT-OS:master Aug 20, 2019
@Citrullin
Copy link
Copy Markdown
Contributor

@Citrullin from the hearts you gave our comments I interpret that everything still runs ok on your side?

Just happy to see this in the mainline. It has been a while when I checked it the last time. But if there are any issues, we can fix them :) Kaizen style.

@maribu maribu deleted the cc110x_rewrite branch August 20, 2019 17:39
@maribu
Copy link
Copy Markdown
Member Author

maribu commented Aug 20, 2019

Hooray! @PeterKietzmann, @miri64, @kYc0o, and @Citrullin: Thanks for reviewing, testing and helping with the driver :-)

@kaspar030
Copy link
Copy Markdown
Contributor

Grats! This was a big one... 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: drivers Area: Device drivers CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Reviewed: 1-fundamentals The fundamentals of the PR were reviewed according to the maintainer guidelines Reviewed: 2-code-design The code design of the PR was reviewed according to the maintainer guidelines Reviewed: 3-testing The PR was tested according to the maintainer guidelines Reviewed: 4-code-style The adherence to coding conventions by the PR were reviewed according to the maintainer guidelines Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CC101x Initialization kernel panic

9 participants