Upload
others
View
12
Download
0
Embed Size (px)
Citation preview
2018 Radiocrafts AS
SPR SDK
User Manual
2018 Radiocrafts AS SPR SDK User Manual rev 1.0
SPR SDK User Manual
Page 1 of 28
Table of Contents 1 RIIOT NETWORK OVERVIEW ................................................................................................ 3 2 INTRODUCTION.......................................................................................................................... 4 3 HOW TO USE THE APPLICATION FRAMEWORK ............................................................. 5 4 AN EXAMPLE ............................................................................................................................... 6 5 SDK SETUP ................................................................................................................................... 9
5.1 SDK DIRECTORY STRUCTURE ................................................................................................ 9 6 BUILDING APPLICATION ...................................................................................................... 10 7 FLASHING APPLICATION FOR TESTING .......................................................................... 11 8 USE IMAGE ENCRYPTION ..................................................................................................... 11 9 USE NETWORK ENCRYPTION .............................................................................................. 11 10 API USAGE .................................................................................................................................. 12
10.1 NODE .................................................................................................................................. 12 10.2 NETWORK ........................................................................................................................... 12 10.3 TIMER ................................................................................................................................. 14 10.4 I2C ...................................................................................................................................... 15 10.5 GPIO .................................................................................................................................. 15 10.6 ADC ................................................................................................................................... 17 10.7 SPI ...................................................................................................................................... 18 10.8 UART ................................................................................................................................. 19 10.9 NON VOLATILE STORAGE .................................................................................................. 20 10.10 UTIL ................................................................................................................................. 20 10.11 DEBUG .............................................................................................................................. 20 10.12 SPECIAL NOTE ON INITIALIZATION OF VARIABLES ......................................................... 21
11 BOOTLOADER UTILITY ......................................................................................................... 22 11.1 BOOTLOADER UTILITY COMMAND-LINE SYNTAX ............................................................ 22 11.2 ENTER BOOTLOADER MODE .............................................................................................. 23 11.3 LOAD APP IMAGE ENCRYPTION KEY ................................................................................. 23 11.4 LOAD NETWORK KEY ........................................................................................................ 24 11.5 LOAD PLATFORM IMAGE .................................................................................................... 24 11.6 LOAD APP IMAGE ............................................................................................................... 25 11.7 LOCK THE MODULE ............................................................................................................ 26
12 REVISION HISTORY ................................................................................................................ 27 DISCLAIMER ........................................................................................................................................ 28 TRADEMARKS ..................................................................................................................................... 28 LIFE SUPPORT POLICY ..................................................................................................................... 28 RADIOCRAFTS SUPPORT: ................................................................................................................ 28 CONTACT RADIOCRAFTS ................................................................................................................ 28
List of Tables Table 1: The Possible Network States ...................................................................................................... 13 Table 2: Available GPIOs on RC1880 module ........................................................................................ 16
List of Figures Figure 1. RIIoT network – system and documentation overview ............................................................... 3 Figure 2. Flash structure ............................................................................................................................. 4 Figure 3: User-driven application platform ................................................................................................ 6 Figure 4: Block diagram of example sensor ............................................................................................... 7
2018 Radiocrafts AS SPR SDK User Manual rev 1.0
SPR SDK User Manual
Page 2 of 28
List of Code Listings Listing 1: User Code for Example Sensor .................................................................................................. 7
Abbreviations Abbreviation Description
SPR Radiocrafts Software-Programmable RF Module
RIIoT Radiocrafts Industrial Internet of Things
2018 Radiocrafts AS SPR SDK User Manual rev 1.0
SPR SDK User Manual
Page 3 of 28
1 RIIoT Network Overview
The RIIoT network consists of some key elements
- The RC1880-SPR module
o The module that can be programmed with user application through the SPR Software Development
Kit (SDK)
- The SPR SDK
o Software development kit with Application framework and tool for building and uploading end
application to the RC1880-SPR module
- The RC1880-GPR module for use in the gateway/concentrator
o Support the concentrator of the gateway. Normally connected to a Linux gateway, but can also be
controlled by MCU through a UART protocol
- The RIIoT Net Controller Linux middleware
o A middleware SW that can be used on a Linux gateway. Interfaces the RC1880-GPR module and
supply user application a socket interface for controlling and sending/receiving data through the
wireless network.
Below is an illustration of the different element and the documentation available
Figure 1. RIIoT network – system and documentation overview
Linux gateway
RIIOT Net Controller UART / USB Socket
User application - Coap Server - MQTT client
Dashboard (example code)
Fog computing
RC1880-GPR RC1880-SPR
RC1880-GPR RC1880-SPR
RC1880-GPR RC1880-SPR
RC1880-SPR Data sheet
SPR SDK
SPR SDK User Manual SPR SDK Quick Start Guide SPR SDK API reference
RC1880-GPR Data sheet RC1880-GPR User Manual
RIIoT Net Controller Quick Start Guide
RIIoT Net Controller Socket API Reference
Sub 1 GHz
IEEE
802.15.4g/e
RC1880-GPR RC1880-GPR
2018 Radiocrafts AS SPR SDK User Manual rev 1.0
SPR SDK User Manual
Page 4 of 28
2 Introduction
This user manual shows how a custom application for wireless sensors or actuators can be quickly and easily
developed using the Radiocrafts SPR (Software-Programmable RF module) application platform on a RIIoT
(Radiocrafts Industrial IoT) network. The programming is done by using the Intelligent C-programmable I/O (ICI)
concept. ICI present the user with an event-driven application framework with high-level C APIs that allow the
appliction to interface any sensor/actuator and to implement any data processing and edge intelligence. A full sensor
application with networking and sensor interface can be written in as less as 100 lines of code. For more complex
application, 4KB of space is available.
Prerequisite is basic knowledge of C programming. No expertise in wireless networking or device specific knowledge
is required.. The goal with this guide is to reduce the complexity and confusion of embedded wireless to something
simple and easy for everybody to get started with.
The guide covers the following topics:
how to quickly develop your application on an event-driven platform
how to interface to sensors or actuators using APIs for I2C, ADC, GPIO, UART, SPI
how to create events based on timers, GPIO and UART
how to join networks, send and receive messages
how to choose trade-offs between responsiveness and power consumption
how to compile and load your application using our free compiler and IDE
In Figure 2 the flash structure of the system is shown. The platform image and the application image can both be
programmed/flashed through the bootloader. Updated or custom variants of the platform image is supplied by
Radiocrafts, while the application image is generated by customer codes and the tools given in this documents.
Figure 2. Flash structure
Real Time Operating System (RTOS)
Low level drivers
High level drivers 802.15.4 g/e stack
Incl. frequency hopping
Application framework
ICI application code
Bootloader(BSL)
Platform image
Application image
2018 Radiocrafts AS SPR SDK User Manual rev 1.0
SPR SDK User Manual
Page 5 of 28
3 How to Use the Application Framework
Everything in the ICI concept is event-driven. It is up to the user application to define the events and the handlers for
these events.
Think of the user application as a list of event handlers — if-this-then-that(IFTT). If this event occurs, then do that in
this handler.
As an example, a simple wireless sensor application could be defined by the following event behaviors.
if network state is offline then turn off the LED
if network state is joining then blink the LED
if network state is online then turn on the LED
after powering up, automatically join or rejoin a network
every 20 seconds, read data from the sensors on I2C
every 60 seconds, send a report to the concentrator
Of course, a lot more is possible. Sensors and actuators can be accessed using different interfaces (I2C, ADC, GPIO,
SPI, UART..). Periodic or one-shot timer events can be created. Custom actions can be triggered by network
commands from the concentrator. Global variables can be used to track internal states. Data can be saved to non-
volatile memory to preserve them across power resets. Algorithms can be implemented to process or filter data.
Underneath, the application platform silently takes care of the security and reliability of the network, any over-the-air
updates, and the powerful real-time operating system (RTOS) that schedules the events.
Figure 3 below gives an overview of the user code structure and how it interacts with the platform.
2018 Radiocrafts AS SPR SDK User Manual rev 1.0
SPR SDK User Manual
Page 6 of 28
Figure 3: User-driven application platform
The user code is is composed of Setup() and a list of event handlers. Setup() is the only function that must be
implemented, and it is called when the node starts up. From within Setup(), you can define events and register
handlers for these events — e.g. when you receive a message, or when a timer expires.
You can also chain events based on other events by defining an event within another event handler. For example, you
can start a one-shot timer when a GPIO edge triggers.
Underneath its simple interface, the application platform runs a real-time operating system (RTOS) with multiple
threads and interrupt handlers. However, you do not need to worry about that. All your code runs on the same thread.
So you can safely share data between different event handlers.
4 An Example
This chapter goes through an example of a wireless temperature and humidity sensor with an I2C interface to SHT35
(digital humidity sensor), a LED and a button.
2018 Radiocrafts AS SPR SDK User Manual rev 1.0
SPR SDK User Manual
Page 7 of 28
Figure 4: Block diagram of example sensor
SPR reduces the cost, size and power requirements of your wireless product because it allows you to develop
custom code right on the radio module. You do not need a separate host processor.
This sensor will have the following behaviors:
Battery-powered, which means the node will sleep as much as possible to save power
Finds and joins a network automatically
When the node is on the network, turn on the LED
When the node is off the network, turn off the LED
Every 30 seconds, read data from the SHT35 sensor digital humidity sensor on the I2C interface
Every 1 minute, or when a button is pressed, send sensor data to the concentrator
Take a look at the code implementation below. Only basic C knowledge is required. The comments will help. And
keep in mind the overview that the entire code is composed of Setup() and a list of event handlers.
Listing 1: User Code for Example Sensor
/**
* User application code.
* In this file, you can interface to your sensor or
* actuator, and register event handlers with the platform.
*
* This example shows interfacing to a SHT35 Temperature/Humidity sensor
*
* @file user.c
* @brief user application code
*/
#include "spr_app.h"
/********* Constants ***********/
#define SHT35_I2C_ADDRESS 0x44
2018 Radiocrafts AS SPR SDK User Manual rev 1.0
SPR SDK User Manual
Page 8 of 28
/********* Private Variables ****************/
// These are variables that can be shared between functions in this file.
// The following 2 variables store the data readings from the sensor.
uint16_t temperature;
uint16_t humidity;
TimerId readSensorTimer;
TimerId reportDataTimer;
/********* Private Function Declarations ****************/
// These are event handlers that will be implemented lower in the file, but
// are declared here so Setup() can reference them when registering events.
void networkStateChangeHandler(NetworkState state);
void receivedMessageHandler(uint8_t *message, uint8_t len);
void readSensor();
void sendData();
/********* Public Functions ****************/
/**
* Setup() is called by the platform on startup
*/
void Setup()
{
Debug.printline("App Setup");
Node.setBatteryPowered(true);
Network.setAutoJoin(true);
Network.setNetworkStateChangeHandler(networkStateChangeHandler);
Network.setReceivedMessageHandler(receivedMessageHandler);
// I2C clock speed to the SHT35 sensor
I2C.init(I2C_400KHZ);
// setup the button GPIO and event detection
GPIO.setDirection(GPIO_0, PIN_INPUT);
GPIO.setHandler(GPIO_0, FALLING_EDGE, sendData);
// setup the LED GPIO
GPIO.setDirection(GPIO_1, PIN_OUTPUT);
// setup periodic timer events
readSensorTimer = Timer.create(PERIODIC, 30 * SECOND, readSensor);
sendDataTimer = Timer.create(PERIODIC, 1 * MINUTE, sendData);
Timer.start(readSensorTimer);
}
/********* Private Functions ****************/
void networkStateChangeHandler(NetworkState state)
{
switch (state)
{
case ONLINE: // turn on the LED
GPIO.write(GPIO_1, HIGH);
Timer.start(sendDataTimer);
break;
default: // turn off LED for all other states
GPIO.write(GPIO_1, LOW);
2018 Radiocrafts AS SPR SDK User Manual rev 1.0
SPR SDK User Manual
Page 9 of 28
}
}
void receivedMessageHandler(uint8_t *message, uint8_t len)
{
// process message. In this example, nothing.
}
void readSensor()
{
uint8_t writeBuffer[2];
uint8_t readBuffer[6];
// sensor command to get the measurement
writeBuffer[0] = 0x2C;
writeBuffer[1] = 0x06;
SPR_Status status = I2C.transfer(SHT35_I2C_ADDRESS, writeBuffer,
sizeof(writeBuffer),
readBuffer, sizeof(readBuffer));
if (SPR_OK == status)
{
// unpacks the data from the byte buffer into 16-bit integer variables
temperature = Util.unpack_uint16_msb(readBuffer, 0);
humidity = Util.unpack_uint16_msb(readBuffer, 3);
}
}
void sendData()
{
uint8_t packet[4];
// packs 16-bit integer values into byte buffers
Util.pack_uint16_msb(packet, 0, temperature);
Util.pack_uint16_msb(packet, 2, humidity);
Network.send(sizeof(packet), packet);
}
Hopefully you get an idea of how easy it is to define and register a handler for an event. For example, the following
line in the code defines a periodic timer that calls your handler sendData() every 1 minute.
Timer.start(TIMER_1, PERIODIC, 1 * MINUTE, sendData);
Timer is an API module, along with others like Node, Network, GPIO, I2C, each containing a set of functions that
your code can call. They will be explained in more details in the next section to help you build more advanced
applications.
5 SDK Setup
Please follow the SPR SDK Quick Start Guide on how to install and setup SPR SDK on your machine.
5.1 SDK Directory Structure The SDK directory contains the following:
docs/
o all the documentation
examples/
o example user applications
2018 Radiocrafts AS SPR SDK User Manual rev 1.0
SPR SDK User Manual
Page 10 of 28
includes/
o SPR platform header files
libraries/
o SPR platform libraries used during linking
platform/
o Containing the platform image
startup/
o Containing source file used during the startup of user application. Do not modify
util/
o Utilities needed to build and flash firmware image
app.c
o your source file, for you to modify as custom application
user_build_options.ini
o Options for you to modify (app version, image encryption, key files, module serial port for flashing)
build.bat
o Double click to compile your application and generate an image for flashing
clean.bat
o Clean and remove any outputs from the last build
flash_app.bat
o Flash the latest generated image to radio module through serial port. It also involves the compile/build
process if no image has been generated yet.
flash_image_key.bat
o Flash the image encryption key into the module
flash_network_key.bat
o Flash the network key into the module
image_encryption_key.txt
o Contains a 16 byte hex string, that you can modify, to use as the key to encrypt your application
image
network_key.txt
o Contains a 16 byte hex string, that you can modify, as the key to encrypt network messages
makefile
o used by the build process. Do not modify!
6 Building Application
Steps to build a custom application:
Modify app.c with your custom code
o Use code editor of your choice (e.g. Notepad++, Atom, Visual Studio Code, Vim)
Modify user_build_options.ini
o Change version attributes (VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH)
o Choose whether to encrypt your image (IMAGE_ENCRYPTION). Encryption should only be enabled
after an image key has been flashed into the module
o Use the option RESET_NETWORK to choose whether the new image will wipe out any saved
network on the module
o Use the option MODULE_COM_PORT to specify the USB serial port that the module you use for
development is connected to.
Double-click build.bat
o A terminal window will open up to show the build process, and display any errors and warnings.
o When the build process completes, press any key to close the terminal window
2018 Radiocrafts AS SPR SDK User Manual rev 1.0
SPR SDK User Manual
Page 11 of 28
If build is successful, the directory will now have the image file: spr_app.bin
o The name of the image can be modified in user_build_options.ini
The image file is now ready to be flashed.
7 Flashing Application for Testing
Steps to flash your new application into a module for testing:
Make sure your development board is connected to an USB port on your computer
Make sure user_build_options.ini is modified to use the correct COM port
Make sure no other application is using the COM port.
Double-click flash_app.bat
o A terminal window will show up
o If an image was not previously built, then the build process will start
o Before flashing starts, terminal will pause, and ask you to put the module in bootloader mode. You
can do so by holding down the BSL/CONFIG button while resetting the development board. Then
press any key to continue.
o Flashing will start
o When complete, press any key to close the terminal window.
Use a serial terminal program (e.g. Putty, YAT) to connect to the COM port
Reset the development board, and you should see debug outputs on the serial terminal program
Flashing can also be done by using the bootloader utility directly. This is covered in chapter 10.12.
8 Use Image Encryption
The application image can be encrypted using a key of your choice. This enables secure field updates.
The encryption algorithm used is AES-CCM.
Steps needed to use image encryption:
Load image encryption key into the SPR module
o Choose your custom key by modifying image_encryption_key.txt
o Double-click flash_image_key.bat
In user_build_options.ini, set IMAGE_ENCRYPTION to Yes.
The image will be encrypted using the key, and it will be decrypted and verified by the bootloader before writing to
internal flash.
The image encryption key cannot be modified after the module is locked. See the section on production process on
how to the lock module, to prevent others from changing the key.
9 Use Network Encryption
Messages on the network can be encrypted and authenticated using a key of your choice. The security algorithm used
is AES-CCM, which provides integrity, confidentiality and authentication on the message.
Steps to use network encryption:
Load network key into the SPR module
o Choose your custom 16-byte network key by modifying network_key.txt
2018 Radiocrafts AS SPR SDK User Manual rev 1.0
SPR SDK User Manual
Page 12 of 28
o Double-click flash_network_key.txt
In your application code, in Setup(), make sure to call: Network.setMessageEncryption(true).
On gateway side, configure RIIoT Net Controller
o Set config networkSecurity to true
o Set config networkKey to the same key that was flashed into the SPR module
Now when the SPR module joins the network created by RIIoT Net Controller, messages will be encrypted using the
key.
10 API Usage
The following sections describes in detail each of the API modules.
10.1 Node The Node API module allow you to set whether it is battery powered. If the node is battery-powered, the node will
sleep when it is idle to optimize power consumption.
Example API calls:
Node.setBatteryPowered(true);
10.2 Network
The Network API module allows you to:
configure the network
join or leave a network
respond to network state changes
send and receive network messages
enable encryption
10.2.1 Configure the Network
You can call the following APIs to configure the network in Setup().
Network.setFreqBand(FREQ_868_MHZ); (1)
Network.setFrequencyHopping(true); (2)
Network.setChannelMask(channelMask); (3)
Network.setPanId(0xABCD); (4)
Network.setTxPower(12); (5)
Network.setPollRate(10 * SECOND); (6)
(1) Can be 868 or 915 MHz
(2) Enables frequency hopping. Only works if the concentrator set up a frequency hopping network.
(3) (Optional) set the channel mask, which is the list of channels that the node will scan when looking for a network
to join. By default, the node scans all available channels for the PHY.
(4) (Optional) restrict the node to only join a network with the specified PAN ID. This could be useful for testing in a
crowded network with many networks. But for field deployment, it is recommended to not set the PAN ID,
allowing the node to join any network that is available and with the correct security settings.
(5) Set the transmit power in dBm
(6) Determines how often the node polls the concentrator for incoming messages. It is a trade-off between how
responsive the node is to downlink messages versus power consumption.
2018 Radiocrafts AS SPR SDK User Manual rev 1.0
SPR SDK User Manual
Page 13 of 28
10.2.2 Join or Leave Network
You can call the following function to enable Auto-Join, which enables the node to automatically start scanning for a
network to join when it starts up or when it is Offline.
Network.setAutoJoin(true);
Alternatively, you can initiate the joining based on an user action – for example, after a button press — by calling the
following function:
Network.join();
When the node successfully joins a network, you will be notified in your handler for network state changes. See
10.2.3.
You can call the following function to leave the network at any time: Network.leave();
10.2.3 Respond to Network State Changes
To track changes to the network state, you can register a handler by calling the following function: Network.setNetworkStateChangedHandler(myNetworkStateChangedHandler);
You can also call the following function to get the current network state:
NetworkState state = Network.getState();
Table 1: The Possible Network States
Network State Description
OFFLINE No network. Waiting for an action to join the network
JOINING Scanning for a network and trying to join. Can be initiated by either Auto-Join or user calling Network.join()
REJOINING Rejoining a network after power reset; or trying to rejoin after losing connection
ONLINE On the network. Can send and receive messages.
When the node is on the network, it automatically monitors the network connection. If connection is lost, the node
automatically tries to rejoin.
When the network state is ONLINE or REJOINING, the user can call the following to get the current PAN ID and
channel.
uint16_t panId = Network.getPanId();
uint8_t channel = Network.getChannel();
10.2.4 Send and Receive Messages
Here is an example of sending a 4 byte message to the concentrator:
uint8_t message[4];
message[0] = 0x01;
message[1] = 0x02;
message[2] = 0x03;
message[3] = 0x04;
Network.send(sizeof(message), message);
There is no destination address. All messages go uplink to the concentrator. There are no peer-to-peer messages.
2018 Radiocrafts AS SPR SDK User Manual rev 1.0
SPR SDK User Manual
Page 14 of 28
You can call the following to enable encryption on all outgoing messages, and to require encryption on incoming
messages.
Network.setMessageEncryption(true);
The node comes with a default key. You can override it with your custom key during production.
You can call the following to register a handler for messages received from the concentrator:
Network.setReceivedMessageHandler(myReceivedMessageHandler);
You then need to implement the received message handler, where you can process the message.
void myReceivedMessageHandler(uint8_t * message, uint8_t len)
{
}
You can call the following to be notified when a message you sent is acknowledged by the concentrator. Network.setMessageSentHandler(SPR_Status status)
The status could either be SUCCESS, which means an acknowledgement was received, or ACK_TIMED_OUT.
The platform automatically manages acknowledgments and retries for every transmitted message, so you can be sure
of reliability when you send a message.
10.3 Timer You can create periodic or one-shot timer events using the Timer API module.
You can create a timer by calling Timer.create(), where you pass in the timer mode (PERIODIC or ONE_SHOT),
the timer duration, and a handler function to be triggered when the timer expires.
For example, to start a periodic timer with a user handler that gets called every 1 minute:
TimerId timer1; (1)
timer1 = Timer.create(PERIODIC, 1*MINUTE, myTimerHandler1); (2)
Timer.start(timer1); (3)
(1) Declare the timer at the top of your file, so it can be referenced in any function.
(2) Call Timer.create() in your Setup()
(3) You can start the timer in any function, e.g. in a button handler
Timer.create() dynamically allocates memory for the new timer. It is a good idea to create all your timers within Setup()
so they are allocated at the start. If your code has rules that create new timers while running, it may deplete the memory heap.
Here is also an example to start a one-shot timer with a handler that gets called after 5 seconds:
TimerId timer2;
timer2 = Timer.create(ONE_SHOT, 5*SECOND, myTimerHandler2);
Timer.start(timer2);
You can stop a timer at any time:
Timer.stop(timer1);
Then you can call Timer.start() to restart a timer that is stopped.
2018 Radiocrafts AS SPR SDK User Manual rev 1.0
SPR SDK User Manual
Page 15 of 28
You can also re-config a timer with different parameters using the Timer.config(). The timer must be stopped
before you can re-config it.
Here is an example where you change the timer parameters before starting it again.
Timer.stop(timer1);
Timer.config(timer1, PERIODIC, 5*MINUTE, myTimerHandler1);
Timer.start(timer1);
10.4 I2C You can use the I2C API module to communicate as a master on the I2C bus.
To initialize the I2C clock (100 or 400 KHz):
I2C.init(I2C_400KHZ);
You can call the I2C.transfer() function to write a sequence of bytes followed by reading a sequence of bytes.
The I2C transfer function blocks until it completes, as shown in following example:
uint8_t writeBuffer[2]; (1)
uint8_t readBuffer[6]; (2)
// sensor command to get the measurement
writeBuffer[0] = 0x2C;
writeBuffer[1] = 0x06;
SPR_Status status = I2C.transfer(SHT35_I2C_ADDRESS, writeBuffer,
sizeof(writeBuffer), readBuffer, sizeof(readBuffer)); (3)
(1) the bytes to write over I2C bus
(2) the buffer to receive bytes read over I2C bus
(3) call the transfer function with the arguments: destination slave address, write buffer number of bytes to write, the
buffer to receive read bytes, the number bytes to read
The I2C.transfer() function automatically takes care of any clock stretching.
You can also initiate transfers that writes but not reads:
SPR_Status status = I2C.write(address, writeBuffer, sizeof(writeBuffer));
Or just read, but not write:
SPR_Status status = I2C.read(address, readBuffer, 6);
10.5 GPIO The GPIO API module allow you to:
configure the direction of a GPIO pin (input, output, output open drain)
configure the pull control of a GPIO pin (pull down, pull up)
set value to an output
toggle value of an output
get value of an input or output
register handlers for edge detections
enable or disable an edge detection
2018 Radiocrafts AS SPR SDK User Manual rev 1.0
SPR SDK User Manual
Page 16 of 28
On RC1880, 9 GPIO pins are available as shown in table below.
Table 2: Available GPIOs on RC1880 module
PIN # GPIO name
42 GPIO_0
41 GPIO_1
40 GPIO_2
39 GPIO_3
38 GPIO_4
37 GPIO_5
36 GPIO_6
35 GPIO_7
34 GPIO_8
10.5.1 Configure Direction
Call the following to configure the direction of a pin:
GPIO.setDirection(GPIO_0, INPUT);
3 direction modes are available:
INPUT
OUTPUT (push-pull)
OUTPUT_OPEN_DRAIN
10.5.2 Configure Pull-up or Pull-down
You can configure pull up or pull down on a pin:
GPIO.setPull(GPIO_1, PULL_UP);
3 options are available:
NO_PULL (default)
PULL_UP
PULL_DOWN
10.5.3 Read Write Pin Value
To get the value of a pin (either input or output):
value = GPIO.getValue(GPIO_2);
The value is an enum of either LOW(0) or HIGH(1).
To set the value of a pin:
GPIO.setValue(GPIO_2, HIGH);
To toggle the value of a pin:
GPIO.toggle(GPIO_2);
10.5.4 Edge Detection
You can call the following to register a handler for GPIO edge detection.
GPIO.setHandler(GPIO_2, RISING_EDGE, myHandler);
2018 Radiocrafts AS SPR SDK User Manual rev 1.0
SPR SDK User Manual
Page 17 of 28
In this example, myHandler() will be called when rising edge is detected on GPIO 2.
The options for edge detection are:
RISING_EDGE
FALLING_EDGE
BOTH_EDGES
The GPIO pin (e.g. GPIO_0) and the edge (e.g. RISING_EDGE) that triggered the interrupt is passed into the handler.
The handler should be implemented like the following:
void myHandler(enum GPIO_Pin pin, enum GPIO_InterruptEdge edge)
{
}
You can call disableEdgeDetection() to disable edge detection. Example below:
GPIO.disableEdgeDetection(GPIO_2);
To re-enable edge detection after it was disabled, you can call enableEdgeDetection() like the example below:
GPIO.enableEdgeDetection(GPIO_2);
Calling GPIO.setHandler() automatically enables edge detection, so GPIO.enableEdgeDetection() only needs to
be called after edge detection is disabled.
10.6 ADC You can sample and convert analog input to digital values using the ADC module.
RC1880 supports 2 ADC channels
ADC 0 (pin 10)
ADC 1 (pin 11)
Initialize an ADC channel by setting the internal reference voltage and the sampling duration. This example sets
sampling duration of 2.7 us.
ADC.init(ADC0, FIXED_REFERENCE, ADC_SAMPLING_DURATION_2_7_US);
Two reference voltages are available:
FIXED_REFERENCE (4.3V)
BATTERY_REFERENCE (relative to battery supply voltage)
Sampling durations available:
ADC_SAMPLING_DURATION_2_7_US
ADC_SAMPLING_DURATION_5_3_US
ADC_SAMPLING_DURATION_10_6_US
ADC_SAMPLING_DURATION_21_3_US
ADC_SAMPLING_DURATION_42_6_US
ADC_SAMPLING_DURATION_85_3_US
ADC_SAMPLING_DURATION_170_US
ADC_SAMPLING_DURATION_341_US
ADC_SAMPLING_DURATION_682_US
ADC_SAMPLING_DURATION_1_37_MS
2018 Radiocrafts AS SPR SDK User Manual rev 1.0
SPR SDK User Manual
Page 18 of 28
ADC_SAMPLING_DURATION_2_73_MS
ADC_SAMPLING_DURATION_5_46_MS
ADC_SAMPLING_DURATION_10_9_MS
Example API call to get the converted raw value:
uint16_t value;
status = ADC.convert(ADC1, &value);
You can also get the version value in micro volts:
uint32_t value;
status = ADC.convertToMicroVolts(ADC1, &value);
The conversion functions block until conversion are complete.
10.7 SPI You can use the SPI API module to communicate on the SPI interface as a Master.
10.7.1 SPI Initializations
The SPI interface must be initialized in Setup() by calling SPI.init(), where you pass in the clock speed and the
clock mode (polarity and phase).
You may also need to setup a GPIO as the Chip Select line.
Below is a code example of initializing the SPI interface with a clock speed of 1 MHz, clock polarity of 0, and clock
phase of 0. It also sets up GPIO_3 as the Chip Select line.
#define SPI_CS GPIO_3 (1)
#define Assert_SPI_CS() GPIO.setValue(SPI_CS, LOW); (2)
#define Deassert_SPI_CS() GPIO.setValue(SPI_CS, HIGH); (3)
Setup()
{
SPI.init(1000000, SPI_POL_0_PHA_0); (4)
GPIO.setDirection(SPI_CS, OUTPUT_OPEN_DRAIN);
GPIO.setPull(SPI_CS, PULL_UP); (5)
Deassert_SPI_CS(); (6)
}
(1) define SPI_CS as an alias for GPIO_3
(2) define a macro to assert SPI chip select line by driving it low
(3) define a macro to de-assert the chip select line by driving it high
(4) initializes SPI clock speed of 1 MHz, clock polarity of 0, clock phase of 0
(5) setup the GPIO as an open drain output with an internall pull up
(6) Start the chip select in the de-asserted state
The possible combinations of clock polarity and phase are:
SPI_POL_0_PHA_0
SPI_POL_0_PHA_1
SPI_POL_1_PHA_0
SPI_POL_1_PHA_1
2018 Radiocrafts AS SPR SDK User Manual rev 1.0
SPR SDK User Manual
Page 19 of 28
10.7.2 SPI Transaction
Call SPI.transfer() to conduct a SPI transaction. You indicate the number of bytes to clock, the transmit buffer,
and the receive buffer.
SPI communication is full-duplex, so for every byte you transmit, you also receive a byte. As the bytes in the transmit buffer goes
out, the receive buffer is filled up with bytes received.
The following code example shows how to read a register from a slave device.
uint8_t txBuffer[2] = {0,}; (1)
uint8_t rxBuffer[2] = {0,};
txBuffer[0] = 0x80 | regAddress; (2)
Assert_SPI_CS(); (3)
SPR_Status status = SPI.transfer(2, txBuffer, rxBuffer); (4)
Deassert_SPI_CS();
Debug.printline("SPI received %x", rxBuffer[1]); (5)
(1) It is a good idea to initialize all values in the buffer to 0
(2) For the slave device in this example, 0x80 indicates a read operation. It is OR’ed with the register address. This
can be different for your SPI slave device.
(3) Uses the assert chip select macro that was defined in the previous example
(4) Transaction of 2 bytes. The first byte is the address, the second byte is for reading back the value
(5) Prints out the received value in the 2nd byte.
10.8 UART UART operations are non-blocking because bytes can be received at any time. So for transmission, you register a
callback to be triggered when the transmission is complete; for reception, you register a callback to be triggered when
bytes are available.
10.8.1 Initialization
In Setup(), call UART.init().
The following example initializes UART with baud=115200, parity=none, data bit=8, stop bit = 1.
UART.init(115200, UART_PARITY_NONE, UART_DATA_8_BITS, UART_STOP_2_BIT);
10.8.2 Transmission
Start the transmission and register a callback to be triggeered when the transmission is complete.
uint8_t data[3] = {1,2,3};
SPR_Status status = UART.startTransmit(data, sizeof(data), txCallback);
UART.startTransmit() returns right away with the status of whether transmission started successfully.
Then implement the callback:
void txCallbac(uint8_t len)
{
// len indicates number of bytes actually transmitted
}
2018 Radiocrafts AS SPR SDK User Manual rev 1.0
SPR SDK User Manual
Page 20 of 28
10.8.3 Receive
Start the reception with the number of expected bytes and register a callback to be triggered when the transmission is
complete.
uint8_t receiveBuffer[6];
SPR_Status status = UART.startReceive(receiveBuffer, 6, FULL_RECEIVE, receiveCallback);
Then implement the callback:
void receiveCallback(uint8_t buffer[], uint8_t len)
{
// process the received data
}
Full vs Partial Receive:
You can start a reception with the option for either FULL_RECEIVE or PARTIAL_RECEIVE.
FULL_RECEIVE indicates that the callback shall only be triggered if expected number of bytes are received.
PARTIAL_RECEIVE indicates that the callback will be called after 32-bit period of inactivity at the end of receiving
some but not all expected number of bytes. This is useful if you do not know how many bytes to expect.
Continuous Receive
An example to continuously receive (e.g. receiving one UART packet after another). In the reception callback, it starts
another receive.
#define RECEIVE_MAX 100
uint8_t receiveBuffer[RECEIVE_MAX];
static void receiveCallback(uint8_t buffer[], uint8_t len);
void Setup()
{
UART.init(115200, UART_PARITY_NONE, UART_DATA_8_BITS, UART_STOP_1_BIT);
UART.startReceive(receiveBuffer, RECEIVE_MAX, PARTIAL_RECEIVE, receiveCallback);
}
static void receiveCallback(uint8_t buffer[], uint8_t len)
{
// process UART packet
// start listening for next packet
UART.startReceive(receiveBuffer, RECEIVE_MAX, PARTIAL_RECEIVE, receiveCallback);
}
10.9 Non Volatile Storage Coming soon
10.10 Util Coming soon
10.11 Debug
You can use the printf() function in the Debug module to log statements to UART for debugging. All the normal C
printf format specifies can be used.
The UART settings: baud=115200, data bits=8, stop bit=1, parity=none.
2018 Radiocrafts AS SPR SDK User Manual rev 1.0
SPR SDK User Manual
Page 21 of 28
Examples:
Debug.printf(“debugging statement\n”);
Debug.printf(“sensor reading=%d”, decimalValue);
Debug.printline(“sensor reading=%2x”, hexValue);
The \n at the end of the string starts a newline. You can also call Debug.printline() where you can omit the \n.
To print an array of bytes:
uint8_t array[6];
Debug.printArray(6, array);
10.12 Special Note on Initialization of Variables Please note that global variables should not be initialized at declaration. They should be initialized in Setup(). Arrays,
either global or within a function, also cannot not be initialized at declaration.
Compiler errors will not be generated when the guidelines are not followed. However, the variables will not be
initialized as expected when the application runs.
This happens because the platform and user app is, in actuality, one application, but managed as 2 different images.
This makes user updates quick and efficient without needing to update the larger platform code. The challenge is that
the variable initialization table must be in the platform image. To have different user apps run on a fixed platform
image, or to have a user app run on different compatible platform images, no initialization values must be stored for
user global variables.
Please see examples below for clarification.
Do NOT initialize a global variable at declaration:
// Global variable
uint16_t counter = 0;
Setup()
{
}
Do initialize a global variable in Setup() or another function:
// Global variable
uint16_t counter;
Setup()
{
counter = 0;
}
Do NOT initialize an array (global or within a function) at declaration:
uint8_t data[3] = {0x01,0x02,0x03};
Do initialize the array in code:
uint8_t data[3];
data[0] = 0x01;
2018 Radiocrafts AS SPR SDK User Manual rev 1.0
SPR SDK User Manual
Page 22 of 28
data[1] = 0x02;
data[2] = 0x03;
Exception: you CAN initialize an array to all zeros:
uint8_t data[10] = {0};
Can initialize variables (non-array) in handler functions:
void sendMessage(void)
{
uint8_t alarmStatus = 10;
for (int i = 0; i < 8; i++)
getSensorValue(i);
}
11 Bootloader Utility
Bootloader Utility is a command-line program that can be used during development or production process to load app
image and keys into SPR modules. The bootloaded utility is automatically run as part of script flash_app.bat.
The program is included in the SDK's util folder as "bootloader_util.exe". It is to be run in a command line terminal.
The recommended production procedure:
1. Reset the module into bootloader mode
2. Load app image encryption key
3. Load network key
4. Load platform image (only if a platform update is required)
5. Load app image
6. Lock module
See the following sections for details on each of the steps.
11.1 Bootloader Utility Command-Line Syntax Bootloader utility uses the following syntax. It also looks for a config.ini file for the default COM port.
bootloader_util.exe <command> [--file <image or key file path>] [--port <serialport>] [-t <timeout>] [--version]
[--help]
<command>:
info
load-image
load-app-image-key
load-network-key
lock
run-app
Options: --file -f <path to image or key file>
This is an argument that is needed when loading an image or key.
e.g. bootloader_util load-app-image-key -f app.bin
2018 Radiocrafts AS SPR SDK User Manual rev 1.0
SPR SDK User Manual
Page 23 of 28
--port -p <serialport>
This is an optional argument to connect to a serial port different from what is specified in the config.ini file. If
unspecified, then the COM port in the config file is used.
e.g. bootloader_util info -p COM14
--timeout -t <serialport>
This is an optional argument to specify the time, in seconds, for trying to connect to the bootloader. If
unspecified, default is 10.
e.g. bootloader_util info -t 10
11.2 Enter Bootloader Mode Before loading images and keys, the module must be reset into its bootloader mode. Normally, on power up, the
module starts running the application. However, if the module receives a valid bootloader command within 0.25
seconds of power up, then it enters the bootloader mode.
To do so, first start the bootloader utility with the 'info' command. While bootloader utility is trying to connect to the
bootloader, reset the module.
When module has entered the bootloader mode, you will see information about the module, e.g. IEEE address
(EUI64), platform and app version, lock state.
Once module enters the bootloader, it stays in the bootloader mode, available for one bootloader command after
another, until you reset the module or if you run bootloader utility with the command 'run-app'.
11.3 Load App Image Encryption Key The key used to encrypt the app image needs to be loaded before loading the app image. The key file must contain 32
hex characters to represent a 16-byte key.
The app image encryption key cannot be written after the module is locked.
2018 Radiocrafts AS SPR SDK User Manual rev 1.0
SPR SDK User Manual
Page 24 of 28
Command-line usage:
bootloader_util.exe load-app-image-key --file <key file path>
Example terminal output:
11.4 Load Network Key The network key is used to encrypt network messages (if enabled through the Network API). You can choose your
own network key. The key can be modified even after the module is locked, allowing you to change network key at
different sites.
The key file must contain 32 hex characters to represent a 16-byte key
Command-line usage:
bootloader_util.exe load-network-key --file <key file path>
Example terminal output:
11.5 Load Platform Image This is only necessary if the platform on the module needs to be updated.
2018 Radiocrafts AS SPR SDK User Manual rev 1.0
SPR SDK User Manual
Page 25 of 28
The latest platform image is included in the SDK's 'platform' folder. The platform image is large, so it could take
approx 10 seconds.
Command-line usage:
bootloader_util.exe load-image --file <image path>
Example terminal output:
11.6 Load App Image Loading the app image (*.bin) follows the same command line arguments as loading a platform image:
bootloader_util.exe load-image --file <image path>
The app image is small, and should be complete within 1 second.
Example terminal output:
2018 Radiocrafts AS SPR SDK User Manual rev 1.0
SPR SDK User Manual
Page 26 of 28
11.7 Lock the Module Locking the module would prevent future modifications of the app image encryption key. This securing the module in
the field from receiving unauthorized firmware updates.
This should be the last step of the production process. Once a module is locked, it cannot be unlocked.
Command line usage:
bootloader_util.exe lock
Example terminal output:
2018 Radiocrafts AS SPR SDK User Manual rev 1.0
SPR SDK User Manual
Page 27 of 28
12 Revision History
Revision Date Changes
v0.8r1 July 23, 2018 Draft for release
v0.9r1 October 18, 2018 Updated ADC API
v1.0 November 15, 2018 Added sections on SDK directory structure, building
app, flashing app, image encryption, network
encryption
Added section on Bootloader Utility
2018 Radiocrafts AS SPR SDK User Manual rev 1.0
SPR SDK User Manual
Page 28 of 28
Disclaimer
Radiocrafts AS believes the information contained herein is correct and accurate at the time of this printing. However, Radiocrafts
AS reserves the right to make changes to this product without notice. Radiocrafts AS does not assume any responsibility for the
use of the described product; neither does it convey any license under its patent rights, or the rights of others. The latest updates
are available at the Radiocrafts website or by contacting Radiocrafts directly.
As far as possible, major changes of product specifications and functionality, will be stated in product specific Errata Notes
published at the Radiocrafts website. Customers are encouraged to check regularly for the most recent updates on products and
support tools.
Trademarks
RIIoT™ is a trademark of Radiocrafts AS.
All other trademarks, registered trademarks and product names are the sole property of their respective owners.
Life Support Policy
This Radiocrafts product is not designed for use in life support appliances, devices, or other systems where malfunction can
reasonably be expected to result in significant personal injury to the user, or as a critical component in any life support device or
system whose failure to perform can be reasonably expected to cause the failure of the life support device or system, or to affect
its safety or effectiveness. Radiocrafts AS customers using or selling these products for use in such applications do so at their own
risk and agree to fully indemnify Radiocrafts AS for any damages resulting from any improper use or sale.
Radiocrafts Support:
Knowledge base: https://radiocrafts.com/knowledge-base/
Application notes library: https://radiocrafts.com/resources/application-notes/
Whitepapers: https://radiocrafts.com/resources/articles-white-papers/
Technology overview: https://radiocrafts.com/technologies/
RF Wireless Expert Training: https://radiocrafts.com/resources/rf-wireless-expert-training/
Contact Radiocrafts
Sales requests: https://radiocrafts.com/contact/
© 2018, Radiocrafts AS. All rights reserved.