mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
tests: Added test for the cc110x driver
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.
This commit is contained in:
parent
ccf713c5ad
commit
f33b963ef4
57
tests/driver_cc110x/Makefile
Normal file
57
tests/driver_cc110x/Makefile
Normal file
@ -0,0 +1,57 @@
|
||||
BOARD ?= msba2
|
||||
include ../Makefile.tests_common
|
||||
|
||||
DEVICE ?= cc1100 # The MSB-A2 uses the CC1100. New boards use CC1101
|
||||
|
||||
BOARD_INSUFFICIENT_MEMORY += arduino-duemilanove
|
||||
BOARD_INSUFFICIENT_MEMORY += arduino-leonardo
|
||||
BOARD_INSUFFICIENT_MEMORY += arduino-mega2560
|
||||
BOARD_INSUFFICIENT_MEMORY += arduino-nano
|
||||
BOARD_INSUFFICIENT_MEMORY += arduino-uno
|
||||
BOARD_INSUFFICIENT_MEMORY += blackpill
|
||||
BOARD_INSUFFICIENT_MEMORY += bluepill
|
||||
BOARD_INSUFFICIENT_MEMORY += i-nucleo-lrwan1
|
||||
BOARD_INSUFFICIENT_MEMORY += mega-xplained
|
||||
BOARD_INSUFFICIENT_MEMORY += nucleo-f031k6
|
||||
BOARD_INSUFFICIENT_MEMORY += nucleo-f042k6
|
||||
BOARD_INSUFFICIENT_MEMORY += nucleo-f072rb
|
||||
BOARD_INSUFFICIENT_MEMORY += nucleo-f302r8
|
||||
BOARD_INSUFFICIENT_MEMORY += nucleo-f303k8
|
||||
BOARD_INSUFFICIENT_MEMORY += nucleo-f334r8
|
||||
BOARD_INSUFFICIENT_MEMORY += nucleo-l031k6
|
||||
BOARD_INSUFFICIENT_MEMORY += nucleo-l053r8
|
||||
BOARD_INSUFFICIENT_MEMORY += saml10-xpro
|
||||
BOARD_INSUFFICIENT_MEMORY += saml11-xpro
|
||||
BOARD_INSUFFICIENT_MEMORY += stm32f0discovery
|
||||
BOARD_INSUFFICIENT_MEMORY += stm32l0538-disco
|
||||
BOARD_INSUFFICIENT_MEMORY += waspmote-pro
|
||||
|
||||
# stdlib.h for msp430 does not provide EXIT_FAILURE and EXIT_SUCCESS
|
||||
BOARD_BLACKLIST += msb-430 msb-430h telosb wsn430-v1_3b wsn430-v1_4 z1
|
||||
|
||||
# This test will rely on a human interacting with the shell, so we better add
|
||||
# the shell and some commands
|
||||
USEMODULE += shell
|
||||
USEMODULE += shell_commands
|
||||
# Add the device driver
|
||||
USEMODULE += $(DEVICE)
|
||||
# Add a network stack and auto init of the network devices
|
||||
USEMODULE += gnrc
|
||||
USEMODULE += auto_init_gnrc_netif
|
||||
USEMODULE += gnrc_ipv6_router_default
|
||||
# checking current state of network threads can be useful for testing/debuggig
|
||||
USEMODULE += ps
|
||||
# txtsnd can be useful to test lower layers
|
||||
USEMODULE += gnrc_txtsnd
|
||||
USEMODULE += auto_init_gnrc_netif
|
||||
# Activate ICMPv6 error messages
|
||||
USEMODULE += gnrc_icmpv6_error
|
||||
# This application dumps received packets to STDIO using the pktdump module
|
||||
USEMODULE += gnrc_pktdump
|
||||
# Additional networking modules that can be dropped if not needed
|
||||
USEMODULE += gnrc_icmpv6_echo
|
||||
# Some statistics could also be helpful
|
||||
USEMODULE += netstats_l2
|
||||
USEMODULE += netstats_ipv6
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
134
tests/driver_cc110x/main.c
Normal file
134
tests/driver_cc110x/main.c
Normal file
@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Otto-von-Guericke-Universität Magdeburg
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup tests
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Test application for the CC110x driver
|
||||
*
|
||||
* @author Marian Buschsieweke <marian.buschsieweke@ovgu.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "shell.h"
|
||||
#include "shell_commands.h"
|
||||
|
||||
#include "net/gnrc/pktdump.h"
|
||||
#include "net/gnrc.h"
|
||||
|
||||
#define MAIN_QUEUE_SIZE (8)
|
||||
|
||||
static int sc_dump(int argc, char **argv);
|
||||
int sc_cc110x(int argc, char **argv);
|
||||
|
||||
static const shell_command_t shell_commands[] = {
|
||||
{ "dump", "Enable/disable dumping of frames", sc_dump },
|
||||
{ "cc110x", "Print the low level state of an CC110x device", sc_cc110x },
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
static msg_t _main_msg_queue[MAIN_QUEUE_SIZE];
|
||||
static gnrc_netreg_entry_t dump;
|
||||
|
||||
static int sc_dump(int argc, char **argv)
|
||||
{
|
||||
static int is_enabled = 0;
|
||||
if (argc == 1) {
|
||||
if (is_enabled) {
|
||||
puts("Currently dumping packets");
|
||||
}
|
||||
else {
|
||||
puts("Currently NOT dumping packets");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else if (argc == 2) {
|
||||
int new_state = 0;
|
||||
if (!strcmp("y", argv[1])) {
|
||||
new_state = 1;
|
||||
}
|
||||
else if (!strcmp("n", argv[1])) {
|
||||
new_state = 0;
|
||||
}
|
||||
else {
|
||||
printf("Usage: %s [y/n]\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
if (new_state == is_enabled) {
|
||||
// Nothing to do;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (new_state) {
|
||||
if (gnrc_netreg_register(GNRC_NETTYPE_SIXLOWPAN, &dump)) {
|
||||
puts("Failed to register packet dumping");
|
||||
}
|
||||
}
|
||||
else {
|
||||
gnrc_netreg_unregister(GNRC_NETTYPE_SIXLOWPAN, &dump);
|
||||
}
|
||||
|
||||
is_enabled = new_state;
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("Usage: %s [y/n]\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
/* we need a message queue for the thread running the shell in order to
|
||||
* receive potentially fast incoming networking packets */
|
||||
msg_init_queue(_main_msg_queue, MAIN_QUEUE_SIZE);
|
||||
|
||||
gnrc_netreg_entry_init_pid(&dump, GNRC_NETREG_DEMUX_CTX_ALL,
|
||||
gnrc_pktdump_pid);
|
||||
|
||||
puts("cc110x driver test application\n"
|
||||
"==============================\n"
|
||||
"\n"
|
||||
"Use the shell and two boards equipped with an CC1100/CC1101\n"
|
||||
"transceiver to test the driver. Common testing tasks:\n"
|
||||
"\n"
|
||||
"- Using \"ifconfig\":\n"
|
||||
" - Check the information stated for plausibility/correctness\n"
|
||||
" - Try to get/set parameters like TX power, channel, address, ...\n"
|
||||
" - BEWARE: With short communication distances (<=1m) for boards\n"
|
||||
" with high gain antennas a high TX power may result in packet\n"
|
||||
" loss: The incoming signal can only be demodulated when the\n"
|
||||
" input signal is at most +10 dBm on the CC1101.\n"
|
||||
" - Check the statistics for correctness/plausibility (after\n"
|
||||
" sending frames using \"txtsnd\" or \"ping6\")\n"
|
||||
"- Using \"ping6\":\n"
|
||||
" - Does the other device respond to the ping?\n"
|
||||
" - Does the measured RSSI increase when the nodes are closer\n"
|
||||
" together?\n"
|
||||
" - Try to increase the size of the pings, so that the TX/RX FIFO\n"
|
||||
" needs to be filled/drain more than once per frame. The TX/RX\n"
|
||||
" FIFO can hold 64 bytes\n"
|
||||
" - Try to increase the size of the pings in order to trigger L2\n"
|
||||
" fragmentation. The driver supports frames of up to 255 bytes\n"
|
||||
"- Using \"txtsnd\":\n"
|
||||
" - Turn on packet dumping using the command \"dump y\" on node A\n"
|
||||
" - Send both unicast and broadcast frame from node B to A\n"
|
||||
"- Using \"cc110x\":\n"
|
||||
" - This tool will print low level details for all CC110x devices\n"
|
||||
" attached\n"
|
||||
" - This will be mostly useful for debugging, not for testing\n");
|
||||
char line_buf[SHELL_DEFAULT_BUFSIZE];
|
||||
shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE);
|
||||
|
||||
return 0;
|
||||
}
|
208
tests/driver_cc110x/sc_cc110x.c
Normal file
208
tests/driver_cc110x/sc_cc110x.c
Normal file
@ -0,0 +1,208 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Otto-von-Guericke-Universität Magdeburg
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "cc110x.h"
|
||||
#include "cc110x_internal.h"
|
||||
#include "cc110x_params.h"
|
||||
|
||||
#define CC110X_NUM (sizeof(cc110x_params) / sizeof(cc110x_params[0]))
|
||||
|
||||
extern cc110x_t _cc110x_devs[CC110X_NUM];
|
||||
|
||||
static const char *pa_settings[] = {
|
||||
"-30",
|
||||
"-20",
|
||||
"-15",
|
||||
"-10",
|
||||
"0",
|
||||
"+5",
|
||||
"+7",
|
||||
"+10",
|
||||
};
|
||||
|
||||
static const char *state2s(cc110x_state_t state)
|
||||
{
|
||||
switch (state) {
|
||||
case CC110X_STATE_IDLE:
|
||||
return "IDLE";
|
||||
case CC110X_STATE_FRAME_READY:
|
||||
return "Frame ready";
|
||||
case CC110X_STATE_OFF:
|
||||
return "Off";
|
||||
case CC110X_STATE_RX_MODE:
|
||||
return "RX mode";
|
||||
case CC110X_STATE_RECEIVING:
|
||||
return "RX mode and currently receiving frame";
|
||||
case CC110X_STATE_TX_MODE:
|
||||
return "TX";
|
||||
case CC110X_STATE_TX_COMPLETING:
|
||||
return "TX completing";
|
||||
case CC110X_STATE_FSTXON:
|
||||
return "Fast TX on";
|
||||
case CC110X_STATE_CALIBRATE:
|
||||
return "Calibrating";
|
||||
case CC110X_STATE_SETTLING:
|
||||
return "Settling";
|
||||
case CC110X_STATE_RXFIFO_OVERFLOW:
|
||||
return "RX FIFO overflow";
|
||||
case CC110X_STATE_TXFIFO_UNDERFLOW:
|
||||
return "TX FIFO underflow";
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
static const char *gdoconf2s(uint8_t conf)
|
||||
{
|
||||
switch (conf) {
|
||||
case CC110X_GDO_ON_RX_DATA:
|
||||
return "High when frame received or RX FIFO needs draining";
|
||||
case CC110X_GDO_ON_TX_DATA:
|
||||
return "Low when TX FIFO needs refilling";
|
||||
case CC110X_GDO_ON_TRANSMISSION:
|
||||
return "High while frame is incoming / outgoing";
|
||||
case CC110X_GDO_ON_CHANNEL_CLEAR:
|
||||
return "High when channel is clear";
|
||||
case CC110X_GDO_ON_PLL_IN_LOCK:
|
||||
return "High when frequency generator is on and PLL is in lock";
|
||||
case CC110X_GDO_CONSTANT_LOW:
|
||||
return "Constant low";
|
||||
case CC110X_GDO_CONSTANT_HIGH:
|
||||
return "Constant high";
|
||||
case CC110X_GDO0_ANALOG_TEMPERATURE:
|
||||
return "Analog output of the temperature sensor (GDO0 only)";
|
||||
}
|
||||
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
static inline const char *b2s(int boolean)
|
||||
{
|
||||
return (boolean) ? "1" : "0";
|
||||
}
|
||||
|
||||
static void print_state(cc110x_t *dev)
|
||||
{
|
||||
uint8_t status;
|
||||
uint8_t pktstatus;
|
||||
int8_t rssi_raw;
|
||||
uint8_t iocfg2;
|
||||
uint8_t iocfg0;
|
||||
uint8_t txbytes;
|
||||
uint8_t rxbytes;
|
||||
uint8_t hwaddr;
|
||||
uint8_t frend0;
|
||||
uint8_t physical_channel;
|
||||
uint8_t virtual_channel;
|
||||
|
||||
/* Get all required data and release device */
|
||||
if (cc110x_acquire(dev) != SPI_OK) {
|
||||
puts("Failed to acquire CC1100/CC1101 transceiver");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Reading out the RSSI changes it, as SPI communication seems to generate
|
||||
* some noise. Reading the RSSI out first yields up to 20 dBm lower
|
||||
* values... (E.g. about -100dBm instead of about -80dBm with no
|
||||
* other sources of Sub-GHz RF)
|
||||
*/
|
||||
status = cc110x_read_reliable(dev, CC110X_REG_RSSI, (uint8_t *)&rssi_raw);
|
||||
cc110x_read_reliable(dev, CC110X_REG_PKTSTATUS, &pktstatus);
|
||||
cc110x_read(dev, CC110X_REG_IOCFG2, &iocfg2);
|
||||
cc110x_read(dev, CC110X_REG_IOCFG0, &iocfg0);
|
||||
cc110x_read(dev, CC110X_REG_ADDR, &hwaddr);
|
||||
cc110x_read(dev, CC110X_REG_FREND0, &frend0);
|
||||
cc110x_read(dev, CC110X_REG_CHANNR, &physical_channel);
|
||||
virtual_channel = dev->channel;
|
||||
cc110x_read_reliable(dev, CC110X_REG_TXBYTES, &txbytes);
|
||||
cc110x_read_reliable(dev, CC110X_REG_RXBYTES, &rxbytes);
|
||||
cc110x_state_t sw_state = dev->state;
|
||||
cc110x_release(dev);
|
||||
|
||||
/* Parse obtained raw data */
|
||||
cc110x_state_t hw_state = (status >> 4) & 0x03;
|
||||
int ready = !(status & 0x80);
|
||||
int rssi = ((int)rssi_raw / 2) - (int)dev->rssi_offset;
|
||||
int gdo0 = pktstatus & CC110X_PKTSTATUS_GDO0;
|
||||
int gdo2 = pktstatus & CC110X_PKTSTATUS_GDO2;
|
||||
int recv = pktstatus & CC110X_PKTSTATUS_RECEIVING;
|
||||
int cca = pktstatus & CC110X_PKTSTATUS_CCA;
|
||||
int cs = pktstatus & CC110X_PKTSTATUS_CS;
|
||||
const char *pa = pa_settings[frend0 & 0x07];
|
||||
|
||||
/* Print all information */
|
||||
if (!ready) {
|
||||
puts(" CRITICAL: Crystal has not stabilized yet!");
|
||||
}
|
||||
printf(" GDO0: %s (%s)\n", b2s(gdo0), gdoconf2s(iocfg0));
|
||||
printf(" GDO2: %s (%s)\n", b2s(gdo2), gdoconf2s(iocfg2));
|
||||
printf(" Receiving: %s, CCA: %s, CS: %s\n", b2s(recv), b2s(cca), b2s(cs));
|
||||
printf(" RSSI: %i.%sdBm, TX power: %sdBm\n",
|
||||
rssi, (rssi_raw & 1) ? "5" : "0", pa);
|
||||
printf(" L2 addr: %02x, physical channel: %u, virtual channel: %u\n",
|
||||
(int)hwaddr, (unsigned)physical_channel, (unsigned)virtual_channel);
|
||||
if (dev->channels->map[virtual_channel] != physical_channel) {
|
||||
puts(" WARNING: Physical channel does not match channel map");
|
||||
}
|
||||
printf(" Driver state: %s, transceiver state: %s\n",
|
||||
state2s(sw_state), state2s(hw_state));
|
||||
if (hw_state != (sw_state & 0x07)) {
|
||||
puts(" WARNING: Transceiver and device state don't match!");
|
||||
}
|
||||
if (0x80 & txbytes) {
|
||||
puts(" TX FIFO: Underflown!");
|
||||
}
|
||||
else {
|
||||
printf(" TX FIFO: %iB\n", (int)txbytes);
|
||||
}
|
||||
if (0x80 & rxbytes) {
|
||||
puts(" RX FIFO: Overflown!");
|
||||
}
|
||||
else {
|
||||
printf(" RX FIFO: %iB\n", (int)rxbytes);
|
||||
}
|
||||
}
|
||||
|
||||
int sc_cc110x(int argc, char **argv)
|
||||
{
|
||||
switch (argc) {
|
||||
case 1:
|
||||
for (unsigned i = 0; i < CC110X_NUM; i++){
|
||||
printf("CC110x #%u:\n", i);
|
||||
print_state(&_cc110x_devs[i]);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if ((!strcmp(argv[1], "-h")) || (!strcmp(argv[1], "--help"))) {
|
||||
printf("Usage: %s [NUM]\n"
|
||||
"\n"
|
||||
"Prints the status of the CC1100/CC1101 transceiver "
|
||||
"identified by NUM, or of\n"
|
||||
"all available CC110x transceivers if no argument is "
|
||||
"given\n", argv[0]);
|
||||
}
|
||||
else {
|
||||
unsigned pos = atoi(argv[1]);
|
||||
if (pos >= CC110X_NUM) {
|
||||
puts("No such transceiver");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
printf("CC110x #%u:\n", pos);
|
||||
print_state(&_cc110x_devs[pos]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("Usage: %s [NUM]\n", argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
Loading…
Reference in New Issue
Block a user