diff options
Diffstat (limited to 'Middlewares/ST/STM32_WPAN/ble_lld/lld/ble_lld.c')
-rw-r--r-- | Middlewares/ST/STM32_WPAN/ble_lld/lld/ble_lld.c | 479 |
1 files changed, 479 insertions, 0 deletions
diff --git a/Middlewares/ST/STM32_WPAN/ble_lld/lld/ble_lld.c b/Middlewares/ST/STM32_WPAN/ble_lld/lld/ble_lld.c new file mode 100644 index 000000000..24c24cf8d --- /dev/null +++ b/Middlewares/ST/STM32_WPAN/ble_lld/lld/ble_lld.c @@ -0,0 +1,479 @@ +/** + ****************************************************************************** + * File Name : ble_lld.c + * Description : LLD messages management. + ****************************************************************************** + * @attention + * + * <h2><center>© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.</center></h2> + * + * This software component is licensed by ST under Ultimate Liberty license + * SLA0044, the "License"; You may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/** + * This file is responsible for command packing and response unpacking + * following ABI defined in ble_lld_transport.h + * Actual transmission and reception of messages is delagated to other functions + */ + +/* Includes ------------------------------------------------------------------*/ +#include "app_common.h" +#include "ble_lld.h" +#include "ble_lld_transport.h" + +/* Private includes ----------------------------------------------------------*/ + +/* Private typedef -----------------------------------------------------------*/ + +/* Private defines -----------------------------------------------------------*/ + +/* Private macros ------------------------------------------------------------*/ + +/* Private function prototypes -----------------------------------------------*/ +static uint8_t sendCommand(BLE_LLD_Code_t bleCmd); + +/* Private variables ---------------------------------------------------------*/ + +/** When sending command to M0, store pointer to action packet for later use +when receiving reply from M0 */ +static ActionPacket *actionPackets[ACTION_PACKET_NB]; + +/* Encryption status is needed to prepare packet */ +static bool encryptStatus[STATE_MACHINE_NB] = {0}; // all flags are initialized to false + +/** Stores event received in interruption for later processing in a task */ +static radioEventType radioEvent; + +/** Stores action packet associated to event received for later processing in a task */ +static ActionPacket *radioEventAp; + +// Parameters stored by init +static param_BLE_LLD_t *params = NULL; +static ipBLE_lld_txrxdata_Type *txBuffer = NULL; +static ipBLE_lld_txrxdata_Type *rxBuffer = NULL; +/** Callback to send commands to M0 */ +static uint8_t (*CB_sendCommand)(BLE_LLD_Code_t bleCmd) = NULL; + +/* Functions Definition ------------------------------------------------------*/ + +/** + * @brief Initializes BLE LLD proxy. + * + * This function must be called before any BLE LLD function. + * + * @param[in] callbackSendCmdM0 Function to send commands to M0 + */ +/* Parameters ble_lld.c needs: + - param_BLE_LLD_t + - Tx buffer + - Rx buffer + - function to send message +*/ +void BLE_LLD_PRX_Init(param_BLE_LLD_t *parameters, + ipBLE_lld_txrxdata_Type *transmitBuffer, + ipBLE_lld_txrxdata_Type *receiveBuffer, + uint8_t (*callbackSend)(BLE_LLD_Code_t bleCmd)) +{ + params = parameters; + txBuffer = transmitBuffer; + rxBuffer = receiveBuffer; + CB_sendCommand = callbackSend; +} + +// DONE: Julien: hs_startup_time documentation is something that even BLE team is not very confident as Hardware Designer have implemented this offset low documentation +// => To understand, this is a global delay that includes: +// the cpu Wake up from Stop mode Low-Power +// the Radio Wake up +// The PLL setting +// The cold config table and hot config table SPI +// => This point is mentionned during CCB BLE +// or a reference to the relevant doc +/** + * @brief Initializes the radio + * + * Whitening improves receiver lock, disabling it is only intended for test mode. + * When whitening is disabled, data payload is limited to 45 bytes (including header). + * + * @param[in] hs_startup_time Startup time (system time unit) + * @param[in] low_speed_osc Source for the 32 kHz slow speed clock: + * 1: internal RO + * 0: external crystal + * @param[in] whitening ENABLE or DISABLE whitening for transmission and reception + */ +void BLE_LLD_Init(uint16_t hs_startup_time, uint8_t low_speed_osc, FunctionalState whitening) +{ + params->init.startupTime = (uint32_t)(hs_startup_time); + params->init.lowSpeedOsc = low_speed_osc; + params->init.whitening = (uint8_t)whitening; + sendCommand(BLE_LLD_INIT_CMDCODE); +} + +/** + * @brief Checks if the radio is busy. + * + * @retval BLUE_IDLE_0 Radio is not busy + * @retval BLUE_BUSY_NOWAKEUP_T2 Radio is busy, but there is no wakeup timer on the schedule but timer2 is + * @retval BLUE_BUSY_WAKEUP Radio is busy and wakeup timer is on the schedule + * @retval BLUE_BUSY_TONE. Radio is in Tone + * @retval BLUE_TONE_DESTROY. Radio Tone has destroyed BLE: need an Init + */ +uint8_t BLE_LLD_GetStatus(void) +{ + return sendCommand(BLE_LLD_GETSTATUS_CMDCODE); +} + +/** + * @brief Sets the 40 bits receive and transmit packet count, used in encryption. + * + * Both set the 39-bit count + 1 bit MSB as defined in the Bluetooth Low Energy specifications + * for encryption nonce calculation. + * + * @param [in] StateMachineNo State machine number in multistate (between 0 and 7) + * @param [in] countTx 40-bit transmit packet count + * @param [in] countRx 40-bit receive packet count + */ +void BLE_LLD_SetEncryptionCount(uint8_t StateMachineNo, const uint8_t (*countTx)[5], const uint8_t (*countRx)[5]) +{ + params->cryptCount.stateMachineNo = StateMachineNo; + memcpy(params->cryptCount.countTx, countTx, sizeof(params->cryptCount.countTx)); + memcpy(params->cryptCount.countRcv, countRx, sizeof(params->cryptCount.countRcv)); + sendCommand(BLE_LLD_SETENCRYPTIONCOUNT_CMDCODE); +} + +/** + * @brief Set the 8-byte encryption initialization vector and the 16-byte encryption key. + * + * @param[in] StateMachineNo State machine number in multistate (between 0 and 7) + * @param[in] encIv 8-byte encryption initialization vector + * @param[in] encKey 16-byte encryption key + */ +void BLE_LLD_SetEncryptionAttributes(uint8_t StateMachineNo, const uint8_t (*encIv)[8], const uint8_t (*encKey)[16]) +{ + params->cryptAttr.stateMachineNo = StateMachineNo; + memcpy(params->cryptAttr.encIv, encIv, sizeof(params->cryptAttr.encIv)); + memcpy(params->cryptAttr.encKey, encKey, sizeof(params->cryptAttr.encKey)); + sendCommand(BLE_LLD_SETENCRYPTIONATTRIBUTES_CMDCODE); +} + +/** + * @brief Enables or disables encryption. + * + * Another point is that, when encryption is enabled the hardware will add + * 4 bytes at the end of the packet as MAC (Message Authentication Code). + * So, the user needs to add 4 to the length of packet when encryption is ON. + * + * @param[in] StateMachineNo State Number in multistate (between 0 and 7) + * @param[in] EncryptFlag Encryption Flag: + * 0: Encryption is turned off + * 1: encryption is turned on + */ +void BLE_LLD_SetEncryptFlags(uint8_t StateMachineNo, FunctionalState EncryptFlag) +{ + params->cryptFlags.StateMachineNo = StateMachineNo; + params->cryptFlags.encFlag = (uint8_t)EncryptFlag; + encryptStatus[StateMachineNo] = EncryptFlag; + sendCommand(BLE_LLD_SETENCRYPTFLAGS_CMDCODE); +} + +/** + * @brief Sets the channel. + * + * @param[in] StateMachineNo State machine number in multistate (between 0 and 7) + * @param[in] channel Frequency channel (between 0 and 39) + */ +void BLE_LLD_SetChannel(uint8_t StateMachineNo, uint8_t channel) +{ + params->chan.stateMachineNo = StateMachineNo; + params->chan.channel = channel; + sendCommand(BLE_LLD_SETCHANNEL_CMDCODE); +} + +/* handle network IDs which may lead to bad radio behavior with one of the following options: + - just document which network IDs are safe to use and why (those conforming to BLE spec) + - add a flag like "rejectNonBle" to the function responsible for network ID setting + - add a function to check for BLE conformance of network ID */ +/** + * @brief Sets the access address (AccessAddress), the CRC initialization value and the Slow Clock Accuracy (SCA). + * + * @param[in] StateMachineNo State machine number in multistate (between 0 and 7) + * @param[in] NetworkID BLE NetworkID + */ +void BLE_LLD_SetTxAttributes(uint8_t StateMachineNo, uint32_t NetworkID) +{ + params->txAttr.stateMachineNo = StateMachineNo; + params->txAttr.networkId = NetworkID; + sendCommand(BLE_LLD_SETTXATTRIBUTES_CMDCODE); +} + +/** + * @brief Sets the time between back-to-back radio transmissions. + * + * A minimum value of 50us must be set. + * + * @param[in] backToBackTime Time between two frames in back to back mode (us) + */ +void BLE_LLD_SetBackToBackTime(uint32_t backToBackTime) +{ + params->b2b.backToBackTime = backToBackTime; + sendCommand(BLE_LLD_SETBACKTOBACKTIME_CMDCODE); +} + +/** + * @brief Sets the transmit power level. + * + * @param[in] powerLevel Transmit power level (between 0 and 31) + */ +void BLE_LLD_SetTxPower(txPower_t powerLevel) +{ + params->power.power = powerLevel; + sendCommand(BLE_LLD_SETTXPOWER_CMDCODE); +} + +/** + * @brief Sets the data speed for transmission and reception. + * + * @param[in] StateMachineNo State machine number in multistate (between 0 and 7) + * @param[in] txPhy Speed for transmission: TX_PHY_1MBPS / TX_PHY_2MBPS + * @param[in] rxPhy Speed for reception RX_PHY_1MBPS / RX_PHY_2MBPS + */ +void BLE_LLD_SetTx_Rx_Phy(uint8_t StateMachineNo, uint8_t txPhy, uint8_t rxPhy) +{ + params->phy.stateMachineNo = StateMachineNo; + params->phy.txPhy = txPhy; + params->phy.rxPhy = rxPhy; + sendCommand(BLE_LLD_SETTX_RX_PHY_CMDCODE); +} + +/** + * @brief Prepares an action packet for execution. + * + * This function must be called after the action packet fields are set. + * + * @param[in] p Action packet to prepare, memory lifetime must extend until response processing + */ +void BLE_LLD_SetReservedArea(ActionPacket *p) +{ + actionPackets[p->actionPacketNb] = p; + actionPackets[p->actionPacketNb]->callback = p->callback; + + params->reserved.stateMachineNo = p->StateMachineNo; + params->reserved.nextTrue = p->nextTrue; + params->reserved.nextFalse = p->nextFalse; + params->reserved.wakeupTime = p->WakeupTime; + params->reserved.receiveWindowLength = p->ReceiveWindowLength; + params->reserved.actionPacketNb = p->actionPacketNb; + params->reserved.actionTag = p->ActionTag; + if(params->reserved.actionTag & TXRX) { + params->reserved.buffer = txBuffer; + BLE_LLD_packetPrepareCopy(txBuffer, p->data, p->dataSize, encryptStatus[p->StateMachineNo]); + }else{ + params->reserved.buffer = rxBuffer; + } + sendCommand(BLE_LLD_SETRESERVEDAREA_CMDCODE); +} + +/** + * @brief Schedules an action packet for execution on the radio. + * + * BLE_LLD_SetReservedArea() must have been called first to prepare the action packet. + * + * @param[in] p Action packet to schedule, memory lifetime must extend until response processing + * + * @retval SUCCESS_0 if success + * @retval RADIO_BUSY_C4 if radio is busy + */ +uint8_t BLE_LLD_MakeActionPacketPending(const ActionPacket *p) +{ + params->pending.actionPacketNb = p->actionPacketNb; + return(sendCommand(BLE_LLD_MAKEACTIONPACKETPENDING_CMDCODE)); +} + +/** + * @brief Stops the radio + * + * After a call to this function ISR will not be triggered, unless + * MakeActionPacketPending() is called again. + * This function returns when radio is ready to be initialized. + * + * @retval true + */ +uint8_t BLE_LLD_StopActivity(void) +{ + return(sendCommand(BLE_LLD_STOPACTIVITY_CMDCODE)); +} + +/** + * @brief Starts tone transmission on selected channel. + * + * This function is dedicated to tests and destroys context and multistate. + * So, after calling this function the radio must be re-initialized. + * + * @param[in] RF_channel Radio frequency channel (between 0 and 39) + * @param[in] PowerLevel Output power level (between 0 and 31) + */ +void BLE_LLD_StartTone(uint8_t RF_channel, uint8_t powerLevel) +{ + params->toneStart.channel = RF_channel; + params->toneStart.power = powerLevel; + sendCommand(BLE_LLD_STARTTONE_CMDCODE); +} + +/** + * @brief Stops tone transmission. + * + * This function is dedicated to tests and destroys context and multistate. + * So, after calling this function the radio must be re-initialized. + */ +void BLE_LLD_StopTone(void) +{ + sendCommand(BLE_LLD_STOPTONE_CMDCODE); +} + + +/** + * @brief Processes received event from radio MCU during interruption. + * + * Stores event data for further processing out of interruption. + * + * @param[in] + * + */ +void BLE_LLD_PRX_EventProcessInter(radioEventType event) +{ + // Action packet for which the event is coming back + ActionPacket *ap = actionPackets[params->reply.actionPacketNb]; + radioEvent = event; + radioEventAp = ap; + ap->status = params->reply.status; + if (RADIO_IS_RX_OK(event)){ + ap->rssi = params->reply.rssi; + } +} + +/** + * @brief Processes received event from radio MCU after interruption. + * + * Run the callback corresponding to the received event. + * + * @param[in] + * + */ +void BLE_LLD_PRX_EventProcessTask(void) +{ + void *data = NULL; + uint8_t size = 0; + const bool encrypt = encryptStatus[radioEventAp->StateMachineNo]; + if (radioEventAp->callback != NULL){ + if (RADIO_IS_RX_OK(radioEvent)){ + size = BLE_LLD_packetExtractInPlace(rxBuffer, &data, encrypt); + } + radioEventAp->callback(radioEvent, radioEventAp, data, size); + } +} + +static uint8_t sendCommand(BLE_LLD_Code_t bleCmd){ + return CB_sendCommand(bleCmd); +} + + +const char *eventToString(radioEventType evt){ + switch(evt){ + case TX_OK_BUSY: return "TX_OK_BUSY"; + case TX_OK_READY: return "TX_OK_READY"; + case TX_FAIL_BUSY: return "TX_FAIL_BUSY"; + case TX_FAIL_READY: return "TX_FAIL_READY"; + case RX_OK_BUSY: return "RX_OK_BUSY"; + case RX_OK_READY: return "RX_OK_READY"; + case RX_TIMEOUT_BUSY: return "RX_TIMEOUT_BUSY"; + case RX_TIMEOUT_READY: return "RX_TIMEOUT_READY"; + case RX_CRC_KO_BUSY: return "RX_CRC_KO_BUSY"; + case RX_CRC_KO_READY: return "RX_CRC_KO_READY"; + case RX_FAIL_BUSY: return "RX_FAIL_BUSY"; + case RX_FAIL_READY: return "RX_FAIL_READY"; + default: return "ERROR: invalid event"; + } +} + +// Utility functions + +/* Header field is interpreted by hardware and has an impact on some flags, so + user should not change it. This is a default safe value */ +#define LLD_HEADER 0x55 + +// Data copy +uint8_t BLE_LLD_packetPrepareCopy(ipBLE_lld_txrxdata_Type *packet, + const void *data, + uint8_t size, + bool encrypt) +{ + uint32_t actual_size = size; + if (encrypt){ + actual_size += MIC_SIZE; + } + assert_param(actual_size <= sizeof(packet->payload)); + + packet->header = LLD_HEADER; + packet->length = actual_size; + memcpy(packet->payload, data, actual_size); + return (uint8_t)actual_size; // Max value has been checked +} + +// No copy +uint8_t BLE_LLD_packetPrepareInPlace(ipBLE_lld_txrxdata_Type *packet, + bool encrypt) +{ + uint32_t actual_size = packet->length; + if (encrypt){ + actual_size += MIC_SIZE; + } + assert_param(actual_size <= sizeof(packet->payload)); + + packet->header = LLD_HEADER; + packet->length = actual_size; + return (uint8_t)actual_size; // Max value has been checked +} + +uint8_t BLE_LLD_packetExtractCopy(const ipBLE_lld_txrxdata_Type *packet, + void *data, + bool encrypt) +{ + uint8_t actual_size = packet->length; + if (encrypt){ + actual_size -= MIC_SIZE; + } + + memcpy(data, packet->payload, actual_size); + return actual_size; +} + +uint8_t BLE_LLD_packetExtractInPlace(ipBLE_lld_txrxdata_Type *packet, + void **data, + bool encrypt) +{ + uint8_t actual_size = packet->length; + if (encrypt){ + actual_size -= MIC_SIZE; + } + + *data = packet->payload; + return actual_size; +} + +uint8_t BLE_LLD_packetGetSize(const ipBLE_lld_txrxdata_Type *packet, + bool encrypt) +{ + uint8_t actual_size = packet->length; + if (encrypt){ + actual_size -= MIC_SIZE; + } + return actual_size; +} + + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ |