mirror of
https://github.com/IoTManagerProject/IoTManager.git
synced 2026-03-30 20:09:14 +03:00
gatewayTransportSend
This commit is contained in:
533
lib/MySensors/hal/architecture/NRF5/MyHwNRF5.cpp
Normal file
533
lib/MySensors/hal/architecture/NRF5/MyHwNRF5.cpp
Normal file
@@ -0,0 +1,533 @@
|
||||
/*
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of
|
||||
* the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2019 Sensnology AB
|
||||
* Copyright (C) 2017 Frank Holtz
|
||||
* Full contributor list:
|
||||
* https://github.com/mysensors/MySensors/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include "MyHwNRF5.h"
|
||||
|
||||
volatile uint8_t _wokeUpByInterrupt = INVALID_INTERRUPT_NUM; // Interrupt number that woke the mcu.
|
||||
volatile uint8_t _wakeUp1Interrupt =
|
||||
INVALID_INTERRUPT_NUM; // Interrupt number for wakeUp1-callback.
|
||||
volatile uint8_t _wakeUp2Interrupt =
|
||||
INVALID_INTERRUPT_NUM; // Interrupt number for wakeUp2-callback.
|
||||
|
||||
void wakeUp1(void) // place to send the interrupts
|
||||
{
|
||||
_wokeUpByInterrupt = _wakeUp1Interrupt;
|
||||
}
|
||||
void wakeUp2(void) // place to send the second interrupts
|
||||
{
|
||||
_wokeUpByInterrupt = _wakeUp2Interrupt;
|
||||
}
|
||||
|
||||
void hwReadConfigBlock(void *buf, void *addr, size_t length)
|
||||
{
|
||||
uint8_t *dst = static_cast<uint8_t *>(buf);
|
||||
const int offs = reinterpret_cast<int>(addr);
|
||||
(void)NVRAM.read_block(dst, offs, length);
|
||||
}
|
||||
|
||||
void hwWriteConfigBlock(void *buf, void *addr, size_t length)
|
||||
{
|
||||
uint8_t *src = static_cast<uint8_t *>(buf);
|
||||
const int offs = reinterpret_cast<int>(addr);
|
||||
(void)NVRAM.write_block(src, offs, length);
|
||||
}
|
||||
|
||||
uint8_t hwReadConfig(const int addr)
|
||||
{
|
||||
return NVRAM.read(addr);
|
||||
}
|
||||
|
||||
void hwWriteConfig(const int addr, uint8_t value)
|
||||
{
|
||||
(void)NVRAM.write(addr, value);
|
||||
}
|
||||
|
||||
bool hwInit(void)
|
||||
{
|
||||
#ifdef MY_LOCK_MCU
|
||||
#ifdef NRF51
|
||||
// Lock MCU
|
||||
if((uint32_t)((NRF_UICR->RBPCONF & UICR_RBPCONF_PALL_Msk) >> UICR_RBPCONF_PALL_Pos) !=
|
||||
UICR_RBPCONF_PALL_Enabled) {
|
||||
Flash.write((uint32_t *)&NRF_UICR->RBPCONF, (NRF_UICR->RBPCONF & ~UICR_RBPCONF_PALL_Msk));
|
||||
hwReboot();
|
||||
}
|
||||
#else
|
||||
// Lock MCU
|
||||
if((uint32_t)((NRF_UICR->APPROTECT & UICR_APPROTECT_PALL_Msk) >> UICR_APPROTECT_PALL_Pos) !=
|
||||
UICR_APPROTECT_PALL_Enabled) {
|
||||
Flash.write((uint32_t *)&NRF_UICR->APPROTECT, (NRF_UICR->APPROTECT & ~UICR_APPROTECT_PALL_Msk));
|
||||
hwReboot();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(NRF51) && defined(CONFIG_ENABLE_PINRESET)
|
||||
// Enabling reset for NRF51 isn't handled by arduino-nrf5. Enable it, if requested.
|
||||
NRF_POWER->RESET = POWER_RESET_RESET_Enabled;
|
||||
NRF_POWER->RAMON |= (POWER_RAMON_ONRAM0_RAM0On << POWER_RAMON_ONRAM0_Pos) |
|
||||
(POWER_RAMON_ONRAM1_RAM1On << POWER_RAMON_ONRAM1_Pos);
|
||||
#endif
|
||||
|
||||
// Clock is manged by sleep modes. Radio depends on HFCLK.
|
||||
// Force to start HFCLK
|
||||
NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
|
||||
NRF_CLOCK->TASKS_HFCLKSTART = 1;
|
||||
while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0)
|
||||
;
|
||||
|
||||
// Enable low latency sleep mode
|
||||
NRF_POWER->TASKS_CONSTLAT = 1;
|
||||
|
||||
// Enable cache on >= NRF52
|
||||
#ifndef NRF51
|
||||
NRF_NVMC->ICACHECNF = NVMC_ICACHECNF_CACHEEN_Msk;
|
||||
#endif
|
||||
|
||||
// Suspend UART
|
||||
NRF_UART0->TASKS_STOPRX = 1;
|
||||
NRF_UART0->TASKS_STOPTX = 1;
|
||||
NRF_UART0->TASKS_SUSPEND = 1;
|
||||
|
||||
#ifdef MY_DISABLED_SERIAL
|
||||
// Disable UART, when not configured
|
||||
#ifdef NRF51
|
||||
NRF_UART0->POWER = 0;
|
||||
#endif
|
||||
#else
|
||||
// Configure UART
|
||||
MY_SERIALDEVICE.begin(MY_BAUD_RATE);
|
||||
#if defined(MY_GATEWAY_SERIAL)
|
||||
while (!MY_SERIALDEVICE) {
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static nrf_ecb_t hwRngData;
|
||||
static int8_t hwRndDataReadPos = -1;
|
||||
|
||||
void hwRandomNumberInit(void)
|
||||
{
|
||||
// Start HWRNG
|
||||
#ifdef NRF51
|
||||
NRF_RNG->POWER = 1;
|
||||
#endif
|
||||
// Enable "more random" numbers
|
||||
NRF_RNG->CONFIG = RNG_CONFIG_DERCEN_Enabled << RNG_CONFIG_DERCEN_Pos;
|
||||
NRF_RNG->TASKS_START = 1;
|
||||
NRF_RNG->EVENTS_VALRDY = 0;
|
||||
|
||||
uint32_t seed = 0;
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
// Wait for an random number
|
||||
while (NRF_RNG->EVENTS_VALRDY == 0) {
|
||||
yield();
|
||||
}
|
||||
seed = (seed << 8) | (uint32_t)NRF_RNG->VALUE;
|
||||
NRF_RNG->EVENTS_VALRDY = 0;
|
||||
}
|
||||
randomSeed(seed);
|
||||
|
||||
// Fill ESB data structure for fast random data generation
|
||||
uint8_t *ecbstruct = (uint8_t *)&hwRngData;
|
||||
for (uint8_t i = 0; i<sizeof(hwRngData); i++) {
|
||||
while (NRF_RNG->EVENTS_VALRDY == 0) {
|
||||
yield();
|
||||
}
|
||||
*(ecbstruct + i) = NRF_RNG->VALUE;
|
||||
NRF_RNG->EVENTS_VALRDY = 0;
|
||||
}
|
||||
hwRndDataReadPos = 0;
|
||||
|
||||
// Stop HWRNG
|
||||
NRF_RNG->TASKS_STOP = 1;
|
||||
#ifdef NRF51
|
||||
NRF_RNG->POWER = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
ssize_t hwGetentropy(void *__buffer, size_t __length)
|
||||
{
|
||||
if (hwRndDataReadPos<0) {
|
||||
// Not initialized
|
||||
hwRandomNumberInit();
|
||||
}
|
||||
|
||||
// cut length if > 256
|
||||
if (__length > 256) {
|
||||
__length = 256;
|
||||
}
|
||||
uint8_t *dst = (uint8_t *)__buffer;
|
||||
|
||||
// Start random number generator
|
||||
for (size_t i = 0; i < __length; i++) {
|
||||
dst[i] = hwRngData.ciphertext[hwRndDataReadPos & 0xfu];
|
||||
MY_CRITICAL_SECTION {
|
||||
if (hwRndDataReadPos >= ((int8_t)sizeof(hwRngData.ciphertext)-1))
|
||||
{
|
||||
// Retry until no error
|
||||
bool need_data = true;
|
||||
while (need_data) {
|
||||
// Stop if another task is running
|
||||
NRF_ECB->TASKS_STOPECB = 1;
|
||||
NRF_ECB->EVENTS_ERRORECB = 0;
|
||||
NRF_ECB->EVENTS_ENDECB = 0;
|
||||
uint32_t ptrbackup = NRF_ECB->ECBDATAPTR;
|
||||
NRF_ECB->ECBDATAPTR = (uint32_t)&hwRngData;
|
||||
NRF_ECB->TASKS_STARTECB = 1;
|
||||
while (!NRF_ECB->EVENTS_ENDECB);
|
||||
NRF_ECB->ECBDATAPTR = ptrbackup;
|
||||
if (NRF_ECB->EVENTS_ERRORECB == 0) {
|
||||
need_data = false;
|
||||
}
|
||||
}
|
||||
hwRndDataReadPos=0;
|
||||
for (uint8_t pos = 0; pos < sizeof(hwRngData.ciphertext); pos++) {
|
||||
hwRngData.cleartext[pos] ^= hwRngData.ciphertext[pos];
|
||||
}
|
||||
} else
|
||||
{
|
||||
hwRndDataReadPos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return __length;
|
||||
}
|
||||
|
||||
void hwWatchdogReset(void)
|
||||
{
|
||||
NRF_WDT->RR[0] = WDT_RR_RR_Reload;
|
||||
}
|
||||
|
||||
void hwReboot(void)
|
||||
{
|
||||
NVIC_SystemReset();
|
||||
while (true)
|
||||
;
|
||||
}
|
||||
|
||||
static volatile bool nrf5_rtc_event_triggered;
|
||||
static volatile bool nrf5_pwr_hfclk;
|
||||
|
||||
void hwSleepPrepare(uint32_t ms)
|
||||
{
|
||||
// Enable low power sleep mode
|
||||
NRF_POWER->TASKS_LOWPWR = 1;
|
||||
|
||||
// Reset RTC trigger flag
|
||||
nrf5_rtc_event_triggered = false;
|
||||
|
||||
if (ms > 0) {
|
||||
// Configure RTC
|
||||
#ifdef NRF51
|
||||
MY_HW_RTC->POWER = 1;
|
||||
#endif
|
||||
// Reset RTC
|
||||
MY_HW_RTC->TASKS_CLEAR = 1;
|
||||
|
||||
// Calculate sleep time and prescaler
|
||||
if (ms<512000) {
|
||||
// prescaler 0, 30.517 μs resolution -> max 512 s sleep
|
||||
MY_HW_RTC->PRESCALER = 0;
|
||||
// Set compare register to 1/30.517 µs to guarantee event triggering
|
||||
// A minimum of 2 ticks must be guaranteed
|
||||
// (1000/32768)<<12 == 125
|
||||
MY_HW_RTC->CC[0] = max(((ms << 12) / 125), 2);
|
||||
} else {
|
||||
// 8 Hz -> max 582.542 hours sleep.
|
||||
MY_HW_RTC->PRESCALER = 4095;
|
||||
// Set compare register to 1/125ms
|
||||
// A minimum of 2 ticks must be guaranteed
|
||||
MY_HW_RTC->CC[0] = max((ms / 125), 2);
|
||||
}
|
||||
|
||||
MY_HW_RTC->INTENSET = RTC_INTENSET_COMPARE0_Msk;
|
||||
MY_HW_RTC->EVTENSET = RTC_EVTENSET_COMPARE0_Msk;
|
||||
MY_HW_RTC->EVENTS_COMPARE[0] = 0;
|
||||
MY_HW_RTC->TASKS_START = 1;
|
||||
NVIC_SetPriority(MY_HW_RTC_IRQN, 15);
|
||||
NVIC_ClearPendingIRQ(MY_HW_RTC_IRQN);
|
||||
NVIC_EnableIRQ(MY_HW_RTC_IRQN);
|
||||
} else {
|
||||
NRF_RTC1->TASKS_STOP = 1;
|
||||
}
|
||||
|
||||
// Stop HFCLK
|
||||
nrf5_pwr_hfclk = NRF_CLOCK->EVENTS_HFCLKSTARTED;
|
||||
NRF_CLOCK->TASKS_HFCLKSTOP = 1;
|
||||
|
||||
// Idle serial device
|
||||
#ifndef MY_DISABLED_SERIAL
|
||||
NRF_UART0->TASKS_STOPRX = 1;
|
||||
NRF_UART0->TASKS_STOPTX = 1;
|
||||
NRF_UART0->TASKS_SUSPEND = 1;
|
||||
#endif
|
||||
|
||||
// Clear NVRAM log, if needed and a time frame of 4 seconds available
|
||||
if (ms > 40000) {
|
||||
// preserve some bytes for writing to NVRAM
|
||||
NVRAM.clean_up(32);
|
||||
}
|
||||
}
|
||||
|
||||
void hwSleepEnd(uint32_t ms)
|
||||
{
|
||||
// Start HFCLK
|
||||
if (nrf5_pwr_hfclk) {
|
||||
NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
|
||||
NRF_CLOCK->TASKS_HFCLKSTART = 1;
|
||||
while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0)
|
||||
;
|
||||
// Enable low latency sleep mode
|
||||
NRF_POWER->TASKS_CONSTLAT = 1;
|
||||
}
|
||||
|
||||
if (ms > 0) {
|
||||
// Stop RTC
|
||||
#ifdef NRF51
|
||||
MY_HW_RTC->POWER = 0;
|
||||
#endif
|
||||
MY_HW_RTC->INTENCLR = RTC_INTENSET_COMPARE0_Msk;
|
||||
MY_HW_RTC->EVTENCLR = RTC_EVTENSET_COMPARE0_Msk;
|
||||
MY_HW_RTC->TASKS_STOP = 1;
|
||||
NVIC_DisableIRQ(MY_HW_RTC_IRQN);
|
||||
} else {
|
||||
// Start Arduino RTC for millis()
|
||||
NRF_RTC1->TASKS_START = 1;
|
||||
}
|
||||
|
||||
// Start serial device
|
||||
#ifndef MY_DISABLED_SERIAL
|
||||
NRF_UART0->TASKS_STARTRX = 1;
|
||||
NRF_UART0->TASKS_STARTTX = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Halt CPU until next interrupt event
|
||||
inline void hwWaitForInterrupt(void)
|
||||
{
|
||||
__DSB();
|
||||
__WFI();
|
||||
}
|
||||
|
||||
// Sleep in System ON mode
|
||||
inline void hwSleep(void)
|
||||
{
|
||||
__WFE();
|
||||
__SEV();
|
||||
__WFE();
|
||||
}
|
||||
|
||||
int8_t hwSleep(uint32_t ms)
|
||||
{
|
||||
hwSleepPrepare(ms);
|
||||
while (nrf5_rtc_event_triggered == false) {
|
||||
hwSleep();
|
||||
}
|
||||
hwSleepEnd(ms);
|
||||
return MY_WAKE_UP_BY_TIMER;
|
||||
}
|
||||
|
||||
int8_t hwSleep(const uint8_t interrupt, const uint8_t mode, uint32_t ms)
|
||||
{
|
||||
return hwSleep(interrupt, mode, INVALID_INTERRUPT_NUM, 0u, ms);
|
||||
}
|
||||
|
||||
int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2,
|
||||
uint8_t mode2, uint32_t ms)
|
||||
{
|
||||
// Disable interrupts until going to sleep, otherwise interrupts occurring
|
||||
// between attachInterrupt()
|
||||
// and sleep might cause the MCU to not wakeup from sleep as interrupt has
|
||||
// already be handled!
|
||||
MY_CRITICAL_SECTION {
|
||||
// attach interrupts
|
||||
_wakeUp1Interrupt = interrupt1;
|
||||
_wakeUp2Interrupt = interrupt2;
|
||||
|
||||
if (interrupt1 != INVALID_INTERRUPT_NUM)
|
||||
{
|
||||
attachInterrupt(interrupt1, wakeUp1, mode1);
|
||||
}
|
||||
if (interrupt2 != INVALID_INTERRUPT_NUM)
|
||||
{
|
||||
attachInterrupt(interrupt2, wakeUp2, mode2);
|
||||
}
|
||||
|
||||
// Reset attribute
|
||||
_wokeUpByInterrupt = INVALID_INTERRUPT_NUM;
|
||||
}
|
||||
|
||||
// Prepare Timer and Hardware
|
||||
hwSleepPrepare(ms);
|
||||
|
||||
// Sleep until timeout or interrupt
|
||||
while ((nrf5_rtc_event_triggered == false) and
|
||||
(_wokeUpByInterrupt == INVALID_INTERRUPT_NUM)) {
|
||||
hwSleep();
|
||||
}
|
||||
|
||||
// Assure any interrupts attached, will get detached when they did not occur.
|
||||
if (interrupt1 != INVALID_INTERRUPT_NUM) {
|
||||
detachInterrupt(interrupt1);
|
||||
}
|
||||
if (interrupt2 != INVALID_INTERRUPT_NUM) {
|
||||
detachInterrupt(interrupt2);
|
||||
}
|
||||
|
||||
// Wake up Hardware
|
||||
hwSleepEnd(ms);
|
||||
|
||||
// Return what woke the mcu.
|
||||
int8_t ret =
|
||||
MY_WAKE_UP_BY_TIMER; // default: no interrupt triggered, timer wake up
|
||||
if (_wokeUpByInterrupt != INVALID_INTERRUPT_NUM) {
|
||||
ret = static_cast<int8_t>(_wokeUpByInterrupt);
|
||||
}
|
||||
// Clear woke-up-by-interrupt flag, so next sleeps won't return immediately.
|
||||
_wokeUpByInterrupt = INVALID_INTERRUPT_NUM;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
// RTC interrupt handler
|
||||
void MY_HW_RTC_IRQ_HANDLER(void)
|
||||
{
|
||||
if (MY_HW_RTC->EVENTS_COMPARE[0] > 0) {
|
||||
nrf5_rtc_event_triggered = true;
|
||||
|
||||
NRF_RESET_EVENT(MY_HW_RTC->EVENTS_COMPARE[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool hwUniqueID(unique_id_t *uniqueID)
|
||||
{
|
||||
uint32_t *buffer = (uint32_t *)uniqueID;
|
||||
buffer[0] = NRF_FICR->DEVICEID[0];
|
||||
buffer[1] = NRF_FICR->DEVICEID[1];
|
||||
buffer[2] = NRF_FICR->DEVICEADDR[0];
|
||||
buffer[3] = NRF_FICR->DEVICEADDR[1];
|
||||
return true;
|
||||
}
|
||||
|
||||
uint16_t hwCPUVoltage(void)
|
||||
{
|
||||
// VDD is prescaled 1/3 and compared with the internal 1.2V reference
|
||||
#if defined(NRF_ADC)
|
||||
// NRF51:
|
||||
// Sampling is done with lowest resolution to minimize the time
|
||||
// 20uS@260uA
|
||||
|
||||
// Concurrent resource: disable
|
||||
uint32_t lpcomp_enabled = NRF_LPCOMP->ENABLE;
|
||||
NRF_LPCOMP->ENABLE = 0;
|
||||
|
||||
// Enable and configure ADC
|
||||
NRF_ADC->ENABLE = 1;
|
||||
NRF_ADC->CONFIG = (ADC_CONFIG_EXTREFSEL_None << ADC_CONFIG_EXTREFSEL_Pos) |
|
||||
(ADC_CONFIG_PSEL_Disabled << ADC_CONFIG_PSEL_Pos) |
|
||||
(ADC_CONFIG_REFSEL_VBG << ADC_CONFIG_REFSEL_Pos) |
|
||||
(ADC_CONFIG_INPSEL_SupplyOneThirdPrescaling << ADC_CONFIG_INPSEL_Pos) |
|
||||
(ADC_CONFIG_RES_8bit << ADC_CONFIG_RES_Pos);
|
||||
NRF_ADC->EVENTS_END = 0;
|
||||
NRF_ADC->TASKS_START = 1;
|
||||
while(!NRF_ADC->EVENTS_END);
|
||||
NRF_ADC->EVENTS_END = 0;
|
||||
int32_t sample = (int32_t)NRF_ADC->RESULT;
|
||||
NRF_ADC->TASKS_STOP = 1;
|
||||
NRF_ADC->ENABLE = 0;
|
||||
|
||||
// Restore LPCOMP state
|
||||
NRF_LPCOMP->ENABLE = lpcomp_enabled;
|
||||
|
||||
return (sample*3600)/255;
|
||||
|
||||
#elif defined(NRF_SAADC)
|
||||
// NRF52:
|
||||
// Sampling time 3uS@700uA
|
||||
int32_t sample;
|
||||
NRF_SAADC->ENABLE = SAADC_ENABLE_ENABLE_Enabled << SAADC_ENABLE_ENABLE_Pos;
|
||||
NRF_SAADC->RESOLUTION = SAADC_RESOLUTION_VAL_8bit << SAADC_RESOLUTION_VAL_Pos;
|
||||
NRF_SAADC->CH[0].PSELP = SAADC_CH_PSELP_PSELP_VDD << SAADC_CH_PSELP_PSELP_Pos;
|
||||
NRF_SAADC->CH[0].CONFIG = (SAADC_CH_CONFIG_BURST_Disabled << SAADC_CH_CONFIG_BURST_Pos) |
|
||||
(SAADC_CH_CONFIG_MODE_SE << SAADC_CH_CONFIG_MODE_Pos) |
|
||||
(SAADC_CH_CONFIG_TACQ_3us << SAADC_CH_CONFIG_TACQ_Pos) |
|
||||
(SAADC_CH_CONFIG_REFSEL_Internal << SAADC_CH_CONFIG_REFSEL_Pos) |
|
||||
(SAADC_CH_CONFIG_GAIN_Gain1_6 << SAADC_CH_CONFIG_GAIN_Pos) |
|
||||
(SAADC_CH_CONFIG_RESN_Bypass << SAADC_CH_CONFIG_RESN_Pos) |
|
||||
(SAADC_CH_CONFIG_RESP_Bypass << SAADC_CH_CONFIG_RESP_Pos);
|
||||
NRF_SAADC->OVERSAMPLE = SAADC_OVERSAMPLE_OVERSAMPLE_Bypass << SAADC_OVERSAMPLE_OVERSAMPLE_Pos;
|
||||
NRF_SAADC->SAMPLERATE = SAADC_SAMPLERATE_MODE_Task << SAADC_SAMPLERATE_MODE_Pos;
|
||||
NRF_SAADC->RESULT.MAXCNT = 1;
|
||||
NRF_SAADC->RESULT.PTR = (uint32_t)&sample;
|
||||
|
||||
NRF_SAADC->EVENTS_STARTED = 0;
|
||||
NRF_SAADC->TASKS_START = 1;
|
||||
while (!NRF_SAADC->EVENTS_STARTED);
|
||||
NRF_SAADC->EVENTS_STARTED = 0;
|
||||
|
||||
NRF_SAADC->EVENTS_END = 0;
|
||||
NRF_SAADC->TASKS_SAMPLE = 1;
|
||||
while (!NRF_SAADC->EVENTS_END);
|
||||
NRF_SAADC->EVENTS_END = 0;
|
||||
|
||||
NRF_SAADC->EVENTS_STOPPED = 0;
|
||||
NRF_SAADC->TASKS_STOP = 1;
|
||||
while (!NRF_SAADC->EVENTS_STOPPED);
|
||||
NRF_SAADC->EVENTS_STOPPED = 1;
|
||||
|
||||
NRF_SAADC->ENABLE = (SAADC_ENABLE_ENABLE_Disabled << SAADC_ENABLE_ENABLE_Pos);
|
||||
|
||||
return (sample*3600)/255;
|
||||
#else
|
||||
// unknown MCU
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint16_t hwCPUFrequency(void)
|
||||
{
|
||||
#if defined(VARIANT_MCK)
|
||||
return (VARIANT_MCK) / 100000UL;
|
||||
#elif defined(F_CPU)
|
||||
return (F_CPU) / 100000UL;
|
||||
#else
|
||||
return 160;
|
||||
#endif
|
||||
}
|
||||
|
||||
int8_t hwCPUTemperature(void)
|
||||
{
|
||||
return -127; // not implemented yet
|
||||
}
|
||||
|
||||
uint16_t hwFreeMem(void)
|
||||
{
|
||||
// TODO: Not supported!
|
||||
return FUNCTION_NOT_SUPPORTED;
|
||||
}
|
||||
208
lib/MySensors/hal/architecture/NRF5/MyHwNRF5.h
Normal file
208
lib/MySensors/hal/architecture/NRF5/MyHwNRF5.h
Normal file
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of
|
||||
* the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2019 Sensnology AB
|
||||
* Copyright (C) 2017 Frank Holtz
|
||||
* Full contributor list:
|
||||
* https://github.com/mysensors/MySensors/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef MyHwNRF5_h
|
||||
#define MyHwNRF5_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <Arduino.h>
|
||||
#endif
|
||||
|
||||
#define CRYPTO_LITTLE_ENDIAN
|
||||
|
||||
#ifndef MY_SERIALDEVICE
|
||||
#define MY_SERIALDEVICE Serial
|
||||
#endif
|
||||
|
||||
#ifndef MY_DEBUGDEVICE
|
||||
#define MY_DEBUGDEVICE MY_SERIALDEVICE
|
||||
#endif
|
||||
|
||||
// Define NRF5_SOFTDEVICE when SoftDevice found
|
||||
#if defined(S110) || defined(S130) || defined(S132) || defined(S140)
|
||||
#ifndef SOFTDEVICE_PRESENT
|
||||
#define SOFTDEVICE_PRESENT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Define ARDUINO_ARCH_NRF5, if not defined
|
||||
#ifndef ARDUINO_ARCH_NRF5
|
||||
#define ARDUINO_ARCH_NRF5
|
||||
#endif
|
||||
|
||||
#include "hal/architecture/NRF5/drivers/nrf5_wiring_digital.c"
|
||||
#include "hal/architecture/NRF5/drivers/wdt.h"
|
||||
#include "hal/architecture/NRF5/drivers/nrf_temp.h"
|
||||
#include "drivers/NVM/NVRAM.cpp"
|
||||
#include "drivers/NVM/VirtualPage.cpp"
|
||||
#include <avr/dtostrf.h>
|
||||
#include <nrf.h>
|
||||
#include <SPI.h>
|
||||
|
||||
// mapping
|
||||
#ifndef strncpy_P
|
||||
#define strncpy_P strncpy
|
||||
#endif
|
||||
#ifndef snprintf_P
|
||||
#define snprintf_P(s, f, ...) snprintf((s), (f), __VA_ARGS__)
|
||||
#endif
|
||||
#ifndef vsnprintf_P
|
||||
#define vsnprintf_P vsnprintf
|
||||
#endif
|
||||
#ifndef printf_P
|
||||
#define printf_P printf
|
||||
#endif
|
||||
|
||||
// redefine 8 bit types of inttypes.h until fix of https://github.com/sandeepmistry/arduino-nRF5/issues/197
|
||||
#undef PRId8
|
||||
#undef PRIi8
|
||||
#undef PRIo8
|
||||
#undef PRIu8
|
||||
#undef PRIx8
|
||||
#undef PRIX8
|
||||
#undef PRIdLEAST8
|
||||
#undef PRIiLEAST8
|
||||
#undef PRIoLEAST8
|
||||
#undef PRIuLEAST8
|
||||
#undef PRIxLEAST8
|
||||
#undef PRIXLEAST8
|
||||
#undef PRIdFAST8
|
||||
#undef PRIiFAST8
|
||||
#undef PRIoFAST8
|
||||
#undef PRIuFAST8
|
||||
#undef PRIxFAST8
|
||||
#undef PRIXFAST8
|
||||
#define PRId8 "hd"
|
||||
#define PRIi8 "hi"
|
||||
#define PRIo8 "ho"
|
||||
#define PRIu8 "hu"
|
||||
#define PRIx8 "hx"
|
||||
#define PRIX8 "hX"
|
||||
#define PRIdLEAST8 "hd"
|
||||
#define PRIiLEAST8 "hi"
|
||||
#define PRIoLEAST8 "ho"
|
||||
#define PRIuLEAST8 "hu"
|
||||
#define PRIxLEAST8 "hx"
|
||||
#define PRIXLEAST8 "hX"
|
||||
#define PRIdFAST8 "hd"
|
||||
#define PRIiFAST8 "hi"
|
||||
#define PRIoFAST8 "ho"
|
||||
#define PRIuFAST8 "hu"
|
||||
#define PRIxFAST8 "hx"
|
||||
#define PRIXFAST8 "hX"
|
||||
|
||||
// Define these as macros to save valuable space
|
||||
#define hwDigitalWrite(__pin, __value) digitalWrite(__pin, __value)
|
||||
#define hwDigitalRead(__pin) digitalRead(__pin)
|
||||
#define hwPinMode(__pin, __value) nrf5_pinMode(__pin, __value)
|
||||
#define hwMillis() millis()
|
||||
// TODO: Can nrf5 determine time slept?
|
||||
#define hwGetSleepRemaining() (0ul)
|
||||
|
||||
bool hwInit(void);
|
||||
void hwWatchdogReset(void);
|
||||
void hwReboot(void);
|
||||
void hwReadConfigBlock(void *buf, void *addr, size_t length);
|
||||
void hwWriteConfigBlock(void *buf, void *addr, size_t length);
|
||||
void hwWriteConfig(const int addr, uint8_t value);
|
||||
uint8_t hwReadConfig(const int addr);
|
||||
void hwRandomNumberInit(void);
|
||||
ssize_t hwGetentropy(void *__buffer, size_t __length);
|
||||
#define MY_HW_HAS_GETENTROPY
|
||||
|
||||
// SOFTSPI
|
||||
#ifdef MY_SOFTSPI
|
||||
#error Soft SPI is not available on this architecture!
|
||||
#endif
|
||||
#define hwSPI SPI //!< hwSPI
|
||||
|
||||
|
||||
/**
|
||||
* Disable all interrupts.
|
||||
* Helper function for MY_CRITICAL_SECTION.
|
||||
*/
|
||||
static __inline__ uint8_t __disableIntsRetVal(void)
|
||||
{
|
||||
__disable_irq();
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore priority mask register.
|
||||
* Helper function for MY_CRITICAL_SECTION.
|
||||
*/
|
||||
static __inline__ void __priMaskRestore(const uint32_t *priMask)
|
||||
{
|
||||
__set_PRIMASK(*priMask);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset events and read back on nRF52
|
||||
* http://infocenter.nordicsemi.com/pdf/nRF52_Series_Migration_v1.0.pdf
|
||||
*/
|
||||
#if __CORTEX_M == 0x04
|
||||
#define NRF_RESET_EVENT(event) \
|
||||
event = 0; \
|
||||
(void)event
|
||||
#else
|
||||
#define NRF_RESET_EVENT(event) event = 0
|
||||
#endif
|
||||
/**
|
||||
* RTC to use for hwSleep
|
||||
* RTC1 is used by arduino-nRF5
|
||||
* RTC2 is used on nRF52
|
||||
* RTC0 is used on nRF51. This conflicts with SoftDevice!
|
||||
*/
|
||||
#ifdef NRF_RTC2
|
||||
#define MY_HW_RTC NRF_RTC2
|
||||
#define MY_HW_RTC_IRQ_HANDLER RTC2_IRQHandler
|
||||
#define MY_HW_RTC_IRQN RTC2_IRQn
|
||||
#else
|
||||
#define MY_HW_RTC NRF_RTC0
|
||||
#define MY_HW_RTC_IRQ_HANDLER RTC0_IRQHandler
|
||||
#define MY_HW_RTC_IRQN RTC0_IRQn
|
||||
#endif
|
||||
|
||||
/** Datastructure for AES ECB unit
|
||||
*/
|
||||
typedef struct {
|
||||
/** AES Key
|
||||
*/
|
||||
uint8_t key[16];
|
||||
/** Unencrypted data
|
||||
*/
|
||||
uint8_t cleartext[16];
|
||||
/** Encrypted data
|
||||
*/
|
||||
uint8_t ciphertext[16];
|
||||
} nrf_ecb_t;
|
||||
|
||||
#if !defined(DOXYGEN) && !defined(CPPCHECK)
|
||||
#define MY_CRITICAL_SECTION \
|
||||
for (uint32_t __savePriMask \
|
||||
__attribute__((__cleanup__(__priMaskRestore))) = __get_PRIMASK(), \
|
||||
__ToDo = __disableIntsRetVal(); \
|
||||
__ToDo; __ToDo = 0)
|
||||
#else
|
||||
#define MY_CRITICAL_SECTION
|
||||
#endif /* DOXYGEN || CPPCHECK */
|
||||
|
||||
#endif // #ifndef MyHwNRF5_h
|
||||
39
lib/MySensors/hal/architecture/NRF5/MyMainNRF5.cpp
Normal file
39
lib/MySensors/hal/architecture/NRF5/MyMainNRF5.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2019 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
// Initialize library and handle sketch functions like we want to
|
||||
|
||||
int main(void)
|
||||
{
|
||||
init();
|
||||
#if defined(USBCON)
|
||||
USBDevice.attach();
|
||||
#endif
|
||||
_begin(); // Startup MySensors library
|
||||
for(;;) {
|
||||
_process(); // Process incoming data
|
||||
if (loop) {
|
||||
loop(); // Call sketch loop
|
||||
}
|
||||
if (serialEventRun) {
|
||||
serialEventRun();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
165
lib/MySensors/hal/architecture/NRF5/drivers/Flash.cpp
Normal file
165
lib/MySensors/hal/architecture/NRF5/drivers/Flash.cpp
Normal file
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
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"
|
||||
#include <nrf.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());
|
||||
}
|
||||
|
||||
uint32_t *FlashClass::top_app_page_address()
|
||||
{
|
||||
#if !defined(MCUBOOT_PRESENT)
|
||||
// Bootcode at the top of the flash memory?
|
||||
// https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.sdk5.v12.0.0%2Flib_bootloader.html
|
||||
if (NRF_UICR->NRFFW[0]<0xFFFFFFFF) {
|
||||
// Return pointer calculated by SoftDevice/bootloader
|
||||
return (uint32_t *)NRF_UICR->NRFFW[0];
|
||||
}
|
||||
#endif
|
||||
|
||||
// Return flash length
|
||||
return (uint32_t *)(Flash.page_count() << Flash.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) {
|
||||
// cppcheck-suppress duplicateConditionalAssign
|
||||
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,0 +1,42 @@
|
||||
/*
|
||||
* nRF5 output modes
|
||||
*/
|
||||
// Standard 0, Standard 1
|
||||
#ifndef OUTPUT_S0S1
|
||||
#define OUTPUT_S0S1 (0x10)
|
||||
#endif
|
||||
|
||||
// High Drive 0, Standard 1
|
||||
#ifndef OUTPUT_H0S1
|
||||
#define OUTPUT_H0S1 (0x11)
|
||||
#endif
|
||||
|
||||
// Standard 0, High Drive 1
|
||||
#ifndef OUTPUT_S0H1
|
||||
#define OUTPUT_S0H1 (0x12)
|
||||
#endif
|
||||
|
||||
// High Drive both
|
||||
#ifndef OUTPUT_H0H1
|
||||
#define OUTPUT_H0H1 (0x13)
|
||||
#endif
|
||||
|
||||
// Disconnected 0, Standard 1
|
||||
#ifndef OUTPUT_D0S1
|
||||
#define OUTPUT_D0S1 (0x14)
|
||||
#endif
|
||||
|
||||
// Disconnected 0, High Drive 1
|
||||
#ifndef OUTPUT_D0H1
|
||||
#define OUTPUT_D0H1 (0x15)
|
||||
#endif
|
||||
|
||||
// Standard 0, Disconnected 1
|
||||
#ifndef OUTPUT_S0D1
|
||||
#define OUTPUT_S0D1 (0x16)
|
||||
#endif
|
||||
|
||||
// High Drive 0, Disconnected 1
|
||||
#ifndef OUTPUT_H0D1
|
||||
#define OUTPUT_H0D1 (0x17)
|
||||
#endif
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
Copyright (c) 2015 Arduino LLC. All right reserved.
|
||||
Copyright (c) 2016 Sandeep Mistry All right reserved.
|
||||
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 "nrf.h"
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "nrf5_wiring_constants.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void nrf5_pinMode(uint32_t ulPin, uint32_t ulMode)
|
||||
{
|
||||
if (ulPin >= PINS_COUNT) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef ARDUINO_ARCH_NRF52
|
||||
// Arduino: https://github.com/arduino-org/arduino-core-nrf52
|
||||
ulPin = g_APinDescription[ulPin].ulPin;
|
||||
#else
|
||||
// Sandeep Mistry: https://github.com/sandeepmistry/arduino-nRF5
|
||||
ulPin = g_ADigitalPinMap[ulPin];
|
||||
#endif
|
||||
|
||||
// Set pin mode according to chapter '22.6.3 I/O Pin Configuration'
|
||||
switch (ulMode) {
|
||||
case INPUT:
|
||||
// Set pin to input mode
|
||||
NRF_GPIO->PIN_CNF[ulPin] =
|
||||
((uint32_t)GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos) |
|
||||
((uint32_t)GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) |
|
||||
((uint32_t)GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) |
|
||||
((uint32_t)GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) |
|
||||
((uint32_t)GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos);
|
||||
break;
|
||||
|
||||
case INPUT_PULLUP:
|
||||
// Set pin to input mode with pull-up resistor enabled
|
||||
NRF_GPIO->PIN_CNF[ulPin] =
|
||||
((uint32_t)GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos) |
|
||||
((uint32_t)GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) |
|
||||
((uint32_t)GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) |
|
||||
((uint32_t)GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) |
|
||||
((uint32_t)GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos);
|
||||
break;
|
||||
|
||||
case INPUT_PULLDOWN:
|
||||
// Set pin to input mode with pull-down resistor enabled
|
||||
NRF_GPIO->PIN_CNF[ulPin] =
|
||||
((uint32_t)GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos) |
|
||||
((uint32_t)GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) |
|
||||
((uint32_t)GPIO_PIN_CNF_PULL_Pulldown << GPIO_PIN_CNF_PULL_Pos) |
|
||||
((uint32_t)GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) |
|
||||
((uint32_t)GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos);
|
||||
break;
|
||||
|
||||
case OUTPUT:
|
||||
// Set pin to output mode
|
||||
NRF_GPIO->PIN_CNF[ulPin] =
|
||||
((uint32_t)GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos) |
|
||||
((uint32_t)GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos) |
|
||||
((uint32_t)GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) |
|
||||
((uint32_t)GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) |
|
||||
((uint32_t)GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos);
|
||||
break;
|
||||
|
||||
default:
|
||||
// calculate nRF specific output modes
|
||||
if ((ulMode >= OUTPUT_S0S1) && (ulMode <= OUTPUT_H0D1)) {
|
||||
// Set pin to given output mode
|
||||
NRF_GPIO->PIN_CNF[ulPin] =
|
||||
((uint32_t)GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos) |
|
||||
((uint32_t)GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos) |
|
||||
((uint32_t)GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) |
|
||||
((uint32_t)(ulMode - OUTPUT_S0S1) << GPIO_PIN_CNF_DRIVE_Pos) |
|
||||
((uint32_t)GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
70
lib/MySensors/hal/architecture/NRF5/drivers/nrf_temp.h
Normal file
70
lib/MySensors/hal/architecture/NRF5/drivers/nrf_temp.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2012 - 2018, Nordic Semiconductor ASA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef NRF_TEMP_H__
|
||||
#define NRF_TEMP_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define MASK_SIGN (0x00000200UL) //!< MASK_SIGN
|
||||
#define MASK_SIGN_EXTENSION (0xFFFFFC00UL) //!< MASK_SIGN_EXTENSION
|
||||
|
||||
/**
|
||||
* @brief Function for preparing the temp module for temperature measurement.
|
||||
*
|
||||
* This function initializes the TEMP module and writes to the hidden configuration register.
|
||||
*/
|
||||
static __INLINE void nrf_temp_init(void)
|
||||
{
|
||||
/**@note Workaround for PAN_028 rev2.0A anomaly 31 - TEMP: Temperature offset value has to be manually loaded to the TEMP module */
|
||||
*(uint32_t *) 0x4000C504 = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function for reading temperature measurement.
|
||||
*
|
||||
* The function reads the 10 bit 2's complement value and transforms it to a 32 bit 2's complement value.
|
||||
*/
|
||||
static __INLINE int32_t nrf_temp_read(void)
|
||||
{
|
||||
/**@note Workaround for PAN_028 rev2.0A anomaly 28 - TEMP: Negative measured values are not represented correctly */
|
||||
return ((NRF_TEMP->TEMP & MASK_SIGN) != 0) ? (int32_t)(NRF_TEMP->TEMP | MASK_SIGN_EXTENSION) :
|
||||
(NRF_TEMP->TEMP);
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
186
lib/MySensors/hal/architecture/NRF5/drivers/wdt.h
Normal file
186
lib/MySensors/hal/architecture/NRF5/drivers/wdt.h
Normal file
@@ -0,0 +1,186 @@
|
||||
/* Copyright (c) 2002, 2004 Marek Michalkiewicz
|
||||
Copyright (c) 2005, 2006, 2007 Eric B. Weddington
|
||||
Copyright (c) 2016 Frank Holtz
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
* Neither the name of the copyright holders nor the names of
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE. */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
avr/wdt.h - macros for AVR watchdog timer
|
||||
*/
|
||||
|
||||
#ifndef _NRF5_WDT_H_
|
||||
#define _NRF5_WDT_H_
|
||||
|
||||
#include <nrf.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/** \file */
|
||||
/** \defgroup avr_watchdog <avr/wdt.h>: Watchdog timer handling
|
||||
\code #include <avr/wdt.h> \endcode
|
||||
@ingroup internals
|
||||
|
||||
This header file declares the interface to some inline macros
|
||||
handling the watchdog timer like present in many AVR devices.
|
||||
In order to prevent the watchdog timer configuration from being
|
||||
accidentally altered by a crashing application, a special timed
|
||||
sequence is required in order to change it. The macros within
|
||||
this header file handle the required sequence automatically
|
||||
before changing any value. Interrupts will be disabled during
|
||||
the manipulation.
|
||||
*/
|
||||
|
||||
/**
|
||||
\ingroup avr_watchdog
|
||||
Reset the watchdog timer. When the watchdog timer is enabled,
|
||||
a call to this instruction is required before the timer expires,
|
||||
otherwise a watchdog-initiated device reset will occur.
|
||||
*/
|
||||
|
||||
#define wdt_reset() NRF_WDT->RR[0] = WDT_RR_RR_Reload
|
||||
|
||||
/**
|
||||
\ingroup avr_watchdog
|
||||
Enable the watchdog timer, configuring it for expiry after
|
||||
\c timeout (ms).
|
||||
|
||||
The WDT is running in sleep mode.
|
||||
|
||||
See also the symbolic constants \c WDTO_15MS et al.
|
||||
*/
|
||||
#define wdt_enable(timeout) \
|
||||
NRF_WDT->CONFIG = NRF_WDT->CONFIG = (WDT_CONFIG_HALT_Pause << WDT_CONFIG_HALT_Pos) | ( WDT_CONFIG_SLEEP_Run << WDT_CONFIG_SLEEP_Pos); \
|
||||
NRF_WDT->CRV = (32768*timeout)/1000; \
|
||||
NRF_WDT->RREN |= WDT_RREN_RR0_Msk; \
|
||||
NRF_WDT->TASKS_START = 1
|
||||
|
||||
/**
|
||||
\ingroup avr_watchdog
|
||||
Disable the watchdog timer. On nRF5 the timer cannot disabled.
|
||||
The period is set to 36h of CPU run time. The WDT is stopped in sleep mode.
|
||||
*/
|
||||
#define wdt_disable() \
|
||||
NRF_WDT->CONFIG = NRF_WDT->CONFIG = (WDT_CONFIG_HALT_Pause << WDT_CONFIG_HALT_Pos) | ( WDT_CONFIG_SLEEP_Pause << WDT_CONFIG_SLEEP_Pos); \
|
||||
NRF_WDT->CRV = 4294967295
|
||||
|
||||
/**
|
||||
\ingroup avr_watchdog
|
||||
Symbolic constants for the watchdog timeout.
|
||||
|
||||
Possible timeout values are: 15 ms, 30 ms, 60 ms, 120 ms, 250 ms,
|
||||
500 ms, 1 s, 2 s, 4s, 8s. (Not all devices allow 4 s or 8 s.)
|
||||
Symbolic constants are formed by the prefix
|
||||
\c WDTO_, followed by the time.
|
||||
|
||||
Example that would select a watchdog timer expiry of approximately
|
||||
500 ms:
|
||||
\code
|
||||
wdt_enable(WDTO_500MS);
|
||||
\endcode
|
||||
*/
|
||||
#define WDTO_15MS 15
|
||||
|
||||
/** \ingroup avr_watchdog
|
||||
See \c WDTO_15MS */
|
||||
#define WDTO_30MS 30
|
||||
|
||||
/** \ingroup avr_watchdog
|
||||
See \c WDTO_15MS */
|
||||
#define WDTO_60MS 60
|
||||
|
||||
/** \ingroup avr_watchdog
|
||||
See \c WDTO_15MS */
|
||||
#define WDTO_120MS 120
|
||||
|
||||
/** \ingroup avr_watchdog
|
||||
See \c WDTO_15MS */
|
||||
#define WDTO_250MS 250
|
||||
|
||||
/** \ingroup avr_watchdog
|
||||
See \c WDTO_15MS */
|
||||
#define WDTO_500MS 500
|
||||
|
||||
/** \ingroup avr_watchdog
|
||||
See \c WDTO_15MS */
|
||||
#define WDTO_1S 1000
|
||||
|
||||
/** \ingroup avr_watchdog
|
||||
See \c WDTO_15MS */
|
||||
#define WDTO_2S 2000
|
||||
|
||||
/** \ingroup avr_watchdog
|
||||
See \c WDTO_15MS
|
||||
Note: This is only available on the
|
||||
ATtiny2313,
|
||||
ATtiny24, ATtiny44, ATtiny84, ATtiny84A,
|
||||
ATtiny25, ATtiny45, ATtiny85,
|
||||
ATtiny261, ATtiny461, ATtiny861,
|
||||
ATmega48, ATmega88, ATmega168,
|
||||
ATmega48P, ATmega88P, ATmega168P, ATmega328P,
|
||||
ATmega164P, ATmega324P, ATmega644P, ATmega644,
|
||||
ATmega640, ATmega1280, ATmega1281, ATmega2560, ATmega2561,
|
||||
ATmega8HVA, ATmega16HVA, ATmega32HVB,
|
||||
ATmega406, ATmega1284P,
|
||||
AT90PWM1, AT90PWM2, AT90PWM2B, AT90PWM3, AT90PWM3B, AT90PWM216, AT90PWM316,
|
||||
AT90PWM81, AT90PWM161,
|
||||
AT90USB82, AT90USB162,
|
||||
AT90USB646, AT90USB647, AT90USB1286, AT90USB1287,
|
||||
ATtiny48, ATtiny88,
|
||||
nRF51822, nRF52832
|
||||
*/
|
||||
#define WDTO_4S 4000
|
||||
|
||||
/** \ingroup avr_watchdog
|
||||
See \c WDTO_15MS
|
||||
Note: This is only available on the
|
||||
ATtiny2313,
|
||||
ATtiny24, ATtiny44, ATtiny84, ATtiny84A,
|
||||
ATtiny25, ATtiny45, ATtiny85,
|
||||
ATtiny261, ATtiny461, ATtiny861,
|
||||
ATmega48, ATmega48A, ATmega48PA, ATmega88, ATmega168,
|
||||
ATmega48P, ATmega88P, ATmega168P, ATmega328P,
|
||||
ATmega164P, ATmega324P, ATmega644P, ATmega644,
|
||||
ATmega640, ATmega1280, ATmega1281, ATmega2560, ATmega2561,
|
||||
ATmega8HVA, ATmega16HVA, ATmega32HVB,
|
||||
ATmega406, ATmega1284P,
|
||||
ATmega2564RFR2, ATmega256RFR2, ATmega1284RFR2, ATmega128RFR2, ATmega644RFR2, ATmega64RFR2
|
||||
AT90PWM1, AT90PWM2, AT90PWM2B, AT90PWM3, AT90PWM3B, AT90PWM216, AT90PWM316,
|
||||
AT90PWM81, AT90PWM161,
|
||||
AT90USB82, AT90USB162,
|
||||
AT90USB646, AT90USB647, AT90USB1286, AT90USB1287,
|
||||
ATtiny48, ATtiny88,
|
||||
ATxmega16a4u, ATxmega32a4u,
|
||||
ATxmega16c4, ATxmega32c4,
|
||||
ATxmega128c3, ATxmega192c3, ATxmega256c3,
|
||||
nRF51822, nRF52832
|
||||
*/
|
||||
#define WDTO_8S 8000
|
||||
|
||||
#endif /* _NRF5_WDT_H_ */
|
||||
Reference in New Issue
Block a user