Skip to content

Commit

Permalink
Add NRF5 platform support
Browse files Browse the repository at this point in the history
This is the support of the Nordic Semiconductor NRF51 (nrf51822,
nrf51422) and NRF52 (nrf52832) platform. Based on arduino-nRF5
(https://github.com/sandeepmistry/arduino-nRF5).

The included radio driver is compatible with the NRF24 devices.
Using a SoftDevice (BLE)is not supported and must be removed before
flashing MySensors with a "mass_erase" operation.
  • Loading branch information
d00616 committed May 6, 2017
1 parent fade164 commit 9e9a03f
Show file tree
Hide file tree
Showing 20 changed files with 2,388 additions and 11 deletions.
92 changes: 92 additions & 0 deletions MyConfig.h
Expand Up @@ -94,6 +94,7 @@

// Selecting uplink transport layer is optional (for a gateway node).
//#define MY_RADIO_RF24
//#define MY_RADIO_NRF5_ESB
//#define MY_RADIO_RFM69
//#define MY_RADIO_RFM95
//#define MY_RS485
Expand Down Expand Up @@ -668,6 +669,94 @@
#define MY_SOFT_SPI_MOSI_PIN (15)
#endif

/**********************************
* NRF5_ESB Driver Defaults
* The NRF5_ESB driver is compatible
* to RF24
***********************************/

/**
* @def MY_NRF5_ESB_ENABLE_ENCRYPTION
* @brief Enables RF24 compatible ncryption (all nodes and gateway must have
* this enabled, and all must be personalized with the same AES key)
* This is compatible to MY_RF24_ENABLE_ENCRYPTION. Because the Initialization
* Vector is always 0, the Encryption is weak.
*/
//#define MY_NRF5_ESB_ENABLE_ENCRYPTION

/**
* @def MY_DEBUG_VERBOSE_NRF5_ESB
* @brief Enable MY_DEBUG_VERBOSE_NRF5_ESB flag for verbose debug prints related
* to the NRF5_ESB driver. Requires DEBUG to be enabled.
*/
//#define MY_DEBUG_VERBOSE_NRF5_ESB

/**
* @def MY_NRF5_ESB_PA_LEVEL
* @brief Default NRF5 PA level. Override in sketch if needed.
*/
#ifndef MY_NRF5_ESB_PA_LEVEL
#define MY_NRF5_ESB_PA_LEVEL NRF5_PA_MAX
#endif

/**
* @def MY_NRF5_ESB_CHANNEL
* @brief RF channel for the sensor net, 0-125.
* Frequence: 2400 Mhz - 2525 Mhz Channels: 126
* http://www.mysensors.org/radio/nRF24L01Plus.pdf
* 0 => 2400 Mhz (RF24 channel 1)
* 1 => 2401 Mhz (RF24 channel 2)
* 76 => 2476 Mhz (RF24 channel 77)
* 83 => 2483 Mhz (RF24 channel 84)
* 124 => 2524 Mhz (RF24 channel 125)
* 125 => 2525 Mhz (RF24 channel 126)
* In some countries there might be limitations, in Germany for example only the
* range 2400,0 - 2483,5 Mhz is allowed
* http://www.bundesnetzagentur.de/SharedDocs/Downloads/DE/Sachgebiete/Telekommunikation/Unternehmen_Institutionen/Frequenzen/Allgemeinzuteilungen/2013_10_WLAN_2,4GHz_pdf.pdf
*/
#ifndef MY_NRF5_ESB_CHANNEL
#define MY_NRF5_ESB_CHANNEL 76
#endif

/**
* @def MY_NRF5_ESB_MODE
* @brief NRF5 mode (NRF5_250KBPS for 250kbs, NRF5_1MBPS for 1Mbps or NRF5_2MBPS
* for 2Mbps).
*/
#ifndef MY_NRF5_ESB_MODE
#define MY_NRF5_ESB_MODE NRF5_250KBPS
#endif

/**
* @def MY_NRF5_ESB_BASE_RADIO_ID
* @brief NRF5 radio network identifier.
*
* This acts as base value for sensor nodeId addresses. Change this (or channel)
* if you have more than one sensor network.
*/
#ifndef MY_NRF5_ESB_BASE_RADIO_ID
#define MY_NRF5_ESB_BASE_RADIO_ID 0x00, 0xFC, 0xE1, 0xA8, 0xA8
#endif

/**
* @def MY_NRF5_ESB_ADDR_WIDTH
* @brief NRF5 address width.
*
* This defines the width of the complete address.
*/
#ifndef MY_NRF5_ESB_ADDR_WIDTH
#define MY_NRF5_ESB_ADDR_WIDTH 5
#endif

/**
* @def MY_NRF5_ESB_RX_BUFFER_SIZE
* @brief Declare the amount of incoming messages that can be buffered at driver
* level.
*/
#ifndef MY_NRF5_ESB_RX_BUFFER_SIZE
#define MY_NRF5_ESB_RX_BUFFER_SIZE (20)
#endif

/**********************************
* RFM69 Driver Defaults
***********************************/
Expand Down Expand Up @@ -1213,6 +1302,9 @@
#define MY_RF24_ENABLE_ENCRYPTION
#define MY_RX_MESSAGE_BUFFER_FEATURE
#define MY_RX_MESSAGE_BUFFER_SIZE
// NRF5_ESB
#define MY_NRF5_ESB_ENABLE_ENCRYPTION
#define MY_DEBUG_VERBOSE_NRF5_ESB
// RFM69
#define MY_IS_RFM69HW
#define MY_RFM69_NEW_DRIVER
Expand Down
33 changes: 27 additions & 6 deletions MySensors.h
Expand Up @@ -66,7 +66,7 @@
#define MY_DEBUG_VERBOSE_OTA_UPDATE //!< MY_DEBUG_VERBOSE_OTA_UPDATE
#endif

#if defined(MY_DEBUG) || defined(MY_DEBUG_VERBOSE_CORE) || defined(MY_DEBUG_VERBOSE_TRANSPORT) || defined(MY_DEBUG_VERBOSE_SIGNING) || defined(MY_DEBUG_VERBOSE_OTA_UPDATE) || defined(MY_DEBUG_VERBOSE_RF24) || defined(MY_DEBUG_VERBOSE_RFM69) || defined(MY_DEBUG_VERBOSE_RFM95)
#if defined(MY_DEBUG) || defined(MY_DEBUG_VERBOSE_CORE) || defined(MY_DEBUG_VERBOSE_TRANSPORT) || defined(MY_DEBUG_VERBOSE_SIGNING) || defined(MY_DEBUG_VERBOSE_OTA_UPDATE) || defined(MY_DEBUG_VERBOSE_RF24) || defined(MY_DEBUG_VERBOSE_NRF5_ESB) || defined(MY_DEBUG_VERBOSE_RFM69) || defined(MY_DEBUG_VERBOSE_RFM95)
#define DEBUG_OUTPUT_ENABLED //!< DEBUG_OUTPUT_ENABLED
#define DEBUG_OUTPUT(x,...) hwDebugPrint(x, ##__VA_ARGS__) //!< debug
#else
Expand All @@ -78,7 +78,7 @@


// Enable sensor network "feature" if one of the transport types was enabled
#if defined(MY_RADIO_RF24) || defined(MY_RADIO_RFM69) || defined(MY_RADIO_RFM95) || defined(MY_RS485)
#if defined(MY_RADIO_RF24) || defined(MY_RADIO_NRF5_ESB) || defined(MY_RADIO_RFM69) || defined(MY_RADIO_RFM95) || defined(MY_RS485)
#define MY_SENSOR_NETWORK
#endif

Expand All @@ -93,6 +93,10 @@
#include "hal/architecture/MyHwSAMD.cpp"
#elif defined(ARDUINO_ARCH_STM32F1)
#include "hal/architecture/MyHwSTM32F1.cpp"
#elif defined(ARDUINO_ARCH_NRF5)
#include "drivers/NVM/VirtualPage.cpp"
#include "drivers/NVM/NVRAM.cpp"
#include "hal/architecture/MyHwNRF5.cpp"
#elif defined(__linux__)
#include "hal/architecture/MyHwLinuxGeneric.cpp"
#endif
Expand Down Expand Up @@ -247,7 +251,12 @@ MY_DEFAULT_RX_LED_PIN in your sketch instead to enable LEDs
#if defined(MY_RADIO_RF24)
#define __RF24CNT 1 //!< __RF24CNT
#else
#define __RF24CNT 0 //!< __RF24CNT
#define __RF24CNT 0 //!< __RF24CNT
#endif
#if defined(MY_RADIO_NRF5_ESB)
#define __NRF5ESBCNT 1 //!< __NRF5ESBCNT
#else
#define __NRF5ESBCNT 0 //!< __NRF5ESBCNT
#endif
#if defined(MY_RADIO_RFM69)
#define __RFM69CNT 1 //!< __RFM69CNT
Expand All @@ -265,12 +274,12 @@ MY_DEFAULT_RX_LED_PIN in your sketch instead to enable LEDs
#define __RS485CNT 0 //!< __RS485CNT
#endif

#if (__RF24CNT + __RFM69CNT + __RFM95CNT + __RS485CNT > 1)
#if (__RF24CNT + __NRF5ESBCNT + __RFM69CNT + __RFM95CNT + __RS485CNT > 1)
#error Only one forward link driver can be activated
#endif

// TRANSPORT INCLUDES
#if defined(MY_RADIO_RF24) || defined(MY_RADIO_RFM69) || defined(MY_RADIO_RFM95) || defined(MY_RS485)
#if defined(MY_RADIO_RF24) || defined(MY_RADIO_NRF5_ESB) || defined(MY_RADIO_RFM69) || defined(MY_RADIO_RFM95) || defined(MY_RS485)
#include "hal/transport/MyTransportHAL.h"
#include "core/MyTransport.h"

Expand All @@ -292,7 +301,7 @@ MY_DEFAULT_RX_LED_PIN in your sketch instead to enable LEDs
// RAM ROUTING TABLE
#if defined(MY_RAM_ROUTING_TABLE_FEATURE) && defined(MY_REPEATER_FEATURE)
// activate feature based on architecture
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_SAMD) || defined(__linux__)
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_NRF5) || defined(__linux__)
#define MY_RAM_ROUTING_TABLE_ENABLED
#elif defined(ARDUINO_ARCH_AVR)
#if defined(__avr_atmega1280__) || defined(__avr_atmega1284__) || defined(__avr_atmega2560__)
Expand Down Expand Up @@ -331,6 +340,16 @@ MY_DEFAULT_RX_LED_PIN in your sketch instead to enable LEDs
#endif
#include "drivers/RF24/RF24.cpp"
#include "hal/transport/MyTransportRF24.cpp"
#elif defined(MY_RADIO_NRF5_ESB)
#if !defined(ARDUINO_ARCH_NRF5)
#error No support for nRF5 radio on this platform
#endif
#if defined(MY_NRF5_ESB_ENABLE_ENCRYPTION)
#include "drivers/AES/AES.cpp"
#endif
#include "drivers/NRF5/Radio.cpp"
#include "drivers/NRF5/Radio_ESB.cpp"
#include "hal/transport/MyTransportNRF5_ESB.cpp"
#elif defined(MY_RS485)
#if !defined(MY_RS485_HWSERIAL)
#if defined(__linux__)
Expand Down Expand Up @@ -399,6 +418,8 @@ MY_DEFAULT_RX_LED_PIN in your sketch instead to enable LEDs
#if !defined(MY_CORE_ONLY)
#if defined(ARDUINO_ARCH_ESP8266)
#include "hal/architecture/MyMainESP8266.cpp"
#elif defined(ARDUINO_ARCH_NRF5)
#include "hal/architecture/MyMainNRF5.cpp"
#elif defined(__linux__)
#include "hal/architecture/MyMainLinux.cpp"
#elif defined(ARDUINO_ARCH_STM32F1)
Expand Down
4 changes: 3 additions & 1 deletion core/MyCapabilities.h
Expand Up @@ -34,7 +34,7 @@
#endif


#if defined(MY_RADIO_NRF24)
#if defined(MY_RADIO_NRF24) || defined(MY_RADIO_NRF5_ESB)
#define MY_CAP_RADIO "N"
#elif defined(MY_RADIO_RFM69)
#if !defined(MY_RFM69_NEW_DRIVER)
Expand Down Expand Up @@ -64,6 +64,8 @@

#if defined(ARDUINO_ARCH_SAMD)
#define MY_CAP_ARCH "S"
#elif defined(ARDUINO_ARCH_NRF5)
#define MY_CAP_ARCH "N"
#elif defined(ARDUINO_ARCH_ESP8266)
#define MY_CAP_ARCH "E"
#elif defined(ARDUINO_ARCH_AVR)
Expand Down
3 changes: 3 additions & 0 deletions core/MyTransport.h
Expand Up @@ -215,6 +215,9 @@
#if defined(MY_RS485)
#error Receive message buffering not supported for RS485!
#endif
#if defined(MY_RADIO_NRF5_ESB)
#error Receive message buffering not supported for NRF5 radio! Please define MY_NRF5_RX_BUFFER_SIZE
#endif
#elif !defined(MY_RX_MESSAGE_BUFFER_FEATURE) && defined(MY_RX_MESSAGE_BUFFER_SIZE)
#error Receive message buffering requires message buffering feature enabled!
#endif
Expand Down
148 changes: 148 additions & 0 deletions drivers/NRF5/Flash.cpp
@@ -0,0 +1,148 @@
/*
Flash.cpp - Flash library
Original Copyright (c) 2017 Frank Holtz. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "drivers/NVM/Flash.h"

FlashClass Flash;

uint32_t FlashClass::page_size() const
{
return (size_t)NRF_FICR->CODEPAGESIZE;
}

uint8_t FlashClass::page_size_bits() const
{
#if defined(NRF51)
return 10;
#elif defined(NRF52)
return 12;
#endif
}

uint32_t FlashClass::page_count() const
{
return (uint32_t)NRF_FICR->CODESIZE;
}

uint32_t FlashClass::specified_erase_cycles() const
{
return FLASH_ERASE_CYCLES;
}

uint32_t *FlashClass::page_address(size_t page)
{
return (uint32_t *)(page << page_size_bits());
}

void FlashClass::erase(uint32_t *address, size_t size)
{
size_t end_address = (size_t)address + size;

// align address
address =
(uint32_t *)((size_t)address & (size_t)((size_t)(~0) - FLASH_PAGE_SIZE));

// Wrong parameters?
if ((size_t)address >= end_address) {
return;
}

// get old nvm controller state
uint32_t old_config = NRF_NVMC->CONFIG;

// Enable erasing flash
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Een << NVMC_CONFIG_WEN_Pos;

// Erase page(s)
while ((size_t)address < end_address) {
wait_for_ready();
// Erase one 1k/4k page
NRF_NVMC->ERASEPAGE = (size_t)(address);
address = (uint32_t *)((size_t)address + FLASH_PAGE_SIZE);
}

// Disable erasing
wait_for_ready();
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos;

// Restore old state
wait_for_ready();
NRF_NVMC->CONFIG = old_config;

// Go back if controller is ready
wait_for_ready();
}

void FlashClass::erase_all()
{
// Enable erasing flash
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Een << NVMC_CONFIG_WEN_Pos;
wait_for_ready();

// Erase Flash and UICR
NRF_NVMC->ERASEALL = 1;
wait_for_ready();

// Disable erasing
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos;
wait_for_ready();
}

void FlashClass::write(uint32_t *address, uint32_t value)
{
// Compare word
if (*address != value) {
// Enable write
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos;
wait_for_ready();
// Write word
*address = value;
// Disable write
wait_for_ready();
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos;
wait_for_ready();
}
}

void FlashClass::write_block(uint32_t *dst_address, uint32_t *src_address,
uint16_t word_count)
{
// Enable write
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos;
wait_for_ready();

while (word_count > 0) {
if (*dst_address != *src_address) {
*dst_address = *src_address;
}
word_count--;
dst_address++;
src_address++;
}

// Disable write
wait_for_ready();
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos;
wait_for_ready();
}

void FlashClass::wait_for_ready()
{
while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {
};
}

0 comments on commit 9e9a03f

Please sign in to comment.