From 7f23b6df0ff57a1633c508c8df6b5d2a71f0e183 Mon Sep 17 00:00:00 2001 From: Paul Szczeanek Date: Wed, 10 Jun 2020 13:16:21 +0100 Subject: [PATCH] update nrf cordio ll files --- .../TARGET_NRF5x/stack/include/audio_board.h | 49 - .../TARGET_NRF5x/stack/sources/pal_bb.c | 71 +- .../TARGET_NRF5x/stack/sources/pal_bb_ble.c | 968 +++++++++++------- .../stack/sources/pal_bb_ble_rf.c | 144 ++- .../TARGET_NRF5x/stack/sources/pal_cfg.c | 131 ++- .../TARGET_NRF5x/stack/sources/pal_crypto.c | 295 ++++-- .../TARGET_NRF5x/stack/sources/pal_led.c | 342 +++---- .../TARGET_NRF5x/stack/sources/pal_rtc.c | 197 +++- .../TARGET_NRF5x/stack/sources/pal_sys.c | 164 +-- .../TARGET_NRF5x/stack/sources/pal_timer.c | 270 +++-- .../TARGET_NRF5x/stack/sources/pal_twi.c | 232 ++--- .../TARGET_NRF5x/stack/sources/pal_uart.c | 305 +++--- 12 files changed, 1852 insertions(+), 1316 deletions(-) delete mode 100644 features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/include/audio_board.h diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/include/audio_board.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/include/audio_board.h deleted file mode 100644 index 05cb6ce085..0000000000 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/include/audio_board.h +++ /dev/null @@ -1,49 +0,0 @@ -/*************************************************************************************************/ -/*! - * \file - * - * \brief Audio board definition. - * - * Copyright (c) 2018-2019 Arm Ltd. All Rights Reserved. - * Arm Ltd. confidential and proprietary. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/*************************************************************************************************/ - -#ifndef AUDIOBOARD_H -#define AUDIOBOARD_H - -#include "stack/platform/include/pal_types.h" -#include "nrf_gpio.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/************************************************************************************************** - Macros -**************************************************************************************************/ - -#define AUDIO_LED_1 NRF_GPIO_PIN_MAP(1,1) -#define AUDIO_LED_2 NRF_GPIO_PIN_MAP(1,2) -#define AUDIO_LED_3 NRF_GPIO_PIN_MAP(1,3) -#define AUDIO_LED_4 NRF_GPIO_PIN_MAP(1,4) -#define AUDIO_LED_5 NRF_GPIO_PIN_MAP(1,5) -#define AUDIO_LED_6 NRF_GPIO_PIN_MAP(1,6) - -#ifdef __cplusplus -}; -#endif - -#endif /* AUDIOBOARD_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_bb.c b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_bb.c index f9ed39323a..18286bb065 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_bb.c +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_bb.c @@ -7,12 +7,14 @@ * Copyright (c) 2016-2018 Arm Ltd. All Rights Reserved. * ARM confidential and proprietary. * + * Copyright (c) 2019-2020 Packetcraft, Inc. + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -21,8 +23,9 @@ */ /*************************************************************************************************/ -#include "stack/platform/include/pal_types.h" -#include "stack/platform/include/pal_bb.h" +#include "pal_types.h" +#include "pal_bb.h" +#include "pal_bb.h" #include "nrf.h" #include "nrf_timer.h" #include @@ -51,8 +54,6 @@ static bbDrvIrqCback_t palBbRadioIrqCbackTbl[BB_PROT_NUM]; /*! * \brief Initialize the baseband driver. * - * \return None. - * * One-time initialization of baseband resources. This routine can be used to setup baseband * resources, load RF trim parameters and execute RF calibrations. * @@ -63,6 +64,10 @@ void PalBbInit(void) { palBbEnableCnt = 0; + /* Cycle radio peripheral power to guarantee known radio state. */ + NRF_RADIO->POWER = 0; + NRF_RADIO->POWER = 1; + memset(palBbTimerIrqCbackTbl, 0, sizeof(palBbTimerIrqCbackTbl)); memset(palBbRadioIrqCbackTbl, 0, sizeof(palBbRadioIrqCbackTbl)); } @@ -71,8 +76,6 @@ void PalBbInit(void) /*! * \brief Enable the BB hardware. * - * \return None. - * * This routine brings the BB hardware out of low power (enable power and clocks) just before a * first BB operation is executed. */ @@ -86,15 +89,13 @@ void PalBbEnable(void) /*! * \brief Disable the BB hardware. * - * \return None. - * * This routine signals the BB hardware to go into low power (disable power and clocks) after all * BB operations have been disabled. */ /*************************************************************************************************/ void PalBbDisable(void) { - if(palBbEnableCnt) + if (palBbEnableCnt) { palBbEnableCnt--; } @@ -105,8 +106,6 @@ void PalBbDisable(void) * \brief Load BB timing configuration. * * \param pCfg Return configuration values. - * - * \return None. */ /*************************************************************************************************/ void PalBbLoadCfg(PalBbCfg_t *pCfg) @@ -115,27 +114,34 @@ void PalBbLoadCfg(PalBbCfg_t *pCfg) pCfg->rfSetupDelayUsec = BB_RF_SETUP_DELAY_US; pCfg->maxScanPeriodMsec = BB_MAX_SCAN_PERIOD_MS; pCfg->schSetupDelayUsec = BB_SCH_SETUP_DELAY_US; +#if (BB_CLK_RATE_HZ == 32768) + pCfg->BbTimerBoundaryUsec = BB_RTC_MAX_VALUE_US; +#elif (BB_CLK_RATE_HZ == 8000000) + pCfg->BbTimerBoundaryUsec = BB_TIMER_8MHZ_MAX_VALUE_US; +#elif (BB_CLK_RATE_HZ == 1000000) + pCfg->BbTimerBoundaryUsec = BB_TIMER_1MHZ_MAX_VALUE_US; +#else + #error "Unsupported platform." +#endif } /*************************************************************************************************/ /*! - * \brief Get the current BB clock value. - * - * \param useRtcBBClk Use RTC BB clock. + * \brief Get the current BB clock value in microseconds. * * \return Current BB clock value, units are microseconds. * * This routine reads the current value from the BB clock and returns its value. */ /*************************************************************************************************/ -uint32_t PalBbGetCurrentTime(bool_t useRtcBBClk) +uint32_t PalBbGetCurrentTime(void) { if (palBbEnableCnt > 0) { - if (useRtcBBClk) + if (USE_RTC_BB_CLK) { /* return the RTC counter value */ - return NRF_RTC0->COUNTER; + return BB_TICKS_TO_US(NRF_RTC1->COUNTER); } else { @@ -143,7 +149,7 @@ uint32_t PalBbGetCurrentTime(bool_t useRtcBBClk) nrf_timer_task_trigger(NRF_TIMER0, NRF_TIMER_TASK_CAPTURE3); /* Read and return the captured count value from capture register 3 */ - return nrf_timer_cc_read(NRF_TIMER0, NRF_TIMER_CC_CHANNEL3); + return BB_TICKS_TO_US(nrf_timer_cc_read(NRF_TIMER0, NRF_TIMER_CC_CHANNEL3)); } } return 0; @@ -151,7 +157,7 @@ uint32_t PalBbGetCurrentTime(bool_t useRtcBBClk) /*************************************************************************************************/ /*! - * \brief Get the current FRC time. + * \brief Get the current FRC time tick. * * \param pTime Pointer to return the current time. * @@ -167,11 +173,22 @@ bool_t PalBbGetTimestamp(uint32_t *pTime) { if (palBbEnableCnt == 0) { - *pTime = 0; return FALSE; } - *pTime = PalBbGetCurrentTime(USE_RTC_BB_CLK); + if (USE_RTC_BB_CLK && pTime) + { + /* return the RTC counter value */ + *pTime = NRF_RTC1->COUNTER; + } + else if (pTime) + { + /* Capture current TIMER0 count to capture register 3 */ + nrf_timer_task_trigger(NRF_TIMER0, NRF_TIMER_TASK_CAPTURE3); + + /* Read and return the captured count value from capture register 3 */ + *pTime = nrf_timer_cc_read(NRF_TIMER0, NRF_TIMER_CC_CHANNEL3); + } return TRUE; } @@ -183,8 +200,6 @@ bool_t PalBbGetTimestamp(uint32_t *pTime) * \param protId Protocol ID. * \param timerCback Timer IRQ callback. * \param radioCback Timer IRQ callback. - * - * \return None. */ /*************************************************************************************************/ void PalBbRegisterProtIrq(uint8_t protId, bbDrvIrqCback_t timerCback, bbDrvIrqCback_t radioCback) @@ -198,8 +213,6 @@ void PalBbRegisterProtIrq(uint8_t protId, bbDrvIrqCback_t timerCback, bbDrvIrqCb * \brief Set protocol ID. * * \param protId Protocol ID. - * - * \return None. */ /*************************************************************************************************/ void PalBbSetProtId(uint8_t protId) @@ -210,8 +223,6 @@ void PalBbSetProtId(uint8_t protId) /*************************************************************************************************/ /*! * \brief Combined BLE and 154 radio interrupt handler. - * - * \return None. */ /*************************************************************************************************/ void RADIO_IRQHandler(void) @@ -225,8 +236,6 @@ void RADIO_IRQHandler(void) /*************************************************************************************************/ /*! * \brief Combined BLE and 154 timer interrupt handler. - * - * \return None. */ /*************************************************************************************************/ void TIMER0_IRQHandler(void) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_bb_ble.c b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_bb_ble.c index cd033fbbc7..35452d15f6 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_bb_ble.c +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_bb_ble.c @@ -5,14 +5,15 @@ * \brief Baseband driver interface file. * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. - * Arm Ltd. confidential and proprietary. * + * Copyright (c) 2019-2020 Packetcraft, Inc. + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -41,24 +42,34 @@ * PPI Channel 15: * Used to trigger timer capture to CC[2] on every radio PAYLOAD event. * + * If BB_CLK_RATE_HZ == 32768 (low power mode): + * + * Additional two channels of NRF RTC1 are controlled here. + * CC[1] - Compare value for NRF timer0 start task. + * CC[2] - Compare value for NRF HFCLK start task. */ -#include "stack/platform/include/pal_types.h" -#include "stack/platform/include/pal_bb.h" -#include "stack/platform/include/pal_rtc.h" -#include "stack/platform/include/pal_led.h" -#include "stack/platform/include/pal_bb_ble.h" -#include "stack/platform/include/pal_radio.h" +#include "pal_types.h" +#include "pal_bb.h" +#include "pal_rtc.h" +#include "pal_bb.h" +#include "pal_led.h" +#include "pal_bb_ble.h" +#include "pal_radio.h" #include "ll_defs.h" -#include "boards.h" #include "nrf.h" #include "nrf_gpio.h" #include "nrf_gpiote.h" #include +#if (LL_ENABLE_TESTER) +#include "ll_tester_api.h" +#endif + /************************************************************************************************** Macros **************************************************************************************************/ + #define PDU_HEADER_LEN 2 #define MAX_PAYLOAD_LEN 255 #define BB_DATA_PDU_LEN_OFFSET 1 @@ -92,13 +103,13 @@ /* scratch area for Nordic encryption engine */ #define ENC_CCM_DATA_STRUCT_LEN 33 /* length of CCM data structure used for encryption/decryption */ -#define ENC_SCRATCH_BUF_LEN 43 /* size of scratch area */ -#define ENC_MAX_PAYLOAD_LEN 27 /* maximum size of payload that can be encrypted/decrytped */ +#define ENC_MAXPACKETSIZE 251 /* length used in MAXPACKETSIZE */ +#define ENC_SCRATCH_BUF_LEN ( 16 + ENC_MAXPACKETSIZE ) /* size of scratch area */ #define ENC_H_FIELD_LEN 1 /* length of "H" field */ #define ENC_LPLUS4_LEN 1 /* length of the "L+4" field */ #define ENC_RFU_LEN 1 /* length of the "RFU" field */ #define ENC_MIC_LEN 4 /* length of the MIC field */ -#define ENC_TX_BUF_LEN ( ENC_H_FIELD_LEN + ENC_LPLUS4_LEN + ENC_RFU_LEN + ENC_MAX_PAYLOAD_LEN ) +#define ENC_TX_BUF_LEN ( ENC_H_FIELD_LEN + ENC_LPLUS4_LEN + ENC_RFU_LEN + ENC_MAXPACKETSIZE ) #define ENC_OUTPUT_BUF_LEN ( ENC_TX_BUF_LEN + ENC_MIC_LEN ) /* +/- range for TIFS adjustment */ @@ -125,15 +136,7 @@ #endif #if (USE_RTC_BB_CLK) -uint32_t USEC_TO_TICKS(uint32_t usec) -{ - uint64_t ticks; /* use long integer so no loss of precision */ - ticks = (uint64_t)usec << UINT64_C(9); /* multiply by 512 */ - ticks /= 15625; - return ticks; -} -#else - #define USEC_TO_TICKS(usec) ((usec) * TICKS_PER_USEC) + #define TICKS_TO_USEC(ticks) (ticks) /* Use 1MHz for HFCLK */ #endif #if defined(NRF52840_XXAA) || defined(NRF52832_XXAA) @@ -152,6 +155,39 @@ uint32_t USEC_TO_TICKS(uint32_t usec) #define BB_ENABLE_INLINE_DEC_RX FALSE #endif +#ifndef DIAG_PINS_ENA +#define DIAG_PINS_ENA 1 +#endif + +/* LED definitions */ +#ifndef BB_LED_ENA +#define BB_LED_ENA 0 +#endif + +#if (BB_LED_ENA == 1) +#define BB_LED_1M_ON() PalLedOn(0) +#define BB_LED_2M_ON() PalLedOn(1) +#define BB_LED_CODED_ON() PalLedOn(0); PalLedOn(1) +#define BB_LED_OFF() PalLedOff(0); PalLedOff(1) +#else +#define BB_LED_1M_ON() +#define BB_LED_2M_ON() +#define BB_LED_CODED_ON() +#define BB_LED_OFF() +#endif + +#if (AUDIO_CAPE == 1) +#define BB_LED_TX_ON() PalLedOn(6) +#define BB_LED_TX_OFF() PalLedOff(6) +#define BB_LED_RX_ON() PalLedOn(7) +#define BB_LED_RX_OFF() PalLedOff(7) +#else +#define BB_LED_TX_ON() +#define BB_LED_TX_OFF() +#define BB_LED_RX_ON() +#define BB_LED_RX_OFF() +#endif + /*! \brief convert little endian byte buffer to uint16_t. */ #define BYTES_TO_UINT16(n, p) {n = ((uint16_t)(p)[0] + ((uint16_t)(p)[1] << 8));} @@ -178,7 +214,6 @@ typedef enum TIFS_RX_RAMPUP } bbTifsState_t; - /************************************************************************************************** Local Functions **************************************************************************************************/ @@ -195,6 +230,7 @@ static void BbBleDrvRadioIRQHandler(void); /************************************************************************************************** Local Variables **************************************************************************************************/ + volatile bbDriverState_t driverState = NULL_STATE; volatile bbTifsState_t tifsState; uint8_t bbRadioPcnf1WhiteEn; @@ -202,7 +238,7 @@ PalBbBleTxIsr_t bbTxCallback = NULL; PalBbBleRxIsr_t bbRxCallback = NULL; uint32_t bbRxTimeoutUsec; uint8_t * bbpRxBuf; -uint32_t bbAntennaDueTime; +uint32_t bbAntennaDueTimeUsec; uint32_t bbEventStartTime; uint16_t bbDueOffsetUsec; int8_t bbTxTifsAdj; @@ -222,6 +258,7 @@ uint8_t bbEncryptCcmData[ENC_CCM_DATA_STRUCT_LEN]; uint8_t bbTrlSave[BB_TRL_MAX_LEN]; uint8_t *bbTrlSavedPtr = NULL; uint8_t bbTrlSavedLen; +PalBbBleOpParam_t bbOpParam; #ifndef BB_ASSERT_ENABLED #define BB_ASSERT_ENABLED FALSE @@ -254,6 +291,8 @@ uint64_t bbRxAccAddrInvalidChanMask = 0; bool_t bbTxAccAddrShiftMask = FALSE; bool_t bbRxAccAddrShiftMask = FALSE; bool_t bbTxAccAddrShiftInc = FALSE; +bool_t invalidateAccAddrOnceRx = FALSE; +bool_t invalidateAccAddrOnceTx = FALSE; #endif /* enable BB assertions */ @@ -344,62 +383,58 @@ uint16_t diagCancels = 0; #endif ///////////////////////////////////////////////////////////////////////////////// -#define DIAG_USER_DEBUG_PINS_ENA 0 +/*************************************************************************************************/ +/*! + * \brief Config GPIO as input or output. + * + * \param pin Pin number. + */ +/*************************************************************************************************/ +void PalBbGpioCfgOutput(uint32_t pin) +{ + nrf_gpio_cfg_output(pin); +} -#define DIAG_PINS_ENA 0 +/*************************************************************************************************/ +/*! + * \brief Set GPIO pin high. + * + * \param pin Pin number. + */ +/*************************************************************************************************/ +void PalBbGpioSet(uint32_t pin) +{ + nrf_gpio_pin_write(pin, 1); +} -#if DIAG_PINS_ENA -#if defined(BOARD_PCA10028) +/*************************************************************************************************/ +/*! + * \brief Set GPIO pin low. + * + * \param pin Pin number. + */ +/*************************************************************************************************/ +void PalBbGpioClear(uint32_t pin) +{ + nrf_gpio_pin_write(pin, 0); +} -#define TX_PIN 12 /* P0.12 */ -#define RX_PIN 13 /* P0.13 */ -#define RADIO_READY_TOGGLE_PIN 15 /* P0.15 */ -#define RADIO_END_TOGGLE_PIN 16 /* P0.16 */ -#define RADIO_INT_PIN 17 /* P0.17 */ -#define TIMER0_INT_PIN 18 /* P0.18 */ - -#define DIAG_PIN_SET(x) { nrf_gpio_pin_set(x); } -#define DIAG_PIN_CLEAR(x) { nrf_gpio_pin_clear(x); } - -#elif defined(BOARD_PCA10040) - -#define TX_PIN 11 /* P0.11 */ -#define RX_PIN 12 /* P0.12 */ -#define RADIO_READY_TOGGLE_PIN 13 /* P0.13 */ -#define RADIO_END_TOGGLE_PIN 14 /* P0.14 */ -#define RADIO_INT_PIN 0 /* P0.00 */ -#define TIMER0_INT_PIN 1 /* P0.01 */ - -#define DIAG_PIN_SET(x) { nrf_gpio_pin_set(x); } -#define DIAG_PIN_CLEAR(x) { nrf_gpio_pin_clear(x); } -#elif defined(BOARD_PCA10056) - -#define TX_PIN 3 /* P0.03 */ -#define RX_PIN 4 /* P0.04 */ -#define RADIO_READY_TOGGLE_PIN 30 /* P0.30 */ -#define RADIO_END_TOGGLE_PIN 31 /* P0.31 */ -#define RADIO_INT_PIN 29 /* P0.29 */ -#define TIMER0_INT_PIN 28 /* P0.28 */ - -#define DIAG_USER_DEBUG_PINS_ENA 1 -#define USER_DEBUG_0_PIN 35 /* P1.03 */ -#define USER_DEBUG_1_PIN 36 /* P1.04 */ -#define USER_DEBUG_2_PIN 37 /* P1.05 */ -#define USER_DEBUG_3_PIN 38 /* P1.06 */ - -#define DIAG_PIN_SET(x) { nrf_gpio_pin_set(x); } -#define DIAG_PIN_CLEAR(x) { nrf_gpio_pin_clear(x); } -#else -#error "Diagnostic pins not supported on board" -#endif - -#else // DIAG_PINS_ENA - -#define DIAG_PIN_SET(x) -#define DIAG_PIN_CLEAR(x) -#endif // DIAG_PINS_ENA - -///////////////////////////////////////////////////////////////////////////////// +/*************************************************************************************************/ +/*! + * \brief Toggle GPIO. + * + * \param pin Pin number. + * \param times GPIO toggle times. + */ +/*************************************************************************************************/ +void PalBbGpioToggle(uint32_t pin, uint32_t times) +{ + for (uint32_t i = 0; i < times; i++) + { + nrf_gpio_pin_write(pin, 1); + nrf_gpio_pin_write(pin, 0); + } +} /*************************************************************************************************/ /*! @@ -407,8 +442,6 @@ uint16_t diagCancels = 0; * * \param phy PHY. * \param option PHY option. - * - * \return None. */ /*************************************************************************************************/ static inline void palBbSetRadioMode(uint8_t phy, uint8_t option) @@ -419,11 +452,7 @@ static inline void palBbSetRadioMode(uint8_t phy, uint8_t option) NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_1Mbit; break; -#if defined(NRF52832_XXAA) - case BB_PHY_BLE_2M: - NRF_RADIO->MODE = RADIO_MODE_MODE_Nrf_2Mbit; - break; -#elif defined(NRF52840_XXAA) +#if defined(NRF52832_XXAA) || defined(NRF52840_XXAA) case BB_PHY_BLE_2M: NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_2Mbit; break; @@ -447,6 +476,22 @@ static inline void palBbSetRadioMode(uint8_t phy, uint8_t option) break; } + /* select LED according to client selection not actual PHY used */ + switch (bbRxPhy) + { + case BB_PHY_BLE_1M: + BB_LED_1M_ON(); + break; + case BB_PHY_BLE_2M: + BB_LED_2M_ON(); + break; + case BB_PHY_BLE_CODED: + BB_LED_CODED_ON(); + break; + default: + break; + } + #if defined(NRF52832_XXAA) *(volatile uint32_t*)0x40001777 = 0UL; /* Disable fault tolerant AA correlator. */ #endif @@ -455,38 +500,36 @@ static inline void palBbSetRadioMode(uint8_t phy, uint8_t option) #if (USE_RTC_BB_CLK) /*************************************************************************************************/ /*! - * \brief Set the time for the HFCLK to start. + * \brief Set the time for the timer0 to start. * - * \param startTime HFCLK start time. + * \param startTime timer0 start time. * - * \return None. - * - * Setup the RTC clock to start the HFCLK. */ /*************************************************************************************************/ -static void palBbSetHfClkStart(uint32_t startTime) +static void palBbStartTimer(uint32_t startTime) { - bbEventStartTime = NRF_RTC0->CC[1] = startTime; - NRF_RTC0->EVENTS_COMPARE[1] = 0; - WAIT_FOR_WR_BUF_EMPTY(NRF_RTC0->EVENTS_COMPARE[1]); - - uint32_t rtcNow = NRF_RTC0->COUNTER; - if (((startTime - rtcNow) & PAL_MAX_RTC_COUNTER_VAL) <= HFCLK_OSC_SETTLE_TICKS) - { - /* not enough time for oscillator to settle; leave HFCLK running */ - return; - } - - NRF_CLOCK->TASKS_HFCLKSTOP = 1; - NRF_CLOCK->EVENTS_HFCLKSTARTED = 0; - WAIT_FOR_WR_BUF_EMPTY(NRF_CLOCK->EVENTS_HFCLKSTARTED); - - NRF_RTC0->CC[2] = (startTime - HFCLK_OSC_SETTLE_TICKS) & PAL_MAX_RTC_COUNTER_VAL; - NRF_RTC0->EVENTS_COMPARE[2] = 0; - WAIT_FOR_WR_BUF_EMPTY(NRF_RTC0->EVENTS_COMPARE[2]); + bbEventStartTime = NRF_RTC1->CC[1] = startTime; + NRF_RTC1->EVENTS_COMPARE[1] = 0; + WAIT_FOR_WR_BUF_EMPTY(NRF_RTC1->EVENTS_COMPARE[1]); } #endif +/*************************************************************************************************/ +/*! + * \brief Low power operation. + * + * \note Called by upper baseband code. + */ +/*************************************************************************************************/ +void PalBbBleLowPower(void) +{ + /* Stop high frequency timer between BLE events if low lower mode. */ +#if (USE_RTC_BB_CLK) + NRF_TIMER0->TASKS_STOP = 1; + NRF_TIMER0->TASKS_CLEAR = 1; +#endif +} + #if (BB_ENABLE_INLINE_ENC_TX || BB_ENABLE_INLINE_DEC_RX) /*************************************************************************************************/ /*! @@ -494,8 +537,6 @@ static void palBbSetHfClkStart(uint32_t startTime) * * \param enable Boolean flag to enable or disable TX encryption * - * \return None. - * */ /*************************************************************************************************/ static void palBbBleInlineEncryptTxEnable(bool_t enable) @@ -504,16 +545,6 @@ static void palBbBleInlineEncryptTxEnable(bool_t enable) /* copy encryption enable to global variable */ bbEncryptTxFlag = enable; - - /* set or clear enable of encryption on transmit */ - if (enable) - { - NRF_CCM->ENABLE = CCM_ENABLE_ENABLE_Enabled; - } - else - { - NRF_CCM->ENABLE = CCM_ENABLE_ENABLE_Disabled; - } } /*************************************************************************************************/ @@ -522,8 +553,6 @@ static void palBbBleInlineEncryptTxEnable(bool_t enable) * * \param enable Boolean flag to indicate if MIC is suppressed * - * \return None. - * */ /*************************************************************************************************/ static void palBbBleInlineEncryptDecryptSuppressMic(bool_t enable) @@ -540,14 +569,10 @@ static void palBbBleInlineEncryptDecryptSuppressMic(bool_t enable) * * \param key Pointer to 16-byte key value * - * \return None. - * */ /*************************************************************************************************/ -static void palBbBleInlineEncryptDecryptSetKey(uint8_t * key) +static void palBbBleInlineEncryptDecryptSetKey(uint8_t *pKey) { - uint8_t i; - BB_ASSERT(driverState == IDLE_STATE); /* driver must be idle */ #if BB_ASSERT_ENABLED == TRUE @@ -555,9 +580,9 @@ static void palBbBleInlineEncryptDecryptSetKey(uint8_t * key) #endif /* populate encryption structure with reversed stored key */ - for (i=0; i<16; i++) + for (unsigned int i=0; i<16; i++) { - bbEncryptCcmData[i] = key[15-i]; + bbEncryptCcmData[i] = pKey[15-i]; } } @@ -567,11 +592,9 @@ static void palBbBleInlineEncryptDecryptSetKey(uint8_t * key) * * \param key Pointer to 8-byte value for IV * - * \return None. - * */ /*************************************************************************************************/ -static void palBbBleDrvInlineEncryptDecryptSetIv(uint8_t * iv) +static void palBbBleDrvInlineEncryptDecryptSetIv(uint8_t *pIV) { BB_ASSERT(driverState == IDLE_STATE); /* driver must be idle */ @@ -579,10 +602,9 @@ static void palBbBleDrvInlineEncryptDecryptSetIv(uint8_t * iv) ivSetFlag = 1; #endif - /* copy the 8-byte initialization vector */ - memcpy(&bbEncryptCcmData[25], iv, 8); + /* populate encryption structure with reversed stored IV */ + memcpy(&bbEncryptCcmData[25], pIV, 8); } -#endif /*************************************************************************************************/ /*! @@ -590,8 +612,6 @@ static void palBbBleDrvInlineEncryptDecryptSetIv(uint8_t * iv) * * \param dir 0=slave, non-zero=master * - * \return None. - * */ /*************************************************************************************************/ void PalBbBleInlineEncryptDecryptSetDirection(uint8_t dir) @@ -613,8 +633,6 @@ void PalBbBleInlineEncryptDecryptSetDirection(uint8_t dir) * * \param count Packet counter value, a 39-bit value * - * \return None. - * */ /*************************************************************************************************/ void PalBbBleInlineEncryptSetPacketCount(uint64_t count) @@ -632,13 +650,12 @@ void PalBbBleInlineEncryptSetPacketCount(uint64_t count) bbEncryptCcmData[19] = (count >> 24) & 0xFF; bbEncryptCcmData[20] = (count >> 32) & 0x7F; /* only 7-bits of MSB are used (packet count is 39 bits) */ } +#endif /*************************************************************************************************/ /*! * \brief Initialize the BLE baseband driver. * - * \return None. - * * One-time initialization of BLE baseband driver. */ /*************************************************************************************************/ @@ -680,13 +697,6 @@ void PalBbBleInit(void) /* enable receive address on logical address 0 (uses PREFIX0.AP0/BASE0 pair) */ NRF_RADIO->RXADDRESSES = 1; /* NOTE: this is a bitmask, a '1' enables logical address 0 */ - /* configure CCM hardware */ - NRF_CCM->INPTR = (uint32_t)bbEncryptTxBuf; - NRF_CCM->MODE = CCM_MODE_MODE_Encryption; - NRF_CCM->OUTPTR = (uint32_t)bbEncryptOutBuf; - NRF_CCM->SCRATCHPTR = (uint32_t)bbEncryptScratchBuf; - NRF_CCM->CNFPTR = (uint32_t)bbEncryptCcmData; - /* set default direction in CCM structure */ bbEncryptCcmData[24] = 0; /* 0=slave, 1=master */ @@ -700,8 +710,8 @@ void PalBbBleInit(void) bbEncryptTxFlag = 0; #if (USE_RTC_BB_CLK) - NRF_RTC0->EVTENCLR = RTC_EVTENCLR_COMPARE1_Msk; - NRF_RTC0->EVTENCLR = RTC_EVTENCLR_COMPARE2_Msk; + NRF_RTC1->EVTENCLR = RTC_EVTENCLR_COMPARE1_Msk; + NRF_RTC1->EVTENCLR = RTC_EVTENCLR_COMPARE2_Msk; #endif /* update driver state */ @@ -716,50 +726,6 @@ void PalBbBleInit(void) #endif ///////////////////////////////////////////////////////////////////////////////// - ///////////////////////////////////////////////////////////////////////////////// - #if DIAG_PINS_ENA - /* initialize diagnostics pins */ - nrf_gpio_cfg_output(TX_PIN); - nrf_gpio_cfg_output(RX_PIN); - nrf_gpio_cfg_output(RADIO_READY_TOGGLE_PIN); - nrf_gpio_cfg_output(RADIO_END_TOGGLE_PIN); - nrf_gpio_cfg_output(RADIO_INT_PIN); - nrf_gpio_cfg_output(TIMER0_INT_PIN); - - /* initialize PPI/GPIOTE to toggle pin on every radio READY event */ - #define READY_GPIOTE_CHAN 0 - NRF_PPI->CH[11].EEP = (uint32_t)&NRF_RADIO->EVENTS_READY; - NRF_PPI->CH[11].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[READY_GPIOTE_CHAN]; - NRF_PPI->CHENSET = PPI_CHENSET_CH11_Msk; - - nrf_gpiote_task_configure( READY_GPIOTE_CHAN, - RADIO_READY_TOGGLE_PIN, - NRF_GPIOTE_POLARITY_TOGGLE, - NRF_GPIOTE_INITIAL_VALUE_LOW ); - nrf_gpiote_task_enable( READY_GPIOTE_CHAN ); - - /* initialize PPI/GPIOTE to toggle pin on every radio END event */ - #define END_GPIOTE_CHAN 1 - NRF_PPI->CH[12].EEP = (uint32_t)&NRF_RADIO->EVENTS_END; - NRF_PPI->CH[12].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[END_GPIOTE_CHAN]; - NRF_PPI->CHENSET = PPI_CHENSET_CH12_Msk; - - nrf_gpiote_task_configure( END_GPIOTE_CHAN, - RADIO_END_TOGGLE_PIN, - NRF_GPIOTE_POLARITY_TOGGLE, - NRF_GPIOTE_INITIAL_VALUE_LOW ); - nrf_gpiote_task_enable( END_GPIOTE_CHAN ); - #endif - ///////////////////////////////////////////////////////////////////////////////// - - #if DIAG_USER_DEBUG_PINS_ENA - /* initialize diagnostics pins for user-debug. */ - nrf_gpio_cfg_output(USER_DEBUG_0_PIN); - nrf_gpio_cfg_output(USER_DEBUG_1_PIN); - nrf_gpio_cfg_output(USER_DEBUG_2_PIN); - nrf_gpio_cfg_output(USER_DEBUG_3_PIN); - #endif - bbTxPhyOptions = BB_PHY_OPTIONS_DEFAULT; bbRxPhyOptions = BB_PHY_OPTIONS_DEFAULT; tifsTxPhyOptions = BB_PHY_OPTIONS_DEFAULT; @@ -772,8 +738,6 @@ void PalBbBleInit(void) /*! * \brief Enable the BB hardware. * - * \return None. - * * Wake the BB hardware out of sleep and enable for operation. All BB functionality is * available when this routine completes. BB clock is set to zero and started. */ @@ -787,7 +751,13 @@ void PalBbBleEnable(void) BB_ASSERT(NVIC_GetPriority(RADIO_IRQn) == NVIC_GetPriority(TIMER0_IRQn)); /* BB driver related interrupts must have same priority */ BB_ASSERT(driverState == SLEEP_STATE); /* the BB driver should never be re-enabled */ BB_ASSERT(NRF_CLOCK->HFCLKSTAT & CLOCK_HFCLKSTAT_STATE_Msk); /* HF clock must be running */ -#if (!USE_RTC_BB_CLK) +#if (USE_RTC_BB_CLK) + if (!(NRF_CLOCK->HFCLKSTAT & CLOCK_HFCLKSTAT_SRC_Msk)) + { + NRF_CLOCK->TASKS_HFCLKSTART = 1; + } + +#else BB_ASSERT(NRF_CLOCK->HFCLKSTAT & CLOCK_HFCLKSTAT_SRC_Msk); /* HF clock source must be the crystal */ #endif @@ -812,12 +782,12 @@ void PalBbBleEnable(void) */ #if (USE_RTC_BB_CLK) /* timer0 starts when RTC0.COMPARE[1] event is triggered */ - NRF_PPI->CH[13].EEP = (uint32_t) &NRF_RTC0->EVENTS_COMPARE[1]; + NRF_PPI->CH[13].EEP = (uint32_t) &NRF_RTC1->EVENTS_COMPARE[1]; NRF_PPI->CH[13].TEP = (uint32_t) &NRF_TIMER0->TASKS_START; NRF_PPI->CHENSET = PPI_CHENSET_CH13_Msk; /* enable channel */ /* HFCLK starts when RTC0.COMPARE[2] event is triggered */ - NRF_PPI->CH[10].EEP = (uint32_t) &NRF_RTC0->EVENTS_COMPARE[2]; + NRF_PPI->CH[10].EEP = (uint32_t) &NRF_RTC1->EVENTS_COMPARE[2]; NRF_PPI->CH[10].TEP = (uint32_t) &NRF_CLOCK->TASKS_HFCLKSTART; NRF_PPI->CHENSET = PPI_CHENSET_CH10_Msk; /* enable channel */ #else @@ -876,8 +846,8 @@ void PalBbBleEnable(void) */ #if (USE_RTC_BB_CLK) - NRF_RTC0->EVTENSET = RTC_EVTENSET_COMPARE1_Msk; - NRF_RTC0->EVTENSET = RTC_EVTENSET_COMPARE2_Msk; + NRF_RTC1->EVTENSET = RTC_EVTENSET_COMPARE1_Msk; + NRF_RTC1->EVTENSET = RTC_EVTENSET_COMPARE2_Msk; #endif /* enable the radio "TIFS Expired" interrupt (triggers on radio PAYLOAD event) */ @@ -904,8 +874,6 @@ void PalBbBleEnable(void) /*! * \brief Disable the BB hardware. * - * \return None. - * * Disable the baseband and put radio hardware to sleep. Must be called from an idle state. * A radio operation cannot be in progress. */ @@ -918,16 +886,15 @@ void PalBbBleDisable(void) palBbRadioHardStop(); /* stop timer */ - NRF_TIMER0->TASKS_STOP = 1; - NRF_TIMER0->TASKS_SHUTDOWN = 1; + PalBbBleLowPower(); /* disable PPI channels */ NRF_PPI->CHENCLR = PPI_CHENCLR_CH14_Msk; /* Chan 14: COMPARE[0] -> TXEN/RXEN */ NRF_PPI->CHENCLR = PPI_CHENCLR_CH15_Msk; /* Chan 15: PAYLOAD -> CAPTURE[2] */ #if (USE_RTC_BB_CLK) - NRF_RTC0->EVTENCLR = RTC_EVTENCLR_COMPARE1_Msk; - NRF_RTC0->EVTENCLR = RTC_EVTENCLR_COMPARE2_Msk; + NRF_RTC1->EVTENCLR = RTC_EVTENCLR_COMPARE1_Msk; + NRF_RTC1->EVTENCLR = RTC_EVTENCLR_COMPARE2_Msk; #endif /* disable and clean up TIMER0 interrupts */ @@ -955,12 +922,9 @@ void PalBbBleDisable(void) * * \param pParam Callback called upon the completion of a transmit operation. * - * \return None. - * * The given \a txCback routine is called once and only once in response to \a BbDrvTx(). It * should be called in the ISR context due to the transmit completion interrupt from the BB. * If \a BbDrvTxCancel() is called with a return value of TRUE, \a txCback must not be executed. - * */ /*************************************************************************************************/ void PalBbBleSetDataParams(const PalBbBleDataParam_t *pParam) @@ -974,15 +938,7 @@ void PalBbBleSetDataParams(const PalBbBleDataParam_t *pParam) bbRxCallback = pParam->rxCback; /* store due time for future use */ - bbAntennaDueTime = pParam->due; - bbDueOffsetUsec = pParam->dueOffsetUsec; - -#if (USE_RTC_BB_CLK) - if (bbDueOffsetUsec > 31) - { - bbDueOffsetUsec = 31; - } -#endif + bbAntennaDueTimeUsec = pParam->dueUsec; /* store timeout value for future use */ bbRxTimeoutUsec = pParam->rxTimeoutUsec; @@ -994,7 +950,7 @@ void PalBbBleSetDataParams(const PalBbBleDataParam_t *pParam) bbRxCallback = DiagFauxRxCallback; diagRxCallback = pParam->rxCback; #endif - // for diagnostic purposes, an override scheme where all callbacks pass through an internal path + /* for diagnostic purposes, an override scheme where all callbacks pass through an internal path. */ ///////////////////////////////////////////////////////////////////////////////// } @@ -1004,14 +960,12 @@ void PalBbBleSetDataParams(const PalBbBleDataParam_t *pParam) * * \param pOpParam Operations parameters. * - * \return None. - * * Calling this routine will set parameters for the next transmit or receive operations. */ /*************************************************************************************************/ void PalBbBleSetOpParams(const PalBbBleOpParam_t *pOpParam) { - + bbOpParam = *pOpParam; } /*************************************************************************************************/ @@ -1019,36 +973,13 @@ void PalBbBleSetOpParams(const PalBbBleOpParam_t *pOpParam) * \brief Set channelization parameters. * * \param pChan Channelization parameters. - * - * \return None. - * - * Calling this routine will set these parameters for all future transmit and receive operations - * until this routine is called again providing new parameters. - * - * The setting of channelization parameters influence the operations of the following listed - * routines. Therefore, this routine is called to set the channel characteristics before - * the use of these listed packet routines. - * - * - \a BbDrvTx() - * - \a BbDrvRx() - * - \a BbDrvTxTifs() - * - \a BbDrvRxTifs() - * - * \note The \a pParam contents are not guaranteed to be static and is only valid in the - * context of the call to this routine. Therefore parameters requiring persistence - * should be copied. */ /*************************************************************************************************/ -void PalBbBleSetChannelParam(PalBbBleChan_t *pChan) +static void palBbBleSetChannelParam(PalBbBleChan_t *pChan) { uint8_t rfChan; int8_t txPower; - BB_ASSERT(driverState == IDLE_STATE); /* driver must be idle */ - - /* stop any TIFS operation that might be ramping up */ - palBbRadioHardStop(); - /* get the channel index into a local variable, for efficiency */ bbChanIndex = pChan->chanIdx; @@ -1151,24 +1082,55 @@ void PalBbBleSetChannelParam(PalBbBleChan_t *pChan) /* set encryption parameters */ if (pChan->enc.enaEncrypt || pChan->enc.enaDecrypt) { - palBbBleInlineEncryptDecryptSuppressMic(pChan->enc.nonceMode); + palBbBleInlineEncryptDecryptSuppressMic(FALSE); /* TODO add MIC suppression */ palBbBleInlineEncryptDecryptSetKey(pChan->enc.sk); palBbBleDrvInlineEncryptDecryptSetIv(pChan->enc.iv); + PalBbBleInlineEncryptDecryptSetDirection(pChan->enc.dir); } #endif } +/*************************************************************************************************/ +/*! + * \brief Set channelization parameters. + * + * \param pChan Channelization parameters. + * + * Calling this routine will set these parameters for all future transmit and receive operations + * until this routine is called again providing new parameters. + * + * The setting of channelization parameters influence the operations of the following listed + * routines. Therefore, this routine is called to set the channel characteristics before + * the use of these listed packet routines. + * + * - \a BbDrvTx() + * - \a BbDrvRx() + * - \a BbDrvTxTifs() + * - \a BbDrvRxTifs() + * + * \note The \a pParam contents are not guaranteed to be static and is only valid in the + * context of the call to this routine. Therefore parameters requiring persistence + * should be copied. + */ +/*************************************************************************************************/ +void PalBbBleSetChannelParam(PalBbBleChan_t *pChan) +{ + BB_ASSERT(driverState == IDLE_STATE); /* driver must be idle */ + + /* stop any TIFS operation that might be ramping up */ + palBbRadioHardStop(); + + palBbBleSetChannelParam(pChan); +} + /*************************************************************************************************/ /*! * \brief Enable or disable data whitening. * * \param enable flag to indicate data whitening * - * \return None. - * * Sets an internal variable that indicates if data whitening is enabled or not. * The value is used later when setting PCNF1 at beginning of TX or RX. - * */ /*************************************************************************************************/ void PalBbBleEnableDataWhitening(bool_t enable) @@ -1191,8 +1153,6 @@ void PalBbBleEnableDataWhitening(bool_t enable) * * \param enable flag to indicate PRBS15 * - * \return None. - * * Immediately enable or disable continuous PRBS15 bitstream. */ /*************************************************************************************************/ @@ -1237,6 +1197,7 @@ void PalBbBleEnablePrbs15(bool_t enable) /* update the driver state */ driverState = IDLE_STATE; + BB_LED_OFF(); } } @@ -1246,9 +1207,6 @@ void PalBbBleEnablePrbs15(bool_t enable) * * \param descs Array of transmit buffer descriptor. * \param cnt Number of descriptors. - * - * \return None. - * */ /*************************************************************************************************/ void PalBbBleTxData(PalBbBleTxBufDesc_t descs[], uint8_t cnt) @@ -1271,12 +1229,12 @@ void PalBbBleTxData(PalBbBleTxBufDesc_t descs[], uint8_t cnt) palBbRadioHardStop(); busycount = 0; - while ((NRF_RADIO->STATE != RADIO_STATE_STATE_Disabled) && (busycount < 20)) + while ((NRF_RADIO->STATE != RADIO_STATE_STATE_Disabled) && (busycount < 10)) { busycount++; } - if (busycount < 20) + if (busycount < 10) { /* Radio state is cleared now, continue TxData operation. */ break; @@ -1308,14 +1266,24 @@ void PalBbBleTxData(PalBbBleTxBufDesc_t descs[], uint8_t cnt) ///////////////////////////////////////////////////////////////////////////////// #if (LL_ENABLE_TESTER == TRUE) + /* set Tx access addresses */ + NRF_RADIO->PREFIX0 = (bbTxAccAddr & 0xFF000000) >> 24; + NRF_RADIO->BASE0 = (bbTxAccAddr & 0x00FFFFFF) << 8; + if (invalidateAccAddrOnceTx) + { + invalidateAccAddrOnceTx = FALSE; + + /* invalidate */ + NRF_RADIO->PREFIX0 = ((bbTxAccAddr ^ 0xFFFFFFFF) & 0xFF000000) >> 24; + NRF_RADIO->BASE0 = ((bbTxAccAddr ^ 0xFFFFFFFF) & 0x00FFFFFF) << 8; + } + uint16_t hdr; BYTES_TO_UINT16(hdr, pBuf); - if ((hdr & bbModifyTxHdrMask) == bbModifyTxHdrValue) - { - /* set Tx access addresses */ - NRF_RADIO->PREFIX0 = (bbTxAccAddr & 0xFF000000) >> 24; - NRF_RADIO->BASE0 = (bbTxAccAddr & 0x00FFFFFF) << 8; + if (bbModifyTxHdrMask && + ((hdr & bbModifyTxHdrMask) == bbModifyTxHdrValue)) + { if (bbTxAccAddrInvalidChanMask & (UINT64_C(1) << bbChanIndex)) { if ((bbTxAccAddrInvalidAdjMask & (1 << bbTxAccAddrInvalidStep)) || bbTxAccAddrShiftMask) @@ -1365,9 +1333,13 @@ void PalBbBleTxData(PalBbBleTxBufDesc_t descs[], uint8_t cnt) } } } + } - /* set Tx CRC init */ - NRF_RADIO->CRCINIT = bbTxCrcInit; + /* set Tx CRC init */ + NRF_RADIO->CRCINIT = bbTxCrcInit; + if (bbModifyTxHdrMask && + ((hdr & bbModifyTxHdrMask) == bbModifyTxHdrValue)) + { if (bbTxCrcInitInvalidChanMask & (UINT64_C(1) << bbChanIndex)) { if (bbTxCrcInitInvalidAdjMask & (1 << bbTxCrcInitInvalidStep)) @@ -1385,10 +1357,28 @@ void PalBbBleTxData(PalBbBleTxBufDesc_t descs[], uint8_t cnt) #endif /* calculate start time */ - uint32_t txStart = bbAntennaDueTime - USEC_TO_TICKS(NRF5x_tTXEN_BLE_USECS + NRF5x_PROP_DELAY_TX_USECS); + uint32_t txStart = BB_US_TO_BB_TICKS(bbAntennaDueTimeUsec - (NRF5x_tTXEN_BLE_USECS + NRF5x_PROP_DELAY_TX_USECS)); /* set timer compare CC[0] for time to trigger a transmit */ #if (USE_RTC_BB_CLK) + uint32_t txStartUsec = bbAntennaDueTimeUsec - (NRF5x_tTXEN_BLE_USECS + NRF5x_PROP_DELAY_TX_USECS); + + if (bbAntennaDueTimeUsec < NRF5x_tTXEN_BLE_USECS + NRF5x_PROP_DELAY_TX_USECS) + { + txStartUsec = bbAntennaDueTimeUsec - NRF5x_tTXEN_BLE_USECS - NRF5x_PROP_DELAY_TX_USECS + BB_RTC_MAX_VALUE_US + 1; + } + + txStart = BB_US_TO_BB_TICKS(txStartUsec); + + int16_t dueOffsetUsec = txStartUsec - BB_TICKS_TO_US(txStart); + + bbDueOffsetUsec = dueOffsetUsec > 0 ? dueOffsetUsec : 0; + + if (bbDueOffsetUsec > 31) + { + bbDueOffsetUsec = 31; + } + if (bbDueOffsetUsec == 0) { bbDueOffsetUsec = 1; /* CC[0] can't trigger on 0 */ @@ -1397,7 +1387,7 @@ void PalBbBleTxData(PalBbBleTxBufDesc_t descs[], uint8_t cnt) NRF_TIMER0->CC[0] = bbDueOffsetUsec; NRF_TIMER0->EVENTS_COMPARE[0] = 0; WAIT_FOR_WR_BUF_EMPTY(NRF_TIMER0->EVENTS_COMPARE[0]); - palBbSetHfClkStart(txStart); + palBbStartTimer(txStart); #else BB_ASSERT(bbDueOffsetUsec == 0); /* Always 0 with HFCLK. */ NRF_TIMER0->CC[0] = txStart; @@ -1412,8 +1402,15 @@ void PalBbBleTxData(PalBbBleTxBufDesc_t descs[], uint8_t cnt) NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk | RADIO_SHORTS_END_DISABLE_Msk; + uint32_t currentBbTick; + (void)PalBbGetTimestamp(¤tBbTick); + /* see if the due time is in the past (or a very long way, away) */ - if ((txStart - PalBbGetCurrentTime(USE_RTC_BB_CLK)) & 0x80000000) +#if (USE_RTC_BB_CLK) + if ((txStart - currentBbTick) & 0x00800000) /* Check MSB of 24 bit RTC counter. */ +#else + if ((txStart - currentBbTick) & 0x80000000) +#endif { ///////////////////////////////////////////////////////////////////////////////// #ifdef DIAGNOSTICS @@ -1467,8 +1464,6 @@ void PalBbBleTxData(PalBbBleTxBufDesc_t descs[], uint8_t cnt) * \param descs Transmit data buffer descriptor. * \param cnt Transmit data count. * - * \return None. - * * If possible, the transmit will occur at the TIFS timing. If not possible, the callback status * will indicate this. */ @@ -1491,13 +1486,23 @@ void PalBbBleTxTifsData(PalBbBleTxBufDesc_t descs[], uint8_t cnt) ///////////////////////////////////////////////////////////////////////////////// #if (LL_ENABLE_TESTER == TRUE) + /* set Tx access addresses */ + NRF_RADIO->PREFIX0 = (bbTxAccAddr & 0xFF000000) >> 24; + NRF_RADIO->BASE0 = (bbTxAccAddr & 0x00FFFFFF) << 8; + if (invalidateAccAddrOnceTx) + { + invalidateAccAddrOnceTx = FALSE; + + /* invalidate */ + NRF_RADIO->PREFIX0 = ((bbTxAccAddr ^ 0xFFFFFFFF) & 0xFF000000) >> 24; + NRF_RADIO->BASE0 = ((bbTxAccAddr ^ 0xFFFFFFFF) & 0x00FFFFFF) << 8; + } + uint16_t hdr; BYTES_TO_UINT16(hdr, pBuf); + if ((hdr & bbModifyTxHdrMask) == bbModifyTxHdrValue) { - /* set Tx access addresses */ - NRF_RADIO->PREFIX0 = (bbTxAccAddr & 0xFF000000) >> 24; - NRF_RADIO->BASE0 = (bbTxAccAddr & 0x00FFFFFF) << 8; if (bbTxAccAddrInvalidChanMask & (UINT64_C(1) << bbChanIndex)) { if ((bbTxAccAddrInvalidAdjMask & (1 << bbTxAccAddrInvalidStep)) || bbTxAccAddrShiftMask) @@ -1547,9 +1552,12 @@ void PalBbBleTxTifsData(PalBbBleTxBufDesc_t descs[], uint8_t cnt) } } } + } - /* set Tx CRC init */ - NRF_RADIO->CRCINIT = bbTxCrcInit; + /* set Tx CRC init */ + NRF_RADIO->CRCINIT = bbTxCrcInit; + if ((hdr & bbModifyTxHdrMask) == bbModifyTxHdrValue) + { if (bbTxCrcInitInvalidChanMask & (UINT64_C(1) << bbChanIndex)) { if (bbTxCrcInitInvalidAdjMask & (1 << bbTxCrcInitInvalidStep)) @@ -1644,14 +1652,28 @@ void PalBbBleTxTifsData(PalBbBleTxBufDesc_t descs[], uint8_t cnt) * * \param pTxBuf - pointer to buffer to transmit * - * \return None. - * * Configuration common to TIFS and non-TIFS transmit. * */ /*===============================================================================================*/ static void palBbTxHwRadioConfig(uint8_t * pTxBuf) { +#if defined(NRF52840_XXAA) + if (bbTxPhy == BB_PHY_BLE_CODED) + { + /* Improve Coded sensitivity for nRF52840 chip. */ + *(volatile uint32_t *)0x4000173C |= 0x80000000; + *(volatile uint32_t *)0x4000173C = ((*(volatile uint32_t *)0x4000173C & 0xFFFFFF00) | 0x5C); + } + + uint32_t plen = ((bbTxPhy != BB_PHY_BLE_1M) ? ((bbTxPhy != BB_PHY_BLE_2M) ? RADIO_PCNF0_PLEN_LongRange : RADIO_PCNF0_PLEN_16bit) \ + : RADIO_PCNF0_PLEN_8bit) << RADIO_PCNF0_PLEN_Pos; +#elif defined(NRF52832_XXAA) + uint32_t plen = ((bbTxPhy == BB_PHY_BLE_2M) ? RADIO_PCNF0_PLEN_16bit : RADIO_PCNF0_PLEN_8bit) << RADIO_PCNF0_PLEN_Pos; +#else + uint32_t plen = 0; +#endif + if (!bbEncryptTxFlag) { /*------------------------------------------------------------------------------ @@ -1662,21 +1684,6 @@ static void palBbTxHwRadioConfig(uint8_t * pTxBuf) * format. This also allows for zero copy as well. * */ -#if defined(NRF52840_XXAA) - if (bbTxPhy == BB_PHY_BLE_CODED) - { - /* Improve Coded sensitivity for nRF52840 chip. */ - *(volatile uint32_t *)0x4000173C |= 0x80000000; - *(volatile uint32_t *)0x4000173C = ((*(volatile uint32_t *)0x4000173C & 0xFFFFFF00) | 0x5C); - } - - uint32_t plen = ((bbTxPhy != BB_PHY_BLE_1M) ? ((bbTxPhy != BB_PHY_BLE_2M) ? RADIO_PCNF0_PLEN_LongRange : RADIO_PCNF0_PLEN_16bit) \ - : RADIO_PCNF0_PLEN_8bit) << RADIO_PCNF0_PLEN_Pos; -#elif defined(NRF52832_XXAA) - uint32_t plen = ((bbTxPhy == BB_PHY_BLE_2M) ? RADIO_PCNF0_PLEN_16bit : RADIO_PCNF0_PLEN_8bit) << RADIO_PCNF0_PLEN_Pos; -#else - uint32_t plen = 0; -#endif /* configure PCNF0 */ NRF_RADIO->PCNF0 = (((uint32_t)( 1 /* S0 field in bytes */ )) << RADIO_PCNF0_S0LEN_Pos) | @@ -1726,22 +1733,23 @@ static void palBbTxHwRadioConfig(uint8_t * pTxBuf) BB_ASSERT( packetCountSetFlag ); /* packet count was not set */ /* configure PCNF0 */ - NRF_RADIO->PCNF0 = (((uint32_t)( 1 /* S0 field in bytes */ )) << RADIO_PCNF0_S0LEN_Pos) | - (((uint32_t)( 5 /* length field in bits */ )) << RADIO_PCNF0_LFLEN_Pos) | + NRF_RADIO->PCNF0 = (((uint32_t)( 1 /* S0 field in bytes */ )) << RADIO_PCNF0_S0LEN_Pos) | + (((uint32_t)( 8 /* length field in bits */ )) << RADIO_PCNF0_LFLEN_Pos) | + (((uint32_t)( 0 /* S1 field in bits */ )) << RADIO_PCNF0_S1LEN_Pos) | #if defined(NRF52840_XXAA) (((uint32_t)((bbTxPhy == BB_PHY_BLE_CODED) ? 3 : 0 /* TERM field in bits*/ )) << RADIO_PCNF0_TERMLEN_Pos) | (((uint32_t)((bbTxPhy == BB_PHY_BLE_CODED) ? 2 : 0 /* CI field in bits */ )) << RADIO_PCNF0_CILEN_Pos) | (((uint32_t)( 0 /* CRCINC field */ )) << RADIO_PCNF0_CRCINC_Pos) | - (((uint32_t)( 0 /* S1INCL filed */ )) << RADIO_PCNF0_S1INCL_Pos) | + (((uint32_t)( 1 /* S1INCL filed */ )) << RADIO_PCNF0_S1INCL_Pos) | #endif - (((uint32_t)( 3 /* S1 field in bits */ )) << RADIO_PCNF0_S1LEN_Pos); + ((uint32_t)( plen /* preamble field in bits */ )); /* configure PCNF1 */ - NRF_RADIO->PCNF1 = (((uint32_t)( 0 /* maximum packet length */ )) << RADIO_PCNF1_MAXLEN_Pos ) | - (((uint32_t)( 0 /* static packet length */ )) << RADIO_PCNF1_STATLEN_Pos ) | - (((uint32_t)( NORDIC_BASE_ADDR_LEN )) << RADIO_PCNF1_BALEN_Pos ) | - (((uint32_t)( RADIO_PCNF1_ENDIAN_Little )) << RADIO_PCNF1_ENDIAN_Pos ) | - (((uint32_t)( bbRadioPcnf1WhiteEn )) << RADIO_PCNF1_WHITEEN_Pos ); + NRF_RADIO->PCNF1 = (((uint32_t)( 0 /* maximum packet length */ )) << RADIO_PCNF1_MAXLEN_Pos ) | + (((uint32_t)( 0 /* static packet length */ )) << RADIO_PCNF1_STATLEN_Pos ) | + (((uint32_t)( NORDIC_BASE_ADDR_LEN )) << RADIO_PCNF1_BALEN_Pos ) | + (((uint32_t)( RADIO_PCNF1_ENDIAN_Little )) << RADIO_PCNF1_ENDIAN_Pos ) | + (((uint32_t)( bbRadioPcnf1WhiteEn )) << RADIO_PCNF1_WHITEEN_Pos ); /* set packet pointer to the soon-to-be encrypted buffer */ NRF_RADIO->PACKETPTR = (uint32_t)&bbEncryptOutBuf[0]; @@ -1760,6 +1768,41 @@ static void palBbTxHwRadioConfig(uint8_t * pTxBuf) BB_ASSERT(bbEncryptTxBuf[sizeof(bbEncryptTxBuf)-1] == 0xAA); /* buffer overrun from memcpy */ BB_ASSERT(bbEncryptTxBuf[sizeof(bbEncryptTxBuf)-2] == 0xAA); /* buffer overrun from memcpy */ + NRF_CCM->ENABLE = (CCM_ENABLE_ENABLE_Disabled << CCM_ENABLE_ENABLE_Pos); + NRF_CCM->ENABLE = (CCM_ENABLE_ENABLE_Enabled << CCM_ENABLE_ENABLE_Pos); + + NRF_CCM->CNFPTR = (uint32_t)bbEncryptCcmData; + NRF_CCM->SCRATCHPTR = (uint32_t)bbEncryptScratchBuf; + + NRF_CCM->INPTR = (uint32_t)bbEncryptTxBuf; + NRF_CCM->OUTPTR = (uint32_t)bbEncryptOutBuf; + + uint32_t ccmModeDatarate; + switch (bbTxPhy) + { + default: + case BB_PHY_BLE_1M: + ccmModeDatarate = CCM_MODE_DATARATE_1Mbit << CCM_MODE_DATARATE_Pos; + break; + case BB_PHY_BLE_2M: + ccmModeDatarate = CCM_MODE_DATARATE_2Mbit << CCM_MODE_DATARATE_Pos; + break; +#if defined(NRF52840_XXAA) + case BB_PHY_BLE_CODED: + ccmModeDatarate = ((bbTxPhyOptions == BB_PHY_OPTIONS_BLE_S2) ? CCM_MODE_DATARATE_500Kbps : CCM_MODE_DATARATE_125Kbps) + << CCM_MODE_DATARATE_Pos; + break; +#endif + } + + NRF_CCM->MODE = (CCM_MODE_MODE_Encryption << CCM_MODE_MODE_Pos) | + (ccmModeDatarate) | + (CCM_MODE_LENGTH_Extended << CCM_MODE_LENGTH_Pos); + + NRF_CCM->EVENTS_ENDCRYPT = 0; + NRF_CCM->EVENTS_ENDKSGEN = 0; + NRF_CCM->EVENTS_ERROR = 0; + /* ---------- handle MIC suppression ---------- */ if (bbEncryptTxSuppressMic) { @@ -1767,7 +1810,6 @@ static void palBbTxHwRadioConfig(uint8_t * pTxBuf) bbEncryptOutBuf[1] = 0xFF; /* clear the ENDKSGEN event, aka "key-stream generation complete" event */ - NRF_CCM->EVENTS_ENDKSGEN = 0; WAIT_FOR_WR_BUF_EMPTY(NRF_CCM->EVENTS_ENDKSGEN); /* enable the ENDKSGEN interrupt, this interrupt will revert length to original "MIC-less" length */ @@ -1775,6 +1817,17 @@ static void palBbTxHwRadioConfig(uint8_t * pTxBuf) } /* -------------------------------------------- */ +#if (LL_ENABLE_TESTER) + if ((llTesterCb.pktMic) || (llTesterCb.pktLlId)) + { + /* clear the ENDCRYPT event */ + WAIT_FOR_WR_BUF_EMPTY(NRF_CCM->EVENTS_ENDCRYPT); + + /* enable the ENDCRYPT interrupt, this interrupt will modify the MIC/LLID */ + NRF_CCM->INTENSET = CCM_INTENSET_ENDCRYPT_Msk; + } +#endif + /* set shortcut to start encryption immediately after key generation */ NRF_CCM->SHORTS = CCM_SHORTS_ENDKSGEN_CRYPT_Msk; // TODO - probably just need to set once at initialization ***** @@ -1789,48 +1842,65 @@ static void palBbTxHwRadioConfig(uint8_t * pTxBuf) * * \param None. * - * \return None. - * * This interrupt undoes Nordic's automatic +4 to the length field. This allows transmitting * without the MIC. - * */ /*************************************************************************************************/ void CCM_AAR_IRQHandler(void) { - BB_ASSERT(NRF_CCM->INTENSET == CCM_INTENSET_ENDKSGEN_Msk); /* only keygen complete should be enabled */ - - /* -----------------------------------------------------------------------------* - * ENDKSGEN - Key Generation Complete - * -----------------------------------------------------------------------------*/ - BB_ASSERT(NRF_CCM->EVENTS_ENDKSGEN); /* this event should have been set */ - - /* disable this interrupt */ - NRF_CCM->INTENCLR = CCM_INTENCLR_ENDKSGEN_Msk; - - /* - * The key-stream generation has just completed. A shortcut should immediately - * start encryption which populates the output buffer. The second byte of the - * output buffer will be the length. Nordic automatically adds four to account for - * the addition of the MIC. To avoid transmitting the MIC in the "MIC-less" mode, - * this interrupt readjusts the length before it gets transmitted. - */ - - /* wait for the length field to be populated by the Nordic hardware */ - while(bbEncryptOutBuf[1] == 0xFF) + if (bbEncryptTxSuppressMic) { - /////////////////////////////////////////////////////////////////////////////// - #ifdef BB_ASSERT_ENABLED - uint8_t busycount = 0; - BB_ASSERT(busycount < 10); /* got stuck */ - busycount++; - #endif - /////////////////////////////////////////////////////////////////////////////// + BB_ASSERT(NRF_CCM->INTENSET == CCM_INTENSET_ENDKSGEN_Msk); /* only keygen complete should be enabled */ + + /* -----------------------------------------------------------------------------* + * ENDKSGEN - Key Generation Complete + * -----------------------------------------------------------------------------*/ + BB_ASSERT(NRF_CCM->EVENTS_ENDKSGEN); /* this event should have been set */ + + /* disable this interrupt */ + NRF_CCM->INTENCLR = CCM_INTENCLR_ENDKSGEN_Msk; + + /* + * The key-stream generation has just completed. A shortcut should immediately + * start encryption which populates the output buffer. The second byte of the + * output buffer will be the length. Nordic automatically adds four to account for + * the addition of the MIC. To avoid transmitting the MIC in the "MIC-less" mode, + * this interrupt readjusts the length before it gets transmitted. + */ + + /* wait for the length field to be populated by the Nordic hardware */ + while (bbEncryptOutBuf[1] == 0xFF) + { + /////////////////////////////////////////////////////////////////////////////// + #ifdef BB_ASSERT_ENABLED + uint8_t busycount = 0; + BB_ASSERT(busycount < 10); /* got stuck */ + busycount++; + #endif + /////////////////////////////////////////////////////////////////////////////// + } + + /* overwrite with the length field with the original length, that does not include the MIC */ + BB_ASSERT(bbTxLen == (bbEncryptOutBuf[1] - 4)); /* the populated length should be exactly +4 */ + bbEncryptOutBuf[1] = bbTxLen; } - /* overwrite with the length field with the original length, that does not include the MIC */ - BB_ASSERT(bbTxLen == (bbEncryptOutBuf[1] - 4)); /* the populated length should be exactly +4 */ - bbEncryptOutBuf[1] = bbTxLen; +#if (LL_ENABLE_TESTER) + if ((llTesterCb.pktMic) || (llTesterCb.pktLlId)) + { + BB_ASSERT(NRF_CCM->EVENTS_ENDCRYPT); /* this event should have been set */ + + /* disable this interrupt */ + NRF_CCM->INTENCLR = CCM_INTENCLR_ENDCRYPT_Msk; + + bbEncryptOutBuf[0] ^= llTesterCb.pktLlId & 0x03; + + bbEncryptOutBuf[bbTxLen] ^= (llTesterCb.pktMic >> 0) & 0xFF; + bbEncryptOutBuf[bbTxLen+1] ^= (llTesterCb.pktMic >> 8) & 0xFF; + bbEncryptOutBuf[bbTxLen+2] ^= (llTesterCb.pktMic >> 16) & 0xFF; + bbEncryptOutBuf[bbTxLen+3] ^= (llTesterCb.pktMic >> 24) & 0xFF; + } +#endif } /*************************************************************************************************/ @@ -1840,8 +1910,6 @@ void CCM_AAR_IRQHandler(void) * \param pBuf Transmit data buffer. * \param len Length of data buffer. * - * \return None. - * * The receiver is kept on for the amount of time previously configured by function call. */ /*************************************************************************************************/ @@ -1866,6 +1934,15 @@ void PalBbBleRxData(uint8_t *pBuf, uint16_t len) /* set Rx access addresses */ NRF_RADIO->PREFIX0 = (bbRxAccAddr & 0xFF000000) >> 24; NRF_RADIO->BASE0 = (bbRxAccAddr & 0x00FFFFFF) << 8; + if (invalidateAccAddrOnceRx) + { + invalidateAccAddrOnceRx = FALSE; + + /* invalidate */ + NRF_RADIO->PREFIX0 = ((bbRxAccAddr ^ 0xFFFFFFFF) & 0xFF000000) >> 24; + NRF_RADIO->BASE0 = ((bbRxAccAddr ^ 0xFFFFFFFF) & 0x00FFFFFF) << 8; + } + if (bbRxAccAddrInvalidChanMask & (UINT64_C(1) << bbChanIndex)) { if (bbRxAccAddrInvalidAdjMask & (1 << bbRxAccAddrInvalidStep)) @@ -1906,10 +1983,28 @@ void PalBbBleRxData(uint8_t *pBuf, uint16_t len) palBbRadioHardStop(); /* calculate start time */ - uint32_t rxStart = bbAntennaDueTime - USEC_TO_TICKS(NRF5x_tRXEN_BLE_USECS + NRF5x_PROP_DELAY_RX_USECS); + uint32_t rxStart = BB_US_TO_BB_TICKS(bbAntennaDueTimeUsec - (NRF5x_tRXEN_BLE_USECS + NRF5x_PROP_DELAY_RX_USECS)); /* set timer compare CC[0] for time to trigger a transmit */ #if (USE_RTC_BB_CLK) + uint32_t rxStartUsec = bbAntennaDueTimeUsec - (NRF5x_tRXEN_BLE_USECS + NRF5x_PROP_DELAY_RX_USECS); + + if (bbAntennaDueTimeUsec < NRF5x_tRXEN_BLE_USECS + NRF5x_PROP_DELAY_RX_USECS) + { + rxStartUsec = bbAntennaDueTimeUsec - NRF5x_tRXEN_BLE_USECS - NRF5x_PROP_DELAY_RX_USECS + BB_RTC_MAX_VALUE_US + 1; + } + + rxStart = BB_US_TO_BB_TICKS(rxStartUsec); + + int16_t dueOffsetUsec = rxStartUsec - BB_TICKS_TO_US(rxStart); + + bbDueOffsetUsec = dueOffsetUsec > 0 ? dueOffsetUsec : 0; + + if (bbDueOffsetUsec > 31) + { + bbDueOffsetUsec = 31; + } + if (bbDueOffsetUsec == 0) { bbDueOffsetUsec = 1; /* CC[0] can't trigger on 0 */ @@ -1918,7 +2013,7 @@ void PalBbBleRxData(uint8_t *pBuf, uint16_t len) NRF_TIMER0->CC[0] = bbDueOffsetUsec; NRF_TIMER0->EVENTS_COMPARE[0] = 0; WAIT_FOR_WR_BUF_EMPTY(NRF_TIMER0->EVENTS_COMPARE[0]); - palBbSetHfClkStart(rxStart - 1); /* Subtract 1 for receive uncertainty due to rounding. */ + palBbStartTimer(rxStart - 1); /* Subtract 1 for receive uncertainty due to rounding. */ #else BB_ASSERT(bbDueOffsetUsec == 0); /* Always 0 with HFCLK. */ NRF_TIMER0->CC[0] = rxStart; @@ -1982,8 +2077,15 @@ void PalBbBleRxData(uint8_t *pBuf, uint16_t len) RADIO_SHORTS_ADDRESS_RSSISTART_Msk | RADIO_SHORTS_DISABLED_RSSISTOP_Msk; - /* see if the requested due is in the past (or a very long way, away) */ - if ((rxStart - PalBbGetCurrentTime(USE_RTC_BB_CLK)) & 0x80000000) + uint32_t currentBbTick; + (void)PalBbGetTimestamp(¤tBbTick); + + /* see if the due time is in the past (or a very long way, away) */ +#if (USE_RTC_BB_CLK) + if ((rxStart - currentBbTick) & 0x00800000) /* Check MSB of 24 bit RTC counter. */ +#else + if ((rxStart - currentBbTick) & 0x80000000) +#endif { ///////////////////////////////////////////////////////////////////////////////// #ifdef DIAGNOSTICS @@ -2035,8 +2137,6 @@ void PalBbBleRxData(uint8_t *pBuf, uint16_t len) * \param pBuf Receive data buffer. * \param len Length of data buffer. * - * \return None. - * * The receiver is left on for the minimum amount of time to recognize a receive. * * If possible, the receive will occur on the TIFS timing. If not possible, the callback status @@ -2064,6 +2164,15 @@ void PalBbBleRxTifsData(uint8_t *pBuf, uint16_t len) /* set Rx access addresses */ NRF_RADIO->PREFIX0 = (bbRxAccAddr & 0xFF000000) >> 24; NRF_RADIO->BASE0 = (bbRxAccAddr & 0x00FFFFFF) << 8; + if (invalidateAccAddrOnceRx) + { + invalidateAccAddrOnceRx = FALSE; + + /* invalidate */ + NRF_RADIO->PREFIX0 = ((bbRxAccAddr ^ 0xFFFFFFFF) & 0xFF000000) >> 24; + NRF_RADIO->BASE0 = ((bbRxAccAddr ^ 0xFFFFFFFF) & 0x00FFFFFF) << 8; + } + if (bbRxAccAddrInvalidChanMask & (UINT64_C(1) << bbChanIndex)) { if (bbRxAccAddrInvalidAdjMask & (1 << bbRxAccAddrInvalidStep)) @@ -2171,8 +2280,6 @@ void PalBbBleRxTifsData(uint8_t *pBuf, uint16_t len) * \param pRxBuf - pointer where receive bytes get written * \param len - maximum length for receive, i.e. size of the allocated receive buffer * - * \return None. - * * Configuration common to TIFS and non-TIFS transmit. * */ @@ -2231,8 +2338,6 @@ static void palBbRxHwRadioConfig(uint8_t * pRxBuf, uint16_t len) * * \param None. * - * \return None. - * * This is the "RX Timeout" interrupt. No other functionality is shared on the TIMER0 interrupt. * If the receive operation has not gotten started, it is cancelled. * @@ -2240,8 +2345,6 @@ static void palBbRxHwRadioConfig(uint8_t * pRxBuf, uint16_t len) /*************************************************************************************************/ void BbBleDrvTimerIRQHandler(void) { - DIAG_PIN_SET( TIMER0_INT_PIN ); - BB_ASSERT(NRF_TIMER0->INTENSET == TIMER_INTENSET_COMPARE1_Msk); /* only RX timeout should be enabled */ /* -----------------------------------------------------------------------------* @@ -2265,8 +2368,6 @@ void BbBleDrvTimerIRQHandler(void) /* send notification of timeout */ bbRxCallback(BB_STATUS_RX_TIMEOUT, 0, 0, 0, 0); } - - DIAG_PIN_CLEAR( TIMER0_INT_PIN ); } /*************************************************************************************************/ @@ -2275,8 +2376,6 @@ void BbBleDrvTimerIRQHandler(void) * * \param None. * - * \return None. - * * This the radio interrupt service routine. It is at the heart of the baseband driver * design. It handles the following interrupts: * @@ -2296,8 +2395,6 @@ void BbBleDrvTimerIRQHandler(void) /*************************************************************************************************/ void BbBleDrvRadioIRQHandler(void) { - DIAG_PIN_SET( RADIO_INT_PIN ); - /* -----------------------------------------------------------------------------* * READY - "TIFS Expired" * -----------------------------------------------------------------------------*/ @@ -2320,7 +2417,7 @@ void BbBleDrvRadioIRQHandler(void) if ((driverState == TX_STATE) || (tifsState == TIFS_TX_RAMPUP)) { - DIAG_PIN_SET( TX_PIN ); + BB_LED_TX_ON(); BB_ASSERT(NRF_RADIO->STATE == RADIO_STATE_STATE_Tx); } @@ -2328,7 +2425,7 @@ void BbBleDrvRadioIRQHandler(void) if ((driverState == RX_STATE) || (tifsState == TIFS_RX_RAMPUP)) { BB_ASSERT(NRF_RADIO->STATE == RADIO_STATE_STATE_Rx); - DIAG_PIN_SET( RX_PIN ); + BB_LED_RX_ON(); /* clear the ADDRESS event, it will indicate if an RX timeout is possible */ NRF_RADIO->EVENTS_ADDRESS = 0; @@ -2378,7 +2475,8 @@ void BbBleDrvRadioIRQHandler(void) /* - - - - - - - - - - - - - - - - - - - - - - - - - * * TX, set up for TIFS-RX * - - - - - - - - - - - - - - - - - - - - - - - - - */ - if (driverState == TX_STATE) + if ((bbOpParam.ifsMode == PAL_BB_IFS_MODE_TOGGLE_TIFS) && + (driverState == TX_STATE)) { uint32_t antennaTimeTxPktEnd; uint32_t crcTime; @@ -2454,8 +2552,6 @@ void BbBleDrvRadioIRQHandler(void) - TICKS_PER_USEC * NRF5x_tRXEN_BLE_USECS /* subtract time it takes to ramp-up for receive */ - TICKS_PER_USEC * MAX_TIFS_DEVIATION_USECS; /* subtract allowed deviation */ - - /* configure and enable PPI trigger for RXEN, happens on next timer COMPARE[0] just configured above */ NRF_PPI->CH[14].TEP = (uint32_t) &NRF_RADIO->TASKS_RXEN; /* configure task */ NRF_PPI->CHENSET = PPI_CHENSET_CH14_Msk; /* enable channel */ @@ -2489,7 +2585,8 @@ void BbBleDrvRadioIRQHandler(void) /* - - - - - - - - - - - - - - - - - - - - - - - - - * * RX, set up for TIFS-TX * - - - - - - - - - - - - - - - - - - - - - - - - - */ - else + else if ((bbOpParam.ifsMode == PAL_BB_IFS_MODE_TOGGLE_TIFS) && + (driverState == RX_STATE)) { uint32_t antennaTimeRxPktEnd; uint32_t crcTime; @@ -2576,6 +2673,105 @@ void BbBleDrvRadioIRQHandler(void) tifsState = TIFS_TX_RAMPUP; } + /* - - - - - - - - - - - - - - - - - - - - - - - - - * + * RX, set up for TIFS-RX + * - - - - - - - - - - - - - - - - - - - - - - - - - */ + else if ((bbOpParam.ifsMode == PAL_BB_IFS_MODE_SAME_ABS) && + (driverState == RX_STATE)) + { + uint32_t preambleTime; + uint32_t accessAddrTime; + int32_t correction; + + /* calculate time to receive preamble and access address */ + switch(bbRxPhy) + { + case BB_PHY_BLE_1M: + preambleTime = LL_BLE_US_PER_BYTE_1M * LL_PREAMBLE_LEN_1M; + accessAddrTime = LL_BLE_US_PER_BYTE_1M * LL_AA_LEN; + correction = 4; + break; + case BB_PHY_BLE_2M: + preambleTime = LL_BLE_US_PER_BYTE_2M * LL_PREAMBLE_LEN_2M; + accessAddrTime = LL_BLE_US_PER_BYTE_2M * LL_AA_LEN; + correction = 20; + break; +#if defined(NRF52840_XXAA) + case BB_PHY_BLE_CODED: + preambleTime = LL_BLE_US_PER_BIT_CODED_S8 * LL_PREAMBLE_LEN_CODED_BITS; + accessAddrTime = LL_BLE_US_PER_BYTE_CODED_S8 * LL_AA_LEN; + correction = 110; + break; +#endif + default: + preambleTime = LL_BLE_US_PER_BYTE_1M * LL_PREAMBLE_LEN_1M; + accessAddrTime = LL_BLE_US_PER_BYTE_1M * LL_AA_LEN; + correction = 4; + } + + NRF_TIMER0->CC[0] = BB_US_TO_BB_TICKS(bbOpParam.ifsTime - (NRF5x_tRXEN_BLE_USECS + NRF5x_PROP_DELAY_RX_USECS)); + + /* configure and enable PPI trigger for RXEN, happens on next timer COMPARE[0] just configured above */ + NRF_PPI->CH[14].TEP = (uint32_t) &NRF_RADIO->TASKS_RXEN; /* configure task */ + NRF_PPI->CHENSET = PPI_CHENSET_CH14_Msk; /* enable channel */ + + /* set timer compare CC[1] for RX timeout (allow time to recognize address, and account for propagation delay) */ + NRF_TIMER0->CC[1] = NRF_TIMER0->CC[0] + + TICKS_PER_USEC * (30 /* TODO Resolve total deviation allowed */ + + preambleTime + + accessAddrTime + + NRF5x_PROP_DELAY_RX_USECS + + NRF5x_tRXEN_BLE_USECS + + correction); + + /* + * NOTE: In the case of an RX timeout, the above compare will trigger an interrupt. + * This interrupt requires time to execute. This delay extends the time the radio + * is active. The effective timeout period is longer than computed above. + * + * This effective timeout period can be reduced using the trim value. + * This would be useful for power savings. But be warned!! Great care + * is required as this involves timing the speed of code execution. + * Any adjustment must be made with debug code disabled. + */ + + /* clear RX timeout compare event, but do not enable interrupt, that happens in radio isr */ + NRF_TIMER0->EVENTS_COMPARE[1] = 0; + WAIT_FOR_WR_BUF_EMPTY(NRF_TIMER0->EVENTS_COMPARE[1]); + + /* update channel parameters */ + if (bbOpParam.pIfsChan) + { + palBbBleSetChannelParam(bbOpParam.pIfsChan); + } + + /* a TX is completing, the radio will soon be ramping up for possible TIFS RX */ + tifsState = TIFS_RX_RAMPUP; + } + + /* - - - - - - - - - - - - - - - - - - - - - - - - - * + * TX, set up for TIFS-TX + * - - - - - - - - - - - - - - - - - - - - - - - - - */ + else if ((bbOpParam.ifsMode == PAL_BB_IFS_MODE_SAME_ABS) && + (driverState == TX_STATE)) + { + /* calculate start time */ + NRF_TIMER0->CC[0] = BB_US_TO_BB_TICKS(bbOpParam.ifsTime - (NRF5x_tTXEN_BLE_USECS + NRF5x_PROP_DELAY_TX_USECS)); + + /* configure and enable PPI trigger for TXEN, happens on next timer COMPARE[0] */ + NRF_PPI->CH[14].TEP = (uint32_t) &NRF_RADIO->TASKS_TXEN; /* configure task */ + NRF_PPI->CHENSET = PPI_CHENSET_CH14_Msk; /* enable channel */ + + /* update channel parameters */ + if (bbOpParam.pIfsChan) + { + palBbBleSetChannelParam(bbOpParam.pIfsChan); + } + + /* a TX is completing, the radio will soon be ramping up for possible TIFS RX */ + tifsState = TIFS_TX_RAMPUP; + } + /* ------------------------------------------------------------------------------ * Check to see if TIFS window already missed. This would happen if * interrupts were suppressed for a long time. @@ -2617,8 +2813,8 @@ void BbBleDrvRadioIRQHandler(void) WAIT_FOR_WR_BUF_EMPTY(NRF_RADIO->EVENTS_END); /* clear diagnostics pins */ - DIAG_PIN_CLEAR( TX_PIN ); - DIAG_PIN_CLEAR( RX_PIN ); + BB_LED_TX_OFF(); + BB_LED_RX_OFF(); /* - - - - - - - - - - - - - - - - - - - - - - - - - * * TX Complete @@ -2627,6 +2823,7 @@ void BbBleDrvRadioIRQHandler(void) { /* update driver state, *before* callback */ driverState = IDLE_STATE; + BB_LED_OFF(); /* run callback function */ palBbRestoreTrl(); @@ -2639,6 +2836,7 @@ void BbBleDrvRadioIRQHandler(void) else if (driverState == RX_STATE) { uint32_t timestamp; + uint32_t timestampUsesc; int8_t rssi; uint8_t pduLen; @@ -2704,21 +2902,30 @@ void BbBleDrvRadioIRQHandler(void) pduLen )); /* PDU payload */ } + #if (USE_RTC_BB_CLK) - /* reduce timestamp to BB clock units add RTC clock offset */ - timestamp = USEC_TO_TICKS(timestamp) + bbEventStartTime; + /* RTC event start time plus timestamp from HFCLK timer. */ + timestampUsesc = BB_TICKS_TO_US(bbEventStartTime) + bbDueOffsetUsec + TICKS_TO_USEC(timestamp); + /* Handle wraparound. */ + if (timestampUsesc > BB_RTC_MAX_VALUE_US) + { + timestampUsesc -= BB_RTC_MAX_VALUE_US; + } +#else + timestampUsesc = BB_TICKS_TO_US(timestamp); #endif /* compute RSSI value at antenna end */ rssi = (int8_t)(-(NRF_RADIO->RSSISAMPLE & 0x7F)) - PalRadioGetRxRfPathComp(); /* update driver state, *before* callback */ driverState = IDLE_STATE; + BB_LED_OFF(); /* Follow Rx PHY options */ bbTxPhyOptions = bbRxPhyOptions; /* Overwrite with TIFS preference */ - if(tifsTxPhyOptions) + if (tifsTxPhyOptions) { bbTxPhyOptions = tifsTxPhyOptions; } @@ -2727,12 +2934,12 @@ void BbBleDrvRadioIRQHandler(void) if ((NRF_RADIO->CRCSTATUS & RADIO_CRCSTATUS_CRCSTATUS_Msk) == RADIO_CRCSTATUS_CRCSTATUS_CRCError) { /* CRC error - run the callback function */ - bbRxCallback(BB_STATUS_CRC_FAILED, rssi, NRF_RADIO->RXCRC, timestamp, bbRxPhyOptions); + bbRxCallback(BB_STATUS_CRC_FAILED, rssi, NRF_RADIO->RXCRC, timestampUsesc, bbRxPhyOptions); } else { /* Success! - run the callback function */ - bbRxCallback(BB_STATUS_SUCCESS, rssi, NRF_RADIO->RXCRC, timestamp, bbRxPhyOptions); + bbRxCallback(BB_STATUS_SUCCESS, rssi, NRF_RADIO->RXCRC, timestampUsesc, bbRxPhyOptions); } } @@ -2757,16 +2964,12 @@ void BbBleDrvRadioIRQHandler(void) { BB_ASSERT(0); } - - DIAG_PIN_CLEAR( RADIO_INT_PIN ); } /*************************************************************************************************/ /*! * \brief Cancel TIFS timer. * - * \return None. - * * This stops any active TIFS timer operation. This routine is always called in the callback * (i.e. ISR) context. */ @@ -2784,8 +2987,6 @@ void PalBbBleCancelTifs(void) /*! * \brief Cancel a pending transmit or receive. * - * \return None. - * * This stops any active radio operation. This routine is never called in the callback * (i.e. ISR) context. */ @@ -2840,8 +3041,6 @@ void PalBbBleCancelData(void) * * \param None. * - * \return None. - * * Immediately stops the radio. All radio interrupts are cancelled. The radio is put into * the disabled state. This function does not return until the disabled state is verified. * @@ -2862,20 +3061,18 @@ static void palBbRadioHardStop(void) NRF_PPI->CHENCLR = PPI_CHENCLR_CH14_Msk; /* COMPARE[0] -> TXEN/RXEN */ /* disable HFCLK */ -#if (USE_RTC_BB_CLK) - NRF_TIMER0->TASKS_STOP = 1; - NRF_TIMER0->TASKS_CLEAR = 1; -#endif + PalBbBleLowPower(); /* update TIFS state */ tifsState = TIFS_NULL; /* update driver state */ driverState = IDLE_STATE; + BB_LED_OFF(); /* clear diagnostics pins */ - DIAG_PIN_CLEAR( TX_PIN ); - DIAG_PIN_CLEAR( RX_PIN ); + BB_LED_TX_OFF(); + BB_LED_RX_OFF(); /* wait for radio to complete shutdown */ /////////////////////////////////////////////////////////////////////////////// @@ -2922,7 +3119,6 @@ static void palBbRadioHardStop(void) * \param cnt Number of descriptors. * * \return Pointer to transmit data. - * */ /*************************************************************************************************/ static uint8_t *palBbGetTxData(PalBbBleTxBufDesc_t descs[], uint8_t cnt) @@ -2982,8 +3178,6 @@ static uint8_t *palBbGetTxData(PalBbBleTxBufDesc_t descs[], uint8_t cnt) /*! * \brief Restore trailer data. * - * \return None. - * */ /*************************************************************************************************/ static void palBbRestoreTrl(void) @@ -3003,8 +3197,6 @@ static void palBbRestoreTrl(void) * * \param status status as reported via callback * - * \return None. - * * For diagnostics, this function is used to intercept passing control to the configured * callback function. It is used to record diagnostic information. * @@ -3056,8 +3248,6 @@ static void DiagFauxTxCallback(uint8_t status) * * \param status status as reported via callback * - * \return None. - * * For diagnostics, this function is used to intercept passing control to the configured * callback function. It is used to record diagnostic information. * diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_bb_ble_rf.c b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_bb_ble_rf.c index 0dfc6f5907..4669be5e46 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_bb_ble_rf.c +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_bb_ble_rf.c @@ -5,14 +5,15 @@ * \brief BLE RF path compensation implementation file. * * Copyright (c) 2016-2019 Arm Ltd. All Rights Reserved. - * Arm Ltd. confidential and proprietary. * + * Copyright (c) 2019-2020 Packetcraft, Inc. + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -21,7 +22,7 @@ */ /*************************************************************************************************/ -#include "stack/platform/include/pal_types.h" +#include "pal_types.h" /************************************************************************************************** Macros @@ -45,18 +46,18 @@ #if defined(NRF52840_XXAA) || defined(NRF52832_XXAA) /* \brief Minimum Tx power level (expressed in 1dBm units). */ -static const int16_t bbBleMinTxPwr = -40; /* -40dBm */ +static const int8_t bbBleMinTxPwr = -40; /* -40dBm */ #else /* \brief Minimum Tx power level (expressed in 1dBm units). */ -static const int16_t bbBleMinTxPwr = -30; /* -30dBm */ +static const int8_t bbBleMinTxPwr = -30; /* -30dBm */ #endif #if defined(NRF52840_XXAA) /* \brief Maximum Tx power level (expressed in 1dBm units). */ -static const int16_t bbBleMaxTxPwr = 9; /* +9dBm */ +static const int8_t bbBleMaxTxPwr = 9; /* +9dBm */ #else /* \brief Maximum Tx power level (expressed in 1dBm units). */ -static const int16_t bbBleMaxTxPwr = 4; /* +4dBm */ +static const int8_t bbBleMaxTxPwr = 4; /* +4dBm */ #endif /************************************************************************************************** @@ -71,37 +72,21 @@ int16_t bbBleRxPathComp = -1280; /*************************************************************************************************/ /*! - * \brief Get transmit RF path compensation. + * \brief Get receive RF path compensation. * * \return Transmit RF path compensation (in 1-dBm units). */ /*************************************************************************************************/ -int8_t palBbBleRfGetTxRfPathComp(void) +int8_t PalRadioGetRxRfPathComp(void) { uint16_t pathCompUnsigned = (uint16_t)(bbBleTxPathComp - BB_BLE_MIN_PATH_COMP); return (int16_t)BB_BLE_MATH_DIV_10(pathCompUnsigned) + BB_BLE_MIN_PATH_COMP_DBM; } -/*************************************************************************************************/ -/*! - * \brief Get receive RF path compensation. - * - * \return Transmit RF path compensation (in 1-dBm units). - */ -/*************************************************************************************************/ -int8_t PalRadioGetRxRfPathComp(void) -{ - uint16_t pathCompUnsigned = (uint16_t)(bbBleRxPathComp - BB_BLE_MIN_PATH_COMP); - - return (int16_t)BB_BLE_MATH_DIV_10(pathCompUnsigned) + BB_BLE_MIN_PATH_COMP_DBM; -} - /*************************************************************************************************/ /*! * \brief Initialize RF path compensation. - * - * \return None. */ /*************************************************************************************************/ void PalRadioInitPathComp(void) @@ -116,8 +101,6 @@ void PalRadioInitPathComp(void) * * \param pMinTxPwr Return buffer for minimum transmit power (expressed in 1dBm units). * \param pMaxTxPwr Return buffer for maximum transmit power (expressed in 1dBm units). - * - * \return None. */ /*************************************************************************************************/ void PalRadioGetSupTxPower(int8_t *pMinTxPwr, int8_t *pMaxTxPwr) @@ -132,8 +115,6 @@ void PalRadioGetSupTxPower(int8_t *pMinTxPwr, int8_t *pMaxTxPwr) * * \param pTxPathComp Return buffer for RF transmit path compensation value (expressed in 0.1dBm units). * \param pRxPathComp Return buffer for RF receive path compensation value (expressed in 0.1dBm units). - * - * \return None. */ /*************************************************************************************************/ void PalRadioReadRfPathComp(int16_t *pTxPathComp, int16_t *pRxPathComp) @@ -214,8 +195,109 @@ int8_t PalRadioGetActualTxPower(int8_t txPwr, bool_t compFlag) if (compFlag) { - txPwr += palBbBleRfGetTxRfPathComp(); + txPwr += PalRadioGetRxRfPathComp(); } return txPwr; } + +/*************************************************************************************************/ +/*! + * \brief Request an increase in power. + + * \param reqPwr Requested Power. + * \param delta Delta + * + * \return TxPower to be set + * + * If increasing power: the controller will increase one step if possible. + * If decreasing power: the controller will only decrease to the ceiling step. + */ +/*************************************************************************************************/ +int8_t PalRadioIncreasePower(int8_t reqPwr, int8_t delta) +{ + /* An increase in power. The controller will always increase one step if possible. */ + if (delta > 0) + { +#if defined(NRF52840_XXAA) + if (reqPwr > 8) { reqPwr = 9; } + else if (reqPwr > 7) { reqPwr = 8; } + else if (reqPwr > 6) { reqPwr = 7; } + else if (reqPwr > 5) { reqPwr = 6; } + else if (reqPwr > 4) { reqPwr = 5; } + else if (reqPwr > 3) { reqPwr = 4; } + else if (reqPwr > 2) { reqPwr = 3; } + else if (reqPwr > 0) { reqPwr = 2; } + else if (reqPwr > -4) { reqPwr = 0; } + else if (reqPwr > -8) { reqPwr = -4; } + else if (reqPwr > -12) { reqPwr = -8; } + else if (reqPwr > -16) { reqPwr = -12; } + else if (reqPwr > -20) { reqPwr = -16; } + else { reqPwr = -20; } +#elif defined(NRF52832_XXAA) + if (reqPwr > 3) { reqPwr = 4; } + else if (reqPwr > 2) { reqPwr = 3; } + else if (reqPwr > 0) { reqPwr = 2; } + else if (reqPwr > -4) { reqPwr = 0; } + else if (reqPwr > -8) { reqPwr = -4; } + else if (reqPwr > -12) { reqPwr = -8; } + else if (reqPwr > -16) { reqPwr = -12; } + else if (reqPwr > -20) { reqPwr = -16; } + else { reqPwr = -20; } +#else + if (reqPwr > 0) { reqPwr = 4; } + else if (reqPwr > -4) { reqPwr = 0; } + else if (reqPwr > -8) { reqPwr = -4; } + else if (reqPwr > -12) { reqPwr = -8; } + else if (reqPwr > -16) { reqPwr = -12; } + else if (reqPwr > -20) { reqPwr = -16; } + else { reqPwr = -20; } +#endif + } + /* A decrease in power. The controller will decrease to higher step if reqPwer is inbetween two steps. */ + else if (delta < 0) + { +#if defined(NRF52840_XXAA) + if (reqPwr <= -40) { reqPwr = -40; } + else if (reqPwr <= -20) { reqPwr = -20; } + else if (reqPwr <= -16) { reqPwr = -16; } + else if (reqPwr <= -12) { reqPwr = -12; } + else if (reqPwr <= -8) { reqPwr = -8; } + else if (reqPwr <= -4) { reqPwr = -4; } + else if (reqPwr <= 0) { reqPwr = 0; } + else if (reqPwr <= 2) { reqPwr = 2; } + else if (reqPwr <= 3) { reqPwr = 3; } + else if (reqPwr <= 4) { reqPwr = 4; } + else if (reqPwr <= 5) { reqPwr = 5; } + else if (reqPwr <= 6) { reqPwr = 6; } + else if (reqPwr <= 7) { reqPwr = 7; } + else if (reqPwr <= 8) { reqPwr = 8; } + else { reqPwr = 9; } +#elif defined(NRF52832_XXAA) + if (reqPwr <= -40) { reqPwr = -40; } + else if (reqPwr <= -20) {reqPwr = -20; } + else if (reqPwr <= -16) {reqPwr = -16; } + else if (reqPwr <= -12) {reqPwr = -12; } + else if (reqPwr <= -8) {reqPwr = -8; } + else if (reqPwr <= -4) {reqPwr = -4; } + else if (reqPwr <= 0) {reqPwr = 0; } + else if (reqPwr <= 3) {reqPwr = 3; } + else {reqPwr = 4; } +#else + if (reqPwr <= -30) {reqPwr = -30; } + else if (reqPwr <= -20) {reqPwr = -20; } + else if (reqPwr <= -16) {reqPwr = -16; } + else if (reqPwr <= -12) {reqPwr = -12; } + else if (reqPwr <= -8) {reqPwr = -8; } + else if (reqPwr <= -4) {reqPwr = -4; } + else if (reqPwr <= 0) {reqPwr = 0; } + else {reqPwr = 4; } +#endif + } + else + { + /* No change. */ + } + + return reqPwr; +} diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_cfg.c b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_cfg.c index f03c5e4c74..ecbb81dbd9 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_cfg.c +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_cfg.c @@ -5,14 +5,15 @@ * \brief System configuration definition. * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. - * Arm Ltd. confidential and proprietary. * + * Copyright (c) 2019-2020 Packetcraft, Inc. + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -21,29 +22,9 @@ */ /*************************************************************************************************/ -#include "stack/platform/include/pal_cfg.h" +#include "pal_cfg.h" #include "nrf.h" -/************************************************************************************************** - Macros -**************************************************************************************************/ - -#ifndef LL_MAX_CIG -#define LL_MAX_CIG 2 /*!< Absolute maximum number of connected isochronous groups. */ -#endif - -#ifndef LL_MAX_CIS -#define LL_MAX_CIS 2 /*!< Absolute maximum number of connected isochronous streams per CIG. */ -#endif - -#ifndef LL_MAX_ADV_DATA_LEN -#define LL_MAX_ADV_DATA_LEN 1650 /*!< Maximum advertising data length. */ -#endif - -#ifndef LL_MAX_ADV_SETS -#define LL_MAX_ADV_SETS 6 /*!< Absolute maximum number of advertising sets. */ -#endif - /************************************************************************************************** Type Definitions **************************************************************************************************/ @@ -69,15 +50,19 @@ typedef struct int8_t defTxPwrLvl; /*!< Default Tx power level for connections. */ uint8_t ceJitterUsec; /*!< Allowable CE jitter on a slave (account for master's sleep clock resolution). */ /* ISO */ - uint8_t numIsoTxBuf; /*!< Default number of ISO transmit buffers. */ - uint8_t numIsoRxBuf; /*!< Default number of ISO receive buffers. */ - uint16_t maxIsoBufLen; /*!< Maximum ISO buffer size between host and controller. */ - uint16_t maxIsoPduLen; /*!< Maximum ISO PDU size between controllers. */ + uint8_t numIsoTxBuf; /*!< Default number of ISO transmit buffers. */ + uint8_t numIsoRxBuf; /*!< Default number of ISO receive buffers. */ + uint16_t maxIsoSduLen; /*!< Maximum ISO buffer size between host and controller. */ + uint16_t maxIsoPduLen; /*!< Maximum ISO PDU size between controllers. */ /* CIS */ - uint8_t maxCig; /*!< Maximum number of CIG. */ - uint8_t maxCis; /*!< Maximum number of CIS. */ - uint16_t subEvtSpaceDelay; /*!< Subevent spacing above T_MSS. */ + uint8_t maxCig; /*!< Maximum number of CIG. */ + uint8_t maxCis; /*!< Maximum number of CIS, it is shared by the CIGs. */ + uint16_t cisSubEvtSpaceDelay; /*!< Subevent spacing above T_MSS. */ + + /* BIS*/ + uint8_t maxBig; /*!< Maximum number of BIG. */ + uint8_t maxBis; /*!< Maximum number of BIS. */ /* DTM */ uint16_t dtmRxSyncMs; /*!< DTM Rx synchronization window in milliseconds. */ } PalCfgLl_t; @@ -88,7 +73,7 @@ typedef struct /*! \brief convert uint32_t to little endian byte stream, incrementing four bytes. */ #define PAL_UINT32_TO_BSTREAM(p, n) {*(p)++ = (uint8_t)(n); *(p)++ = (uint8_t)((n) >> 8); \ - *(p)++ = (uint8_t)((n) >> 16); *(p)++ = (uint8_t)((n) >> 24);} + *(p)++ = (uint8_t)((n) >> 16); *(p)++ = (uint8_t)((n) >> 24);} /************************************************************************************************** Functions @@ -102,14 +87,12 @@ typedef struct * \param phyCodedSup Coded PHY supported. * \param stableModIdxTxSup Tx stable modulation index supported. * \param stableModIdxRxSup Rx stable modulation index supported. - * - * \return None. */ /*************************************************************************************************/ void palCfgGetBlePhyFeatures(uint8_t *pPhy2mSup, uint8_t *pPhyCodedSup, - uint8_t *pStableModIdxTxSup, uint8_t *pStableModIdxRxSup) + uint8_t *pStableModIdxTxSup, uint8_t *pStableModIdxRxSup) { -#if defined(NRF52840_XXAA) +#if defined(NRF52840_XXAA) || defined(NRF52832_XXAA) *pPhy2mSup = TRUE; *pPhyCodedSup = TRUE; #else @@ -125,42 +108,55 @@ void palCfgGetBlePhyFeatures(uint8_t *pPhy2mSup, uint8_t *pPhyCodedSup, * \brief Load LL advertising configuration. * * \param pConfig Return configuration values. - * - * \return None. */ /*************************************************************************************************/ void palCfgLoadLlParams(uint8_t *pConfig) { PalCfgLl_t *pCfg = (PalCfgLl_t *)pConfig; - #if !defined(NRF52840_XXAA) - const uint16_t advDataLen = 512; - const uint16_t connDataLen = 256; - const uint16_t numTxBufs = 8; - #else - const uint16_t advDataLen = LL_MAX_ADV_DATA_LEN; - const uint16_t connDataLen = 512; - const uint16_t numTxBufs = 16; - #endif +#if defined(BOARD_NRF6832) + const uint16_t maxAdvSets = 1; + const uint16_t advDataLen = 256; + const uint16_t aclDataLen = 256; + const uint16_t maxConn = 1; + const uint16_t maxGroup = 1; + const uint16_t maxStream = 2; +#elif !defined(NRF52840_XXAA) + const uint16_t maxAdvSets = 1; + const uint16_t advDataLen = 512; + const uint16_t aclDataLen = 512; + const uint16_t maxConn = 1; + const uint16_t maxGroup = 1; + const uint16_t maxStream = 2; +#else /* Default */ + const uint16_t maxAdvSets = 6; + const uint16_t advDataLen = 1650; + const uint16_t aclDataLen = 512; + const uint16_t maxConn = 4; + const uint16_t maxGroup = 2; + const uint16_t maxStream = 6; +#endif - pCfg->maxAdvSets = LL_MAX_ADV_SETS; - pCfg->maxAdvReports = 16; + pCfg->maxAdvSets = maxAdvSets; + pCfg->maxAdvReports = 8; pCfg->maxExtAdvDataLen = advDataLen; /* pCfg->defExtAdvDataFragLen */ /* Use default. */ pCfg->auxDelayUsec = 0; pCfg->maxScanReqRcvdEvt = 4; pCfg->maxExtScanDataLen = advDataLen; - pCfg->maxConn = 4; - pCfg->maxAclLen = connDataLen; - pCfg->numTxBufs = numTxBufs; + pCfg->maxConn = maxConn; + pCfg->maxAclLen = aclDataLen; + pCfg->numTxBufs = 16; pCfg->numRxBufs = 8; - pCfg->numIsoTxBuf = 6; - pCfg->numIsoRxBuf = 6; - pCfg->maxIsoBufLen = 251; - pCfg->maxIsoPduLen = 64; - pCfg->maxCig = LL_MAX_CIG; - pCfg->maxCis = LL_MAX_CIS; - pCfg->subEvtSpaceDelay = 0; + pCfg->numIsoTxBuf = 16; + pCfg->numIsoRxBuf = 8; + pCfg->maxIsoSduLen = aclDataLen; + pCfg->maxIsoPduLen = 251; + pCfg->maxCig = maxGroup; + pCfg->maxCis = maxStream; + pCfg->cisSubEvtSpaceDelay = 0; + pCfg->maxBig = maxGroup; + pCfg->maxBis = maxStream; } /*************************************************************************************************/ @@ -168,8 +164,6 @@ void palCfgLoadLlParams(uint8_t *pConfig) * \brief Load device address. * * \param pDevAddr device address. - * - * \return None. */ /*************************************************************************************************/ void palCfgLoadBdAddress(uint8_t *pDevAddr) @@ -195,8 +189,6 @@ void palCfgLoadBdAddress(uint8_t *pDevAddr) * \brief Load 15.4 address. * * \param pDevAddr device address. - * - * \return None. */ /*************************************************************************************************/ void palCfgLoadExtMac154Address(uint8_t *pDevAddr) @@ -220,13 +212,12 @@ void palCfgLoadExtMac154Address(uint8_t *pDevAddr) * \brief Set device UUID. * * \param pBuf Return device UUID. - * - * \return None. */ /*************************************************************************************************/ void PalCfgSetDeviceUuid(uint8_t *pBuf) { - /* Not used on this platform. */ + /* Not used on this platform. */ + (void)pBuf; } /*************************************************************************************************/ @@ -234,8 +225,6 @@ void PalCfgSetDeviceUuid(uint8_t *pBuf) * \brief Load device UUID. * * \param pDevUuid Return device UUID. - * - * \return None. */ /*************************************************************************************************/ void palCfgLoadDeviceUuid(uint8_t *pDevUuid) @@ -263,12 +252,12 @@ void palCfgLoadDeviceUuid(uint8_t *pDevUuid) * \param cfgId Configuration ID. * \param pBuf Buffer. * \param len Buffer length. - * - * \return None. */ /*************************************************************************************************/ -void PalCfgLoadData(uint8_t cfgId, uint8_t *pBuf, uint32_t len) +void PalCfgLoadData(uint8_t cfgId, void *pBuf, uint32_t len) { + (void)len; + switch (cfgId) { case PAL_CFG_ID_BD_ADDR: diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_crypto.c b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_crypto.c index 0242a6d0b2..802215868f 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_crypto.c +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_crypto.c @@ -5,14 +5,15 @@ * \brief Crypto driver implementation. * * Copyright (c) 2018-2019 Arm Ltd. All Rights Reserved. - * Arm Ltd. confidential and proprietary. * + * Copyright (c) 2019-2020 Packetcraft, Inc. + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -21,24 +22,25 @@ */ /*************************************************************************************************/ -#include "stack/platform/include/pal_types.h" -#include "stack/platform/include/pal_bb_ble.h" -#if defined(NRF52840_XXAA) && defined(FEATURE_CRYPTOCELL310) && MBED_CONF_CORDIO_LL_NRF52840_CRYPTOCELL310_ACCELERATION -#include "crys_rsa_kg.h" -#include "crys_dh.h" -#include "ssi_pal_types.h" -#include "ssi_aes.h" -#include "sns_silib.h" -#include "crys_aesccm.h" -#endif +#include "pal_crypto.h" +#include "pal_bb_ble.h" +#include /* Nordic specific definitions. */ #include "nrf_ecb.h" #include "nrf.h" -#if defined(NRF52840_XXAA) && defined(FEATURE_CRYPTOCELL310) && MBED_CONF_CORDIO_LL_NRF52840_CRYPTOCELL310_ACCELERATION + +#if defined(NRF52840_XXAA) #include "nrf52840.h" +/* Crypto Cell definitions */ +#include "crys_rsa_kg.h" +#include "crys_dh.h" +#include "crys_aesccm.h" +#include "ssi_pal_types.h" +//#include "ssi_pal_mem.h" +#include "sns_silib.h" +#include "ssi_aes.h" #endif -#include /************************************************************************************************** Macros @@ -82,16 +84,8 @@ enum #endif -#ifndef LL_MAX_CONN -#define LL_MAX_CONN 4 /*!< Absolute maximum number of connections (maximum is 32). */ -#endif - -#ifndef LL_MAX_CIG -#define LL_MAX_CIG 2 /*!< Absolute maximum number of connected isochronous groups. */ -#endif - -#ifndef LL_MAX_CIS -#define LL_MAX_CIS 2 /*!< Absolute maximum number of connected isochronous streams per CIG. */ +#ifndef PAL_CRYPTO_MAX_ID +#define PAL_CRYPTO_MAX_ID 14 /*!< Absolute maximum number of cipher blocks. */ #endif #ifndef BB_ENABLE_INLINE_ENC_TX @@ -110,15 +104,13 @@ enum typedef union { uint8_t b[BB_AES_BLOCK_SIZE]; /*!< Byte access block. */ - uint32_t w[BB_AES_BLOCK_SIZE / sizeof(uint32_t)]; /*!< Word acess block. */ + uint32_t w[BB_AES_BLOCK_SIZE / sizeof(uint32_t)]; /*!< Word access block. */ struct { uint8_t flags[1]; /*!< Flags. */ uint8_t pctr[5]; /*!< Control. */ - uint8_t iv[8]; /*!< iv. */ - uint8_t iMSO[1]; /*!< iMSO. */ - uint8_t iLSO[1]; /*!< iLSO. */ + uint8_t iv[8]; /*!< IV. */ } f; /*!< Field access. */ } palCryptoCipherBlk_t; @@ -144,7 +136,7 @@ typedef union **************************************************************************************************/ /*! \brief Cipher block context. */ -static palCryptoCipherBlk_t palCryptoCipherBlkTbl[LL_MAX_CONN+LL_MAX_CIS*LL_MAX_CIG][PAL_CRYPTO_MODE_TOTAL]; +static palCryptoCipherBlk_t palCryptoCipherBlkTbl[PAL_CRYPTO_MAX_ID][PAL_CRYPTO_MODE_TOTAL]; /*! \brief Nordic ECB encryption data block. */ static palCryptoEcbData_t palCryptoEcb; @@ -153,11 +145,104 @@ static palCryptoEcbData_t palCryptoEcb; Functions **************************************************************************************************/ +/*************************************************************************************************/ +/*! + * \brief XOR block. + */ +/*************************************************************************************************/ +static void palXor128(const uint8_t *pInA, const uint8_t *pInB, uint8_t *pOut) +{ + const uint32_t *pInA_w = (uint32_t *)pInA; + const uint32_t *pInB_w = (uint32_t *)pInB; + uint32_t *pOut_w = (uint32_t *)pOut; + + pOut_w[0] = pInA_w[0] ^ pInB_w[0]; + pOut_w[1] = pInA_w[1] ^ pInB_w[1]; + pOut_w[2] = pInA_w[2] ^ pInB_w[2]; + pOut_w[3] = pInA_w[3] ^ pInB_w[3]; +} + +/*************************************************************************************************/ +/*! + * \brief Shift block left by 1 bit. + */ +/*************************************************************************************************/ +void palShiftLeft128(const uint8_t *pIn, uint8_t *pOut) +{ + uint8_t of = 0; + + for (int i = 15; i >= 0; i--) + { + pOut[i] = pIn[i] << 1; + pOut[i] |= of; + + of = pIn[i] >> 7; + } +} + +/*************************************************************************************************/ +/*! + * \brief Generate subkeys. + */ +/*************************************************************************************************/ +static void palGenSubkey(const uint8_t *pKey, uint8_t *pK1, uint8_t *pK2) +{ + static const uint8_t Rb[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87 }; + + unsigned char L[16]; + unsigned char Z[16] = { 0 }; + unsigned char t[16]; + + while (nrf_ecb_crypt(L, Z) != TRUE); + + if ((L[0] & 0x80) == 0) + { + palShiftLeft128(L, pK1); + } + else + { + palShiftLeft128(L, t); + palXor128(t, Rb, pK1); + } + + if ((pK1[0] & 0x80) == 0) + { + palShiftLeft128(pK1, pK2); + } + else + { + palShiftLeft128(pK1, t); + palXor128(t, Rb, pK2); + } +} + +/*************************************************************************************************/ +/*! + * \brief Pad block. + */ +/*************************************************************************************************/ +static void palPadBlock(const uint8_t *pIn, uint8_t *pOut, uint8_t len) +{ + for (size_t i = 0; i < BB_AES_BLOCK_SIZE; i++) + { + if (i < len) + { + pOut[i] = pIn[i]; + } + else if (i == len) + { + pOut[i] = 0x80; + } + else + { + pOut[i] = 0x00; + } + } +} + /*************************************************************************************************/ /*! * \brief Execute Nordic AES ECB. - * - * \return None. */ /*************************************************************************************************/ static inline void palCryptoExecuteAesEcb(void) @@ -184,8 +269,6 @@ static inline void palCryptoExecuteAesEcb(void) * \brief Load Nordic AES ECB data. * * \param pEnc Encryption parameters. - * - * \return None. */ /*************************************************************************************************/ static inline void palCryptoLoadEcbData(PalCryptoEnc_t *pEnc) @@ -207,11 +290,9 @@ static inline void palCryptoLoadEcbData(PalCryptoEnc_t *pEnc) * \param pMic Inplace MIC buffer. * \param pBuf Inplace cleartext/ciphertext buffer. * \param pldLen Length of buffer payload. - * - * \return None. */ /*************************************************************************************************/ -static void PalCryptPdu(palCryptoCipherBlk_t *pAx, uint8_t *pMic, uint8_t *pBuf, uint16_t pldLen) +static void palCryptoPdu(palCryptoCipherBlk_t *pAx, uint8_t *pMic, uint8_t *pBuf, uint16_t pldLen) { /* X_1 := ECB(K, A_0) */ palCryptoEcb.w.clear[0] = pAx->w[0]; @@ -260,8 +341,6 @@ static void PalCryptPdu(palCryptoCipherBlk_t *pAx, uint8_t *pMic, uint8_t *pBuf, * \param pHdr Header buffer. * \param pBuf Inplace cleartext/ciphertext buffer. * \param pldLen Length of payload. - * - * \return None. */ /*************************************************************************************************/ static void palCryptoAuthPdu(uint8_t type, palCryptoCipherBlk_t *pBx, uint8_t *pMic, uint8_t *pHdr, uint8_t *pBuf, uint16_t pldLen) @@ -334,8 +413,6 @@ static void palCryptoAuthPdu(uint8_t type, palCryptoCipherBlk_t *pBx, uint8_t *p * \brief Increment cipher block packet counter. * * \param pCb Cipher block. - * - * \return None. */ /*************************************************************************************************/ static inline void palCryptoIncPktCnt(palCryptoCipherBlk_t *pCb) @@ -367,8 +444,6 @@ static inline void palCryptoIncPktCnt(palCryptoCipherBlk_t *pCb) * * \param pCb Cipher block. * \param evtCnt Connection event counter. - * - * \return None. */ /*************************************************************************************************/ static inline void palCryptoLoadPktCnt(palCryptoCipherBlk_t *pCb, uint16_t evtCnt) @@ -389,11 +464,9 @@ static inline void palCryptoLoadPktCnt(palCryptoCipherBlk_t *pCb, uint16_t evtCn * * \param pCb Cipher block. * \param evtCnt Connection event counter. - * - * \return None. */ /*************************************************************************************************/ -static inline void palCryptoLoadCisPktCnt(palCryptoCipherBlk_t *pCb, uint64_t pktCnt) +static inline void palCryptoLoadIsoPktCnt(palCryptoCipherBlk_t *pCb, uint64_t pktCnt) { /* Pack connEventCounter. */ pCb->f.pctr[0] = pktCnt >> 0; @@ -414,8 +487,6 @@ static inline void palCryptoLoadCisPktCnt(palCryptoCipherBlk_t *pCb, uint64_t pk * \param pOut Output data. * \param pIn Input data. * - * \return None. - * * \note Packet length is 16 bytes. */ /*************************************************************************************************/ @@ -455,14 +526,86 @@ void PalCryptoAesEcb(const uint8_t *pKey, uint8_t *pOut, const uint8_t *pIn) memcpy(pOut, revOut, sizeof(revOut)); } +/*************************************************************************************************/ +/*! + * \fn PalCryptoAesCmac + * + * \brief Calculate AES CMAC. + * + * \param pKey Encryption key. + * \param pOut Output data. + * \param pIn Input data. + * + * \note Packet length is 16 bytes. + */ +/*************************************************************************************************/ +void PalCryptoAesCmac(const uint8_t *pKey, uint8_t *pOut, const uint8_t *pIn, uint16_t len) +{ + uint32_t alignKey[4]; + memcpy(alignKey, pKey, sizeof(alignKey)); + + uint32_t revKey[4]; + revKey[0] = __REV(alignKey[3]); + revKey[1] = __REV(alignKey[2]); + revKey[2] = __REV(alignKey[1]); + revKey[3] = __REV(alignKey[0]); + + uint32_t *pIn_w = (uint32_t *)pIn; + uint32_t revIn[4]; + if (len == 16) + { + revIn[0] = __REV(pIn_w[3]); + revIn[1] = __REV(pIn_w[2]); + revIn[2] = __REV(pIn_w[1]); + revIn[3] = __REV(pIn_w[0]); + } + else + { + revIn[0] = __REV(pIn_w[0]); + } + + nrf_ecb_init(); + nrf_ecb_set_key((uint8_t *)revKey); + + uint8_t K1[BB_AES_BLOCK_SIZE], K2[BB_AES_BLOCK_SIZE]; + palGenSubkey(pKey, K1, K2); + + uint32_t alignM[4]; + if (len == BB_AES_BLOCK_SIZE) + { + /* Complete block. */ + palXor128((uint8_t *)revIn, K1, (uint8_t *)alignM); + } + else + { + uint32_t alignInPad[4]; + /* Partial block. */ + palPadBlock((uint8_t *)revIn, (uint8_t *)alignInPad, len); + palXor128((uint8_t *)alignInPad, K2, (uint8_t *)alignM); + } + + const uint32_t alignX[4] = { 0 }; + uint32_t alignY[4]; + palXor128((const uint8_t *)alignX, (uint8_t *)alignM, (uint8_t *)alignY); + + uint32_t alignOut[4]; + while (nrf_ecb_crypt((uint8_t *)alignOut, (uint8_t *)alignY) != TRUE); + + uint32_t revOut[4]; + revOut[0] = __REV(alignOut[3]); + revOut[1] = __REV(alignOut[2]); + revOut[2] = __REV(alignOut[1]); + revOut[3] = __REV(alignOut[0]); + + memcpy(pOut, revOut, sizeof(revOut)); +} + /*************************************************************************************************/ /*! * \brief Generate cryptographic grade random number. * * \param pBuf Buffer to store random number. * \param len Number of bytes. - * - * \return None. */ /*************************************************************************************************/ void PalCryptoGenerateRandomNumber(uint8_t *pBuf, uint8_t len) @@ -488,17 +631,21 @@ void PalCryptoGenerateRandomNumber(uint8_t *pBuf, uint8_t len) * \param id Context ID. * \param localDir Direction bit of local device (0=slave, 1=master). * - * \return None. - * * This routine completes the transformation in a blocking manner. * * \note Leave this implementation empty if inline hardware encryption is available. */ /*************************************************************************************************/ -void PalCryptoAesSetupCipherBlock(PalCryptoEnc_t *pEnc, uint8_t id, uint8_t localDir) +void PalCryptoAesEnable(PalCryptoEnc_t *pEnc, uint8_t id, uint8_t localDir) { unsigned int mode; + if (id > PAL_CRYPTO_MAX_ID) + { + /* TODO handle error condition */ + return; + } + /* Clear */ memset(&palCryptoCipherBlkTbl[id], 0, sizeof(palCryptoCipherBlkTbl[id])); @@ -527,10 +674,6 @@ void PalCryptoAesSetupCipherBlock(PalCryptoEnc_t *pEnc, uint8_t id, uint8_t loca /* Store context. */ pEnc->pEncryptCtx = &palCryptoCipherBlkTbl[id][PAL_CRYPTO_MODE_ENC]; pEnc->pDecryptCtx = &palCryptoCipherBlkTbl[id][PAL_CRYPTO_MODE_DEC]; - -#if (BB_ENABLE_INLINE_ENC_TX || BB_ENABLE_INLINE_DEC_RX) - PalBbBleInlineEncryptDecryptSetDirection(localDir); -#endif } /*************************************************************************************************/ @@ -571,16 +714,16 @@ bool_t PalCryptoAesCcmEncrypt(PalCryptoEnc_t *pEnc, uint8_t *pHdr, uint8_t *pBuf pHdr[BB_DATA_PDU_LEN_OFFSET] += PAL_CRYPTO_LL_DATA_MIC_LEN; /* Add length of MIC to payload. */ } - if ((pEnc->nonceMode == PAL_BB_NONCE_MODE_EVT_CNTR) && + if ((pEnc->nonceMode == PAL_BB_NONCE_MODE_EXT16_CNTR) && (pEnc->pEventCounter)) { palCryptoLoadPktCnt(pCb, *pEnc->pEventCounter + 1); } - if ((pEnc->nonceMode == PAL_BB_NONCE_MODE_CIS_CNTR) && - (pEnc->pCisTxPktCounter)) + if ((pEnc->nonceMode == PAL_BB_NONCE_MODE_EXT64_CNTR) && + (pEnc->pTxPktCounter)) { - palCryptoLoadCisPktCnt(pCb, *pEnc->pCisTxPktCounter); + palCryptoLoadIsoPktCnt(pCb, *pEnc->pTxPktCounter); } palCryptoLoadEcbData(pEnc); @@ -590,7 +733,7 @@ bool_t PalCryptoAesCcmEncrypt(PalCryptoEnc_t *pEnc, uint8_t *pHdr, uint8_t *pBuf palCryptoAuthPdu(pEnc->type, pCb, pMic, pHdr, pBuf, pldLen); } - PalCryptPdu(pCb, pMic, pBuf, pldLen); + palCryptoPdu(pCb, pMic, pBuf, pldLen); if (pEnc->nonceMode == PAL_BB_NONCE_MODE_PKT_CNTR) { @@ -646,7 +789,7 @@ bool_t PalCryptoAesCcmDecrypt(PalCryptoEnc_t *pEnc, uint8_t *pBuf) } uint8_t *pMic = pBuf + pldLen; - if ((pEnc->nonceMode == PAL_BB_NONCE_MODE_EVT_CNTR) && + if ((pEnc->nonceMode == PAL_BB_NONCE_MODE_EXT16_CNTR) && (pEnc->pEventCounter)) { /* Synchronized event counter stored in packet headroom. */ @@ -657,14 +800,14 @@ bool_t PalCryptoAesCcmDecrypt(PalCryptoEnc_t *pEnc, uint8_t *pBuf) palCryptoLoadPktCnt(pCb, eventCounter); } - if ((pEnc->nonceMode == PAL_BB_NONCE_MODE_CIS_CNTR) && - (pEnc->pCisRxPktCounter)) + if ((pEnc->nonceMode == PAL_BB_NONCE_MODE_EXT64_CNTR) && + (pEnc->pRxPktCounter)) { - palCryptoLoadCisPktCnt(pCb, *pEnc->pCisRxPktCounter - 1); /* Rx counter is already incremented when packet is received in the LCTR layer. Need to decrement one here. */ + palCryptoLoadIsoPktCnt(pCb, *pEnc->pRxPktCounter); } palCryptoLoadEcbData(pEnc); - PalCryptPdu(pCb, pMic, pBuf, pldLen); + palCryptoPdu(pCb, pMic, pBuf, pldLen); if (pEnc->enaAuth) { @@ -691,7 +834,7 @@ bool_t PalCryptoAesCcmDecrypt(PalCryptoEnc_t *pEnc, uint8_t *pBuf) return TRUE; } -#if defined(NRF52840_XXAA) && defined(FEATURE_CRYPTOCELL310) && MBED_CONF_CORDIO_LL_NRF52840_CRYPTOCELL310_ACCELERATION +#if defined(NRF52840_XXAA) /*************************************************************************************************/ /*! * \brief Execute the CCM-Mode encryption algorithm. @@ -719,6 +862,10 @@ void PalCryptoCcmEnc(const uint8_t *pKey, uint8_t *pNonce, uint8_t *pPlainText, CRYS_AESCCM_Key_t key; + (void)handlerId; + (void)param; + (void)event; + /* Copy key */ memcpy(key, pKey, SEC_CCM_KEY_LEN); @@ -756,6 +903,10 @@ uint32_t PalCryptoCcmDec(const uint8_t *pKey, uint8_t *pNonce, uint8_t *pCypherT CRYS_AESCCM_Key_t key; + (void)handlerId; + (void)param; + (void)event; + /* Copy key */ memcpy(key, pKey, SEC_CCM_KEY_LEN); @@ -773,8 +924,6 @@ uint32_t PalCryptoCcmDec(const uint8_t *pKey, uint8_t *pNonce, uint8_t *pCypherT /*************************************************************************************************/ /*! * \brief Called to initialize CCM-Mode security. - * - * \return None. */ /*************************************************************************************************/ void PalCryptoInit(void) @@ -787,8 +936,6 @@ void PalCryptoInit(void) /*************************************************************************************************/ /*! * \brief Called to De-initialize CCM-Mode security. - * - * \return None. */ /*************************************************************************************************/ void PalCryptoDeInit(void) @@ -806,8 +953,6 @@ void PalCryptoDeInit(void) * * \param pEnc Encryption parameters. * \param pktCnt Counter value. - * - * \return None. */ /*************************************************************************************************/ #if (BB_ENABLE_INLINE_ENC_TX) @@ -823,8 +968,6 @@ void PalCryptoSetEncryptPacketCount(PalCryptoEnc_t *pEnc, uint64_t pktCnt) * * \param pEnc Encryption parameters. * \param pktCnt Counter value. - * - * \return None. */ /*************************************************************************************************/ #if (BB_ENABLE_INLINE_DEC_RX) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_led.c b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_led.c index 5b6da04d84..c114b63262 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_led.c +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_led.c @@ -5,14 +5,15 @@ * \brief LED driver implementation. * * Copyright (c) 2018-2019 Arm Ltd. All Rights Reserved. - * Arm Ltd. confidential and proprietary. * + * Copyright (c) 2019-2020 Packetcraft, Inc. + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -21,207 +22,126 @@ */ /*************************************************************************************************/ -#include "stack/platform/include/pal_led.h" +#include "pal_led.h" + +#if defined(BOARD_PCA10056) #include "boards.h" -#include "stack/platform/include/pal_types.h" - -/************************************************************************************************** - Macros -**************************************************************************************************/ - -#define PAL_LED0_MASK 0x00002000 -#define PAL_LED1_MASK 0x00004000 -#define PAL_LED2_MASK 0x00008000 -#define PAL_LED3_MASK 0x00010000 - -/*! \brief LED masks. */ -#if (AUDIO_CAPE == 1) - -#define PAL_LED_AUDIO_LED1_MASK 0x00000002 -#define PAL_LED_AUDIO_LED2_MASK 0x00000004 -#define PAL_LED_AUDIO_LED3_MASK 0x00000008 -#define PAL_LED_AUDIO_LED4_MASK 0x00000010 -#define PAL_LED_AUDIO_LED5_MASK 0x00000020 -#define PAL_LED_AUDIO_LED6_MASK 0x00000040 - -#define PAL_LED_P0_MASK 0x01E000 -#define PAL_LED_P1_MASK 0x00007E - -#else -#define PAL_LED_P0_MASK 0x01E000 -#define PAL_LED_P1_MASK 0x000000 - +#include "nrfx_gpiote.h" #endif -/*! \brief Invalid LED mask. */ -#define PAL_LED_INVALID_MASK 0xFF - -/*! \brief LED count using GPIO P0. */ -#define PAL_LED_COUNT_P0 0x04 - -/*! \brief I/O Expander definitions */ -enum -{ - PAL_LED_IO_EXP_SUB_ADDR = 0x06 /*!< Lower 3 bit of I/O expander address connected with LEDs. */ -}; - -/*! \brief I/O Expander accessories */ -enum -{ - PAL_LED_IO_EXP_CONFIG = 0x00 /*!< LED3 to LED10 are defined as outputs.*/ -}; - -#ifdef DEBUG - -/*! \brief Parameter check. */ -#define PAL_LED_PARAM_CHECK(expr) { if (!(expr)) { return; } } - -/*! \brief Parameter check, with return value. */ -#define PAL_LED_PARAM_CHECK_RET(expr, rv) { if (!(expr)) { return (rv); } } - -#else - -/*! \brief Parameter check (disabled). */ -#define PAL_LED_PARAM_CHECK(expr) - -/*! \brief Parameter check, with return value (disabled). */ -#define PAL_LED_PARAM_CHECK_RET(expr, rv) - +#if defined(BOARD_NRF6832) +#include "lp5562.h" #endif /************************************************************************************************** Functions: Initialization **************************************************************************************************/ +#if defined(BOARD_NRF6832) /*************************************************************************************************/ /*! - * \brief Get LED pin number from LED ID. + * \brief Map LED ID to physical LED. * * \param ledId LED ID. * - * \return LED pin mask. + * \return Mapped physical LED. */ /*************************************************************************************************/ -static uint32_t palLedGetPinMask(uint8_t ledId) +static int palLedMapId(uint8_t ledId) { - uint32_t ledMask = PAL_LED_INVALID_MASK; - switch (ledId) { - case PAL_LED_ID_CPU_ACTIVE: - ledMask = PAL_LED1_MASK; - break; - + /* Predefined */ case PAL_LED_ID_ERROR: - ledMask = PAL_LED3_MASK; + return LP5562_LED_W; /* bottom */ break; + /* Application defined */ case 0: - ledMask = PAL_LED0_MASK; - break; + return LP5562_LED_R; /* top/left */ case 1: - ledMask = PAL_LED1_MASK; - break; + return LP5562_LED_G; /* top/middle */ case 2: - ledMask = PAL_LED2_MASK; - break; - case 3: - ledMask = PAL_LED3_MASK; - break; - -#if (AUDIO_CAPE == 1) - case 4: - ledMask = PAL_LED_AUDIO_LED1_MASK; - break; - case 5: - ledMask = PAL_LED_AUDIO_LED2_MASK; - break; - case 6: - ledMask = PAL_LED_AUDIO_LED3_MASK; - break; - case 7: - ledMask = PAL_LED_AUDIO_LED4_MASK; - break; - case 8: - ledMask = PAL_LED_AUDIO_LED5_MASK; - break; - case 9: - ledMask = PAL_LED_AUDIO_LED6_MASK; - break; -#endif + return LP5562_LED_B; /* top/right */ + /* Ignore */ + case PAL_LED_ID_CPU_ACTIVE: default: - ledMask = PAL_LED_INVALID_MASK; break; } - return ledMask; + return -1; } +#endif /*************************************************************************************************/ /*! * \brief Initialize LEDs. - * - * \return None. */ /*************************************************************************************************/ void PalLedInit(void) { - nrf_gpio_port_dir_output_set(NRF_P0, PAL_LED_P0_MASK); - nrf_gpio_port_out_set(NRF_P0, PAL_LED_P0_MASK); -#if (GPIO_COUNT > 1) - nrf_gpio_port_dir_output_set(NRF_P1, PAL_LED_P1_MASK); - nrf_gpio_port_out_set(NRF_P1, PAL_LED_P1_MASK); +#if defined(BOARD_PCA10056) + nrfx_err_t err; + + if (!nrfx_gpiote_is_init()) + { + err = nrfx_gpiote_init(); + + if (err != NRFX_SUCCESS) + { + return; + } + } + + nrfx_gpiote_out_config_t cfg = NRFX_GPIOTE_CONFIG_OUT_SIMPLE(true); + + nrfx_gpiote_out_init(LED_1, &cfg); + nrfx_gpiote_out_init(LED_2, &cfg); + nrfx_gpiote_out_init(LED_3, &cfg); + nrfx_gpiote_out_init(LED_4, &cfg); +#endif + +#if AUDIO_CAPE + nrfx_gpiote_out_init(NRF_GPIO_PIN_MAP(1, 1), &cfg); + nrfx_gpiote_out_init(NRF_GPIO_PIN_MAP(1, 2), &cfg); + nrfx_gpiote_out_init(NRF_GPIO_PIN_MAP(1, 3), &cfg); + nrfx_gpiote_out_init(NRF_GPIO_PIN_MAP(1, 4), &cfg); + nrfx_gpiote_out_init(NRF_GPIO_PIN_MAP(1, 5), &cfg); + nrfx_gpiote_out_init(NRF_GPIO_PIN_MAP(1, 6), &cfg); +#endif + +#if defined(BOARD_NRF6832) + lp5562_LedInit(); #endif } /*************************************************************************************************/ /*! * \brief De-initialize LEDs. - * - * \return None. */ /*************************************************************************************************/ void PalLedDeInit(void) { - nrf_gpio_port_dir_input_set(NRF_P0, PAL_LED_P0_MASK); -#if (GPIO_COUNT > 1) - nrf_gpio_port_dir_input_set(NRF_P1, PAL_LED_P1_MASK); +#if defined(BOARD_PCA10056) + nrfx_gpiote_out_uninit(LED_1); + nrfx_gpiote_out_uninit(LED_2); + nrfx_gpiote_out_uninit(LED_3); + nrfx_gpiote_out_uninit(LED_4); #endif -} -/*************************************************************************************************/ -/*! - * \brief Set multiple LEDs on. - * - * \param mask LED mask. - * - * \return None. - * - */ -/*************************************************************************************************/ -void PalLedOnGroup(uint32_t mask) -{ - PAL_LED_PARAM_CHECK(mask); +#if defined(BOARD_NRF6832) + lp5562_LedDeInit(); +#endif - nrf_gpio_port_out_clear(NRF_P0, mask); -} - -/*************************************************************************************************/ -/*! - * \brief Set multiple LEDs off. - * - * \param mask LED mask. - * - * \return None. - * - */ -/*************************************************************************************************/ -void PalLedOffGroup(uint32_t mask) -{ - PAL_LED_PARAM_CHECK(mask); - - nrf_gpio_port_out_set(NRF_P0, mask); +#if AUDIO_CAPE + nrfx_gpiote_out_uninit(NRF_GPIO_PIN_MAP(1, 1)); + nrfx_gpiote_out_uninit(NRF_GPIO_PIN_MAP(1, 2)); + nrfx_gpiote_out_uninit(NRF_GPIO_PIN_MAP(1, 3)); + nrfx_gpiote_out_uninit(NRF_GPIO_PIN_MAP(1, 4)); + nrfx_gpiote_out_uninit(NRF_GPIO_PIN_MAP(1, 5)); + nrfx_gpiote_out_uninit(NRF_GPIO_PIN_MAP(1, 6)); +#endif } /*************************************************************************************************/ @@ -229,24 +149,61 @@ void PalLedOffGroup(uint32_t mask) * \brief Set LED on. * * \param ledId LED ID. - * - * \return None. - * */ /*************************************************************************************************/ void PalLedOn(uint8_t ledId) { - uint32_t ledMask = palLedGetPinMask(ledId); - PAL_LED_PARAM_CHECK(ledMask != PAL_LED_INVALID_MASK); - - if ((ledId < PAL_LED_COUNT_P0) || (ledId >= PAL_LED_ID_CPU_ACTIVE)) +#if defined(BOARD_PCA10056) + switch (ledId) { - nrf_gpio_port_out_clear(NRF_P0, ledMask); + case PAL_LED_ID_CPU_ACTIVE: + nrfx_gpiote_out_clear(LED_2); + break; + case PAL_LED_ID_ERROR: + nrfx_gpiote_out_clear(LED_4); + break; + case 0: + nrfx_gpiote_out_clear(LED_1); + break; + case 1: + nrfx_gpiote_out_clear(LED_3); + break; + default: + break; } -#if (GPIO_COUNT > 1) - else +#endif + +#if defined(BOARD_NRF6832) + int ledPin = palLedMapId(ledId); + if (ledPin >= 0) { - nrf_gpio_port_out_clear(NRF_P1, ledMask); + lp5562_LedOn(ledPin); + } +#endif + +#if AUDIO_CAPE + switch (ledId) + { + case 2: + nrfx_gpiote_out_clear(NRF_GPIO_PIN_MAP(1, 1)); + break; + case 3: + nrfx_gpiote_out_clear(NRF_GPIO_PIN_MAP(1, 2)); + break; + case 4: + nrfx_gpiote_out_clear(NRF_GPIO_PIN_MAP(1, 3)); + break; + case 5: + nrfx_gpiote_out_clear(NRF_GPIO_PIN_MAP(1, 4)); + break; + case 6: + nrfx_gpiote_out_clear(NRF_GPIO_PIN_MAP(1, 5)); + break; + case 7: + nrfx_gpiote_out_clear(NRF_GPIO_PIN_MAP(1, 6)); + break; + default: + break; } #endif } @@ -256,24 +213,61 @@ void PalLedOn(uint8_t ledId) * \brief Set LED off. * * \param ledId LED ID. - * - * \return None. - * */ /*************************************************************************************************/ void PalLedOff(uint8_t ledId) { - uint32_t ledMask = palLedGetPinMask(ledId); - PAL_LED_PARAM_CHECK(ledMask != PAL_LED_INVALID_MASK); - - if ((ledId < PAL_LED_COUNT_P0) || (ledId >= PAL_LED_ID_CPU_ACTIVE)) +#if defined(BOARD_PCA10056) + switch (ledId) { - nrf_gpio_port_out_set(NRF_P0, ledMask); + case PAL_LED_ID_CPU_ACTIVE: + nrfx_gpiote_out_set(LED_2); + break; + case PAL_LED_ID_ERROR: + nrfx_gpiote_out_set(LED_4); + break; + case 0: + nrfx_gpiote_out_set(LED_1); + break; + case 1: + nrfx_gpiote_out_set(LED_3); + break; + default: + break; } -#if (GPIO_COUNT > 1) - else +#endif + +#if defined(BOARD_NRF6832) + int ledPin = palLedMapId(ledId); + if (ledPin >= 0) { - nrf_gpio_port_out_set(NRF_P1, ledMask); + lp5562_LedOff(ledPin); + } +#endif + +#if AUDIO_CAPE + switch (ledId) + { + case 2: + nrfx_gpiote_out_set(NRF_GPIO_PIN_MAP(1, 1)); + break; + case 3: + nrfx_gpiote_out_set(NRF_GPIO_PIN_MAP(1, 2)); + break; + case 4: + nrfx_gpiote_out_set(NRF_GPIO_PIN_MAP(1, 3)); + break; + case 5: + nrfx_gpiote_out_set(NRF_GPIO_PIN_MAP(1, 4)); + break; + case 6: + nrfx_gpiote_out_set(NRF_GPIO_PIN_MAP(1, 5)); + break; + case 7: + nrfx_gpiote_out_set(NRF_GPIO_PIN_MAP(1, 6)); + break; + default: + break; } #endif } diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_rtc.c b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_rtc.c index ebdf3d95f5..084485e019 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_rtc.c +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_rtc.c @@ -5,50 +5,139 @@ * \brief Tickless timer implementation. * * Copyright (c) 2013-2018 Arm Ltd. All Rights Reserved. - * Arm Ltd. confidential and proprietary. * + * Copyright (c) 2019-2020 Packetcraft, Inc. + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. + * + * Notes: + * + * This is timer driver is used by wsf_timer.c and pal_timer.c. + * */ /*************************************************************************************************/ #include "nrf.h" -#include "stack/platform/include/pal_rtc.h" +#include "pal_rtc.h" +#include "pal_timer.h" + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +#ifdef DEBUG + +/*! \brief Parameter and state check. */ +#define PAL_RTC_CHECK(expr) { if (!(expr)) { while(1); } } + +#else + +/*! \brief Parameter and state check (disabled). */ +#define PAL_RTC_CHECK(expr) + +#endif + +#define RTC_TIMER_TOTAL_CHANNEL 4 + +/************************************************************************************************** + Variables +**************************************************************************************************/ + +static palRtcIrqCback_t palRtcTimerCback[RTC_TIMER_TOTAL_CHANNEL]; + +/*************************************************************************************************/ +/*! + * \brief Function for clearing rtc events. + * + * \param channelId Channel ID Number. + */ +/*************************************************************************************************/ +void PalRtcClearCompareEvents(uint8_t channelId) +{ + PAL_RTC_CHECK(channelId < RTC_TIMER_TOTAL_CHANNEL); + + NRF_RTC1->EVENTS_COMPARE[channelId] = 0; + (void)NRF_RTC1->EVENTS_COMPARE[channelId]; +} /*************************************************************************************************/ /*! * \brief Function for starting the RTC timer. * - * \return None. + * \param channelId Channel ID Number. */ /*************************************************************************************************/ -void PalRtcEnableCompareIrq(void) +void PalRtcEnableCompareIrq(uint8_t channelId) { - NRF_RTC0->EVENTS_COMPARE[0] = 0; - NRF_RTC0->INTENSET = RTC_INTENSET_COMPARE0_Msk; - NRF_RTC0->EVTENSET = RTC_EVTENSET_COMPARE0_Msk; + PAL_RTC_CHECK(channelId < RTC_TIMER_TOTAL_CHANNEL); + + PalRtcClearCompareEvents(channelId); + + switch (channelId) + { + case 0: + NRF_RTC1->INTENSET = RTC_INTENSET_COMPARE0_Msk; + NRF_RTC1->EVTENSET = RTC_EVTENSET_COMPARE0_Msk; + break; + case 1: + NRF_RTC1->INTENSET = RTC_INTENSET_COMPARE1_Msk; + NRF_RTC1->EVTENSET = RTC_EVTENSET_COMPARE1_Msk; + break; + case 2: + NRF_RTC1->INTENSET = RTC_INTENSET_COMPARE2_Msk; + NRF_RTC1->EVTENSET = RTC_EVTENSET_COMPARE2_Msk; + break; + case 3: + NRF_RTC1->INTENSET = RTC_INTENSET_COMPARE3_Msk; + NRF_RTC1->EVTENSET = RTC_EVTENSET_COMPARE3_Msk; + break; + default: + break; + } } /*************************************************************************************************/ /*! * \brief Function for stopping the RTC timer. * - * \return None. + * \param channelId Channel ID Number. */ /*************************************************************************************************/ -void PalRtcDisableCompareIrq(void) +void PalRtcDisableCompareIrq(uint8_t channelId) { - NRF_RTC0->INTENCLR = RTC_INTENCLR_COMPARE0_Msk; - NRF_RTC0->EVTENCLR = RTC_EVTENCLR_COMPARE0_Msk; + PAL_RTC_CHECK(channelId < RTC_TIMER_TOTAL_CHANNEL); + + switch (channelId) + { + case 0: + NRF_RTC1->INTENCLR = RTC_INTENCLR_COMPARE0_Msk; + NRF_RTC1->EVTENCLR = RTC_EVTENCLR_COMPARE0_Msk; + break; + case 1: + NRF_RTC1->INTENCLR = RTC_INTENCLR_COMPARE1_Msk; + NRF_RTC1->EVTENCLR = RTC_EVTENCLR_COMPARE1_Msk; + break; + case 2: + NRF_RTC1->INTENCLR = RTC_INTENCLR_COMPARE2_Msk; + NRF_RTC1->EVTENCLR = RTC_EVTENCLR_COMPARE2_Msk; + break; + case 3: + NRF_RTC1->INTENCLR = RTC_INTENCLR_COMPARE3_Msk; + NRF_RTC1->EVTENCLR = RTC_EVTENCLR_COMPARE3_Msk; + break; + default: + break; + } } /*************************************************************************************************/ @@ -63,81 +152,109 @@ uint32_t PalRtcCounterGet(void) NRF_CLOCK->EVENTS_LFCLKSTARTED = 0; NRF_CLOCK->TASKS_LFCLKSTART = 1; while (NRF_CLOCK->EVENTS_LFCLKSTARTED == 0) {} - NRF_RTC0->TASKS_STOP = 0; + NRF_RTC1->TASKS_STOP = 0; - return NRF_RTC0->COUNTER; + return NRF_RTC1->COUNTER; } /*************************************************************************************************/ /*! * \brief Set the RTC capture compare value. * + * \param channelId Channel ID Number. * \param value Set new value for compare value. - * - * \return None */ /*************************************************************************************************/ -void PalRtcCompareSet(uint32_t value) +void PalRtcCompareSet(uint8_t channelId, uint32_t value) { - NRF_RTC0->CC[0] = value; + PAL_RTC_CHECK(channelId < RTC_TIMER_TOTAL_CHANNEL); + NRF_RTC1->CC[channelId] = value; } /*************************************************************************************************/ /*! * \brief Get the current value of the RTC capture compare. * + * \param channelId Channel ID Number. + * * \return Current value of the capture compare. */ /*************************************************************************************************/ -uint32_t PalRtcCompareGet(void) +uint32_t PalRtcCompareGet(uint8_t channelId) { - return NRF_RTC0->CC[0]; + PAL_RTC_CHECK(channelId < RTC_TIMER_TOTAL_CHANNEL); + return NRF_RTC1->CC[channelId]; } /*************************************************************************************************/ /*! * \brief RTC interrupt handler. * - * \return None. - * * This handler stores the RTC start time which is used as a reference to compute the receive * packet timestamp using the HFCLK. * */ /*************************************************************************************************/ -void RTC0_IRQHandler(void) +void RTC1_IRQHandler(void) { - if (NRF_RTC0->EVENTS_COMPARE[0]) + for (unsigned int channelId = 0; channelId < RTC_TIMER_TOTAL_CHANNEL; channelId++) { - /* clear the interrupt */ - NRF_RTC0->EVENTS_COMPARE[0] = 0; - (void)NRF_RTC0->EVENTS_COMPARE[0]; /* wait for write buffer to empty */ + if (NRF_RTC1->EVENTS_COMPARE[channelId]) + { + PalRtcClearCompareEvents(channelId); + + if (palRtcTimerCback[channelId]) + { + palRtcTimerCback[channelId](); + } + } } } /*************************************************************************************************/ /*! * \brief Tickless timer initialization routine. - * - * \return None. */ /*************************************************************************************************/ void PalRtcInit(void) { /* Stop RTC to prevent any running timers from expiring. */ - PalRtcDisableCompareIrq(); + for (unsigned int channelId = 0; channelId < RTC_TIMER_TOTAL_CHANNEL; channelId++) + { + PalRtcDisableCompareIrq(channelId); + } + + /* Configure low-frequency clock. */ + NRF_CLOCK->LFCLKSRC = (CLOCK_LFCLKSRC_SRC_Xtal << CLOCK_LFCLKSRC_SRC_Pos); NRF_CLOCK->EVENTS_LFCLKSTARTED = 0; NRF_CLOCK->TASKS_LFCLKSTART = 1; - while (NRF_CLOCK->EVENTS_LFCLKSTARTED == 0) {} - NRF_RTC0->TASKS_STOP = 0; + while (NRF_CLOCK->EVENTS_LFCLKSTARTED == 0) { } + NRF_RTC1->TASKS_STOP = 0; - NRF_RTC0->TASKS_STOP = 1; - NRF_RTC0->TASKS_CLEAR = 1; - NRF_RTC0->PRESCALER = 0; /* clear prescaler */ - NRF_RTC0->TASKS_START = 1; + NRF_RTC1->TASKS_STOP = 1; + NRF_RTC1->TASKS_CLEAR = 1; + NRF_RTC1->PRESCALER = 0; /* clear prescaler */ + NRF_RTC1->TASKS_START = 1; - NVIC_SetPriority(RTC0_IRQn, 0x80); /* medium priority */ - NVIC_ClearPendingIRQ(RTC0_IRQn); - NVIC_EnableIRQ(RTC0_IRQn); + NVIC_SetPriority(RTC1_IRQn, 0x80); /* medium priority */ + NVIC_ClearPendingIRQ(RTC1_IRQn); + NVIC_EnableIRQ(RTC1_IRQn); +} + +/*************************************************************************************************/ +/*! + * \brief Register rtc IRQ callback. + * + * \param channelId Channel ID Number. + * \param cback Call back for ISR. + * + * This callback is dedicated for scheduler timer in low power code. + * + */ +/*************************************************************************************************/ +void PalRtcIrqRegister(uint8_t channelId, palRtcIrqCback_t cback) +{ + PAL_RTC_CHECK(channelId < RTC_TIMER_TOTAL_CHANNEL); + palRtcTimerCback[channelId] = cback; } diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_sys.c b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_sys.c index 10235e70c4..ccbd06dd58 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_sys.c +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_sys.c @@ -5,14 +5,15 @@ * \brief System hooks. * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. - * Arm Ltd. confidential and proprietary. * + * Copyright (c) 2019-2020 Packetcraft, Inc. + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -22,11 +23,12 @@ /*************************************************************************************************/ #include "nrf.h" -#include "stack/platform/include/pal_bb.h" -#include "stack/platform/include/pal_rtc.h" -#include "stack/platform/include/pal_sys.h" -#include "stack/platform/include/pal_led.h" -#include "platform/mbed_power_mgmt.h" +#include "pal_rtc.h" +#include "pal_sys.h" +#include "pal_led.h" +#include "pal_timer.h" +#include "pal_bb.h" +#include "pal_uart.h" #include @@ -34,16 +36,37 @@ Macros **************************************************************************************************/ +#ifdef __GNUC__ + +/*! \brief Stack initial values. */ +#define INIT_STACK_VAL 0xAFAFAFAF + +/*! \brief Starting memory location of free memory. */ +#define FREE_MEM_START ((uint8_t *)&__heap_start__) + +/*! \brief Total size in bytes of free memory. */ +#define FREE_MEM_SIZE ((uint32_t)&__heap_end__ - (uint32_t)&__heap_start__) + extern uint8_t *SystemHeapStart; extern uint32_t SystemHeapSize; -#if defined(__GNUC__) && !defined(__ARMCC_VERSION) - -/*! \brief Stack initial values. */ -#define INIT_STACK_VAL 0xAFAFAFAF - +extern unsigned long __text_end__; +extern unsigned long __data_start__; +extern unsigned long __data_end__; +extern unsigned long __bss_start__; +extern unsigned long __bss_end__; extern unsigned long __stack_top__; extern unsigned long __stack_limit__; +extern unsigned long __heap_end__; +extern unsigned long __heap_start__; + +#else + +/*! \brief Starting memory location of free memory. */ +#define FREE_MEM_START ((uint8_t *)palSysFreeMem) + +/*! \brief Total size in bytes of free memory. */ +#define FREE_MEM_SIZE (1024 * 196) #endif @@ -51,6 +74,21 @@ extern unsigned long __stack_limit__; Global Variables **************************************************************************************************/ +#ifdef __GNUC__ + +uint8_t *SystemHeapStart; +uint32_t SystemHeapSize; + +#else + +/*! \brief Free memory for pool buffers (align to word boundary). */ +uint32_t palSysFreeMem[FREE_MEM_SIZE/sizeof(uint32_t)]; + +uint8_t *SystemHeapStart = (uint8_t *) palSysFreeMem; +uint32_t SystemHeapSize = FREE_MEM_SIZE; + +#endif + /*! \brief Number of assertions. */ static uint32_t palSysAssertCount; @@ -66,19 +104,17 @@ static uint32_t palSysBusyCount; /*************************************************************************************************/ /*! * \brief Enter a critical section. - * - * \return None. */ /*************************************************************************************************/ -static inline void palEnterCs(void) +void PalEnterCs(void) { #ifdef __IAR_SYSTEMS_ICC__ __disable_interrupt(); #endif - #if defined(__GNUC__) && !defined(__ARMCC_VERSION) + #ifdef __GNUC__ __asm volatile ("cpsid i"); #endif - #if defined(__ARMCC_VERSION) + #ifdef __CC_ARM __disable_irq(); #endif } @@ -86,19 +122,17 @@ static inline void palEnterCs(void) /*************************************************************************************************/ /*! * \brief Exit a critical section. - * - * \return None. */ /*************************************************************************************************/ -static inline void palExitCs(void) +void PalExitCs(void) { #ifdef __IAR_SYSTEMS_ICC__ __enable_interrupt(); #endif - #if defined(__GNUC__) && !defined(__ARMCC_VERSION) + #ifdef __GNUC__ __asm volatile ("cpsie i"); #endif - #if defined(__ARMCC_VERSION) + #ifdef __CC_ARM __enable_irq(); #endif } @@ -106,34 +140,17 @@ static inline void palExitCs(void) /*************************************************************************************************/ /*! * \brief Common platform initialization. - * - * \return None. */ /*************************************************************************************************/ void PalSysInit(void) { - /* enable Flash cache */ + /* Enable Flash cache */ NRF_NVMC->ICACHECNF |= (NVMC_ICACHECNF_CACHEEN_Enabled << NVMC_ICACHECNF_CACHEEN_Pos); - /* switch to more accurate 16 MHz crystal oscillator (system starts up using 16MHz RC oscillator) */ + /* Use 16 MHz crystal oscillator (system starts up using 16MHz RC oscillator). */ NRF_CLOCK->EVENTS_HFCLKSTARTED = 0; NRF_CLOCK->TASKS_HFCLKSTART = 1; - while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0) - { - } - - /* configure low-frequency clock */ - NRF_CLOCK->LFCLKSRC = (CLOCK_LFCLKSRC_SRC_Xtal << CLOCK_LFCLKSRC_SRC_Pos); - NRF_CLOCK->EVENTS_LFCLKSTARTED = 0; - NRF_CLOCK->TASKS_LFCLKSTART = 1; - while (NRF_CLOCK->EVENTS_LFCLKSTARTED == 0) - { - } - NRF_CLOCK->EVENTS_LFCLKSTARTED = 0; - - /* cycle radio peripheral power to guarantee known radio state */ - NRF_RADIO->POWER = 0; - NRF_RADIO->POWER = 1; + while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0) { } palSysAssertCount = 0; PalSysAssertTrapEnable = TRUE; @@ -141,6 +158,10 @@ void PalSysInit(void) PalRtcInit(); + PalLedInit(); + PalLedOff(PAL_LED_ID_ERROR); + PalLedOn(PAL_LED_ID_CPU_ACTIVE); + #ifdef DEBUG /* Reset free memory. */ memset(SystemHeapStart, 0, SystemHeapSize); @@ -150,12 +171,12 @@ void PalSysInit(void) /*************************************************************************************************/ /*! * \brief System fault trap. - * - * \return None. */ /*************************************************************************************************/ void PalSysAssertTrap(void) { + PalLedOn(PAL_LED_ID_ERROR); + palSysAssertCount++; while (PalSysAssertTrapEnable); @@ -166,8 +187,6 @@ void PalSysAssertTrap(void) * \brief Set system trap. * * \param enable Enable assert trap or not. - * - * \return None. */ /*************************************************************************************************/ void PalSysSetTrap(bool_t enable) @@ -178,8 +197,6 @@ void PalSysSetTrap(bool_t enable) /*************************************************************************************************/ /*! * \brief Get assert count. - * - * \return None. */ /*************************************************************************************************/ uint32_t PalSysGetAssertCount(void) @@ -196,7 +213,7 @@ uint32_t PalSysGetAssertCount(void) /*************************************************************************************************/ uint32_t PalSysGetStackUsage(void) { -#if defined(__GNUC__) && !defined(__ARMCC_VERSION) +#ifdef __GNUC__ unsigned long *pUnused = &__stack_limit__; while (pUnused < &__stack_top__) @@ -219,28 +236,53 @@ uint32_t PalSysGetStackUsage(void) /*************************************************************************************************/ /*! * \brief System sleep. - * - * \return none. */ /*************************************************************************************************/ void PalSysSleep(void) { - sleep(); + /* Clock management for low power mode. */ + #if BB_CLK_RATE_HZ == 32768 + uint32_t rtcNow = NRF_RTC1->COUNTER; + + if ((BbGetCurrentBod() == NULL) && PalUartGetState(PAL_UART_ID_CHCI) == PAL_UART_STATE_UNINIT) + { + if ((PalTimerGetState() == PAL_TIMER_STATE_BUSY && + ((NRF_RTC1->CC[3] - rtcNow) & PAL_MAX_RTC_COUNTER_VAL) > PAL_HFCLK_OSC_SETTLE_TICKS) || + (PalTimerGetState() == PAL_TIMER_STATE_READY)) + { + /* disable HFCLK */ + NRF_CLOCK->TASKS_HFCLKSTOP = 1; + NRF_CLOCK->EVENTS_HFCLKSTARTED = 0; + (void)NRF_CLOCK->EVENTS_HFCLKSTARTED; + } + } + #endif + + /* CPU sleep. */ + #ifdef __IAR_SYSTEMS_ICC__ + __wait_for_interrupt(); + #endif + #ifdef __GNUC__ + __asm volatile ("wfi"); + #endif + #ifdef __CC_ARM + __wfi(); + #endif } /*************************************************************************************************/ /*! * \brief Check if system is busy. * - * \return True if system is busy. + * \return TRUE if system is busy. */ /*************************************************************************************************/ bool_t PalSysIsBusy(void) { bool_t sysIsBusy = FALSE; - palEnterCs(); + PalEnterCs(); sysIsBusy = ((palSysBusyCount == 0) ? FALSE : TRUE); - palExitCs(); + PalExitCs(); return sysIsBusy; } @@ -253,24 +295,22 @@ bool_t PalSysIsBusy(void) /*************************************************************************************************/ void PalSysSetBusy(void) { - palEnterCs(); + PalEnterCs(); palSysBusyCount++; - palExitCs(); + PalExitCs(); } /*************************************************************************************************/ /*! * \brief Set system idle. - * - * \return none. */ /*************************************************************************************************/ void PalSysSetIdle(void) { - palEnterCs(); + PalEnterCs(); if (palSysBusyCount) { palSysBusyCount--; } - palExitCs(); + PalExitCs(); } diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_timer.c b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_timer.c index c9acf8da1e..c2ec5f834d 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_timer.c +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_timer.c @@ -5,14 +5,15 @@ * \brief Timer driver * * Copyright (c) 2013-2019 Arm Ltd. All Rights Reserved. - * Arm Ltd. confidential and proprietary. * + * Copyright (c) 2019-2020 Packetcraft, Inc. + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -24,22 +25,56 @@ /* * Notes: * - * This is timer driver dedicated to scheduler, an interrupt will be triggered to do scheduler task - * when timer hits compare value. TIMER2 is used here. + * This is timer driver used for scheduler and other low power related tasks. + * It has dependency on pal_rtc.c, and some scheduler and BB API due to the complexity explained below. + * This is not ideal and should be fixed later. * - * TIMER2's compare/capture registers are assigned specific uses: - * CC[0] - Compare value for timer expiry interrupt - * CC[1] - manual capture of current time + * If SCH_TIMER_REQUIRED == FALSE: + * No hardware timer is needed for scheduler. + * + * If SCH_TIMER_REQUIRED == TRUE and BB_CLK_RATE_HZ == 32768: + * RTC1 timer(channel 3) is in use for scheduler. + * + * If SCH_TIMER_REQUIRED == TRUE and BB_CLK_RATE_HZ == 1MHz or 8MHz: + * Timer1 is in used for scheduler. + * + * RTC1 timer(Channel 0) is required for wsf software timer no matter what options are chosen. + * + * RTC1 timer(Channel 1 and 2) are required as long as BB_CLK_RATE_HZ == 32768. + * + * NRF timer1's compare/capture registers are assigned specific uses: + * CC[0] - Compare value for timer expiry interrupt. + * CC[1] - manual capture of current time. + * + * NRF RTC1's compare/capture registers are assigned specific uses: + * CC[0] - Compare value for wsf software timer interrupt. + * CC[1] - Compare value for NRF timer0 start task. + * CC[2] - Compare value for NRF HFCLK start task. + * CC[3] - Compare value for scheduler load interrupt. * */ +#include "pal_timer.h" +#include "pal_rtc.h" +#include "sch_api.h" +#include "bb_api.h" + #include "nrf.h" -#include "stack/platform/include/pal_timer.h" #include "nrf_gpio.h" /************************************************************************************************** Macros **************************************************************************************************/ + +/*! \brief Ticks and microseconds conversion. */ +#if BB_CLK_RATE_HZ == 32768 + #define PAL_TIMER_US_TO_TICKS(us) ((uint32_t)(((uint64_t)(us) * (uint64_t)(70368745)) >> 31)) /* calculated value may be one tick low */ + #define PAL_TIMER_TICKS_TO_US(ticks) ((uint32_t)(((uint64_t)(ticks) * 15625) >> 9)) +#else + #define PAL_TIMER_US_TO_TICKS(us) (us) + #define PAL_TIMER_TICKS_TO_US(ticks) (ticks) +#endif + #ifdef DEBUG /*! \brief Parameter and state check. */ @@ -53,12 +88,20 @@ #endif /* Scheduler timer resolution is fixed at 1us per tick. */ -#define PAL_TIMER_1MHZ_PRESCALER 4 +#define PAL_TIMER_1MHZ_PRESCALER 4 #ifdef DEBUG -#define PAL_TIMER_DEBUG_0_PIN 35 /* P1.03 */ +#define PAL_TIMER_DEBUG_0_PIN 35 /* P1.03 */ #endif +/* Predefined channel ID for timer1 and rtc1. */ +#define TIMER_CHANNEL_START_BB 0 +#define TIMER_CHANNEL_READ_TICK 1 + +#define RTC_CHANNEL_START_HFCLK 2 +#define RTC_CHANNEL_START_BB 3 + + /************************************************************************************************** Global Variables **************************************************************************************************/ @@ -71,6 +114,38 @@ static struct PalTimerCompCback_t expCback; /*!< Timer expiry call back function. */ } palTimerCb; +/* Nordic specific internal functions. */ +extern void PalRtcIrqRegister(uint8_t channelId, palRtcIrqCback_t cback); +extern void PalRtcClearCompareEvents(uint8_t channelId); + +#if BB_CLK_RATE_HZ == 32768 +/*************************************************************************************************/ +/*! + * \brief scheduler callback handler from RTC interrupt. + */ +/*************************************************************************************************/ +static void palTimerRtcIrqHandler(void) +{ + #ifdef DEBUG + nrf_gpio_pin_set(PAL_TIMER_DEBUG_0_PIN); + #endif + + PAL_TIMER_CHECK(palTimerCb.state == PAL_TIMER_STATE_BUSY); + + palTimerCb.state = PAL_TIMER_STATE_READY; + + if (palTimerCb.expCback) + { + palTimerCb.expCback(); + } + + #ifdef DEBUG + nrf_gpio_pin_clear(PAL_TIMER_DEBUG_0_PIN); + #endif +} +#endif + +#if SCH_TIMER_REQUIRED /*************************************************************************************************/ /*! * \brief Get the current tick of the scheduler timer. @@ -78,60 +153,69 @@ static struct * \return Current tick of the scheduler timer. */ /*************************************************************************************************/ -uint32_t PalTimerGetCurrentTime(void) +static uint32_t palTimerGetCurrentTime(void) { /* Only valid for initialized scheduler timer. */ - if (palTimerCb.state) { - /* Capture current TIMER2 count to capture register 1 */ - NRF_TIMER2->TASKS_CAPTURE[1] = 1; - /* Read and return the captured count value from capture register 1 */ - return NRF_TIMER2->CC[1]; + #if BB_CLK_RATE_HZ == 32768 + /* Read and return the captured count value from capture register 1 */ + return PalRtcCounterGet(); + #else + /* Capture current TIMER1 count to capture register 1 */ + NRF_TIMER1->TASKS_CAPTURE[TIMER_CHANNEL_READ_TICK] = 1; + /* Read and return the captured count value from capture register 1 */ + return NRF_TIMER1->CC[TIMER_CHANNEL_READ_TICK]; + #endif } - return 0; } +#endif /*************************************************************************************************/ /*! * \brief Initialize the scheduler timer. * * \param expCback Timer expire call back function. - * - * \return None. */ /*************************************************************************************************/ void PalTimerInit(PalTimerCompCback_t expCback) { -#ifdef DEBUG - nrf_gpio_cfg_output(PAL_TIMER_DEBUG_0_PIN); -#endif + #ifdef DEBUG + nrf_gpio_cfg_output(PAL_TIMER_DEBUG_0_PIN); + #endif PAL_TIMER_CHECK(palTimerCb.state == PAL_TIMER_STATE_UNINIT); PAL_TIMER_CHECK(expCback != NULL); - /* Give scheduler timer the highest priority. */ - NVIC_SetPriority(TIMER2_IRQn, 0); + #if SCH_TIMER_REQUIRED == TRUE + #if BB_CLK_RATE_HZ == 32768 + PalRtcIrqRegister(RTC_CHANNEL_START_BB, palTimerRtcIrqHandler); + #else + /* Give scheduler timer the highest priority. */ + NVIC_SetPriority(TIMER1_IRQn, 0); /* highest priority */ + NVIC_DisableIRQ(TIMER1_IRQn); - /* stop timer if it was somehow running (timer must be stopped for configuration) */ - NRF_TIMER2->TASKS_STOP = 1; + /* stop timer if it was somehow running (timer must be stopped for configuration) */ + NRF_TIMER1->TASKS_STOP = 1; - /* clear timer to zero count */ - NRF_TIMER2->TASKS_CLEAR = 1; + /* clear timer to zero count */ + NRF_TIMER1->TASKS_CLEAR = 1; - /* configure timer */ - NRF_TIMER2->MODE = TIMER_MODE_MODE_Timer; - NRF_TIMER2->BITMODE = TIMER_BITMODE_BITMODE_32Bit; - NRF_TIMER2->PRESCALER = PAL_TIMER_1MHZ_PRESCALER; /* f = 16MHz / (2 ^ TIMER_PRESCALER) */ + /* configure timer */ + NRF_TIMER1->MODE = TIMER_MODE_MODE_Timer; + NRF_TIMER1->BITMODE = TIMER_BITMODE_BITMODE_32Bit; + NRF_TIMER1->PRESCALER = PAL_TIMER_1MHZ_PRESCALER; /* f = 16MHz / (2 ^ TIMER_PRESCALER) */ - /* TIMER2 is a free running clock. */ - NRF_TIMER2->TASKS_START = 1; + /* timer1 is a free running clock. */ + NRF_TIMER1->TASKS_START = 1; - /* Clear out and enable TIMER2 interrupt at system level. */ - NRF_TIMER2->INTENCLR = 0xFFFFFFFF; - NRF_TIMER2->EVENTS_COMPARE[0] = 0; - NVIC_ClearPendingIRQ(TIMER2_IRQn); - NVIC_EnableIRQ(TIMER2_IRQn); + /* Clear out and enable timer1 interrupt at system level. */ + NRF_TIMER1->INTENCLR = 0xFFFFFFFF; + NRF_TIMER1->EVENTS_COMPARE[TIMER_CHANNEL_START_BB] = 0; + NVIC_ClearPendingIRQ(TIMER1_IRQn); + NVIC_EnableIRQ(TIMER1_IRQn); + #endif + #endif palTimerCb.compareVal = 0; palTimerCb.expCback = expCback; @@ -141,18 +225,18 @@ void PalTimerInit(PalTimerCompCback_t expCback) /*************************************************************************************************/ /*! * \brief De-initialize the scheduler timer. - * - * \return None. */ /*************************************************************************************************/ void PalTimerDeInit(void) { + #if SCH_TIMER_REQUIRED == TRUE + #if BB_CLK_RATE_HZ != 32768 + NVIC_DisableIRQ(TIMER1_IRQn); - NVIC_DisableIRQ(TIMER2_IRQn); - - /* stop timer */ - NRF_TIMER2->TASKS_STOP = 1; - NRF_TIMER2->TASKS_SHUTDOWN = 1; + /* stop timer */ + NRF_TIMER1->TASKS_STOP = 1; + #endif + #endif palTimerCb.state = PAL_TIMER_STATE_UNINIT; } @@ -174,69 +258,95 @@ PalTimerState_t PalTimerGetState(void) * \brief Start the scheduler timer. * * \param expTimeUsec Set timer expiry in microseconds. - * - * \return None */ /*************************************************************************************************/ - void PalTimerStart(uint32_t expTimeUsec) { PAL_TIMER_CHECK(palTimerCb.state == PAL_TIMER_STATE_READY); PAL_TIMER_CHECK(expTimeUsec != 0); - uint32_t startTimeTick = PalTimerGetCurrentTime() + PAL_TIMER_US_TO_TICKS(expTimeUsec); + #if SCH_TIMER_REQUIRED == TRUE + #if BB_CLK_RATE_HZ == 32768 + uint32_t startTimeTick = palTimerGetCurrentTime() + PAL_TIMER_US_TO_TICKS(expTimeUsec); - /* Clear pending events. */ - NRF_TIMER2->EVENTS_COMPARE[0] = 0; + /* Set compare value to start BB. */ + PalRtcCompareSet(RTC_CHANNEL_START_BB, startTimeTick); + /* Enable RTC interrupt source to start BB. */ + PalRtcEnableCompareIrq(RTC_CHANNEL_START_BB); - /* Set compare value. */ - NRF_TIMER2->CC[0] = startTimeTick; + /* Set compare value to start HFCLK. */ - /* Enable TIMER2 interrupt source for CC[0]. */ - NRF_TIMER2->INTENSET = TIMER_INTENSET_COMPARE0_Msk; + uint32_t startHFCLKTick = (startTimeTick - PAL_HFCLK_OSC_SETTLE_TICKS) & PAL_MAX_RTC_COUNTER_VAL; - palTimerCb.compareVal = startTimeTick; - palTimerCb.state = PAL_TIMER_STATE_BUSY; + PalRtcClearCompareEvents(RTC_CHANNEL_START_HFCLK); + PalRtcCompareSet(RTC_CHANNEL_START_HFCLK, startHFCLKTick); + #else + uint32_t startTimeTick = palTimerGetCurrentTime() + PAL_TIMER_US_TO_TICKS(expTimeUsec); + + /* Clear pending events. */ + NRF_TIMER1->EVENTS_COMPARE[TIMER_CHANNEL_START_BB] = 0; + + /* Set compare value. */ + NRF_TIMER1->CC[TIMER_CHANNEL_START_BB] = startTimeTick; + + /* Enable timer1 interrupt source for CC[0]. */ + NRF_TIMER1->INTENSET = TIMER_INTENSET_COMPARE0_Msk; + #endif + + palTimerCb.compareVal = startTimeTick; + palTimerCb.state = PAL_TIMER_STATE_BUSY; + #else + (void)expTimeUsec; + if (BbGetCurrentBod() == NULL) + { + SchLoadHandler(); + } + #endif } /*************************************************************************************************/ /*! * \brief Stop the scheduler timer. - * - * \return None */ /*************************************************************************************************/ void PalTimerStop() { - /* Disable this interrupt */ - NRF_TIMER2->INTENCLR = TIMER_INTENCLR_COMPARE0_Msk; + #if SCH_TIMER_REQUIRED == TRUE + #if BB_CLK_RATE_HZ == 32768 + /* Disable this interrupt */ + PalRtcDisableCompareIrq(RTC_CHANNEL_START_BB); + #else + /* Disable this interrupt */ + NRF_TIMER1->INTENCLR = TIMER_INTENCLR_COMPARE0_Msk; + #endif - palTimerCb.state = PAL_TIMER_STATE_READY; + palTimerCb.state = PAL_TIMER_STATE_READY; + #else + BbCancelBod(); + #endif } /*************************************************************************************************/ /*! - * \brief TIMER2 interrupt handler dedicated to scheduler timer. - * - * \return None. + * \brief TIMER1 interrupt handler dedicated to scheduler timer. */ /*************************************************************************************************/ -void TIMER2_IRQHandler_v(void) +void TIMER1_IRQHandler(void) { -#ifdef DEBUG - nrf_gpio_pin_set(PAL_TIMER_DEBUG_0_PIN); -#endif + #ifdef DEBUG + nrf_gpio_pin_set(PAL_TIMER_DEBUG_0_PIN); + #endif PAL_TIMER_CHECK(palTimerCb.state == PAL_TIMER_STATE_BUSY); /* Check hardware status */ - PAL_TIMER_CHECK(NRF_TIMER2->EVENTS_COMPARE[0]); - PAL_TIMER_CHECK(NRF_TIMER2->CC[0] == palTimerCb.compareVal); - PAL_TIMER_CHECK(NRF_TIMER2->INTENSET == TIMER_INTENSET_COMPARE0_Msk); + PAL_TIMER_CHECK(NRF_TIMER1->EVENTS_COMPARE[TIMER_CHANNEL_START_BB]); + PAL_TIMER_CHECK(NRF_TIMER1->CC[TIMER_CHANNEL_START_BB] == palTimerCb.compareVal); + PAL_TIMER_CHECK(NRF_TIMER1->INTENSET == TIMER_INTENSET_COMPARE0_Msk); - /* Callback function could restart TIMER2. However, we blindly stop TIMER2 first. */ - NRF_TIMER2->INTENCLR = TIMER_INTENCLR_COMPARE0_Msk; + /* Callback function could restart timer1. However, we blindly stop timer1 first. */ + NRF_TIMER1->INTENCLR = TIMER_INTENCLR_COMPARE0_Msk; /* Clear event again just in case. */ - NRF_TIMER2->EVENTS_COMPARE[0] = 0; + NRF_TIMER1->EVENTS_COMPARE[TIMER_CHANNEL_START_BB] = 0; palTimerCb.state = PAL_TIMER_STATE_READY; @@ -245,7 +355,7 @@ void TIMER2_IRQHandler_v(void) palTimerCb.expCback(); } -#ifdef DEBUG - nrf_gpio_pin_clear(PAL_TIMER_DEBUG_0_PIN); -#endif + #ifdef DEBUG + nrf_gpio_pin_clear(PAL_TIMER_DEBUG_0_PIN); + #endif } diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_twi.c b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_twi.c index 5f30efd882..7142877ff3 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_twi.c +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_twi.c @@ -4,15 +4,14 @@ * * \brief TWI driver implementation. * - * Copyright (c) 2018-2019 Arm Ltd. All Rights Reserved. - * Arm Ltd. confidential and proprietary. - * + * Copyright (c) 2019-2020 Packetcraft, Inc. + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -21,11 +20,15 @@ */ /*************************************************************************************************/ -#include -#include "stack/platform/include/pal_twi.h" +#include "pal_twi.h" #include "nrfx_twim.h" #include "nrf_twim.h" #include "app_util_platform.h" +#include + +#if defined(BOARD_PCA10056) | defined(BOARD_PCA10040) +#include "boards.h" +#endif /************************************************************************************************** Macros @@ -35,7 +38,7 @@ #ifndef PAL_TWI_MAX_DEVICE /*! \brief Maximum device count (must be an even multiple of 2^N). */ -#define PAL_TWI_MAX_DEVICE 4 +#define PAL_TWI_MAX_DEVICE 4 #endif /*! \brief Get next handle value, includes wrap around. */ @@ -44,10 +47,10 @@ #ifdef DEBUG /*! \brief Parameter check. */ -#define PAL_TWI_PARAM_CHECK(expr) { if (!(expr)) { twiDevCb.drvState = PAL_TWI_STATE_ERROR; return; } } +#define PAL_TWI_PARAM_CHECK(expr) { if (!(expr)) { palTwiCb.drvState = PAL_TWI_STATE_ERROR; return; } } /*! \brief Parameter check, with return value. */ -#define PAL_TWI_PARAM_CHECK_RET(expr, rv) { if (!(expr)) { twiDevCb.drvState = PAL_TWI_STATE_ERROR; return (rv); } } +#define PAL_TWI_PARAM_CHECK_RET(expr, rv) { if (!(expr)) { palTwiCb.drvState = PAL_TWI_STATE_ERROR; return (rv); } } #else @@ -62,12 +65,15 @@ /*! \brief TWI instance ID. */ #define PAL_TWI_INSTANCE_ID 0 -/*! \brief Pin number for SCL. */ -#define PAL_TWI_CLOCK_PIN_NUMBER (27U) - -/*! \brief Pin number for SDA. */ -#define PAL_TWI_DATA_PIN_NUMBER (26U) +#if defined(BOARD_PCA10056) | defined(BOARD_PCA10040) +#define PAL_TWI_SCL_PIN ARDUINO_SCL_PIN /*!< Pin number for SCL. */ +#define PAL_TWI_SDA_PIN ARDUINO_SDA_PIN /*!< Pin number for SDA. */ +#endif +#if defined(BOARD_NRF6832) +#define PAL_TWI_SCL_PIN (6U) /*!< Pin number for SCL. */ +#define PAL_TWI_SDA_PIN (7U) /*!< Pin number for SDA. */ +#endif /************************************************************************************************** Type Definitions @@ -76,9 +82,9 @@ /*! \brief Commands state. */ typedef enum { - PAL_TWI_CMD_IDLE, /*!< Idle state. */ - PAL_TWI_CMD_TX_DATA, /*!< Write data state. */ - PAL_TWI_CMD_RX_DATA /*!< Read data state. */ + PAL_TWI_CMD_IDLE, /*!< Idle state. */ + PAL_TWI_CMD_TX_DATA, /*!< Write data state. */ + PAL_TWI_CMD_RX_DATA /*!< Read data state. */ } PalTwiCmdState_t; /*! \brief Device configuration. */ @@ -88,8 +94,6 @@ typedef struct PalTwiDevConfig_t devCfg; /*!< Device configuration. */ } PalTwiDevCtx_t; -#if NRFX_CHECK(NRFX_TWIM0_ENABLED) - /************************************************************************************************** Global Variables **************************************************************************************************/ @@ -98,10 +102,9 @@ typedef struct static struct { uint8_t curHandle; /*!< Current device handle. */ - PalTwiCmdState_t cmdState; /*!< Command transaction state, Tx or Rx. */ - PalTwiState_t drvState; /*!< Current state. */ - bool_t firstCmd; /*!< First command after operation start flag. */ -} twiDevCb; + PalTwiCmdState_t cmdState; /*!< Command transaction state, Tx or Rx. */ + PalTwiState_t drvState; /*!< Current state. */ +} palTwiCb = { 0 }; /*! \brief Device context table. */ static PalTwiDevCtx_t twiDevCtx[PAL_TWI_MAX_DEVICE]; @@ -113,10 +116,10 @@ static const nrfx_twim_t twiId = NRFX_TWIM_INSTANCE(PAL_TWI_INSTANCE_ID); const nrfx_twim_config_t twiConfig = { .frequency = NRF_TWIM_FREQ_400K, - .scl = PAL_TWI_CLOCK_PIN_NUMBER, - .sda = PAL_TWI_DATA_PIN_NUMBER, - .interrupt_priority = APP_IRQ_PRIORITY_LOWEST, - .hold_bus_uninit = false + .scl = PAL_TWI_SCL_PIN, + .sda = PAL_TWI_SDA_PIN, + .interrupt_priority = APP_IRQ_PRIORITY_LOWEST, // TODO define in common platform BSP + .hold_bus_uninit = FALSE }; /************************************************************************************************** @@ -125,59 +128,59 @@ const nrfx_twim_config_t twiConfig = /*************************************************************************************************/ /*! - * \brief Control callback. + * \brief Operation complete callback. * - * \param event Event parameters. - * - * \return None. + * \param pEvt Event parameters. + * \param pContext Unused context. */ /*************************************************************************************************/ -static void palTwiCallback(nrfx_twim_evt_t *event, void *pContext) +static void palTwiCallback(nrfx_twim_evt_t *pEvt, void *pCtx) { + (void)pCtx; + /* Pre-resolve device configuration. */ - PalTwiDevConfig_t *pCfg = &twiDevCtx[twiDevCb.curHandle].devCfg; + PalTwiDevConfig_t *pCfg = &twiDevCtx[palTwiCb.curHandle].devCfg; bool_t success = FALSE; - twiDevCb.firstCmd = FALSE; - - if ((event->type) == NRFX_TWIM_EVT_DONE) + if ((pEvt->type) == NRFX_TWIM_EVT_DONE) { success = TRUE; } - if (twiDevCb.cmdState == PAL_TWI_CMD_TX_DATA) + if (palTwiCb.cmdState == PAL_TWI_CMD_TX_DATA) { - twiDevCb.cmdState = PAL_TWI_CMD_IDLE; + palTwiCb.cmdState = PAL_TWI_CMD_IDLE; if (pCfg->wrCback) { - pCfg->wrCback(twiDevCb.curHandle, success); + pCfg->wrCback(palTwiCb.curHandle, success); } } - else if (twiDevCb.cmdState == PAL_TWI_CMD_RX_DATA) + else if (palTwiCb.cmdState == PAL_TWI_CMD_RX_DATA) { - twiDevCb.cmdState = PAL_TWI_CMD_IDLE; + palTwiCb.cmdState = PAL_TWI_CMD_IDLE; if (pCfg->rdCback) { - pCfg->rdCback(twiDevCb.curHandle, success); + pCfg->rdCback(palTwiCb.curHandle, success); } } + + palTwiCb.drvState = PAL_TWI_STATE_BUSY_DATA_PEND; } /*************************************************************************************************/ /*! * \brief Initialize TWI resources. - * - * \return None. */ /*************************************************************************************************/ void PalTwiInit(void) { - if (twiDevCb.drvState != PAL_TWI_STATE_UNINIT) + if (palTwiCb.drvState != PAL_TWI_STATE_UNINIT) { + /* Only initialize once. */ return; } - memset(&twiDevCb, 0, sizeof(twiDevCb)); + memset(&palTwiCb, 0, sizeof(palTwiCb)); for (unsigned int handle = 0; handle < PAL_TWI_MAX_DEVICE; handle++) { @@ -187,24 +190,20 @@ void PalTwiInit(void) twiDevCtx[handle].devCfg.wrCback = NULL; } - twiDevCb.drvState = PAL_TWI_STATE_READY; + palTwiCb.drvState = PAL_TWI_STATE_READY; nrfx_twim_init(&twiId, &twiConfig, (nrfx_twim_evt_handler_t)palTwiCallback, NULL); nrfx_twim_enable(&twiId); - NVIC_ClearPendingIRQ(SPI0_TWI0_IRQn); - NVIC_EnableIRQ(SPI0_TWI0_IRQn); } /*************************************************************************************************/ /*! * \brief De-Initialize the TWI resources. - * - * \return None. */ /*************************************************************************************************/ void PalTwiDeInit(void) { - PAL_TWI_PARAM_CHECK(twiDevCb.drvState != PAL_TWI_STATE_BUSY); + PAL_TWI_PARAM_CHECK(palTwiCb.drvState == PAL_TWI_STATE_READY); for (unsigned int handle = 0; handle < PAL_TWI_MAX_DEVICE; handle++) { @@ -214,10 +213,10 @@ void PalTwiDeInit(void) twiDevCtx[handle].devCfg.wrCback = NULL; } - nrfx_twim_uninit(&twiId); nrfx_twim_disable(&twiId); + nrfx_twim_uninit(&twiId); - twiDevCb.drvState = PAL_TWI_STATE_UNINIT; + palTwiCb.drvState = PAL_TWI_STATE_UNINIT; } /*************************************************************************************************/ @@ -232,7 +231,6 @@ void PalTwiDeInit(void) uint8_t PalTwiRegisterDevice(PalTwiDevConfig_t *pDevCfg) { PAL_TWI_PARAM_CHECK_RET(pDevCfg != NULL, PAL_TWI_INVALID_ID); - PAL_TWI_PARAM_CHECK_RET(pDevCfg->opReadyCback, PAL_TWI_INVALID_ID); uint8_t retValue = PAL_TWI_INVALID_ID; @@ -263,7 +261,7 @@ uint8_t PalTwiRegisterDevice(PalTwiDevConfig_t *pDevCfg) /*************************************************************************************************/ PalTwiState_t PalTwiGetState(void) { - return twiDevCb.drvState; + return palTwiCb.drvState; } /************************************************************************************************** @@ -275,28 +273,16 @@ PalTwiState_t PalTwiGetState(void) * \brief Always start an operation before reading or writing on TWI interface. * * \param handle Device handle. - * - * \return None. */ /*************************************************************************************************/ void PalTwiStartOperation(uint8_t handle) { PAL_TWI_PARAM_CHECK(handle < PAL_TWI_MAX_DEVICE); - if (twiDevCb.drvState != PAL_TWI_STATE_READY) + if (palTwiCb.drvState == PAL_TWI_STATE_READY) { - PAL_TWI_PARAM_CHECK(handle != twiDevCb.curHandle); /* Client operation already in progress. */ - PAL_TWI_PARAM_CHECK(twiDevCtx[handle].opPending == FALSE); /* Client already pended an operation. */ - } - - __disable_irq(); - - if (twiDevCb.drvState == PAL_TWI_STATE_READY) - { - __enable_irq(); - twiDevCb.drvState = PAL_TWI_STATE_BUSY; - twiDevCb.firstCmd = TRUE; - twiDevCb.curHandle = handle; + palTwiCb.drvState = PAL_TWI_STATE_BUSY_DATA_PEND; + palTwiCb.curHandle = handle; if (twiDevCtx[handle].devCfg.opReadyCback) { twiDevCtx[handle].devCfg.opReadyCback(handle); @@ -304,9 +290,11 @@ void PalTwiStartOperation(uint8_t handle) } else { + PAL_TWI_PARAM_CHECK(handle != palTwiCb.curHandle); /* Client operation already in progress. */ + PAL_TWI_PARAM_CHECK(twiDevCtx[handle].opPending == FALSE); /* Client already pended an operation. */ + /* Pend the operation until current operation completes. */ twiDevCtx[handle].opPending = TRUE; - __enable_irq(); } } @@ -315,29 +303,18 @@ void PalTwiStartOperation(uint8_t handle) * \brief Always stop an operation after reading or writing on TWI interface. * * \param handle Device handle. - * - * \return None. */ /*************************************************************************************************/ void PalTwiStopOperation(uint8_t handle) { PAL_TWI_PARAM_CHECK(handle < PAL_TWI_MAX_DEVICE); - PAL_TWI_PARAM_CHECK(handle == twiDevCb.curHandle); - PAL_TWI_PARAM_CHECK(twiDevCb.cmdState == PAL_TWI_CMD_IDLE); - PAL_TWI_PARAM_CHECK(twiDevCb.drvState == PAL_TWI_STATE_BUSY); + PAL_TWI_PARAM_CHECK(handle == palTwiCb.curHandle); + PAL_TWI_PARAM_CHECK(palTwiCb.cmdState == PAL_TWI_CMD_IDLE); + PAL_TWI_PARAM_CHECK(palTwiCb.drvState == PAL_TWI_STATE_BUSY_DATA_PEND); unsigned int nextHandle = PAL_TWI_GET_NEXT_HANDLE(handle); - twiDevCb.curHandle = PAL_TWI_INVALID_ID; - - /* Only when address or command is sent, then issue stop. */ - if (!twiDevCb.firstCmd) - { - nrf_twim_event_clear(twiId.p_twim, NRF_TWIM_EVENT_STOPPED); - nrf_twim_task_trigger(twiId.p_twim, NRF_TWIM_TASK_RESUME); - nrf_twim_task_trigger(twiId.p_twim, NRF_TWIM_TASK_STOP); - nrf_twim_int_disable(twiId.p_twim, 0xFFFFFFFF); - } + palTwiCb.curHandle = PAL_TWI_INVALID_ID; while (nextHandle != handle) { @@ -346,13 +323,13 @@ void PalTwiStopOperation(uint8_t handle) /* Set the operation pending to FALSE first in case of race condition. */ twiDevCtx[nextHandle].opPending = FALSE; - twiDevCb.firstCmd = TRUE; - twiDevCb.curHandle = nextHandle; + palTwiCb.curHandle = nextHandle; if (twiDevCtx[nextHandle].devCfg.opReadyCback) { twiDevCtx[nextHandle].devCfg.opReadyCback(nextHandle); } + /* Remain in BUSY state. */ return; } @@ -360,7 +337,32 @@ void PalTwiStopOperation(uint8_t handle) } /* No pending operations. */ - twiDevCb.drvState = PAL_TWI_STATE_READY; + palTwiCb.drvState = PAL_TWI_STATE_READY; +} + +/*************************************************************************************************/ +/*! + * \brief Read data from TWI interface. + * + * \param handle Device handle. + * \param pData Read buffer. + * \param len Number of bytes to write. + * + * Read \a len bytes from \a pData to the TWI device. + */ +/*************************************************************************************************/ +void PalTwiReadData(uint8_t handle, uint8_t *pData, uint8_t len) +{ + PAL_TWI_PARAM_CHECK(len != 0); + PAL_TWI_PARAM_CHECK(pData != NULL); + PAL_TWI_PARAM_CHECK(handle < PAL_TWI_MAX_DEVICE); + PAL_TWI_PARAM_CHECK(handle == palTwiCb.curHandle); + + palTwiCb.curHandle =handle; + palTwiCb.cmdState = PAL_TWI_CMD_RX_DATA; + palTwiCb.drvState = PAL_TWI_STATE_BUSY_DATA_XFER; + + nrfx_twim_rx(&twiId, twiDevCtx[handle].devCfg.devAddr, pData, len); } /*************************************************************************************************/ @@ -371,8 +373,6 @@ void PalTwiStopOperation(uint8_t handle) * \param pData Write buffer. * \param len Number of bytes to write. * - * \return None. - * * Transfer \a len bytes from \a pData to the TWI device. */ /*************************************************************************************************/ @@ -381,43 +381,15 @@ void PalTwiWriteData(uint8_t handle, const uint8_t *pData, uint8_t len) PAL_TWI_PARAM_CHECK(len != 0); PAL_TWI_PARAM_CHECK(pData != NULL); PAL_TWI_PARAM_CHECK(handle < PAL_TWI_MAX_DEVICE); - PAL_TWI_PARAM_CHECK(handle == twiDevCb.curHandle); - PAL_TWI_PARAM_CHECK(twiDevCb.drvState == PAL_TWI_STATE_BUSY); - PAL_TWI_PARAM_CHECK(twiDevCb.cmdState == PAL_TWI_CMD_IDLE); + PAL_TWI_PARAM_CHECK(handle == palTwiCb.curHandle); - twiDevCb.curHandle = handle; - twiDevCb.cmdState = PAL_TWI_CMD_TX_DATA; + palTwiCb.curHandle = handle; + palTwiCb.cmdState = PAL_TWI_CMD_TX_DATA; + palTwiCb.drvState = PAL_TWI_STATE_BUSY_DATA_XFER; - nrfx_twim_tx(&twiId, twiDevCtx[handle].devCfg.devAddr, pData, len, NRFX_TWIM_FLAG_TX_NO_STOP); + nrfx_err_t err = nrfx_twim_tx(&twiId, twiDevCtx[handle].devCfg.devAddr, pData, len, NRFX_TWIM_FLAG_TX_NO_STOP); + PAL_TWI_PARAM_CHECK(err == NRFX_SUCCESS); + #ifndef DEBUG + (void)err; + #endif } - -/*************************************************************************************************/ -/*! - * \brief Read data from TWI interface. - * - * \param handle Device handle. - * \param pData Write buffer. - * \param len Number of bytes to write. - * - * \return None. - * - * Read \a len bytes from \a pData to the TWI device. - */ -/*************************************************************************************************/ -void PalTwiReadData(uint8_t handle, uint8_t *pData, uint8_t len) -{ - PAL_TWI_PARAM_CHECK(len != 0); - PAL_TWI_PARAM_CHECK(pData != NULL); - PAL_TWI_PARAM_CHECK(handle < PAL_TWI_MAX_DEVICE); - PAL_TWI_PARAM_CHECK(handle == twiDevCb.curHandle); - PAL_TWI_PARAM_CHECK(twiDevCb.drvState == PAL_TWI_STATE_BUSY); - PAL_TWI_PARAM_CHECK(twiDevCb.cmdState == PAL_TWI_CMD_IDLE); - - twiDevCb.curHandle =handle; - twiDevCb.cmdState = PAL_TWI_CMD_RX_DATA; - - nrfx_twim_rx(&twiId, twiDevCtx[handle].devCfg.devAddr, pData, len); -} - -#endif // NRFX_CHECK(NRFX_TWIM0_ENABLED) - diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_uart.c b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_uart.c index 5dbe137793..f72feb801c 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_uart.c +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_CORDIO/TARGET_NRF5x/stack/sources/pal_uart.c @@ -4,15 +4,14 @@ * * \brief UART driver definition. * - * Copyright (c) 2018-2019 ARM Ltd. All Rights Reserved. - * ARM Ltd. confidential and proprietary. - * + * Copyright (c) 2019-2020 Packetcraft, Inc. + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -21,237 +20,196 @@ */ /*************************************************************************************************/ -#include "stack/platform/include/pal_uart.h" -#include "sdk_config.h" +#include "pal_uart.h" #include "nrfx_uarte.h" -#include "boards.h" -#if NRFX_CHECK(NRFX_UARTE0_ENABLED) +#if defined(BOARD_NRF6832) +#define RX_PIN_NUMBER 26 +#define TX_PIN_NUMBER 27 +#define CTS_PIN_NUMBER 0xFF +#define RTS_PIN_NUMBER 0xFF +#else +#include "boards.h" +#endif + +/************************************************************************************************** + Type definitions +**************************************************************************************************/ + +/*! \brief Control block. */ +typedef struct +{ + PalUartState_t state; /*!< UART state. */ + PalUartConfig_t config; /*!< UART configuration. */ + nrfx_uarte_t inst; /*!< nRF UART driver instance. */ +} palUartCtrlBlk_t; /************************************************************************************************** Local Variables **************************************************************************************************/ -#define PAL_UART_INVALID_INSTANCE_NUM 0xFF + +#define PAL_UART_INVALID_INSTANCE_NUM 0xFF #ifdef DEBUG /*! \brief Parameter check. */ -#define PAL_UART_PARAM_CHECK(num, expr) { if (!(expr)) { palUartCb[num].state = PAL_UART_STATE_ERROR; while(1){}; } } +#define PAL_UART_PARAM_CHECK(p, expr) { if (!(expr)) { p->state = PAL_UART_STATE_ERROR; return; } } #else /*! \brief Parameter check (disabled). */ -#define PAL_UART_PARAM_CHECK(num, expr) +#define PAL_UART_PARAM_CHECK(p, expr) #endif /*! \brief Control block. */ -static struct -{ - PalUartId_t id; /*!< PAL UART id. */ - PalUartConfig_t config; /*!< PAL UART configuration. */ - PalUartState_t state; /*!< PAL UART state. */ - nrfx_uarte_t uart; /*!< NRF UART driver instance */ -} palUartCb[NRFX_UARTE0_ENABLED + NRFX_UARTE1_ENABLED] = {{0, {0}, 0, {NRF_UARTE0, NRFX_UARTE0_INST_IDX}}}; +static palUartCtrlBlk_t palUartCb[2]; /************************************************************************************************** Local Functions **************************************************************************************************/ + /*************************************************************************************************/ /*! * \brief Get UART instance number from UART ID. * - * \param uartId UART ID. + * \param id UART ID. * * \return UART instance number. */ /*************************************************************************************************/ -static uint8_t palUartGetNum(PalUartId_t uartId) +static palUartCtrlBlk_t *palUartGetContext(PalUartId_t id) { - uint8_t uartNum; - /* Nordic platform has total two UART instances. - * By default, only UART0 is enabled. - */ - switch (uartId) + switch (id) { case PAL_UART_ID_CHCI: - uartNum = 0; - break; case PAL_UART_ID_TERMINAL: - uartNum = 0; - break; + return &palUartCb[0]; + case PAL_UART_ID_USER: - uartNum = 0; - break; + return (NRFX_UARTE_ENABLED_COUNT > 1) ? &palUartCb[1] : &palUartCb[0]; default: - uartNum = PAL_UART_INVALID_INSTANCE_NUM; break; } - return uartNum; -} - -/*************************************************************************************************/ -/*! - * \brief Set UART baud rate. - * - * \param baud Baud rate. - * - * \return nrf baud rate. - */ -/*************************************************************************************************/ -static nrf_uarte_baudrate_t palUartSetBaud(uint32_t baud) -{ - nrf_uarte_baudrate_t baudRate; - - switch (baud) - { - default: - case 115200: - baudRate = NRF_UARTE_BAUDRATE_115200; - break; - case 230400: - baudRate = NRF_UARTE_BAUDRATE_230400; - break; - case 460800: - baudRate = NRF_UARTE_BAUDRATE_460800; - break; - case 921600: - baudRate = NRF_UARTE_BAUDRATE_921600; - break; - case 1000000: - baudRate = NRF_UARTE_BAUDRATE_1000000; - break; - } - - return baudRate; + return NULL; } /*************************************************************************************************/ /*! * \brief UART NRF event handler. * - * \param pEvent Pointer to event. - * \param pContext Pointer to event context. - * - * \return None. + * \param pEvent UART event. + * \param pContext Instance context. */ /*************************************************************************************************/ -static void palUartEventHandler(nrfx_uarte_event_t *pEvent, void *pContext) +static void palUartEventHandler(nrfx_uarte_event_t const *pEvent, void *pInstCtx) { - uint8_t uartNum = palUartGetNum(*(PalUartId_t *)pContext); + palUartCtrlBlk_t *pCtx = (palUartCtrlBlk_t *)pInstCtx; switch (pEvent->type) { case NRFX_UARTE_EVT_RX_DONE: - if (palUartCb[uartNum].config.rdCback != NULL) + if (pCtx->config.rdCback != NULL) { - palUartCb[uartNum].config.rdCback(); + pCtx->config.rdCback(); } break; case NRFX_UARTE_EVT_TX_DONE: - palUartCb[uartNum].state = PAL_UART_STATE_READY; - if (palUartCb[uartNum].config.wrCback != NULL) + pCtx->state = PAL_UART_STATE_READY; + if (pCtx->config.wrCback != NULL) { - palUartCb[uartNum].config.wrCback(); + pCtx->config.wrCback(); } break; case NRFX_UARTE_EVT_ERROR: - palUartCb[uartNum].state = PAL_UART_STATE_ERROR; + pCtx->state = PAL_UART_STATE_ERROR; break; default: break; } } -/************************************************************************************************** - Global Functions -**************************************************************************************************/ /*************************************************************************************************/ /*! * \brief Initialize UART. * - * \param id UART Id. - * \param pCfg Peripheral configuration. - * - * \return None. - * - * Initialize UART peripheral with \a pCfg values. + * \param id UART ID. + * \param pCfg Peripheral configuration. */ /*************************************************************************************************/ - void PalUartInit(PalUartId_t id, const PalUartConfig_t *pCfg) { - uint8_t uartNum = palUartGetNum(id); + palUartCtrlBlk_t *pCtx = palUartGetContext(id); + PAL_UART_PARAM_CHECK(pCtx, pCtx != NULL); + PAL_UART_PARAM_CHECK(pCtx, pCfg != NULL); - if (uartNum == PAL_UART_INVALID_INSTANCE_NUM) + pCtx->config = *pCfg; + + /* Resolve instance. */ + switch (pCtx - palUartCb) { - return; + default: + case 0: + pCtx->inst.p_reg = NRF_UARTE0; + pCtx->inst.drv_inst_idx = 0; + break; +#if (NRFX_UARTE1_ENABLED) + case 1: + pCtx->inst.p_reg = NRF_UARTE1; + pCtx->inst.drv_inst_idx = 1; + break; +#endif } - palUartCb[uartNum].id = id; + nrfx_uarte_config_t nrfCfg = NRFX_UARTE_DEFAULT_CONFIG; + nrfCfg.pselrxd = RX_PIN_NUMBER; + nrfCfg.pseltxd = TX_PIN_NUMBER; + nrfCfg.pselcts = CTS_PIN_NUMBER; + nrfCfg.pselrts = RTS_PIN_NUMBER; + nrfCfg.p_context = pCtx; + nrfCfg.parity = NRF_UARTE_PARITY_EXCLUDED; + nrfCfg.interrupt_priority = 0xFF; /* Lowest priority. */ + nrfCfg.hwfc = pCfg->hwFlow ? NRF_UARTE_HWFC_ENABLED : NRF_UARTE_HWFC_DISABLED; - PAL_UART_PARAM_CHECK(uartNum, pCfg != NULL); + switch (pCfg->baud) + { + default: + case 115200: nrfCfg.baudrate = NRF_UARTE_BAUDRATE_115200; break; + case 230400: nrfCfg.baudrate = NRF_UARTE_BAUDRATE_230400; break; + case 460800: nrfCfg.baudrate = NRF_UARTE_BAUDRATE_460800; break; + case 921600: nrfCfg.baudrate = NRF_UARTE_BAUDRATE_921600; break; + case 1000000: nrfCfg.baudrate = NRF_UARTE_BAUDRATE_1000000; break; + } - palUartCb[uartNum].config = *pCfg; - - /* Configure UART. */ - nrfx_uarte_config_t nrfConfig = NRFX_UARTE_DEFAULT_CONFIG; - nrfConfig.pselrxd = RX_PIN_NUMBER; - nrfConfig.pseltxd = TX_PIN_NUMBER; - nrfConfig.pselcts = CTS_PIN_NUMBER; - nrfConfig.pselrts = RTS_PIN_NUMBER; - nrfConfig.p_context = &(palUartCb[uartNum].id); - nrfConfig.parity = NRF_UARTE_PARITY_EXCLUDED; - nrfConfig.interrupt_priority = 0xFF; /* Lowest priority. */ - - nrfConfig.baudrate = palUartSetBaud(pCfg->baud); - nrfConfig.hwfc = pCfg->hwFlow ? NRF_UARTE_HWFC_ENABLED : NRF_UARTE_HWFC_DISABLED; - - /* Make sure UART is uninitialized. */ - nrfx_uarte_uninit(&(palUartCb[uartNum].uart)); - - /* Initialize UART. */ - nrfx_err_t err_code = nrfx_uarte_init(&(palUartCb[uartNum].uart), &nrfConfig, (nrfx_uarte_event_handler_t)palUartEventHandler); - - //this is for uart only not for uarte - //nrfx_uart_rx_enable(&palUartCb[uartNum].uart); + nrfx_err_t err_code = nrfx_uarte_init(&(pCtx->inst), &nrfCfg, palUartEventHandler); if (err_code != NRFX_SUCCESS) { - palUartCb[uartNum].state = PAL_UART_STATE_ERROR; + pCtx->state = PAL_UART_STATE_ERROR; return; } - palUartCb[uartNum].state = PAL_UART_STATE_READY; - - NVIC_EnableIRQ(UART0_IRQn); + pCtx->state = PAL_UART_STATE_READY; } /*************************************************************************************************/ /*! * \brief De-Initialize UART. * - * \param id UART id. - * - * \return None. - * - * De-Initialize UART. + * \param id UART ID. */ /*************************************************************************************************/ void PalUartDeInit(PalUartId_t id) { - uint8_t uartNum = palUartGetNum(id); + palUartCtrlBlk_t *pCtx = palUartGetContext(id); + PAL_UART_PARAM_CHECK(pCtx, pCtx != NULL); + PAL_UART_PARAM_CHECK(pCtx, pCtx->state == PAL_UART_STATE_READY); - if (uartNum == PAL_UART_INVALID_INSTANCE_NUM) - { - return; - } + nrfx_uarte_uninit(&pCtx->inst); - nrfx_uarte_uninit(&(palUartCb[uartNum].uart)); - - palUartCb[uartNum].state = PAL_UART_STATE_UNINIT; + pCtx->state = PAL_UART_STATE_UNINIT; } /*************************************************************************************************/ @@ -260,81 +218,62 @@ void PalUartDeInit(PalUartId_t id) * * \param id UART id. * -* \return Current state. - * - * Return the current state. + * \return Current state. */ /*************************************************************************************************/ PalUartState_t PalUartGetState(PalUartId_t id) { - uint8_t uartNum = palUartGetNum(id); + palUartCtrlBlk_t *pCtx = palUartGetContext(id); - if (uartNum == PAL_UART_INVALID_INSTANCE_NUM) + if (pCtx == NULL) { return PAL_UART_STATE_ERROR; } - return palUartCb[uartNum].state; + return pCtx->state; } /*************************************************************************************************/ /*! * \brief Read data from Rx FIFO. * - * \param id UART id. - * \param pData Read buffer. - * \param len Number of bytes to read. - * - * \return None. - * - * Store \a len received bytes in \a pData. After \a len is transferred, call - * \a UartInitInfo_t::rdCback to signal read completion. Alway call this function to setup buffer - * when boot up or after a reading is done + * \param id UART ID. + * \param pData Read buffer. + * \param len Number of bytes to read. */ /*************************************************************************************************/ void PalUartReadData(PalUartId_t id, uint8_t *pData, uint16_t len) { - uint8_t uartNum = palUartGetNum(id); + palUartCtrlBlk_t *pCtx = palUartGetContext(id); + PAL_UART_PARAM_CHECK(pCtx, pCtx != NULL); + PAL_UART_PARAM_CHECK(pCtx, pCtx->state != PAL_UART_STATE_UNINIT); + PAL_UART_PARAM_CHECK(pCtx, pData != NULL); + PAL_UART_PARAM_CHECK(pCtx, len > 0); - PAL_UART_PARAM_CHECK(uartNum, pData != NULL); - PAL_UART_PARAM_CHECK(uartNum, len > 0); - PAL_UART_PARAM_CHECK(uartNum, palUartCb[uartNum].state != PAL_UART_STATE_UNINIT); - - if (uartNum == PAL_UART_INVALID_INSTANCE_NUM) - { - return; - } - nrfx_uarte_rx(&(palUartCb[uartNum].uart), pData, (uint16_t)len); + nrfx_err_t err = nrfx_uarte_rx(&pCtx->inst, pData, len); + PAL_UART_PARAM_CHECK(pCtx, err == NRFX_SUCCESS); + (void)err; } /*************************************************************************************************/ /*! * \brief Write data to Tx FIFO. * - * \param id UART id. - * \param pData Write buffer. - * \param len Number of bytes to write. - * - * \return None. - * - * Assign buffer and length and transmit data. + * \param id UART ID. + * \param pData Write buffer. + * \param len Number of bytes to write. */ /*************************************************************************************************/ void PalUartWriteData(PalUartId_t id, const uint8_t *pData, uint16_t len) { - uint8_t uartNum = palUartGetNum(id); + palUartCtrlBlk_t *pCtx = palUartGetContext(id); + PAL_UART_PARAM_CHECK(pCtx, pCtx != NULL); + PAL_UART_PARAM_CHECK(pCtx, pCtx->state != PAL_UART_STATE_UNINIT); + PAL_UART_PARAM_CHECK(pCtx, pData != NULL); + PAL_UART_PARAM_CHECK(pCtx, len > 0); - PAL_UART_PARAM_CHECK(uartNum, pData != NULL); - PAL_UART_PARAM_CHECK(uartNum, len > 0); - PAL_UART_PARAM_CHECK(uartNum, palUartCb[uartNum].state == PAL_UART_STATE_READY); - - if (uartNum == PAL_UART_INVALID_INSTANCE_NUM) - { - return; - } - - nrfx_uarte_tx(&(palUartCb[uartNum].uart), pData, (uint16_t)len); - palUartCb[uartNum].state = PAL_UART_STATE_BUSY; + pCtx->state = PAL_UART_STATE_BUSY; + nrfx_err_t err = nrfx_uarte_tx(&pCtx->inst, pData, len); + PAL_UART_PARAM_CHECK(pCtx, err == NRFX_SUCCESS); + (void)err; } - -#endif // NRFX_CHECK(NRFX_UARTE0_ENABLED)