update nrf cordio ll files

pull/13228/head
Paul Szczeanek 2020-06-10 13:16:21 +01:00 committed by Vincent Coubard
parent 568d0a287e
commit 7f23b6df0f
12 changed files with 1852 additions and 1316 deletions

View File

@ -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 */

View File

@ -7,6 +7,8 @@
* 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
@ -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 <string.h>
@ -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)

View File

@ -5,7 +5,8 @@
* \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.
@ -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;
}

View File

@ -5,7 +5,8 @@
* \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.
@ -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
**************************************************************************************************/
@ -71,13 +52,17 @@ typedef struct
/* 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 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 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;
@ -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)
{
#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)
#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 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
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. */
(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:

View File

@ -5,7 +5,8 @@
* \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.
@ -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 <string.h>
/* 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 <string.h>
/**************************************************************************************************
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)

View File

@ -5,7 +5,8 @@
* \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.
@ -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
}

View File

@ -5,7 +5,8 @@
* \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.
@ -18,37 +19,125 @@
* 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;
}

View File

@ -5,7 +5,8 @@
* \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.
@ -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 <string.h>
@ -34,16 +36,37 @@
Macros
**************************************************************************************************/
extern uint8_t *SystemHeapStart;
extern uint32_t SystemHeapSize;
#if defined(__GNUC__) && !defined(__ARMCC_VERSION)
#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;
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();
}

View File

@ -5,7 +5,8 @@
* \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.
@ -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. */
@ -59,6 +94,14 @@
#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;
#if BB_CLK_RATE_HZ == 32768
/* Read and return the captured count value from capture register 1 */
return NRF_TIMER2->CC[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
#ifdef DEBUG
nrf_gpio_cfg_output(PAL_TIMER_DEBUG_0_PIN);
#endif
#endif
PAL_TIMER_CHECK(palTimerCb.state == PAL_TIMER_STATE_UNINIT);
PAL_TIMER_CHECK(expCback != NULL);
#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(TIMER2_IRQn, 0);
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;
NRF_TIMER1->TASKS_STOP = 1;
/* clear timer to zero count */
NRF_TIMER2->TASKS_CLEAR = 1;
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) */
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)
{
NVIC_DisableIRQ(TIMER2_IRQn);
#if SCH_TIMER_REQUIRED == TRUE
#if BB_CLK_RATE_HZ != 32768
NVIC_DisableIRQ(TIMER1_IRQn);
/* stop timer */
NRF_TIMER2->TASKS_STOP = 1;
NRF_TIMER2->TASKS_SHUTDOWN = 1;
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);
/* 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 to start HFCLK. */
uint32_t startHFCLKTick = (startTimeTick - PAL_HFCLK_OSC_SETTLE_TICKS) & PAL_MAX_RTC_COUNTER_VAL;
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_TIMER2->EVENTS_COMPARE[0] = 0;
NRF_TIMER1->EVENTS_COMPARE[TIMER_CHANNEL_START_BB] = 0;
/* Set compare value. */
NRF_TIMER2->CC[0] = startTimeTick;
NRF_TIMER1->CC[TIMER_CHANNEL_START_BB] = startTimeTick;
/* Enable TIMER2 interrupt source for CC[0]. */
NRF_TIMER2->INTENSET = TIMER_INTENSET_COMPARE0_Msk;
/* 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()
{
#if SCH_TIMER_REQUIRED == TRUE
#if BB_CLK_RATE_HZ == 32768
/* Disable this interrupt */
NRF_TIMER2->INTENCLR = TIMER_INTENCLR_COMPARE0_Msk;
PalRtcDisableCompareIrq(RTC_CHANNEL_START_BB);
#else
/* Disable this interrupt */
NRF_TIMER1->INTENCLR = TIMER_INTENCLR_COMPARE0_Msk;
#endif
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
#ifdef DEBUG
nrf_gpio_pin_set(PAL_TIMER_DEBUG_0_PIN);
#endif
#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
#ifdef DEBUG
nrf_gpio_pin_clear(PAL_TIMER_DEBUG_0_PIN);
#endif
#endif
}

View File

@ -4,8 +4,7 @@
*
* \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.
@ -21,11 +20,15 @@
*/
/*************************************************************************************************/
#include <string.h>
#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 <string.h>
#if defined(BOARD_PCA10056) | defined(BOARD_PCA10040)
#include "boards.h"
#endif
/**************************************************************************************************
Macros
@ -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
@ -88,8 +94,6 @@ typedef struct
PalTwiDevConfig_t devCfg; /*!< Device configuration. */
} PalTwiDevCtx_t;
#if NRFX_CHECK(NRFX_TWIM0_ENABLED)
/**************************************************************************************************
Global Variables
**************************************************************************************************/
@ -100,8 +104,7 @@ 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;
} 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)

View File

@ -4,8 +4,7 @@
*
* \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.
@ -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
#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 id UART ID.
* \param pCfg Peripheral configuration.
*
* \return None.
*
* Initialize UART peripheral with \a pCfg values.
*/
/*************************************************************************************************/
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 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
*/
/*************************************************************************************************/
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 id UART ID.
* \param pData Write buffer.
* \param len Number of bytes to write.
*
* \return None.
*
* Assign buffer and length and transmit data.
*/
/*************************************************************************************************/
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)