1 /*
2  * Copyright (c) 2021-2024, Texas Instruments Incorporated
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * *  Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * *  Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * *  Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 /*
33  *  ======== ble5.c ========
34  */
35 
36 #include <stdint.h>
37 #include <stdlib.h>
38 
39 #include <ti/devices/DeviceFamily.h>
40 
41 #include <ti/log/Log.h>
42 
43 #include <ti/drivers/rcl/RCL_Command.h>
44 #include <ti/drivers/rcl/RCL_Buffer.h>
45 #include <ti/drivers/rcl/RCL_Scheduler.h>
46 #include <ti/drivers/rcl/RCL_Profiling.h>
47 
48 #include <ti/drivers/rcl/hal/hal.h>
49 #include <ti/drivers/rcl/commands/ble5.h>
50 
51 #include <ti/drivers/dpl/HwiP.h>
52 #include <ti/drivers/utils/Random.h>
53 
54 #include DeviceFamily_constructPath(inc/pbe_ble5_ram_regs.h)
55 #include DeviceFamily_constructPath(inc/hw_lrfdtxf.h)
56 #include DeviceFamily_constructPath(inc/hw_lrfdrxf.h)
57 #include DeviceFamily_constructPath(inc/hw_lrfddbell.h)
58 #include DeviceFamily_constructPath(inc/hw_lrfdpbe.h)
59 #include DeviceFamily_constructPath(inc/hw_lrfdpbe32.h)
60 #include DeviceFamily_constructPath(inc/hw_lrfdmdm.h)
61 #include DeviceFamily_constructPath(inc/hw_lrfdrfe.h)
62 #include DeviceFamily_constructPath(inc/pbe_ble5_ram_regs.h)
63 #include DeviceFamily_constructPath(inc/pbe_common_ram_regs.h)
64 #include DeviceFamily_constructPath(inc/pbe_ble5_regdef_regs.h)
65 
66 #define RCL_HANDLER_BLE5_RESTORE_NONE           0x0000
67 #define RCL_HANDLER_BLE5_RESTORE_MODCTRL        0x0001
68 #define RCL_HANDLER_BLE5_RESTORE_WHITEN_POLY    0x0002
69 
70 typedef struct
71 {
72     RCL_Buffer_TxBuffer *lastEnteredTxBuffer;
73     uint8_t *lastTxHdr;
74     bool     isConnBuffer;
75     uint16_t numBytes;
76     uint16_t numBuffers;
77 } RCL_TxBufferInfo;
78 
79 typedef struct
80 {
81     uint8_t    pktLen;
82     uint8_t    chIndex: 6;
83     uint8_t    ca: 1;
84     uint8_t    offsetUnits: 1;
85     uint16_t   auxOffset: 13;
86     uint16_t   auxPhy: 3;
87     uint8_t    ptrIndex;
88     uint8_t   *auxOffsetLowFifoPtr;
89     uint8_t   *auxOffsetHighFifoPtr;
90     uint8_t   *auxChCaOffsetUnitsFifoPtr;
91     uint8_t    numPrimaryChPackets;
92     bool       auxPtrPresent;
93 } RCL_AuxPtrInfo;
94 
95 struct
96 {
97     struct {
98         uint32_t          defaultRfFrequency;
99         bool              accessAddressModification;
100         RCL_CommandStatus endStatus;
101         bool              activeUpdate;
102         RCL_Ble5Channel   channel;
103         uint16_t          rxFifoSz;
104         uint16_t          txFifoSz;
105         uint16_t          phyFeatures;
106         uint16_t          fifoCfg;
107         int8_t            filterListUpdateIndex;
108         RCL_MultiBuffer  *curBuffer;
109         uint32_t          timestampAdjust;
110         RCL_FilterList   *updatableFilterList;
111         RCL_AuxPtrInfo    auxPtrInfo;
112         RCL_TxBufferInfo  txBufferInfo;
113     } common;
114     union {
115         struct {
116             uint8_t       chanMap;
117             bool          runRx;
118             bool          gracefulStopObserved;
119             bool          isExtAdv;
120             bool          switchPhy;
121             bool          auxScanReqReceived;
122             uint8_t       auxScanRspLen;
123             uint8_t       auxAdvIndLen;
124         } adv;
125         struct {
126             bool          runRx;
127             bool          gracefulStopObserved;
128             bool          sendAuxAdv;
129             bool          auxScanReqReceived;
130             uint8_t       auxScanRspLen;
131             uint8_t       auxAdvIndLen;
132         } auxAdv;
133         struct {
134             bool          gracefulStopObserved;
135         } perAdv;
136         struct {
137             bool          initiator;
138             bool          dynamicWinOffset;
139             bool          switchPhy;
140             bool          followAuxPtr;
141             bool          isExtAdv;
142             uint8_t       advPktLen;
143             uint16_t     *winOffsetFifoPtr;
144             uint16_t     *winOffsetBufferPtr;
145             uint16_t      transmitWindowOffset;
146             uint16_t     *intervalFifoPtr;
147             uint16_t      connectInterval;
148             uint16_t      filterListInvertMask;
149         } scanInit;
150         struct {
151             bool          followAuxPtr;
152         } perScan;
153         struct {
154             bool          isPeripheral;
155         } conn;
156         struct {
157             uint16_t      demc1be0;
158             uint16_t      demc1be1;
159             uint16_t      demc1be2;
160 #ifdef DeviceFamily_CC27XX
161             uint16_t      demc1be12;
162 #endif
163             bool          restoreThresh;
164         } genericRx;
165         struct {
166             uint16_t      storedPbeTimPre;
167         } dtmTx;
168         struct {
169             uint8_t       restoreSelector;
170             uint32_t      storedWhitenPoly;
171         } txTest;
172 
173     };
174 } ble5HandlerState;
175 
176 uint32_t RCL_Handler_BLE5_getRandomNumber(void);
177 static void RCL_Handler_BLE5_updateRxCurBufferAndFifo(List_List *rxBuffers);
178 static uint16_t RCL_Handler_BLE5_findWhitenInit(RCL_Ble5Channel channel);
179 static uint32_t RCL_Handler_BLE5_findRfFreq(RCL_Ble5Channel channel);
180 static RCL_Ble5Channel RCL_Handler_BLE5_findAdvChannel(uint32_t advMap, uint32_t order);
181 static RCL_CommandStatus RCL_Handler_BLE5_setPhy(uint16_t phyFeatures);
182 static RCL_CommandStatus  RCL_Handler_BLE5_findPbeErrorEndStatus(uint16_t pbeEndStatus);
183 static uint32_t RCL_Handler_BLE5_updateTxBuffers(List_List *txBuffers,
184                                                  uint32_t maxBuffers,
185                                                  RCL_TxBufferInfo *txBufferInfo,
186                                                  bool retransPossible);
187 static void RCL_Handler_BLE5_commitPacket(RCL_MultiBuffer *curBuffer, uint32_t numBytes);
188 static uint32_t RCL_Handler_BLE5_maskEventsByFifoConf(uint32_t mask, uint16_t fifoConfVal, bool activeUpdate);
189 static bool RCL_Handler_BLE5_initAdvScanInitStats(RCL_StatsAdvScanInit *stats, uint32_t startTime);
190 static void RCL_Handler_BLE5_updateAdvScanInitStats(RCL_StatsAdvScanInit *stats, uint32_t startTime);
191 static bool RCL_Handler_BLE5_initConnStats(RCL_StatsConnection *stats, uint32_t startTime);
192 static void RCL_Handler_BLE5_updateConnStats(RCL_StatsConnection *stats, uint32_t startTime);
193 static bool RCL_Handler_BLE5_initGenericRxStats(RCL_StatsGenericRx *stats, uint32_t startTime);
194 static void RCL_Handler_BLE5_updateGenericRxStats(RCL_StatsGenericRx *stats, uint32_t startTime);
195 static void RCL_Handler_BLE5_InitializeFilterList(RCL_FilterList *filterList, uint32_t *pbeFilterList, uint32_t invertMask);
196 static void RCL_Handler_BLE5_updateFilterListEntry(RCL_FilterList *filterList, uint32_t *pbeFilterList, uint32_t invertMask, uint32_t index);
197 static uint32_t RCL_Handler_BLE5_prepareConnectTime(uint32_t *connectTime, uint32_t referenceTime, uint32_t interval);
198 static uint32_t RCL_Handler_BLE5_findConnectTime(uint32_t initialConnectTime, uint32_t referenceTime, uint32_t interval);
199 static uint32_t RCL_Handler_BLE5_findPacketDuration(uint32_t length, uint16_t phyFeatures);
200 static uint16_t RCL_Handler_BLE5_findRxSyncOverhead(uint16_t phyFeatures);
201 static uint32_t RCL_Handler_BLE5_findNumExtraBytes(uint32_t fifoCfg);
202 static void RCL_Handler_BLE5_getAuxPtrFromTxBuffer(RCL_Buffer_TxBuffer *curBuffer, RCL_AuxPtrInfo *auxPtrInfo, uint8_t offset);
203 static bool RCL_Handler_BLE5_updateAuxPtr(RCL_AuxPtrInfo *auxPtr, uint32_t packetDuration, uint8_t chanMap, bool switchPhy);
204 static void RCL_Handler_BLE5_readAuxPtrFromRxBuffer(uint32_t *data32, RCL_AuxPtrInfo *auxPtrInfo);
205 static void RCL_Handler_BLE5_updateBackoffParams(RCL_CtxScanInit * ctx, uint16_t endCause);
206 static uint8_t RCL_Handler_BLE5_checkExtHdrField(uint8_t extHdrFlags, uint8_t fieldMask);
207 
208 
209 
210 /* First BLE data channel number */
211 #define BLE_DATA_CHAN_MIN      0U
212 /* Last BLE data channel number */
213 #define BLE_DATA_CHAN_MAX      36U
214 /* Frequency of first BLE data channel */
215 #define BLE_DATA_CHAN_BASE     2404000000U
216 /* BLE channel spacing */
217 #define BLE_CHAN_SPACE         2000000U
218 /* Lower advertising channel */
219 #define BLE_ADV_CHAN_LO        37U
220 /* Middle advertising channel */
221 #define BLE_ADV_CHAN_MID       38U
222 /* Upper advertising channel */
223 #define BLE_ADV_CHAN_HI        39U
224 /* First BLE PHY channel number */
225 #define BLE_PHY_CHAN_MIN       64U
226 /* Last BLE PHY channel number */
227 #define BLE_PHY_CHAN_MAX       103U
228 /* Frequency of lower advertising channel */
229 #define BLE_ADV_CHAN_LO_FREQ   2402000000U
230 /* Frequency of middle advertising channel */
231 #define BLE_ADV_CHAN_MID_FREQ  2426000000U
232 /* Frequency of upper advertising channel */
233 #define BLE_ADV_CHAN_HI_FREQ   2480000000U
234 /* Interval between advertising packets when using high duty cycle advertising */
235 #define HIGH_DUTY_CYCLE_INTERVAL RCL_SCHEDULER_SYSTIM_US(1250)
236 /* Transmit delay between primary channel extended advertising packets */
237 #define EXT_ADV_INTERVAL_US 330U
238 /* Transmit delay associated with phy switching */
239 #define EXT_ADV_PHY_SWITCHING_DELAY_US 120U
240 /* See RCL-513.To be characterized */
241 #define RX_START_OVERHEAD      240U
242 #define RX_SYNC_OVERHEAD_1MBPS 164U
243 #define RX_SYNC_OVERHEAD_2MBPS 120U
244 #define RX_SYNC_OVERHEAD_CODED 1600U
245 /* Express systim units in terms of offset units */
246 #define BLE_convertSystimUnitsToOffsetUnits(x, offsetUnit) \
247 ((((uint32_t)(x) >> 2) + offsetUnit - 1) / ((uint32_t)(offsetUnit)))
248 /* Time from start of preamble to SYSTIM capture at sync found */
249 #define TIMESTAMP_ADJUST_1MBPS 267U
250 /* Time from start of preamble to SYSTIM capture at sync found */
251 #define TIMESTAMP_ADJUST_2MBPS 148U
252 /* Time from start of preamble to SYSTIM capture at sync found */
253 #define TIMESTAMP_ADJUST_CODED 1673U
254 /* Access address for advertising */
255 #define ADV_ACCESS_ADDRESS 0x8E89BED6U
256 /* Access address for DTM packets */
257 #define DTM_ACCESS_ADDRESS (~ADV_ACCESS_ADDRESS)
258 /* CRC initialization for advertising */
259 #define ADV_CRC_INIT (0x555555U << 8)
260 /* Maximum exponent of backoff algorithm */
261 #define BACKOFF_UPPER_MAX      8U
262 /* Timing of packets: */
263 /* Duration of a 1 Mbps packet with length = 0 */
264 #define BLE_1MBPS_PACKET_BASE_TIME RCL_SCHEDULER_SYSTIM_US(80)
265 /* Duration of an additional byte for 1 Mbps */
266 #define BLE_1MBPS_TIME_PER_BYTE RCL_SCHEDULER_SYSTIM_US(8)
267 /* Duration of a 2 Mbps packet with length = 0 */
268 #define BLE_2MBPS_PACKET_BASE_TIME RCL_SCHEDULER_SYSTIM_US(44)
269 /* Duration of an additional byte for 2 Mbps */
270 #define BLE_2MBPS_TIME_PER_BYTE RCL_SCHEDULER_SYSTIM_US(4)
271 /* Duration of a 125 kbps packet with length = 0 */
272 #define BLE_CODED_S8_PACKET_BASE_TIME RCL_SCHEDULER_SYSTIM_US(720)
273 /* Duration of an additional byte for 125 kbps */
274 #define BLE_CODED_S8_TIME_PER_BYTE RCL_SCHEDULER_SYSTIM_US(64)
275 /* Duration of a 500 kbps packet with length = 0 */
276 #define BLE_CODED_S2_PACKET_BASE_TIME RCL_SCHEDULER_SYSTIM_US(462)
277 /* Duration of an additional byte for 500 kbps */
278 #define BLE_CODED_S2_TIME_PER_BYTE RCL_SCHEDULER_SYSTIM_US(16)
279 /* Interframe space */
280 #define BLE_T_IFS RCL_SCHEDULER_SYSTIM_US(150)
281 /* Header length in bytes */
282 #define BLE_HEADER_LENGTH 2
283 /* Number of padding bytes */
284 #define BLE_NUM_PAD 3
285 /* CRC length in bytes */
286 #define BLE_CRC_LENGTH 3
287 /* Maximum length of a BLE packet */
288 #define BLE_MAX_PKT_LEN 255
289 /* Maximum length of a legacy advertising packet */
290 #define BLE_ADV_LEGACY_MAX_PKT_LEN 37
291 /* Maximum length of an extended advertising packet */
292 #define BLE_ADV_EXTENDED_MAX_PKT_LEN 255
293 /* Length of an AUX_SCAN_REQ */
294 #define BLE_ADV_AUX_SCAN_REQ_PKT_LEN 12
295 /* Clock Accuracy scale factor */
296 #define BLE_CLK_ACCURACY_SCALE_FACTOR 26
297 /* 50 PPM clock accuracy scaled by 2^26 */
298 #define BLE_SCALED_CLK_ACCURACY_50PPM 3355
299 /* 500 PPM clock accuracy scaled by 2^26 */
300 #define BLE_SCALED_CLK_ACCURACY_500PPM 33550
301 
302 /* Bit controlling advertiser filter policy for scanning */
303 #define BLE_ADV_FILTER_POLICY_SCAN 1
304 /* Bit controlling advertiser filter policy for connection */
305 #define BLE_ADV_FILTER_POLICY_CONN 2
306 
307 /* Number of filter list entries in PBE */
308 #define PBE_NUM_FILTER_ENTRIES 16U
309 
310 /* PHY feature definitions - must match the setup */
311 #define BLE_PHY_FEATURE_PHY_1MBPS 0
312 #define BLE_PHY_FEATURE_PHY_2MBPS 1
313 #define BLE_PHY_FEATURE_PHY_CODED 2
314 #define BLE_PHY_FEATURE_PHY_MASK  0x0003
315 #define BLE_PHY_FEATURE_CODING_S8 0
316 #define BLE_PHY_FEATURE_CODING_S2 4
317 #define BLE_PHY_FEATURE_CODING_MASK  0x0004
318 
319 /* DTM packet header definition */
320 #define BLE_DTM_PAYLOAD_TYPE_PRBS9                  0x00
321 #define BLE_DTM_PAYLOAD_TYPE_11110000               0x01
322 #define BLE_DTM_PAYLOAD_TYPE_10101010               0x02
323 #define BLE_DTM_PAYLOAD_TYPE_PRBS15                 0x03
324 #define BLE_DTM_PAYLOAD_TYPE_11111111               0x04
325 #define BLE_DTM_PAYLOAD_TYPE_00000000               0x05
326 #define BLE_DTM_PAYLOAD_TYPE_00001111               0x06
327 #define BLE_DTM_PAYLOAD_TYPE_01010101               0x07
328 
329 /** Polynomial to use for PRBS9 data */
330 #define RCL_HANDLER_BLE5_PRBS9_POLY                 0x08800000
331 #define RCL_HANDLER_BLE5_PRBS9_INIT                 0x0000001F
332 /** Polynomial to use for PRBS15 data */
333 #define RCL_HANDLER_BLE5_PRBS15_POLY                0x00060000
334 #define RCL_HANDLER_BLE5_PRBS15_INIT                0x00003FFF
335 /** Polynomial to use for PRBS32 data */
336 #define RCL_HANDLER_BLE5_PRBS32_POLY                0x00400007
337 #define RCL_HANDLER_BLE5_PRBS32_INIT                0x00005555
338 #define RCL_HANDLER_BLE5_PRBS_SYNC                  0xAB05FA1C
339 
340 /* Transmit window timing constants */
341 /* Payload length of a CONNECT_IND or AUX_CONNECT_REQ in bytes */
342 #define BLE_CONNECT_MSG_LEN                         34U
343 /* Payload length of an AUX_CONNECT_RSP in bytes */
344 #define BLE_AUX_CONNECT_RSP_MSG_LEN                 14U
345 /* Position of WinSize in a CONNECT_IND or AUX_CONNECT_REQ */
346 #define BLE_WIN_SIZE_POS                            19U
347 /* Position of WinOffset in a CONNECT_IND or AUX_CONNECT_REQ */
348 #define BLE_WIN_OFFSET_POS                          20U
349 /* Position of Interval in a CONNECT_IND or AUX_CONNECT_REQ */
350 #define BLE_INTERVAL_POS                            22U
351 /* Position of Latency in a CONNECT_IND or AUX_CONNECT_REQ */
352 #define BLE_LATENCY_POS                             24U
353 /* Position of Timeout in a CONNECT_IND or AUX_CONNECT_REQ */
354 #define BLE_TIMEOUT_POS                             26U
355 /* Transmit window delay for legacy advertising */
356 #define BLE_TRANSMIT_WINDOW_DELAY_LEGACY            RCL_SCHEDULER_SYSTIM_US(1250)
357 /* Transmit window delay for extended advertising */
358 #define BLE_TRANSMIT_WINDOW_DELAY_EXT_UNCODED       RCL_SCHEDULER_SYSTIM_US(2500)
359 #define BLE_TRANSMIT_WINDOW_DELAY_EXT_CODED         RCL_SCHEDULER_SYSTIM_US(3750)
360 /* Connection interval unit */
361 #define BLE_CONNECT_INT_UNIT                        RCL_SCHEDULER_SYSTIM_US(1250)
362 /* Number of sub-intervals per connection interval unit used in connection setup */
363 #define RCL_BLE5_CONNECT_INT_SUB_DIV                4
364 /* Duration of a sub-interval */
365 #define RCL_BLE5_CONNECT_SUB_INT                    (BLE_CONNECT_INT_UNIT / RCL_BLE5_CONNECT_INT_SUB_DIV)
366 
367 /* LRFD runs on a 48 MHz clock */
368 #define LRF_CLOCK_TICKS_PER_US                      48
369 
370 /* Offset units for Extended advertising */
371 #define BLE_AUX_OFFSET_300_US                       300U
372 #define BLE_AUX_OFFSET_30_US                        30U
373 
374 /* Bitmask for the advertiser's device address flag in the Extended Header Flags byte */
375 #define BLE_EXTENDED_HEADER_ADVA_BM                 0x01
376 /* Bitmask for the target's device address flag in the Extended Header Flags byte */
377 #define BLE_EXTENDED_HEADER_TARGETA_BM              0x02
378 /* Bitmask for the CTEInfo flag in the Extended Header Flags byte */
379 #define BLE_EXTENDED_HEADER_CTEINFO_BM              0x04
380 /* Bitmask for the ADI flag in the Extended Header Flags byte */
381 #define BLE_EXTENDED_HEADER_ADI_BM                  0x08
382 /* Bitmask for the AuxPtr flag in the Extended Header Flags byte */
383 #define BLE_EXTENDED_HEADER_AUXPTR_BM               0x10
384 /* Bitmask for the SyncInfo flag in the Extended Header Flags byte */
385 #define BLE_EXTENDED_HEADER_SYNCINFO_BM             0x20
386 /* Bitmask for the Tx Power flag in the Extended Header Flags byte */
387 #define BLE_EXTENDED_HEADER_TXPOWER_BM              0x40
388 
389 /* Length in bytes of the advertiser's device address */
390 #define BLE_EXTENDED_HEADER_ADVA_LEN                6
391 /* Length in bytes of the target's device address */
392 #define BLE_EXTENDED_HEADER_TARGETA_LEN             6
393 /* Length in bytes of the CTEInfo field */
394 #define BLE_EXTENDED_HEADER_CTEINFO_LEN             1
395 /* Length in bytes of the CTEInfo field */
396 #define BLE_EXTENDED_HEADER_ADI_LEN                 2
397 /* Length in bytes of the AuxPtr field */
398 #define BLE_EXTENDED_HEADER_AUXPTR_LEN              3
399 /* Length in bytes of the SyncInfo field */
400 #define BLE_EXTENDED_HEADER_SYNCINFO_LEN            18
401 /* Length in bytes of the Tx Power field */
402 #define BLE_EXTENDED_HEADER_TXPOWER_LEN             1
403 
404 /* Bitmask for accessing PDU Type */
405 #define BLE_PDU_TYPE_BM                             0x0F
406 
407 /* Bitmask for accessing advertising mode */
408 #define BLE_ADV_MODE_BM                             0xC0
409 
410 /* Advertising physical channel PDU header's PDU Type */
411 #define BLE_PDU_ADV_IND                             0x00
412 #define BLE_PDU_ADV_DIRECT_IND                      0x01
413 #define BLE_PDU_ADV_NONCONN_IND                     0x02
414 #define BLE_PDU_ADV_SCAN_IND                        0x06
415 #define BLE_PDU_ADV_EXTENDED                        0x07
416 #define BLE_PDU_AUX_CONNECT_RSP                     0x08
417 
418 /* Available advertising modes in the common extended advertising payload format */
419 #define BLE_ADV_MODE_NONCONN_NONSCAN                0x00
420 #define BLE_ADV_MODE_CONN_NONSCAN                   0x01
421 #define BLE_ADV_MODE_NONCONN_SCAN                   0x02
422 
423 
424 /**
425  *  @brief Pointer to a given byte in the data part of a TX buffer
426  *
427  *  @param  buffer    Pointer to TX buffer
428  *
429  *  @param  pos       Position
430  *
431  */
432 #define txBuffer_dataByte(buffer, pos) ((buffer->data) + ((buffer->numPad) - 1 + pos))
433 
434 /*
435  *  ======== RCL_Handler_BLE5_adv ========
436  */
RCL_Handler_BLE5_adv(RCL_Command * cmd,LRF_Events lrfEvents,RCL_Events rclEventsIn)437 RCL_Events RCL_Handler_BLE5_adv(RCL_Command *cmd, LRF_Events lrfEvents, RCL_Events rclEventsIn)
438 {
439     uint32_t rfFreq;
440     RCL_CmdBle5Advertiser *advCmd = (RCL_CmdBle5Advertiser *) cmd;
441     bool runAdv = false;
442     bool runExtAdv = false;
443     bool advDone = false;
444     RCL_Ble5Channel curChannel;
445     RCL_Events rclEvents = {.value = 0};
446     uint32_t earliestStartTime = 0;
447 
448     if (rclEventsIn.setup != 0)
449     {
450         /* Start by enabling refsys */
451         earliestStartTime = LRF_enableSynthRefsys();
452 
453         ble5HandlerState.adv.chanMap = advCmd->chanMap;
454 
455         /* Keep track of the number of primary channel packets to be sent based on the channel map */
456         ble5HandlerState.common.auxPtrInfo.numPrimaryChPackets = (advCmd->chanMap & 1) + ((advCmd->chanMap >> 1) & 1) + ((advCmd->chanMap >> 2) & 1);
457         HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_MDMSYNCA) = ADV_ACCESS_ADDRESS;
458 
459         /* 32-bit access to also write CRCINITH */
460         HWREG_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_CRCINITL) = ADV_CRC_INIT;
461 
462         ble5HandlerState.common.fifoCfg = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FIFOCFG);
463         HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_EXTRABYTES) = RCL_Handler_BLE5_findNumExtraBytes(ble5HandlerState.common.fifoCfg);
464 
465         /* Default end status */
466         ble5HandlerState.common.endStatus = RCL_CommandStatus_Finished;
467 
468         RCL_CommandStatus status = RCL_Handler_BLE5_setPhy(cmd->phyFeatures);
469         if (LRF_programTxPower(advCmd->txPower) != TxPowerResult_Ok)
470         {
471             status = RCL_CommandStatus_Error_Param;
472         }
473 
474         if (status == RCL_CommandStatus_Active)
475         {
476             /* Initialize RF FIFOs */
477             ble5HandlerState.common.rxFifoSz = LRF_prepareRxFifo();
478             ble5HandlerState.common.curBuffer = NULL;
479             RCL_Handler_BLE5_updateRxCurBufferAndFifo(&advCmd->ctx->rxBuffers);
480             ble5HandlerState.common.txFifoSz = LRF_prepareTxFifo();
481 
482             /* Enter address */
483             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_OWNADRL) = advCmd->ctx->advA[0];
484             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_OWNADRM) = advCmd->ctx->advA[1];
485             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_OWNADRH) = advCmd->ctx->advA[2];
486             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_OWNADRTYPE) = advCmd->ctx->addrType.own;
487 
488             /* Find which type of advertising */
489             RCL_Buffer_TxBuffer *txBuffer = RCL_TxBuffer_head(&advCmd->ctx->txBuffers);
490             uint16_t advCfg = 0;
491 
492             if (txBuffer != NULL)
493             {
494                 uint8_t header = txBuffer->data[txBuffer->numPad - 1];
495 
496                 /* Check advertising type */
497                 switch (header & BLE_PDU_TYPE_BM)
498                 {
499                     case BLE_PDU_ADV_IND:
500                         advCfg = PBE_BLE5_RAM_ADVCFG_CONNECTABLE_M | PBE_BLE5_RAM_ADVCFG_SCANNABLE_M;
501                         ble5HandlerState.adv.runRx = true;
502                         ble5HandlerState.adv.isExtAdv = false;
503                         ble5HandlerState.adv.auxScanReqReceived = false;
504                         ble5HandlerState.common.auxPtrInfo.auxPtrPresent = false;
505                         break;
506 
507                     case BLE_PDU_ADV_DIRECT_IND:
508                         advCfg = PBE_BLE5_RAM_ADVCFG_CONNECTABLE_M | PBE_BLE5_RAM_ADVCFG_DIRECTED_M;
509                         /* Enter address */
510                         HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_PEERADRL) = advCmd->ctx->peerA[0];
511                         HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_PEERADRM) = advCmd->ctx->peerA[1];
512                         HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_PEERADRH) = advCmd->ctx->peerA[2];
513                         HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_PEERADRTYPE) = advCmd->ctx->addrType.peer;
514                         ble5HandlerState.adv.runRx = true;
515                         ble5HandlerState.adv.isExtAdv = false;
516                         ble5HandlerState.adv.auxScanReqReceived = false;
517                         ble5HandlerState.common.auxPtrInfo.auxPtrPresent = false;
518                         break;
519 
520                     case BLE_PDU_ADV_NONCONN_IND:
521                         advCfg = 0;
522                         ble5HandlerState.adv.runRx = false;
523                         ble5HandlerState.adv.isExtAdv = false;
524                         ble5HandlerState.adv.auxScanReqReceived = false;
525                         ble5HandlerState.common.auxPtrInfo.auxPtrPresent = false;
526                         break;
527 
528                     case BLE_PDU_ADV_SCAN_IND:
529                         advCfg = PBE_BLE5_RAM_ADVCFG_SCANNABLE_M;
530                         ble5HandlerState.adv.runRx = true;
531                         ble5HandlerState.adv.isExtAdv = false;
532                         ble5HandlerState.adv.auxScanReqReceived = false;
533                         ble5HandlerState.common.auxPtrInfo.auxPtrPresent = false;
534                         break;
535 
536                     case BLE_PDU_ADV_EXTENDED:
537                         advCfg = 0;
538                         ble5HandlerState.adv.runRx = false;
539                         ble5HandlerState.adv.isExtAdv = true;
540                         ble5HandlerState.adv.auxScanReqReceived = false;
541                         /* Extract AuxPtr information if available */
542                         RCL_Handler_BLE5_getAuxPtrFromTxBuffer(txBuffer, &ble5HandlerState.common.auxPtrInfo, 0);
543                         if (ble5HandlerState.common.auxPtrInfo.auxPtrPresent)
544                         {
545                             /* Check if a PHY switch is needed before the move to secondary channel advertising */
546                             if ((cmd->phyFeatures & 0x03) != ble5HandlerState.common.auxPtrInfo.auxPhy)
547                             {
548                                 ble5HandlerState.adv.switchPhy = true;
549                             }
550                             else
551                             {
552                                 ble5HandlerState.adv.switchPhy = false;
553                             }
554                         }
555                         else
556                         {
557                             ble5HandlerState.adv.switchPhy = false;
558                         }
559                         break;
560 
561                     default:
562                         advCfg = 0;
563                         ble5HandlerState.adv.runRx = false;
564                         ble5HandlerState.adv.isExtAdv = false;
565                         ble5HandlerState.adv.auxScanReqReceived = false;
566                         ble5HandlerState.common.auxPtrInfo.auxPtrPresent = false;
567                         break;
568                 }
569             }
570             /* Enter payload.
571              * For legacy advertising, maximum two Tx buffers can be entered (to account for possible SCAN_RSP PDUs).
572              * For extended advertising, enter only one Tx buffer (corresponding to the ADV_EXT_IND PDU).
573              */
574             uint32_t nBuffer;
575             if (ble5HandlerState.adv.isExtAdv)
576             {
577                 ble5HandlerState.common.txBufferInfo = (RCL_TxBufferInfo) { 0 };
578                 nBuffer = RCL_Handler_BLE5_updateTxBuffers(&advCmd->ctx->txBuffers, 1,
579                                                            &ble5HandlerState.common.txBufferInfo,
580                                                             false);
581             }
582             else
583             {
584                 nBuffer = RCL_Handler_BLE5_updateTxBuffers(&advCmd->ctx->txBuffers, 2,
585                                                             NULL, false);
586             }
587             if (nBuffer == 0)
588             {
589                 status = RCL_CommandStatus_Error_MissingTxBuffer;
590             }
591             else
592             {
593                 /* Scannable types also need a SCAN_RSP */
594                 if (((advCfg & PBE_BLE5_RAM_ADVCFG_SCANNABLE_M) != 0) && (nBuffer < 2))
595                 {
596                     status = RCL_CommandStatus_Error_MissingTxBuffer;
597                 }
598                 else
599                 {
600                     HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_ADVCFG) = advCfg;
601                     HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FILTPOLICY) = (advCmd->ctx->filterPolicy << PBE_BLE5_RAM_FILTPOLICY_ADV_S) &
602                                                                                       PBE_BLE5_RAM_FILTPOLICY_ADV_M;
603                     HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_RPAMODE) = (advCmd->ctx->rpaModePeer << PBE_BLE5_RAM_RPAMODE_PEERADR_S);
604                     HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_RPACONNECT) = advCmd->ctx->acceptAllRpaConnectInd << PBE_BLE5_RAM_RPACONNECT_ENDADV_S;
605 
606                     if ((advCfg & PBE_BLE5_RAM_ADVCFG_SCANNABLE_M) != 0)
607                     {
608                         RCL_FilterList *filterList = advCmd->ctx->filterListScan;
609                         uint32_t invertMask = 0;
610                         if ((advCmd->ctx->filterPolicy & BLE_ADV_FILTER_POLICY_SCAN) != 0)
611                         {
612                             /* Set filter list masks to normal accept list use: */
613                             /* Bit 0: Consider enable bit */
614                             /* Bit 1: Consider type bit */
615                             /* Bit 3: Consider privIgn bit */
616                             /* Bit 15: Consider match bit (found by PBE) */
617                             /* Other bits are not checked */
618                             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FL1MASK) = PBE_BLE5_RAM_FL1MASK_MATCH_M |
619                                                                                           PBE_BLE5_RAM_FL1MASK_PRIVIGN_M |
620                                                                                           PBE_BLE5_RAM_FL1MASK_TYPE_M |
621                                                                                           PBE_BLE5_RAM_FL1MASK_EN_M;
622                         }
623                         else
624                         {
625                             if (advCmd->ctx->privIgnMode != 0)
626                             {
627                                 /* Set filter list masks for RPA filtering: */
628                                 /* Bit 1: Consider type bit */
629                                 /* Bit 3: Consider pribvIgn bit */
630                                 /* Bit 15: Consider match bit (found by PBE) */
631                                 /* Other bits are not checked */
632                                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FL1MASK) = PBE_BLE5_RAM_FL1MASK_MATCH_M |
633                                                                                               PBE_BLE5_RAM_FL1MASK_PRIVIGN_M |
634                                                                                               PBE_BLE5_RAM_FL1MASK_TYPE_M;
635                                 invertMask = PBE_BLE5_RAM_FL1MASK_PRIVIGN_M;
636                             }
637                             else
638                             {
639                                 /* Filter list not used */
640                                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FL1MASK) = 0;
641                                 filterList = NULL;
642                             }
643                         }
644                         RCL_Handler_BLE5_InitializeFilterList(filterList, (uint32_t *) (volatile unsigned short*) (LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FL1INFO0), invertMask);
645                     }
646                     else
647                     {
648                         /* Filter list not applicable */
649                         HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FL1MASK) = 0;
650                     }
651                     if ((advCfg & PBE_BLE5_RAM_ADVCFG_CONNECTABLE_M) != 0)
652                     {
653                         RCL_FilterList *filterList = advCmd->ctx->filterListConn;
654                         uint32_t invertMask = 0;
655                         if ((advCmd->ctx->filterPolicy & BLE_ADV_FILTER_POLICY_CONN) != 0)
656                         {
657                             /* Set filter list masks to normal accept list use: */
658                             /* Bit 0: Consider enable bit */
659                             /* Bit 1: Consider type bit */
660                             /* Bit 3: Consider privIgn bit */
661                             /* Bit 15: Consider match bit (found by PBE) */
662                             /* Other bits are not checked */
663                             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FL2MASK) = PBE_BLE5_RAM_FL2MASK_MATCH_M |
664                                                                                           PBE_BLE5_RAM_FL2MASK_PRIVIGN_M |
665                                                                                           PBE_BLE5_RAM_FL2MASK_TYPE_M |
666                                                                                           PBE_BLE5_RAM_FL2MASK_EN_M;
667                         }
668                         else
669                         {
670                             if (advCmd->ctx->privIgnMode != 0)
671                             {
672                                 /* Set filter list masks for RPA filtering: */
673                                 /* Bit 1: Consider type bit */
674                                 /* Bit 3: Consider privIgn bit */
675                                 /* Bit 15: Consider match bit (found by PBE) */
676                                 /* Other bits are not checked */
677                                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FL2MASK) = PBE_BLE5_RAM_FL2MASK_MATCH_M |
678                                                                                               PBE_BLE5_RAM_FL2MASK_PRIVIGN_M |
679                                                                                               PBE_BLE5_RAM_FL2MASK_TYPE_M;
680                                 invertMask = PBE_BLE5_RAM_FL2MASK_PRIVIGN_M;
681                             }
682                             else
683                             {
684                                 /* Filter list not used */
685                                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FL2MASK) = 0;
686                                 filterList = NULL;
687                             }
688                         }
689                         RCL_Handler_BLE5_InitializeFilterList(filterList, (uint32_t *) (volatile unsigned short*) (LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FL2INFO0), invertMask);
690                     }
691                     else
692                     {
693                         /* Filter list not applicable */
694                         HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FL2MASK) = 0;
695                     }
696                     /* Run advertiser next */
697                     runAdv = true;
698                 }
699 
700                 /* Once packets are copied to the TX FIFO, consume them from the Tx Buffer list and notify the caller (only for extended) */
701                 if (ble5HandlerState.adv.isExtAdv)
702                 {
703                     RCL_Buffer_TxBuffer *txBuffer;
704                     txBuffer = RCL_TxBuffer_get(&advCmd->ctx->txBuffers);
705                     if (txBuffer == NULL)
706                     {
707                         /* Error */
708                         ble5HandlerState.common.endStatus = RCL_CommandStatus_Error_TxBufferCorruption;
709                     }
710                     txBuffer->state = RCL_BufferStateFinished;
711                     if (txBuffer == ble5HandlerState.common.txBufferInfo.lastEnteredTxBuffer)
712                     {
713                         ble5HandlerState.common.txBufferInfo.lastEnteredTxBuffer = NULL;
714                     }
715                     rclEvents.txBufferFinished = 1;
716                 }
717             }
718         }
719         /* Set status */
720         cmd->status = status;
721         if (status >= RCL_CommandStatus_Finished)
722         {
723             rclEvents.lastCmdDone = 1;
724         }
725     }
726     if(rclEventsIn.handlerCmdUpdate != 0)
727     {
728         /* PHY change concluded successfully. Proceed with the advertising event */
729         runExtAdv = true;
730     }
731 
732     if (cmd->status == RCL_CommandStatus_Active)
733     {
734         if (lrfEvents.rxOk != 0 || lrfEvents.rxNok != 0 || lrfEvents.rxIgnored != 0 || lrfEvents.rxBufFull != 0)
735         {
736             /* Copy received packet from PBE FIFO to buffer */
737             /* First, check that there is actually a buffer available */
738             while (HWREG_READ_LRF(LRFDPBE_BASE + LRFDPBE_O_RXFREADABLE) >= 4)
739             {
740                 /* Check length of received buffer by peeking */
741                 uint32_t fifoWord = LRF_peekRxFifo(0);
742                 uint32_t wordLength = RCL_Buffer_DataEntry_paddedLen(fifoWord & 0xFFFF) / 4;
743                 if (wordLength > 0)
744                 {
745                     RCL_MultiBuffer *curBuffer;
746                     curBuffer = RCL_MultiBuffer_getBuffer(ble5HandlerState.common.curBuffer,
747                                                           wordLength * 4);
748                     if (curBuffer != ble5HandlerState.common.curBuffer)
749                     {
750                         rclEvents.rxBufferFinished = 1;
751                         ble5HandlerState.common.curBuffer = curBuffer;
752                     }
753                     if (curBuffer == NULL)
754                     {
755                         /* Error */
756                         ble5HandlerState.common.endStatus = RCL_CommandStatus_Error_RxBufferCorruption;
757                         /* Send abort */
758                         HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_API) = PBE_BLE5_REGDEF_API_OP_STOP;
759                         /* Do not check for more packets from the RX FIFO */
760                         break;
761                     }
762                     else
763                     {
764                         uint32_t *data32;
765                         data32 = (uint32_t *)RCL_MultiBuffer_getNextWritableByte(curBuffer);
766                         LRF_readRxFifoWords(data32, wordLength);
767                         RCL_Handler_BLE5_commitPacket(curBuffer, wordLength * 4);
768                         /* Raise event */
769                         rclEvents.rxEntryAvail = 1;
770                         /* Adjust effective FIFO size */
771                         RCL_Handler_BLE5_updateRxCurBufferAndFifo(&advCmd->ctx->rxBuffers);
772                         rclEventsIn.rxBufferUpdate = 0;
773                         if (ble5HandlerState.adv.isExtAdv)
774                         {
775                             ble5HandlerState.adv.auxScanReqReceived = true;
776                         }
777                     }
778                 }
779             }
780             if (ble5HandlerState.common.activeUpdate)
781             {
782                 RCL_Handler_BLE5_updateAdvScanInitStats(advCmd->stats, rclSchedulerState.actualStartTime);
783             }
784         }
785         if (rclEventsIn.timerStart != 0)
786         {
787             rclEvents.cmdStarted = 1;
788         }
789         if (rclEventsIn.gracefulStop != 0)
790         {
791             ble5HandlerState.adv.gracefulStopObserved = true;
792         }
793 
794         if (lrfEvents.opDone != 0 && rclEventsIn.handlerCmdUpdate == 0)
795         {
796             uint16_t endCause = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_COMMON_RAM_O_ENDCAUSE);
797 
798             if (endCause == PBE_COMMON_RAM_ENDCAUSE_STAT_CONNECT)
799             {
800                 /* 32-bit access to also read LASTTIMESTAMPH */
801                 advCmd->connectPktTime = HWREG_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_LASTTIMESTAMPL) - ble5HandlerState.common.timestampAdjust;
802                 ble5HandlerState.common.endStatus = RCL_CommandStatus_Connect;
803                 RCL_Profiling_eventHook(RCL_ProfilingEvent_PostprocStart);
804                 runAdv = false;
805                 runExtAdv = false;
806                 advDone = true;
807             }
808             else if (rclEventsIn.hardStop != 0)
809             {
810                 ble5HandlerState.common.endStatus = RCL_Scheduler_findStopStatus(RCL_StopType_Hard);
811                 runAdv = false;
812                 runExtAdv = false;
813                 advDone = true;
814             }
815             else if (endCause == PBE_COMMON_RAM_ENDCAUSE_STAT_EOPSTOP ||
816                         ble5HandlerState.adv.gracefulStopObserved ||
817                         rclEventsIn.gracefulStop != 0)
818             {
819                 ble5HandlerState.common.endStatus = RCL_Scheduler_findStopStatus(RCL_StopType_Graceful);
820                 runAdv = false;
821                 runExtAdv = false;
822                 advDone = true;
823             }
824             else if (endCause == PBE_COMMON_RAM_ENDCAUSE_STAT_NOSYNC && ble5HandlerState.common.auxPtrInfo.auxPtrPresent)
825             {
826                 /* If no AUX_SCAN_REQ is received, no point in sending any subsequent AUX_CHAIN_IND PDUs */
827                 runAdv = false;
828                 runExtAdv = false;
829                 advDone = true;
830             }
831             else
832             {
833                 if (ble5HandlerState.adv.chanMap != 0)
834                 {
835                     /* Retry TX FIFO. Writing to FCMD is safe because PBE is finished, ref. RCL-367 */
836                     HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_FCMD) = (LRFDPBE_FCMD_DATA_TXFIFO_RETRY >> LRFDPBE_FCMD_DATA_S);
837 
838                     if (ble5HandlerState.common.activeUpdate)
839                     {
840                         RCL_Handler_BLE5_updateAdvScanInitStats(advCmd->stats, rclSchedulerState.actualStartTime);
841                     }
842 
843                     /* Turn off LRF to allow new synth programming  */
844                     LRF_disable();
845                     runAdv = true;
846                     runExtAdv = false;
847                     advDone = false;
848                 }
849                 else
850                 {
851                     /* Once done with primary channel advertising, check AuxPtr and proceed with extended advertising if needed. */
852                     if (ble5HandlerState.common.auxPtrInfo.auxPtrPresent)
853                     {
854                         if (ble5HandlerState.common.auxPtrInfo.offsetUnits == 1 && ble5HandlerState.common.auxPtrInfo.auxOffset == 0)
855                         {
856                             /* Reset TX FIFO to handle auxPtr updates. Writing to FCMD is safe because PBE is finished, ref. RCL-367 */
857                             HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_FCMD) = (LRFDPBE_FCMD_DATA_TXFIFO_RESET >> LRFDPBE_FCMD_DATA_S);
858 
859                             /* Turn off LRF to allow new synth programming  */
860                             LRF_disable();
861 
862                             if (ble5HandlerState.adv.switchPhy)
863                             {
864                                 /* Update phyFeatures while keeping the code rate selection intact */
865                                 rclSchedulerState.requestedPhyFeatures = ble5HandlerState.common.auxPtrInfo.auxPhy | (cmd->phyFeatures & 0x04);
866 
867                                 /* Raise a partialSetup event so that the PHY switching can be applied by the RCL */
868                                 rclEvents.partialSetup = 1;
869                             }
870                             else
871                             {
872                                 runExtAdv = true;
873                             }
874                             runAdv = false;
875                             advDone = false;
876                         }
877                         else
878                         {
879                             advDone = true;
880                         }
881                     }
882                     else
883                     {
884                         advDone = true;
885                     }
886                 }
887             }
888             if (advDone)
889             {
890                 cmd->status = ble5HandlerState.common.endStatus;
891                 rclEvents.lastCmdDone = 1;
892                 runAdv = false;
893                 runExtAdv = false;
894                 RCL_Profiling_eventHook(RCL_ProfilingEvent_PostprocStart);
895             }
896         }
897         else if (lrfEvents.opError != 0)
898         {
899             RCL_CommandStatus endStatus = ble5HandlerState.common.endStatus;
900             if (endStatus == RCL_CommandStatus_Finished)
901             {
902                 cmd->status = RCL_Handler_BLE5_findPbeErrorEndStatus(HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_COMMON_RAM_O_ENDCAUSE));
903             }
904             else
905             {
906                 cmd->status = endStatus;
907             }
908             rclEvents.lastCmdDone = 1;
909             runAdv = false;
910             runExtAdv = false;
911         }
912         else
913         {
914             /* Other events need to be handled unconditionally */
915         }
916 
917         if (rclEventsIn.rxBufferUpdate != 0)
918         {
919             RCL_Handler_BLE5_updateRxCurBufferAndFifo(&advCmd->ctx->rxBuffers);
920             rclEventsIn.rxBufferUpdate = 0;
921         }
922 
923         if (runAdv)
924         {
925             curChannel = RCL_Handler_BLE5_findAdvChannel(ble5HandlerState.adv.chanMap, advCmd->order);
926             uint32_t pktDuration = RCL_Handler_BLE5_findPacketDuration(ble5HandlerState.common.auxPtrInfo.pktLen, ble5HandlerState.common.phyFeatures);
927 
928             rfFreq = RCL_Handler_BLE5_findRfFreq(curChannel);
929             if (rfFreq == 0)
930             {
931                 cmd->status = RCL_CommandStatus_Error_Param;
932                 rclEvents.lastCmdDone = 1;
933             }
934             else
935             {
936                 /* Program frequency word */
937                 LRF_programFrequency(rfFreq, true);
938                 LRF_enable();
939 
940                 RCL_CommandStatus startTimeStatus;
941 
942                 if (rclEventsIn.setup != 0)
943                 {
944                     startTimeStatus = RCL_Scheduler_setStartStopTimeEarliestStart(cmd, earliestStartTime);
945                     if (startTimeStatus < RCL_CommandStatus_Finished)
946                     {
947                         if (ble5HandlerState.adv.isExtAdv && ble5HandlerState.common.auxPtrInfo.auxPtrPresent)
948                         {
949                             /* Calculate auxPtr offset and update Tx FIFO if needed */
950                             if(!RCL_Handler_BLE5_updateAuxPtr(&ble5HandlerState.common.auxPtrInfo, pktDuration, ble5HandlerState.adv.chanMap, ble5HandlerState.adv.switchPhy))
951                             {
952                                 startTimeStatus = RCL_CommandStatus_Error_Param;
953                             }
954                         }
955                         /* Initialize counters */
956                         ble5HandlerState.common.activeUpdate =
957                             RCL_Handler_BLE5_initAdvScanInitStats(advCmd->stats, rclSchedulerState.actualStartTime);
958                         ble5HandlerState.adv.gracefulStopObserved = false;
959                         if (rclSchedulerState.gracefulStopInfo.cmdStopEnabled || rclSchedulerState.gracefulStopInfo.schedStopEnabled)
960                         {
961                             /* Enable interrupt to service graceful stop */
962                             hal_enable_graceful_stop_time_irq();
963                         }
964                     }
965                 }
966                 else
967                 {
968                     if (advCmd->highDuty != 0)
969                     {
970                         startTimeStatus = RCL_Scheduler_setNewStartRelTime(HIGH_DUTY_CYCLE_INTERVAL);
971                     }
972                     else
973                     {
974                         if (ble5HandlerState.adv.isExtAdv && ble5HandlerState.common.auxPtrInfo.auxPtrPresent)
975                         {
976                             /*
977                              * All primary advertising packets must point to the same time at which the auxiliary packet will be sent.
978                              * Achieve this by using a relative start time to previous LRF start where the packet duration is also expressed
979                              * in terms of 30 [us] units. This facilitates the calculation of the auxOffset.
980                              */
981                             uint32_t pktDurationInOffsetUnits = BLE_convertSystimUnitsToOffsetUnits(pktDuration, BLE_AUX_OFFSET_30_US);
982                             uint32_t relStartTime = RCL_SCHEDULER_SYSTIM_US((pktDurationInOffsetUnits * BLE_AUX_OFFSET_30_US) + EXT_ADV_INTERVAL_US);
983                             startTimeStatus = RCL_Scheduler_setNewStartRelTime(relStartTime);
984 
985                             /* Calculate auxPtr offset and update Tx FIFO if needed */
986                             if(!RCL_Handler_BLE5_updateAuxPtr(&ble5HandlerState.common.auxPtrInfo, pktDuration, ble5HandlerState.adv.chanMap, ble5HandlerState.adv.switchPhy))
987                             {
988                                 startTimeStatus = RCL_CommandStatus_Error_Param;
989                             }
990                         }
991                         else
992                         {
993                             startTimeStatus = RCL_Scheduler_setNewStartNow();
994                         }
995                     }
996                 }
997                 if (startTimeStatus >= RCL_CommandStatus_Finished)
998                 {
999                     cmd->status = startTimeStatus;
1000                     rclEvents.lastCmdDone = 1;
1001                 }
1002                 else
1003                 {
1004                     HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_OPCFG) = 0;
1005                     uint16_t whitenInit = RCL_Handler_BLE5_findWhitenInit(curChannel);
1006                     HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_WHITEINIT) = whitenInit;
1007                     if (ble5HandlerState.common.accessAddressModification)
1008                     {
1009                         HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_MDMSYNCA) = ADV_ACCESS_ADDRESS ^ (whitenInit << 24);
1010                     }
1011 
1012                     /* Enable interrupts */
1013                     if (ble5HandlerState.adv.runRx)
1014                     {
1015                         /* Set up sync found capture */
1016                         hal_setup_sync_found_cap();
1017                         uint16_t fifoCfg = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FIFOCFG);
1018                         LRF_enableHwInterrupt(RCL_Handler_BLE5_maskEventsByFifoConf(LRF_EventOpDone.value | LRF_EventOpError.value |
1019                                                                                     LRF_EventRxOk.value | LRF_EventRxIgnored.value |
1020                                                                                     LRF_EventRxNok.value | LRF_EventRxBufFull.value,
1021                                                                                     fifoCfg, ble5HandlerState.common.activeUpdate));
1022                     }
1023                     else
1024                     {
1025                         LRF_enableHwInterrupt(LRF_EventOpDone.value | LRF_EventOpError.value);
1026                     }
1027 
1028                     /* Post cmd */
1029                     Log_printf(RclCore, Log_VERBOSE, "Starting advertiser on channel %1d", curChannel);
1030 
1031                     LRF_waitForTopsmReady();
1032                     RCL_Profiling_eventHook(RCL_ProfilingEvent_PreprocStop);
1033                     HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_API) = PBE_BLE5_REGDEF_API_OP_ADV;
1034 
1035                     if ((curChannel & BLE_CUSTOM_FREQ_BM) != 0)
1036                     {
1037                         /* Custom channel - run only once */
1038                         ble5HandlerState.adv.chanMap = 0;
1039                     }
1040                     else
1041                     {
1042                         ble5HandlerState.adv.chanMap &= ~(1 << (curChannel - 37));
1043                         if (advCmd->highDuty != 0 && ble5HandlerState.adv.chanMap == 0)
1044                         {
1045                             /* High duty cycle advertising: Reload channel map when one round is done */
1046                             ble5HandlerState.adv.chanMap = advCmd->chanMap;
1047                         }
1048                     }
1049                 }
1050             }
1051         }
1052         if (runExtAdv)
1053         {
1054             RCL_CommandStatus startTimeStatus;
1055             RCL_Ble5Channel channel;
1056             uint32_t startTimeDelta = 0;
1057 
1058             /* Switch to the channel indicated by the auxPtr */
1059             channel = ble5HandlerState.common.auxPtrInfo.chIndex;
1060             rfFreq = RCL_Handler_BLE5_findRfFreq(channel);
1061             if (rfFreq == 0)
1062             {
1063                 cmd->status = RCL_CommandStatus_Error_Param;
1064                 rclEvents.lastCmdDone = 1;
1065             }
1066             else
1067             {
1068                 /* Program frequency word */
1069                 LRF_programFrequency(rfFreq, true);
1070                 LRF_enable();
1071 
1072                 RCL_Buffer_TxBuffer *nextTxBuffer = RCL_TxBuffer_head(&advCmd->ctx->txBuffers);
1073                 uint16_t advCfg = 0;
1074                 uint16_t aeCfg = PBE_BLE5_RAM_AECFG_CHNL_SECONDARY;
1075 
1076                 if (nextTxBuffer != NULL)
1077                 {
1078                     /*
1079                     * Start time is calculated relative to the duration of the previous packet. If there was a PHY change,
1080                     * consider its duration with the previous PHY, before updating the timestamps associated with the new PHY.
1081                     */
1082                     if (ble5HandlerState.adv.switchPhy)
1083                     {
1084                         startTimeDelta = RCL_Handler_BLE5_findPacketDuration(ble5HandlerState.common.auxPtrInfo.pktLen, ble5HandlerState.common.phyFeatures);
1085                         /* Consider the time that it takes to handle the PHY switching */
1086                         startTimeDelta += RCL_SCHEDULER_SYSTIM_US(EXT_ADV_PHY_SWITCHING_DELAY_US);
1087                         /* Adjust timestamps accordingly */
1088                         RCL_Handler_BLE5_setPhy(rclSchedulerState.requestedPhyFeatures);
1089                         ble5HandlerState.adv.switchPhy = false;
1090                     }
1091                     else
1092                     {
1093                         startTimeDelta = RCL_Handler_BLE5_findPacketDuration(ble5HandlerState.common.auxPtrInfo.pktLen, ble5HandlerState.common.phyFeatures);
1094                     }
1095 
1096                     /*  Check advertising type and mode */
1097                     uint8_t header = nextTxBuffer->data[nextTxBuffer->numPad - 1];
1098                     uint8_t extHeader = nextTxBuffer->data[nextTxBuffer->numPad - 1 + BLE_HEADER_LENGTH];
1099 
1100                     if ((header & BLE_PDU_TYPE_BM) == BLE_PDU_ADV_EXTENDED)
1101                     {
1102                         switch ((extHeader & BLE_ADV_MODE_BM) >> 6)
1103                         {
1104                             case BLE_ADV_MODE_NONCONN_NONSCAN: /* Non-connectable - Non-scannable */
1105                                 advCfg = 0;
1106                                 /* Extract AuxPtr information if available */
1107                                 RCL_Handler_BLE5_getAuxPtrFromTxBuffer(nextTxBuffer, &ble5HandlerState.common.auxPtrInfo, 0);
1108                                 ble5HandlerState.adv.runRx = false;
1109                                 break;
1110 
1111                             case BLE_ADV_MODE_CONN_NONSCAN: /* Connectable - Non-scannable */
1112 
1113                                 RCL_Handler_BLE5_getAuxPtrFromTxBuffer(nextTxBuffer, &ble5HandlerState.common.auxPtrInfo, 0);
1114                                 if (ble5HandlerState.common.auxPtrInfo.auxPtrPresent)
1115                                 {
1116                                     ble5HandlerState.adv.runRx = false;
1117                                     /* Connectable PDUs must not have an AuxPtr */
1118                                     ble5HandlerState.common.endStatus = RCL_CommandStatus_Error_TxBufferCorruption;
1119                                 }
1120                                 else
1121                                 {
1122                                     advCfg = PBE_BLE5_RAM_ADVCFG_CONNECTABLE_M;
1123                                     ble5HandlerState.adv.runRx = true;
1124                                 }
1125                                 break;
1126 
1127                             case BLE_ADV_MODE_NONCONN_SCAN: /* Non-connectable - Scannable */
1128                                 /* Scannable PDUs must not have an AuxPtr in the AUX_ADV_IND, so perform a sanity check on it to be sure */
1129                                 RCL_Handler_BLE5_getAuxPtrFromTxBuffer(nextTxBuffer, &ble5HandlerState.common.auxPtrInfo, 0);
1130                                 if (ble5HandlerState.common.auxPtrInfo.auxPtrPresent)
1131                                 {
1132                                     ble5HandlerState.adv.runRx = false;
1133                                     ble5HandlerState.common.endStatus = RCL_CommandStatus_Error_TxBufferCorruption;
1134                                 }
1135                                 else
1136                                 {
1137                                     advCfg = PBE_BLE5_RAM_ADVCFG_SCANNABLE_M;
1138                                     ble5HandlerState.adv.runRx = true;
1139                                 }
1140                                 break;
1141 
1142                             default:
1143                                 advCfg = 0;
1144                                 ble5HandlerState.adv.runRx = false;
1145                                 ble5HandlerState.common.auxPtrInfo.auxPtrPresent = false;
1146                                 break;
1147                         }
1148                     }
1149                     else
1150                     {
1151                         /* Only extended PDUs are valid at this point */
1152                         ble5HandlerState.common.endStatus = RCL_CommandStatus_Error_Param;
1153                     }
1154                 }
1155 
1156                 /* Enter payload */
1157                 uint32_t nBuffer = 0;
1158                 if ((advCfg & PBE_BLE5_RAM_ADVCFG_SCANNABLE_M) != 0)
1159                 {
1160                     /* Scannable advertising requires the presence of an additional Tx Buffer with an AUX_SCAN_RSP in the Tx buffer list */
1161                     RCL_Buffer_TxBuffer *auxScanRspTxBuffer;
1162                     auxScanRspTxBuffer = RCL_TxBuffer_next(nextTxBuffer);
1163 
1164                     if (auxScanRspTxBuffer != NULL)
1165                     {
1166                         uint8_t header = auxScanRspTxBuffer->data[auxScanRspTxBuffer->numPad - 1];
1167                         uint8_t extHeader = auxScanRspTxBuffer->data[auxScanRspTxBuffer->numPad - 1 + BLE_HEADER_LENGTH];
1168 
1169                         /* AUX_SCAN_RSP PDUs may or may not point to a subsequent auxiliary packet. Check the Tx Buffer to see if there is one */
1170                         if (((header & BLE_PDU_TYPE_BM) == BLE_PDU_ADV_EXTENDED) && ((extHeader & BLE_ADV_MODE_BM) >> 6) == 0)
1171                         {
1172                             /*
1173                              * Since both Tx buffers will be put in the PBE FIFO, consider the entry length of the AUX_ADV_IND to determine
1174                              * the location of the AuxPtr in the PBE FIFO. This needs to be known so that the AuxPtr fields can be updated
1175                              * later.
1176                              */
1177                             uint8_t auxAdvEntryLength = RCL_Buffer_entryLen(BLE_NUM_PAD, BLE_HEADER_LENGTH, nextTxBuffer->data[nextTxBuffer->numPad]);
1178                             RCL_Handler_BLE5_getAuxPtrFromTxBuffer(auxScanRspTxBuffer, &ble5HandlerState.common.auxPtrInfo, auxAdvEntryLength);
1179                         }
1180                         /* Enter the two Tx Buffers corresponding to the AUX_ADV_IND and the AUX_SCAN_RSP */
1181                         nBuffer = RCL_Handler_BLE5_updateTxBuffers(&advCmd->ctx->txBuffers, 2,
1182                                                                    &ble5HandlerState.common.txBufferInfo,
1183                                                                    false);
1184                         /* Keep track of the lengths of the AUX_ADV_IND and the AUX_SCAN_IND since they will be used if an AUX_CHAIN_IND is to be sent afterwards */
1185                         ble5HandlerState.adv.auxScanRspLen = auxScanRspTxBuffer->data[auxScanRspTxBuffer->numPad];
1186                         ble5HandlerState.adv.auxAdvIndLen = nextTxBuffer->data[nextTxBuffer->numPad];
1187                     }
1188                 }
1189                 else if ((advCfg & PBE_BLE5_RAM_ADVCFG_CONNECTABLE_M) != 0)
1190                 {
1191                     /* Connectable advertising requires a Tx Buffer with an AUX_CONNECT_RSP */
1192                     RCL_Buffer_TxBuffer *auxConnectRspTxBuffer;
1193                     auxConnectRspTxBuffer = RCL_TxBuffer_next(nextTxBuffer);
1194 
1195                     if (auxConnectRspTxBuffer != NULL)
1196                     {
1197                         /* Enter the two Tx Buffers corresponding to the AUX_ADV_IND and the AUX_CONNECT_RSP */
1198                         nBuffer = RCL_Handler_BLE5_updateTxBuffers(&advCmd->ctx->txBuffers, 2,
1199                                                                    &ble5HandlerState.common.txBufferInfo,
1200                                                                    false);
1201                     }
1202                 }
1203                 else
1204                 {
1205                     /* Non-scannable advertising is handled one Tx buffer at a time */
1206                     nBuffer = RCL_Handler_BLE5_updateTxBuffers(&advCmd->ctx->txBuffers, 1,
1207                                                                &ble5HandlerState.common.txBufferInfo,
1208                                                                false);
1209                 }
1210 
1211                 if (nBuffer == 0 || (((advCfg & PBE_BLE5_RAM_ADVCFG_SCANNABLE_M) != 0) && (nBuffer < 2)) ||
1212                    (((advCfg & PBE_BLE5_RAM_ADVCFG_CONNECTABLE_M) != 0) && (nBuffer < 2)))
1213                 {
1214                     /* Error */
1215                     ble5HandlerState.common.endStatus = RCL_CommandStatus_Error_MissingTxBuffer;
1216                 }
1217                 else
1218                 {
1219                     /*
1220                      * Express the startTimeDelta in terms of offset units so that the relative start time is rounded up
1221                      * to the closest offset unit. Add a delay of a couple of microseconds to avoid sending the packets right
1222                      * at the beginning of the offset window.
1223                      */
1224                     startTimeDelta += RCL_SCHEDULER_SYSTIM_US(EXT_ADV_INTERVAL_US);
1225                     uint32_t startTimeDeltaInOffsetUnits = BLE_convertSystimUnitsToOffsetUnits(startTimeDelta, BLE_AUX_OFFSET_30_US);
1226                     uint32_t relStartTime = RCL_SCHEDULER_SYSTIM_US((startTimeDeltaInOffsetUnits * BLE_AUX_OFFSET_30_US)) + RCL_SCHEDULER_SYSTIM_US(2);
1227                     /*
1228                      * If an AUX_SCAN_REQ was received, the relative start time for the packet needs to consider the
1229                      * time spent sending the AUX_ADV_IND, receiving the AUX_SCAN_REQ and replying with the AUX_SCAN_RSP.
1230                      * In this particular case, the AUX_SCAN_RSP is the previously sent packet, so no need to include it here.
1231                      */
1232                     if (ble5HandlerState.adv.auxScanReqReceived)
1233                     {
1234                         /* Time spent sending the AUX_ADV_IND */
1235                         relStartTime += RCL_Handler_BLE5_findPacketDuration(ble5HandlerState.adv.auxAdvIndLen, ble5HandlerState.common.phyFeatures);
1236                         /* Time spent receiving the AUX_SCAN_REQ */
1237                         relStartTime += RCL_Handler_BLE5_findPacketDuration(BLE_ADV_AUX_SCAN_REQ_PKT_LEN, ble5HandlerState.common.phyFeatures);
1238                         /* Time spent switching from Tx to Rx to receive the AUX_SCAN_REQ, and then back from Rx to Tx to send the AUX_SCAN_RSP */
1239                         relStartTime += (2 * BLE_T_IFS);
1240                         ble5HandlerState.adv.auxScanReqReceived = false;
1241                     }
1242                     startTimeStatus = RCL_Scheduler_setNewStartRelTime(relStartTime);
1243 
1244                     if (ble5HandlerState.common.auxPtrInfo.auxPtrPresent)
1245                     {
1246                         /* Consider the current packet duration when calculating the AuxOffset */
1247                         uint32_t pktDuration = RCL_Handler_BLE5_findPacketDuration(ble5HandlerState.common.auxPtrInfo.pktLen, ble5HandlerState.common.phyFeatures);
1248 
1249                         if(!RCL_Handler_BLE5_updateAuxPtr(&ble5HandlerState.common.auxPtrInfo, pktDuration, ble5HandlerState.adv.chanMap, ble5HandlerState.adv.switchPhy))
1250                         {
1251                             startTimeStatus = RCL_CommandStatus_Error_Param;
1252                         }
1253                     }
1254 
1255                     HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_ADVCFG) = advCfg;
1256                     HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_AECFG) = aeCfg;
1257                     HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FILTPOLICY) = (advCmd->ctx->filterPolicy << PBE_BLE5_RAM_FILTPOLICY_ADV_S) &
1258                                                                                       PBE_BLE5_RAM_FILTPOLICY_ADV_M;
1259                     HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_RPAMODE) = (advCmd->ctx->rpaModePeer << PBE_BLE5_RAM_RPAMODE_PEERADR_S);
1260                     HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_RPACONNECT) = advCmd->ctx->acceptAllRpaConnectInd << PBE_BLE5_RAM_RPACONNECT_ENDADV_S;
1261 
1262                     if ((advCfg & PBE_BLE5_RAM_ADVCFG_SCANNABLE_M) != 0)
1263                     {
1264                         RCL_FilterList *filterList = advCmd->ctx->filterListScan;
1265                         uint32_t invertMask = 0;
1266                         if ((advCmd->ctx->filterPolicy & BLE_ADV_FILTER_POLICY_SCAN) != 0)
1267                         {
1268                             /* Set filter list masks to normal accept list use: */
1269                             /* Bit 0: Consider enable bit */
1270                             /* Bit 1: Consider type bit */
1271                             /* Bit 3: Consider privIgn bit */
1272                             /* Bit 15: Consider match bit (found by PBE) */
1273                             /* Other bits are not checked */
1274                             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FL1MASK) = PBE_BLE5_RAM_FL1MASK_MATCH_M |
1275                                                                                           PBE_BLE5_RAM_FL1MASK_PRIVIGN_M |
1276                                                                                           PBE_BLE5_RAM_FL1MASK_TYPE_M |
1277                                                                                           PBE_BLE5_RAM_FL1MASK_EN_M;
1278                         }
1279                         else
1280                         {
1281                             if (advCmd->ctx->privIgnMode != 0)
1282                             {
1283                                 /* Set filter list masks for RPA filtering: */
1284                                 /* Bit 1: Consider type bit */
1285                                 /* Bit 3: Consider pribvIgn bit */
1286                                 /* Bit 15: Consider match bit (found by PBE) */
1287                                 /* Other bits are not checked */
1288                                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FL1MASK) = PBE_BLE5_RAM_FL1MASK_MATCH_M |
1289                                                                                     PBE_BLE5_RAM_FL1MASK_PRIVIGN_M |
1290                                                                                     PBE_BLE5_RAM_FL1MASK_TYPE_M;
1291                                 invertMask = PBE_BLE5_RAM_FL1MASK_PRIVIGN_M;
1292                             }
1293                             else
1294                             {
1295                                 /* Filter list not used */
1296                                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FL1MASK) = 0;
1297                                 filterList = NULL;
1298                             }
1299                         }
1300                         RCL_Handler_BLE5_InitializeFilterList(filterList, (uint32_t *) (volatile unsigned short*) (LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FL1INFO0), invertMask);
1301                     }
1302                     else
1303                     {
1304                         /* Filter list not applicable */
1305                         HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FL1MASK) = 0;
1306                     }
1307                     if ((advCfg & PBE_BLE5_RAM_ADVCFG_CONNECTABLE_M) != 0)
1308                     {
1309                         RCL_FilterList *filterList = advCmd->ctx->filterListConn;
1310                         uint32_t invertMask = 0;
1311                         if ((advCmd->ctx->filterPolicy & BLE_ADV_FILTER_POLICY_CONN) != 0)
1312                         {
1313                             /* Set filter list masks to normal accept list use: */
1314                             /* Bit 0: Consider enable bit */
1315                             /* Bit 1: Consider type bit */
1316                             /* Bit 3: Consider privIgn bit */
1317                             /* Bit 15: Consider match bit (found by PBE) */
1318                             /* Other bits are not checked */
1319                             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FL2MASK) = PBE_BLE5_RAM_FL2MASK_MATCH_M |
1320                                                                                           PBE_BLE5_RAM_FL2MASK_PRIVIGN_M |
1321                                                                                           PBE_BLE5_RAM_FL2MASK_TYPE_M |
1322                                                                                           PBE_BLE5_RAM_FL2MASK_EN_M;
1323                         }
1324                         else
1325                         {
1326                             if (advCmd->ctx->privIgnMode != 0)
1327                             {
1328                                 /* Set filter list masks for RPA filtering: */
1329                                 /* Bit 1: Consider type bit */
1330                                 /* Bit 3: Consider privIgn bit */
1331                                 /* Bit 15: Consider match bit (found by PBE) */
1332                                 /* Other bits are not checked */
1333                                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FL2MASK) = PBE_BLE5_RAM_FL2MASK_MATCH_M |
1334                                                                                               PBE_BLE5_RAM_FL2MASK_PRIVIGN_M |
1335                                                                                               PBE_BLE5_RAM_FL2MASK_TYPE_M;
1336                                 invertMask = PBE_BLE5_RAM_FL2MASK_PRIVIGN_M;
1337                             }
1338                             else
1339                             {
1340                                 /* Filter list not used */
1341                                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FL2MASK) = 0;
1342                                 filterList = NULL;
1343                             }
1344                         }
1345                         RCL_Handler_BLE5_InitializeFilterList(filterList, (uint32_t *) (volatile unsigned short*) (LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FL2INFO0), invertMask);
1346                     }
1347                     else
1348                     {
1349                         /* Filter list not applicable */
1350                         HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FL2MASK) = 0;
1351                     }
1352                     if (startTimeStatus >= RCL_CommandStatus_Finished)
1353                     {
1354                         cmd->status = startTimeStatus;
1355                         rclEvents.lastCmdDone = 1;
1356                     }
1357                     else
1358                     {
1359                         HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_OPCFG) = 0;
1360                         uint16_t whitenInit = RCL_Handler_BLE5_findWhitenInit(channel);
1361                         HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_WHITEINIT) = whitenInit;
1362                         if (ble5HandlerState.common.accessAddressModification)
1363                         {
1364                             HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_MDMSYNCA) = ADV_ACCESS_ADDRESS ^ (whitenInit << 24);
1365                         }
1366 
1367                         /* Enable interrupts */
1368                         if (ble5HandlerState.adv.runRx)
1369                         {
1370                             /* Set up sync found capture */
1371                             hal_setup_sync_found_cap();
1372                             uint16_t fifoCfg = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FIFOCFG);
1373                             LRF_enableHwInterrupt(RCL_Handler_BLE5_maskEventsByFifoConf(LRF_EventOpDone.value | LRF_EventOpError.value |
1374                                                                                         LRF_EventRxOk.value | LRF_EventRxIgnored.value |
1375                                                                                         LRF_EventRxNok.value | LRF_EventRxBufFull.value,
1376                                                                                         fifoCfg, ble5HandlerState.common.activeUpdate));
1377                         }
1378                         else
1379                         {
1380                             LRF_enableHwInterrupt(LRF_EventOpDone.value | LRF_EventOpError.value);
1381                         }
1382 
1383                         LRF_waitForTopsmReady();
1384 
1385                         /* Post cmd */
1386                         Log_printf(RclCore, Log_VERBOSE, "Starting extended advertiser on channel %1d", channel);
1387                         HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_API) = PBE_BLE5_REGDEF_API_OP_ADV;
1388 
1389                         /* Free up finished Tx buffers from the Tx Buffer list and raise the appropriate RCL event */
1390                         uint32_t numBuffers = nBuffer;
1391                         RCL_Buffer_TxBuffer *txBuffer;
1392                         do
1393                         {
1394                             txBuffer = RCL_TxBuffer_get(&advCmd->ctx->txBuffers);
1395                             if (txBuffer == NULL)
1396                             {
1397                                 /* Error */
1398                                 ble5HandlerState.common.endStatus = RCL_CommandStatus_Error_TxBufferCorruption;
1399                             }
1400                             txBuffer->state = RCL_BufferStateFinished;
1401                             if (txBuffer == ble5HandlerState.common.txBufferInfo.lastEnteredTxBuffer)
1402                             {
1403                                 ble5HandlerState.common.txBufferInfo.lastEnteredTxBuffer = NULL;
1404                             }
1405                             numBuffers--;
1406                         } while (numBuffers > 0);
1407                         /* Raise RCL event indicating that the buffers have been consumed */
1408                         rclEvents.txBufferFinished = 1;
1409                     }
1410                 }
1411             }
1412         }
1413         if (rclEvents.lastCmdDone != 0)
1414         {
1415             RCL_Handler_BLE5_updateAdvScanInitStats(advCmd->stats, rclSchedulerState.actualStartTime);
1416         }
1417     }
1418 
1419     if (rclEvents.lastCmdDone != 0)
1420     {
1421         LRF_disable();
1422         LRF_disableSynthRefsys();
1423     }
1424     return rclEvents;
1425 }
1426 
1427 /*
1428  *  ======== RCL_Handler_BLE5_aux_adv ========
1429  */
RCL_Handler_BLE5_aux_adv(RCL_Command * cmd,LRF_Events lrfEvents,RCL_Events rclEventsIn)1430 RCL_Events RCL_Handler_BLE5_aux_adv(RCL_Command *cmd, LRF_Events lrfEvents, RCL_Events rclEventsIn)
1431 {
1432     uint32_t rfFreq;
1433     RCL_CmdBle5AuxAdvertiser *auxAdvCmd = (RCL_CmdBle5AuxAdvertiser *) cmd;
1434     bool runAuxAdv = false;
1435     bool runAuxChain = false;
1436     RCL_Events rclEvents = {.value = 0};
1437     uint32_t earliestStartTime = 0;
1438     RCL_Ble5Channel channel;
1439 
1440     if (rclEventsIn.setup != 0)
1441     {
1442         /* Start by enabling refsys */
1443         earliestStartTime = LRF_enableSynthRefsys();
1444 
1445         HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_MDMSYNCA) = ADV_ACCESS_ADDRESS;
1446 
1447         /* 32-bit access to also write CRCINITH */
1448         HWREG_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_CRCINITL) = ADV_CRC_INIT;
1449 
1450         ble5HandlerState.common.fifoCfg = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FIFOCFG);
1451         HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_EXTRABYTES) = RCL_Handler_BLE5_findNumExtraBytes(ble5HandlerState.common.fifoCfg);
1452 
1453         /* Default end status */
1454         ble5HandlerState.common.endStatus = RCL_CommandStatus_Finished;
1455 
1456         RCL_CommandStatus status = RCL_Handler_BLE5_setPhy(cmd->phyFeatures);
1457 
1458         if (LRF_programTxPower(auxAdvCmd->txPower) != TxPowerResult_Ok)
1459         {
1460             status = RCL_CommandStatus_Error_Param;
1461         }
1462 
1463         if (status == RCL_CommandStatus_Active)
1464         {
1465             /* Initialize RF FIFOs */
1466             ble5HandlerState.common.rxFifoSz = LRF_prepareRxFifo();
1467             ble5HandlerState.common.curBuffer = NULL;
1468             RCL_Handler_BLE5_updateRxCurBufferAndFifo(&auxAdvCmd->ctx->rxBuffers);
1469             ble5HandlerState.common.txFifoSz = LRF_prepareTxFifo();
1470 
1471             /* Enter address */
1472             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_OWNADRL) = auxAdvCmd->ctx->advA[0];
1473             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_OWNADRM) = auxAdvCmd->ctx->advA[1];
1474             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_OWNADRH) = auxAdvCmd->ctx->advA[2];
1475             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_OWNADRTYPE) = auxAdvCmd->ctx->addrType.own;
1476 
1477             /* Find which type of advertising */
1478             RCL_Buffer_TxBuffer *txBuffer = RCL_TxBuffer_head(&auxAdvCmd->ctx->txBuffers);
1479             uint16_t auxAdvCfg = 0;
1480             uint16_t aeCfg = PBE_BLE5_RAM_AECFG_CHNL_SECONDARY;
1481             channel = auxAdvCmd->channel;
1482 
1483             if (txBuffer != NULL)
1484             {
1485                 uint8_t header = txBuffer->data[txBuffer->numPad - 1];
1486                 uint8_t extHeader = txBuffer->data[txBuffer->numPad - 1 + BLE_HEADER_LENGTH];
1487 
1488                 /* Check advertising type */
1489                 if ((header & BLE_PDU_TYPE_BM) == BLE_PDU_ADV_EXTENDED)
1490                 {
1491                     ble5HandlerState.common.auxPtrInfo.numPrimaryChPackets = 0;
1492 
1493                     /* Check advertising mode */
1494                     switch ((extHeader & BLE_ADV_MODE_BM) >> 6)
1495                     {
1496                         case BLE_ADV_MODE_NONCONN_NONSCAN: /* Non-connectable - Non-scannable */
1497                             RCL_Handler_BLE5_getAuxPtrFromTxBuffer(txBuffer, &ble5HandlerState.common.auxPtrInfo, 0);
1498                             ble5HandlerState.auxAdv.runRx = false;
1499                             ble5HandlerState.auxAdv.sendAuxAdv = true;
1500                             ble5HandlerState.auxAdv.auxScanReqReceived = false;
1501                             break;
1502                         case BLE_ADV_MODE_CONN_NONSCAN: /* Connectable - Non-scannable */
1503                             ble5HandlerState.auxAdv.runRx = false;
1504                             ble5HandlerState.common.auxPtrInfo.auxPtrPresent = false;
1505                             ble5HandlerState.auxAdv.auxScanReqReceived = false;
1506                             auxAdvCfg = PBE_BLE5_RAM_ADVCFG_CONNECTABLE_M;
1507                             break;
1508                         case BLE_ADV_MODE_NONCONN_SCAN: /* Non-connectable - Scannable */
1509                             RCL_Handler_BLE5_getAuxPtrFromTxBuffer(txBuffer, &ble5HandlerState.common.auxPtrInfo, 0);
1510                             if (ble5HandlerState.common.auxPtrInfo.auxPtrPresent)
1511                             {
1512                                 ble5HandlerState.auxAdv.runRx = false;
1513                                 ble5HandlerState.auxAdv.auxScanReqReceived = false;
1514                                 /* Scannable PDUs must not have an AuxPtr */
1515                                 ble5HandlerState.common.endStatus = RCL_CommandStatus_Error_TxBufferCorruption;
1516                             }
1517                             else
1518                             {
1519                                 auxAdvCfg = PBE_BLE5_RAM_ADVCFG_SCANNABLE_M;
1520                                 ble5HandlerState.auxAdv.runRx = true;
1521                                 ble5HandlerState.auxAdv.auxScanReqReceived = false;
1522                             }
1523                             break;
1524                         default:
1525                             ble5HandlerState.auxAdv.runRx = false;
1526                             ble5HandlerState.common.auxPtrInfo.auxPtrPresent = false;
1527                             ble5HandlerState.auxAdv.auxScanReqReceived = false;
1528                             break;
1529                     }
1530                 }
1531                 else
1532                 {
1533                     /* Error. Tx Buffer does not correspond to an Extended Advertising PDU */
1534                     status = RCL_CommandStatus_Error_TxBufferCorruption;
1535                 }
1536             }
1537 
1538             /* Enter payload */
1539             uint32_t nBuffer = 0;
1540             if ((auxAdvCfg & PBE_BLE5_RAM_ADVCFG_SCANNABLE_M) != 0)
1541             {
1542                 /* Scannable advertising requires a Tx Buffer with an AUX_SCAN_RSP */
1543                 RCL_Buffer_TxBuffer *auxScanRspTxBuffer;
1544                 auxScanRspTxBuffer = RCL_TxBuffer_next(txBuffer);
1545                 if (auxScanRspTxBuffer != NULL)
1546                 {
1547                     uint8_t header = auxScanRspTxBuffer->data[auxScanRspTxBuffer->numPad - 1];
1548                     uint8_t extHeader = auxScanRspTxBuffer->data[auxScanRspTxBuffer->numPad - 1 + BLE_HEADER_LENGTH];
1549 
1550                     /* Perform a sanity check on the AUX_SCAN_RSP and extract its AuxPtr if needed */
1551                     if (((header & BLE_PDU_TYPE_BM) == BLE_PDU_ADV_EXTENDED) && ((extHeader & BLE_ADV_MODE_BM) >> 6) == 0)
1552                     {
1553                         /* Consider the entry length of the AUX_ADV_IND to determine the pointer to the AuxPtr in the FIFO */
1554                         uint8_t auxAdvEntryLength = RCL_Buffer_entryLen(BLE_NUM_PAD, BLE_HEADER_LENGTH, txBuffer->data[txBuffer->numPad]);
1555                         RCL_Handler_BLE5_getAuxPtrFromTxBuffer(auxScanRspTxBuffer, &ble5HandlerState.common.auxPtrInfo, auxAdvEntryLength);
1556                     }
1557                     /* If it's scannable advertising, two Tx buffers are needed */
1558                     ble5HandlerState.common.txBufferInfo = (RCL_TxBufferInfo) { 0 };
1559                     nBuffer = RCL_Handler_BLE5_updateTxBuffers(&auxAdvCmd->ctx->txBuffers, 2,
1560                                                                &ble5HandlerState.common.txBufferInfo,
1561                                                                false);
1562                     /* Keep track of the lengths of the AUX_ADV_IND and the AUX_SCAN_IND since they will be used if an AUX_CHAIN_IND is to be sent afterwards */
1563                     ble5HandlerState.auxAdv.auxScanRspLen = auxScanRspTxBuffer->data[auxScanRspTxBuffer->numPad];
1564                     ble5HandlerState.auxAdv.auxAdvIndLen = txBuffer->data[txBuffer->numPad];
1565                 }
1566             }
1567             else
1568             {
1569                 ble5HandlerState.common.txBufferInfo = (RCL_TxBufferInfo) { 0 };
1570                 nBuffer = RCL_Handler_BLE5_updateTxBuffers(&auxAdvCmd->ctx->txBuffers, 1,
1571                                                            &ble5HandlerState.common.txBufferInfo,
1572                                                            false);
1573             }
1574 
1575             if (nBuffer == 0 || (((auxAdvCfg & PBE_BLE5_RAM_ADVCFG_SCANNABLE_M) != 0) && (nBuffer < 2)))
1576             {
1577                 /* Error */
1578                 ble5HandlerState.common.endStatus = RCL_CommandStatus_Error_MissingTxBuffer;
1579             }
1580             else
1581             {
1582                 /* Free up finished Tx buffers from the Tx Buffer list and raise the appropriate RCL event */
1583                 uint32_t numBuffers = nBuffer;
1584                 RCL_Buffer_TxBuffer *txBuffer;
1585                 do
1586                 {
1587                     txBuffer = RCL_TxBuffer_get(&auxAdvCmd->ctx->txBuffers);
1588                     if (txBuffer == NULL)
1589                     {
1590                         /* Error */
1591                         ble5HandlerState.common.endStatus = RCL_CommandStatus_Error_TxBufferCorruption;
1592                     }
1593                     txBuffer->state = RCL_BufferStateFinished;
1594                     if (txBuffer == ble5HandlerState.common.txBufferInfo.lastEnteredTxBuffer)
1595                     {
1596                         ble5HandlerState.common.txBufferInfo.lastEnteredTxBuffer = NULL;
1597                     }
1598                     numBuffers--;
1599                 } while (numBuffers > 0);
1600                 /* Raise RCL event indicating that the buffers have been consumed */
1601                 rclEvents.txBufferFinished = 1;
1602 
1603                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_ADVCFG) = auxAdvCfg;
1604                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FILTPOLICY) = (auxAdvCmd->ctx->filterPolicy << PBE_BLE5_RAM_FILTPOLICY_ADV_S) &
1605                                                                                   PBE_BLE5_RAM_FILTPOLICY_ADV_M;
1606                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_RPAMODE) = (auxAdvCmd->ctx->rpaModePeer << PBE_BLE5_RAM_RPAMODE_PEERADR_S);
1607                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_RPACONNECT) = auxAdvCmd->ctx->acceptAllRpaConnectInd << PBE_BLE5_RAM_RPACONNECT_ENDADV_S;
1608 
1609                 if ((auxAdvCfg & PBE_BLE5_RAM_ADVCFG_SCANNABLE_M) != 0)
1610                 {
1611                     RCL_FilterList *filterList = auxAdvCmd->ctx->filterListScan;
1612                     uint32_t invertMask = 0;
1613                     if ((auxAdvCmd->ctx->filterPolicy & BLE_ADV_FILTER_POLICY_SCAN) != 0)
1614                     {
1615                         /* Set filter list masks to normal accept list use: */
1616                         /* Bit 0: Consider enable bit */
1617                         /* Bit 1: Consider type bit */
1618                         /* Bit 3: Consider privIgn bit */
1619                         /* Bit 15: Consider match bit (found by PBE) */
1620                         /* Other bits are not checked */
1621                         HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FL1MASK) = PBE_BLE5_RAM_FL1MASK_MATCH_M |
1622                                                                                       PBE_BLE5_RAM_FL1MASK_PRIVIGN_M |
1623                                                                                       PBE_BLE5_RAM_FL1MASK_TYPE_M |
1624                                                                                       PBE_BLE5_RAM_FL1MASK_EN_M;
1625                     }
1626                     else
1627                     {
1628                         if (auxAdvCmd->ctx->privIgnMode != 0)
1629                         {
1630                             /* Set filter list masks for RPA filtering: */
1631                             /* Bit 1: Consider type bit */
1632                             /* Bit 3: Consider pribvIgn bit */
1633                             /* Bit 15: Consider match bit (found by PBE) */
1634                             /* Other bits are not checked */
1635                             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FL1MASK) = PBE_BLE5_RAM_FL1MASK_MATCH_M |
1636                                                                                           PBE_BLE5_RAM_FL1MASK_PRIVIGN_M |
1637                                                                                           PBE_BLE5_RAM_FL1MASK_TYPE_M;
1638                             invertMask = PBE_BLE5_RAM_FL1MASK_PRIVIGN_M;
1639                         }
1640                         else
1641                         {
1642                             /* Filter list not used */
1643                             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FL1MASK) = 0;
1644                             filterList = NULL;
1645                         }
1646                     }
1647                     RCL_Handler_BLE5_InitializeFilterList(filterList, (uint32_t *) (volatile unsigned short*) (LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FL1INFO0), invertMask);
1648                 }
1649                 else
1650                 {
1651                     /* Filter list not applicable */
1652                     HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FL1MASK) = 0;
1653                 }
1654                 if (status >= RCL_CommandStatus_Finished)
1655                 {
1656                     cmd->status = status;
1657                     rclEvents.lastCmdDone = 1;
1658                 }
1659                 else
1660                 {
1661                     HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_AECFG) = aeCfg;
1662                     HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_ADVCFG) = auxAdvCfg;
1663 
1664                     HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_OPCFG) = 0;
1665                     uint16_t whitenInit = RCL_Handler_BLE5_findWhitenInit(channel);
1666                     HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_WHITEINIT) = whitenInit;
1667                     if (ble5HandlerState.common.accessAddressModification)
1668                     {
1669                         HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_MDMSYNCA) = ADV_ACCESS_ADDRESS ^ (whitenInit << 24);
1670                     }
1671                     /* Run advertiser next */
1672                     runAuxAdv = true;
1673                 }
1674             }
1675         }
1676 
1677         /* Set status */
1678         cmd->status = status;
1679         if (status >= RCL_CommandStatus_Finished)
1680         {
1681             rclEvents.lastCmdDone = 1;
1682         }
1683     }
1684 
1685     if (cmd->status == RCL_CommandStatus_Active)
1686     {
1687         if (lrfEvents.rxOk != 0 || lrfEvents.rxNok != 0 || lrfEvents.rxIgnored != 0 || lrfEvents.rxBufFull != 0)
1688         {
1689             /* Copy received packet from PBE FIFO to buffer */
1690             /* First, check that there is actually a buffer available */
1691             while (HWREG_READ_LRF(LRFDPBE_BASE + LRFDPBE_O_RXFREADABLE) >= 4)
1692             {
1693                 /* Check length of received buffer by peeking */
1694                 uint32_t fifoWord = LRF_peekRxFifo(0);
1695                 uint32_t wordLength = RCL_Buffer_DataEntry_paddedLen(fifoWord & 0xFFFF) / 4;
1696                 if (wordLength > 0)
1697                 {
1698                     RCL_MultiBuffer *curBuffer;
1699                     curBuffer = RCL_MultiBuffer_getBuffer(ble5HandlerState.common.curBuffer,
1700                                                           wordLength * 4);
1701                     if (curBuffer != ble5HandlerState.common.curBuffer)
1702                     {
1703                         rclEvents.rxBufferFinished = 1;
1704                         ble5HandlerState.common.curBuffer = curBuffer;
1705                     }
1706                     if (curBuffer == NULL)
1707                     {
1708                         /* Error */
1709                         ble5HandlerState.common.endStatus = RCL_CommandStatus_Error_RxBufferCorruption;
1710                         /* Send abort */
1711                         HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_API) = PBE_BLE5_REGDEF_API_OP_STOP;
1712                         /* Do not check for more packets from the RX FIFO */
1713                         break;
1714                     }
1715                     else
1716                     {
1717                         uint32_t *data32;
1718                         data32 = (uint32_t *)RCL_MultiBuffer_getNextWritableByte(curBuffer);
1719                         LRF_readRxFifoWords(data32, wordLength);
1720                         RCL_Handler_BLE5_commitPacket(curBuffer, wordLength * 4);
1721                         /* Raise event */
1722                         rclEvents.rxEntryAvail = 1;
1723                         /* Adjust effective FIFO size */
1724                         RCL_Handler_BLE5_updateRxCurBufferAndFifo(&auxAdvCmd->ctx->rxBuffers);
1725                         rclEventsIn.rxBufferUpdate = 0;
1726                         ble5HandlerState.auxAdv.auxScanReqReceived = true;
1727                     }
1728                 }
1729             }
1730             if (ble5HandlerState.common.activeUpdate)
1731             {
1732                 RCL_Handler_BLE5_updateAdvScanInitStats(auxAdvCmd->stats, rclSchedulerState.actualStartTime);
1733             }
1734         }
1735         if (rclEventsIn.timerStart != 0)
1736         {
1737             rclEvents.cmdStarted = 1;
1738         }
1739         if (rclEventsIn.gracefulStop != 0)
1740         {
1741             ble5HandlerState.auxAdv.gracefulStopObserved = true;
1742         }
1743 
1744         if (lrfEvents.opDone != 0)
1745         {
1746             uint16_t endCause = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_COMMON_RAM_O_ENDCAUSE);
1747 
1748             if (endCause == PBE_COMMON_RAM_ENDCAUSE_STAT_CONNECT)
1749             {
1750                 /* 32-bit access to also read LASTTIMESTAMPH */
1751                 auxAdvCmd->connectPktTime = HWREG_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_LASTTIMESTAMPL) - ble5HandlerState.common.timestampAdjust;
1752 
1753                 ble5HandlerState.common.endStatus = RCL_CommandStatus_Connect;
1754                 runAuxAdv = false;
1755                 runAuxChain = false;
1756             }
1757             else if (rclEventsIn.hardStop != 0)
1758             {
1759                 ble5HandlerState.common.endStatus = RCL_Scheduler_findStopStatus(RCL_StopType_Hard);
1760                 runAuxAdv = false;
1761                 runAuxChain = false;
1762 
1763             }
1764             else if (endCause == PBE_COMMON_RAM_ENDCAUSE_STAT_EOPSTOP ||
1765                         ble5HandlerState.auxAdv.gracefulStopObserved ||
1766                         rclEventsIn.gracefulStop != 0)
1767             {
1768                 ble5HandlerState.common.endStatus = RCL_Scheduler_findStopStatus(RCL_StopType_Graceful);
1769                 runAuxAdv = false;
1770                 runAuxChain = false;
1771             }
1772             else if (endCause == PBE_COMMON_RAM_ENDCAUSE_STAT_NOSYNC && ble5HandlerState.common.auxPtrInfo.auxPtrPresent)
1773             {
1774                 /* If no AUX_SCAN_REQ is received, no point in sending any subsequent AUX_CHAIN_IND PDUs */
1775                 runAuxAdv = false;
1776                 runAuxChain = false;
1777             }
1778             else
1779             {
1780                 if (!ble5HandlerState.auxAdv.sendAuxAdv)
1781                 {
1782                     if(ble5HandlerState.common.auxPtrInfo.auxPtrPresent)
1783                     {
1784                         if (ble5HandlerState.common.auxPtrInfo.offsetUnits == 1 && ble5HandlerState.common.auxPtrInfo.auxOffset == 0)
1785                         {
1786                             /* Reset TX FIFO to handle auxPtr updates. Writing to FCMD is safe because PBE is finished, ref. RCL-367 */
1787                             HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_FCMD) = (LRFDPBE_FCMD_DATA_TXFIFO_RESET >> LRFDPBE_FCMD_DATA_S) ;
1788                             /* Turn off LRF to allow new synth programming  */
1789                             LRF_disable();
1790                             runAuxChain = true;
1791                         }
1792                         else
1793                         {
1794                             runAuxChain = false;
1795                         }
1796                     }
1797                     else
1798                     {
1799                         runAuxChain = false;
1800                     }
1801                     runAuxAdv = false;
1802                 }
1803             }
1804             if (!runAuxAdv && !runAuxChain && cmd->status == RCL_CommandStatus_Active)
1805             {
1806                 cmd->status = ble5HandlerState.common.endStatus;
1807                 rclEvents.lastCmdDone = 1;
1808                 runAuxAdv = false;
1809                 runAuxChain = false;
1810             }
1811         }
1812         else if (lrfEvents.opError != 0)
1813         {
1814             RCL_CommandStatus endStatus = ble5HandlerState.common.endStatus;
1815             if (endStatus == RCL_CommandStatus_Finished)
1816             {
1817                 cmd->status = RCL_Handler_BLE5_findPbeErrorEndStatus(HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_COMMON_RAM_O_ENDCAUSE));
1818             }
1819             else
1820             {
1821                 cmd->status = endStatus;
1822             }
1823             rclEvents.lastCmdDone = 1;
1824             runAuxAdv = false;
1825             runAuxChain = false;
1826         }
1827         else
1828         {
1829             /* Other events need to be handled unconditionally */
1830         }
1831 
1832         if (rclEventsIn.rxBufferUpdate != 0)
1833         {
1834             RCL_Handler_BLE5_updateRxCurBufferAndFifo(&auxAdvCmd->ctx->rxBuffers);
1835             rclEventsIn.rxBufferUpdate = 0;
1836         }
1837 
1838         if (runAuxAdv)
1839         {
1840             RCL_CommandStatus startTimeStatus;
1841 
1842             /* Set up channel */
1843             channel = auxAdvCmd->channel;
1844             rfFreq = RCL_Handler_BLE5_findRfFreq(channel);
1845             if (rfFreq == 0)
1846             {
1847                 cmd->status = RCL_CommandStatus_Error_Param;
1848                 rclEvents.lastCmdDone = 1;
1849             }
1850             else
1851             {
1852                 /* Program frequency word */
1853                 LRF_programFrequency(rfFreq, true);
1854                 LRF_enable();
1855 
1856                 startTimeStatus = RCL_Scheduler_setStartStopTimeEarliestStart(cmd, earliestStartTime);
1857 
1858                 /* Consider the current packet duration when calculating the AuxOffset */
1859                 uint32_t pktDuration = RCL_Handler_BLE5_findPacketDuration(ble5HandlerState.common.auxPtrInfo.pktLen, ble5HandlerState.common.phyFeatures);
1860                 if (ble5HandlerState.common.auxPtrInfo.auxPtrPresent)
1861                 {
1862                     if(!RCL_Handler_BLE5_updateAuxPtr(&ble5HandlerState.common.auxPtrInfo, pktDuration, 0, false))
1863                     {
1864                         startTimeStatus = RCL_CommandStatus_Error_Param;
1865                     }
1866                 }
1867                 if (startTimeStatus < RCL_CommandStatus_Finished)
1868                 {
1869                     /* Initialize counters */
1870                     ble5HandlerState.common.activeUpdate =
1871                         RCL_Handler_BLE5_initAdvScanInitStats(auxAdvCmd->stats, rclSchedulerState.actualStartTime);
1872                     ble5HandlerState.auxAdv.gracefulStopObserved = false;
1873 
1874                     if (rclSchedulerState.gracefulStopInfo.cmdStopEnabled || rclSchedulerState.gracefulStopInfo.schedStopEnabled)
1875                     {
1876                         /* Enable interrupt to service graceful stop */
1877                         hal_enable_graceful_stop_time_irq();
1878                     }
1879                 }
1880 
1881                 if (startTimeStatus >= RCL_CommandStatus_Finished)
1882                 {
1883                     cmd->status = startTimeStatus;
1884                     rclEvents.lastCmdDone = 1;
1885                 }
1886                 else
1887                 {
1888                     HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_OPCFG) = 0;
1889                     uint16_t whitenInit = RCL_Handler_BLE5_findWhitenInit(channel);
1890                     HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_WHITEINIT) = whitenInit;
1891                     if (ble5HandlerState.common.accessAddressModification)
1892                     {
1893                         HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_MDMSYNCA) = ADV_ACCESS_ADDRESS ^ (whitenInit << 24);
1894                     }
1895 
1896                     /* Enable interrupts */
1897                     if (ble5HandlerState.auxAdv.runRx)
1898                     {
1899                         /* Set up sync found capture */
1900                         hal_setup_sync_found_cap();
1901                         uint16_t fifoCfg = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FIFOCFG);
1902                         LRF_enableHwInterrupt(RCL_Handler_BLE5_maskEventsByFifoConf(LRF_EventOpDone.value | LRF_EventOpError.value |
1903                                                                                     LRF_EventRxOk.value | LRF_EventRxIgnored.value |
1904                                                                                     LRF_EventRxNok.value | LRF_EventRxBufFull.value,
1905                                                                                     fifoCfg, ble5HandlerState.common.activeUpdate));
1906                     }
1907                     else
1908                     {
1909                         LRF_enableHwInterrupt(LRF_EventOpDone.value | LRF_EventOpError.value);
1910                     }
1911 
1912                     /* Post cmd */
1913                     Log_printf(RclCore, Log_VERBOSE, "Starting extended advertiser on channel %1d", channel);
1914 
1915                     LRF_waitForTopsmReady();
1916                     HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_API) = PBE_BLE5_REGDEF_API_OP_ADV;
1917                     ble5HandlerState.auxAdv.sendAuxAdv = false;
1918                 }
1919             }
1920         }
1921         if (runAuxChain)
1922         {
1923             RCL_CommandStatus startTimeStatus;
1924 
1925             RCL_Ble5Channel channel = ble5HandlerState.common.auxPtrInfo.chIndex;
1926             uint16_t auxAdvCfg = 0;
1927 
1928             uint32_t startTimeDelta = RCL_Handler_BLE5_findPacketDuration(ble5HandlerState.common.auxPtrInfo.pktLen, ble5HandlerState.common.phyFeatures);
1929 
1930             rfFreq = RCL_Handler_BLE5_findRfFreq(channel);
1931             if (rfFreq == 0)
1932             {
1933                 cmd->status = RCL_CommandStatus_Error_Param;
1934                 rclEvents.lastCmdDone = 1;
1935             }
1936             else
1937             {
1938                 /* Program frequency word */
1939                 LRF_programFrequency(rfFreq, true);
1940                 LRF_enable();
1941 
1942                 /* Check advertising type */
1943                 RCL_Buffer_TxBuffer *nextTxBuffer = RCL_TxBuffer_head(&auxAdvCmd->ctx->txBuffers);
1944                 if(nextTxBuffer != NULL)
1945                 {
1946                     uint8_t header = nextTxBuffer->data[nextTxBuffer->numPad - 1];
1947                     uint8_t extHeader = nextTxBuffer->data[nextTxBuffer->numPad - 1 + BLE_HEADER_LENGTH];
1948 
1949                     if (((header & BLE_PDU_TYPE_BM) == BLE_PDU_ADV_EXTENDED) && ((extHeader & BLE_ADV_MODE_BM) >> 6) == 0)
1950                     {
1951                         RCL_Handler_BLE5_getAuxPtrFromTxBuffer(nextTxBuffer, &ble5HandlerState.common.auxPtrInfo, 0);
1952                         ble5HandlerState.auxAdv.runRx = false;
1953                     }
1954                 }
1955 
1956                 uint32_t nBuffer = 0;
1957                 nBuffer = RCL_Handler_BLE5_updateTxBuffers(&auxAdvCmd->ctx->txBuffers, 1,
1958                                                            &ble5HandlerState.common.txBufferInfo,
1959                                                            false);
1960                 if (nBuffer == 0)
1961                 {
1962                     /* Error */
1963                     ble5HandlerState.common.endStatus = RCL_CommandStatus_Error_MissingTxBuffer;
1964                 }
1965                 else
1966                 {
1967                     /*
1968                      * Express the startTimeDelta in terms of offset units so that the relative start time is rounded up
1969                      * to the closest offset unit. Also add a couple of microseconds to avoid sending the packets right
1970                      * at the beginning of the offset window.
1971                      */
1972                     startTimeDelta += RCL_SCHEDULER_SYSTIM_US(EXT_ADV_INTERVAL_US);
1973                     uint32_t startTimeDeltaInOffsetUnits = BLE_convertSystimUnitsToOffsetUnits(startTimeDelta, BLE_AUX_OFFSET_30_US);
1974                     uint32_t relStartTime = RCL_SCHEDULER_SYSTIM_US((startTimeDeltaInOffsetUnits * BLE_AUX_OFFSET_30_US)) + RCL_SCHEDULER_SYSTIM_US(2);
1975 
1976                     /*
1977                      * If an AUX_SCAN_REQ was received, the relative start time for the packet needs to consider the
1978                      * time spent sending the AUX_ADV_IND, receiving the AUX_SCAN_REQ and replying with the AUX_SCAN_RSP.
1979                      * In this particular case, the AUX_SCAN_RSP is the previously sent packet, so no need to include it here.
1980                      */
1981                     if (ble5HandlerState.auxAdv.auxScanReqReceived)
1982                     {
1983                         /* Time spent sending the AUX_ADV_IND */
1984                         relStartTime += RCL_Handler_BLE5_findPacketDuration(ble5HandlerState.auxAdv.auxAdvIndLen, ble5HandlerState.common.phyFeatures);
1985                         /* Time spent receiving the AUX_SCAN_REQ */
1986                         relStartTime += RCL_Handler_BLE5_findPacketDuration(BLE_ADV_AUX_SCAN_REQ_PKT_LEN, ble5HandlerState.common.phyFeatures);
1987                         /* Time spent switching from Tx to Rx, and then back from Rx to Tx */
1988                         relStartTime += (2 * BLE_T_IFS);
1989                         ble5HandlerState.auxAdv.auxScanReqReceived = false;
1990                     }
1991 
1992                     /* Set new start time */
1993                     startTimeStatus = RCL_Scheduler_setNewStartRelTime(relStartTime);
1994 
1995                     /* Calculate auxPtr offset and update Tx FIFO if needed */
1996                     if (ble5HandlerState.common.auxPtrInfo.auxPtrPresent)
1997                     {
1998                         /* Consider the current packet duration when calculating the AuxOffset */
1999                         uint32_t pktDuration = RCL_Handler_BLE5_findPacketDuration(ble5HandlerState.common.auxPtrInfo.pktLen, ble5HandlerState.common.phyFeatures);
2000 
2001                         if(!RCL_Handler_BLE5_updateAuxPtr(&ble5HandlerState.common.auxPtrInfo, pktDuration, 0, false))
2002                         {
2003                             startTimeStatus = RCL_CommandStatus_Error_Param;
2004                         }
2005                     }
2006                     if (startTimeStatus >= RCL_CommandStatus_Finished)
2007                     {
2008                         cmd->status = startTimeStatus;
2009                         rclEvents.lastCmdDone = 1;
2010                     }
2011                     else
2012                     {
2013                         HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_ADVCFG) = auxAdvCfg;
2014                         HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_OPCFG) = 0;
2015                         uint16_t whitenInit = RCL_Handler_BLE5_findWhitenInit(channel);
2016                         HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_WHITEINIT) = whitenInit;
2017                         if (ble5HandlerState.common.accessAddressModification)
2018                         {
2019                             HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_MDMSYNCA) = ADV_ACCESS_ADDRESS ^ (whitenInit << 24);
2020                         }
2021 
2022                         /* Enable interrupts */
2023                         if (ble5HandlerState.auxAdv.runRx)
2024                         {
2025                             /* Set up sync found capture */
2026                             hal_setup_sync_found_cap();
2027                             uint16_t fifoCfg = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FIFOCFG);
2028                             LRF_enableHwInterrupt(RCL_Handler_BLE5_maskEventsByFifoConf(LRF_EventOpDone.value | LRF_EventOpError.value |
2029                                                                                         LRF_EventRxOk.value | LRF_EventRxIgnored.value |
2030                                                                                         LRF_EventRxNok.value | LRF_EventRxBufFull.value,
2031                                                                                         fifoCfg, ble5HandlerState.common.activeUpdate));
2032                         }
2033                         else
2034                         {
2035                             LRF_enableHwInterrupt(LRF_EventOpDone.value | LRF_EventOpError.value);
2036                         }
2037 
2038                         LRF_waitForTopsmReady();
2039 
2040                         /* Deallocate TX FIFO. Writing to FCMD is safe because PBE is finished, ref. RCL-367 */
2041                         HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_FCMD) = (LRFDPBE_FCMD_DATA_TXFIFO_DEALLOC >> LRFDPBE_FCMD_DATA_S);
2042 
2043                         /* Post cmd */
2044                         Log_printf(RclCore, Log_VERBOSE, "Starting extended advertiser on channel %1d", channel);
2045                         HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_API) = PBE_BLE5_REGDEF_API_OP_ADV;
2046 
2047                         /* Free up the TxBuffer and notify caller with an RCL event */
2048                         RCL_Buffer_TxBuffer *txBuffer;
2049                         txBuffer = RCL_TxBuffer_get(&auxAdvCmd->ctx->txBuffers);
2050                         if (txBuffer == NULL)
2051                         {
2052                             /* Error */
2053                             ble5HandlerState.common.endStatus = RCL_CommandStatus_Error_TxBufferCorruption;
2054                         }
2055                         txBuffer->state = RCL_BufferStateFinished;
2056                         if (txBuffer == ble5HandlerState.common.txBufferInfo.lastEnteredTxBuffer)
2057                         {
2058                             ble5HandlerState.common.txBufferInfo.lastEnteredTxBuffer = NULL;
2059                         }
2060                         rclEvents.txBufferFinished = 1;
2061                     }
2062                 }
2063             }
2064         }
2065         if (rclEvents.lastCmdDone != 0)
2066         {
2067             RCL_Handler_BLE5_updateAdvScanInitStats(auxAdvCmd->stats, rclSchedulerState.actualStartTime);
2068         }
2069     }
2070     if (rclEvents.lastCmdDone != 0)
2071     {
2072         LRF_disable();
2073         LRF_disableSynthRefsys();
2074     }
2075     return rclEvents;
2076 }
2077 
2078 /*
2079  *  ======== RCL_Handler_BLE5_periodicAdv ========
2080  */
RCL_Handler_BLE5_periodicAdv(RCL_Command * cmd,LRF_Events lrfEvents,RCL_Events rclEventsIn)2081 RCL_Events RCL_Handler_BLE5_periodicAdv(RCL_Command *cmd, LRF_Events lrfEvents, RCL_Events rclEventsIn)
2082 {
2083     uint32_t rfFreq;
2084     RCL_CmdBle5PeriodicAdvertiser *perAdvCmd = (RCL_CmdBle5PeriodicAdvertiser *) cmd;
2085     bool runAuxSync = false;
2086     bool runAuxChain = false;
2087     RCL_Ble5Channel channel;
2088     RCL_Events rclEvents = {.value = 0};
2089     uint32_t earliestStartTime = 0;
2090 
2091     if (rclEventsIn.setup != 0)
2092     {
2093         /* Start by enabling refsys */
2094         earliestStartTime = LRF_enableSynthRefsys();
2095 
2096         RCL_CtxPeriodicAdvertiser *ctx = perAdvCmd->ctx;
2097         uint32_t crcInit = ctx->crcInit;
2098         uint32_t accessAddress = ctx->accessAddress;
2099 
2100         /* 32-bit access to set the Access Address for the periodic advertisement */
2101         HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_MDMSYNCA) = accessAddress;
2102 
2103         /* 32-bit access to also write CRCINITH */
2104         HWREG_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_CRCINITL) = crcInit << 8;
2105 
2106         ble5HandlerState.common.fifoCfg = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FIFOCFG);
2107         HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_EXTRABYTES) = RCL_Handler_BLE5_findNumExtraBytes(ble5HandlerState.common.fifoCfg);
2108 
2109         /* Default end status */
2110         ble5HandlerState.common.endStatus = RCL_CommandStatus_Finished;
2111 
2112         RCL_CommandStatus status = RCL_Handler_BLE5_setPhy(cmd->phyFeatures);
2113         if (LRF_programTxPower(perAdvCmd->txPower) != TxPowerResult_Ok)
2114         {
2115             status = RCL_CommandStatus_Error_Param;
2116         }
2117 
2118         if (status == RCL_CommandStatus_Active)
2119         {
2120             /* Initialize RF FIFOs */
2121             ble5HandlerState.common.txFifoSz = LRF_prepareTxFifo();
2122 
2123             /* This operation is always non-connectable/non-scannable */
2124             RCL_Buffer_TxBuffer *txBuffer = RCL_TxBuffer_head(&perAdvCmd->ctx->txBuffers);
2125             uint16_t advCfg = 0;
2126             uint16_t aeCfg = PBE_BLE5_RAM_AECFG_CHNL_SECONDARY;
2127             channel = perAdvCmd->channel;
2128 
2129             if (txBuffer != NULL)
2130             {
2131                 uint8_t header = txBuffer->data[txBuffer->numPad - 1];
2132                 uint8_t extHeader = txBuffer->data[txBuffer->numPad - 1 + BLE_HEADER_LENGTH];
2133 
2134                 /* Check advertising type. Only extended PDUs with AdvMode set to 0 are allowed */
2135                 if (((header & BLE_PDU_TYPE_BM) == BLE_PDU_ADV_EXTENDED) && (((extHeader & BLE_ADV_MODE_BM) >> 6) == BLE_ADV_MODE_NONCONN_NONSCAN))
2136                 {
2137                     /* Extract AuxPtr information if available indicating that an AUX_CHAIN_IND will follow the AUX_SYNC_IND */
2138                     RCL_Handler_BLE5_getAuxPtrFromTxBuffer(txBuffer, &ble5HandlerState.common.auxPtrInfo, 0);
2139                 }
2140                 else
2141                 {
2142                     status = RCL_CommandStatus_Error_TxBufferCorruption;
2143                 }
2144             }
2145 
2146             /* Enter payload. Enter only one Tx Buffer corresponding to the AUX_SYNC_IND */
2147             uint32_t nBuffer;
2148             ble5HandlerState.common.txBufferInfo = (RCL_TxBufferInfo) { 0 };
2149             nBuffer = RCL_Handler_BLE5_updateTxBuffers(&perAdvCmd->ctx->txBuffers, 1,
2150                                                        &ble5HandlerState.common.txBufferInfo,
2151                                                        false);
2152             if (nBuffer == 0)
2153             {
2154                 status = RCL_CommandStatus_Error_MissingTxBuffer;
2155             }
2156             else
2157             {
2158                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_ADVCFG) = advCfg;
2159                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_AECFG) = aeCfg;
2160                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FILTPOLICY) = 0;
2161                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_RPAMODE) = 0;
2162                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_RPACONNECT) = 0;
2163                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FL1MASK) = 0;
2164                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FL2MASK) = 0;
2165 
2166                 /* Once packets are copied to the TX FIFO, consume them from the Tx Buffer list and notify the caller */
2167                 RCL_Buffer_TxBuffer *txBuffer;
2168                 txBuffer = RCL_TxBuffer_get(&perAdvCmd->ctx->txBuffers);
2169                 if (txBuffer == NULL)
2170                 {
2171                     /* Error */
2172                     ble5HandlerState.common.endStatus = RCL_CommandStatus_Error_TxBufferCorruption;
2173                 }
2174                 txBuffer->state = RCL_BufferStateFinished;
2175                 if (txBuffer == ble5HandlerState.common.txBufferInfo.lastEnteredTxBuffer)
2176                 {
2177                     ble5HandlerState.common.txBufferInfo.lastEnteredTxBuffer = NULL;
2178                 }
2179                 rclEvents.txBufferFinished = 1;
2180 
2181                 /* Run periodic advertising next */
2182                 runAuxSync = true;
2183             }
2184         }
2185         /* Set status */
2186         cmd->status = status;
2187         if (status >= RCL_CommandStatus_Finished)
2188         {
2189             rclEvents.lastCmdDone = 1;
2190         }
2191     }
2192 
2193     if (cmd->status == RCL_CommandStatus_Active)
2194     {
2195         if (rclEventsIn.timerStart != 0)
2196         {
2197             rclEvents.cmdStarted = 1;
2198         }
2199         if (rclEventsIn.gracefulStop != 0)
2200         {
2201             ble5HandlerState.perAdv.gracefulStopObserved = true;
2202         }
2203 
2204         if (lrfEvents.opDone != 0)
2205         {
2206             uint16_t endCause = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_COMMON_RAM_O_ENDCAUSE);
2207 
2208             if (rclEventsIn.hardStop != 0)
2209             {
2210                 ble5HandlerState.common.endStatus = RCL_Scheduler_findStopStatus(RCL_StopType_Hard);
2211                 runAuxSync = false;
2212                 runAuxChain = false;
2213             }
2214             else if (endCause == PBE_COMMON_RAM_ENDCAUSE_STAT_EOPSTOP ||
2215                         ble5HandlerState.adv.gracefulStopObserved ||
2216                         rclEventsIn.gracefulStop != 0)
2217             {
2218                 ble5HandlerState.common.endStatus = RCL_Scheduler_findStopStatus(RCL_StopType_Graceful);
2219                 runAuxSync = false;
2220                 runAuxChain = false;
2221             }
2222             else
2223             {
2224                 if(ble5HandlerState.common.auxPtrInfo.auxPtrPresent)
2225                 {
2226                     if (ble5HandlerState.common.auxPtrInfo.offsetUnits == 1 && ble5HandlerState.common.auxPtrInfo.auxOffset == 0)
2227                     {
2228                         /* Reset TX FIFO to handle auxPtr updates. Writing to FCMD is safe because PBE is finished, ref. RCL-367 */
2229                         HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_FCMD) = (LRFDPBE_FCMD_DATA_TXFIFO_RESET >> LRFDPBE_FCMD_DATA_S) ;
2230                         /* Turn off LRF to allow new synth programming  */
2231                         LRF_disable();
2232                         runAuxChain = true;
2233                     }
2234                     else
2235                     {
2236                         runAuxChain = false;
2237                     }
2238                 }
2239                 else
2240                 {
2241                     runAuxChain = false;
2242                 }
2243                 runAuxSync = false;
2244             }
2245             if (!runAuxSync && !runAuxChain && cmd->status == RCL_CommandStatus_Active)
2246             {
2247                 cmd->status = ble5HandlerState.common.endStatus;
2248                 rclEvents.lastCmdDone = 1;
2249                 runAuxSync = false;
2250                 runAuxChain = false;
2251             }
2252         }
2253         else if (lrfEvents.opError != 0)
2254         {
2255             RCL_CommandStatus endStatus = ble5HandlerState.common.endStatus;
2256             if (endStatus == RCL_CommandStatus_Finished)
2257             {
2258                 cmd->status = RCL_Handler_BLE5_findPbeErrorEndStatus(HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_COMMON_RAM_O_ENDCAUSE));
2259             }
2260             else
2261             {
2262                 cmd->status = endStatus;
2263             }
2264             rclEvents.lastCmdDone = 1;
2265             runAuxSync = false;
2266             runAuxChain = false;
2267         }
2268         else
2269         {
2270             /* Other events need to be handled unconditionally */
2271         }
2272 
2273         if (runAuxSync)
2274         {
2275             RCL_CommandStatus startTimeStatus;
2276 
2277             /* Set up channel */
2278             channel = perAdvCmd->channel;
2279             rfFreq = RCL_Handler_BLE5_findRfFreq(channel);
2280             if (rfFreq == 0)
2281             {
2282                 cmd->status = RCL_CommandStatus_Error_Param;
2283                 rclEvents.lastCmdDone = 1;
2284             }
2285             else
2286             {
2287                 /* Program frequency word */
2288                 LRF_programFrequency(rfFreq, true);
2289                 LRF_enable();
2290 
2291                 startTimeStatus = RCL_Scheduler_setStartStopTimeEarliestStart(cmd, earliestStartTime);
2292 
2293                 /* Consider the current packet duration when calculating the AuxOffset */
2294                 uint32_t pktDuration = RCL_Handler_BLE5_findPacketDuration(ble5HandlerState.common.auxPtrInfo.pktLen, ble5HandlerState.common.phyFeatures);
2295                 if (ble5HandlerState.common.auxPtrInfo.auxPtrPresent)
2296                 {
2297                     if(!RCL_Handler_BLE5_updateAuxPtr(&ble5HandlerState.common.auxPtrInfo, pktDuration, 0, false))
2298                     {
2299                         startTimeStatus = RCL_CommandStatus_Error_Param;
2300                     }
2301                 }
2302                 if (startTimeStatus < RCL_CommandStatus_Finished)
2303                 {
2304                     /* Initialize counters */
2305                     ble5HandlerState.common.activeUpdate =
2306                         RCL_Handler_BLE5_initAdvScanInitStats(perAdvCmd->stats, rclSchedulerState.actualStartTime);
2307                     ble5HandlerState.perAdv.gracefulStopObserved = false;
2308 
2309                     if (rclSchedulerState.gracefulStopInfo.cmdStopEnabled || rclSchedulerState.gracefulStopInfo.schedStopEnabled)
2310                     {
2311                         /* Enable interrupt to service graceful stop */
2312                         hal_enable_graceful_stop_time_irq();
2313                     }
2314                 }
2315 
2316                 if (startTimeStatus >= RCL_CommandStatus_Finished)
2317                 {
2318                     cmd->status = startTimeStatus;
2319                     rclEvents.lastCmdDone = 1;
2320                 }
2321                 else
2322                 {
2323                     HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_OPCFG) = 0;
2324                     uint16_t whitenInit = RCL_Handler_BLE5_findWhitenInit(channel);
2325                     HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_WHITEINIT) = whitenInit;
2326                     if (ble5HandlerState.common.accessAddressModification)
2327                     {
2328                         HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_MDMSYNCA) = perAdvCmd->ctx->accessAddress ^ (whitenInit << 24);
2329                     }
2330 
2331                     /* Enable interrupts */
2332                     LRF_enableHwInterrupt(LRF_EventOpDone.value | LRF_EventOpError.value);
2333 
2334                     /* Post cmd */
2335                     Log_printf(RclCore, Log_VERBOSE, "Starting periodic advertising on channel %1d (access address %08X)", channel, perAdvCmd->ctx->accessAddress);
2336                     LRF_waitForTopsmReady();
2337                     HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_API) = PBE_BLE5_REGDEF_API_OP_ADV;
2338                 }
2339             }
2340         }
2341         if (runAuxChain)
2342         {
2343             RCL_CommandStatus startTimeStatus;
2344 
2345             RCL_Ble5Channel channel = ble5HandlerState.common.auxPtrInfo.chIndex;
2346 
2347             /* Non-connectable/Non-scannable always*/
2348             uint16_t advCfg = 0;
2349             uint32_t startTimeDelta = RCL_Handler_BLE5_findPacketDuration(ble5HandlerState.common.auxPtrInfo.pktLen, ble5HandlerState.common.phyFeatures);
2350 
2351             rfFreq = RCL_Handler_BLE5_findRfFreq(channel);
2352             if (rfFreq == 0)
2353             {
2354                 cmd->status = RCL_CommandStatus_Error_Param;
2355                 rclEvents.lastCmdDone = 1;
2356             }
2357             else
2358             {
2359                 /* Program frequency word */
2360                 LRF_programFrequency(rfFreq, true);
2361                 LRF_enable();
2362 
2363                 /* Check advertising type */
2364                 RCL_Buffer_TxBuffer *nextTxBuffer = RCL_TxBuffer_head(&perAdvCmd->ctx->txBuffers);
2365                 if(nextTxBuffer != NULL)
2366                 {
2367                     uint8_t header = nextTxBuffer->data[nextTxBuffer->numPad - 1];
2368                     uint8_t extHeader = nextTxBuffer->data[nextTxBuffer->numPad - 1 + BLE_HEADER_LENGTH];
2369 
2370                     if (((header & BLE_PDU_TYPE_BM) == BLE_PDU_ADV_EXTENDED) && ((extHeader & BLE_ADV_MODE_BM) >> 6) == 0)
2371                     {
2372                         RCL_Handler_BLE5_getAuxPtrFromTxBuffer(nextTxBuffer, &ble5HandlerState.common.auxPtrInfo, 0);
2373                     }
2374                 }
2375                 uint32_t nBuffer = 0;
2376                 nBuffer = RCL_Handler_BLE5_updateTxBuffers(&perAdvCmd->ctx->txBuffers, 1,
2377                                                            &ble5HandlerState.common.txBufferInfo,
2378                                                            false);
2379                 if (nBuffer == 0)
2380                 {
2381                     /* Error */
2382                     ble5HandlerState.common.endStatus = RCL_CommandStatus_Error_MissingTxBuffer;
2383                 }
2384                 else
2385                 {
2386                     /*
2387                      * Express the startTimeDelta in terms of offset units so that the relative start time is rounded up
2388                      * to the closest offset unit. Also add a couple of microseconds to avoid sending the packets right
2389                      * at the beginning of the offset window.
2390                      */
2391                     startTimeDelta += RCL_SCHEDULER_SYSTIM_US(EXT_ADV_INTERVAL_US);
2392                     uint32_t startTimeDeltaInOffsetUnits = BLE_convertSystimUnitsToOffsetUnits(startTimeDelta, BLE_AUX_OFFSET_30_US);
2393                     uint32_t relStartTime = RCL_SCHEDULER_SYSTIM_US((startTimeDeltaInOffsetUnits * BLE_AUX_OFFSET_30_US)) + RCL_SCHEDULER_SYSTIM_US(2);
2394 
2395                     /* Set new start time */
2396                     startTimeStatus = RCL_Scheduler_setNewStartRelTime(relStartTime);
2397 
2398                     /* Calculate auxPtr offset and update Tx FIFO if needed */
2399                     if (ble5HandlerState.common.auxPtrInfo.auxPtrPresent)
2400                     {
2401                         /* Consider the current packet duration when calculating the AuxOffset */
2402                         uint32_t pktDuration = RCL_Handler_BLE5_findPacketDuration(ble5HandlerState.common.auxPtrInfo.pktLen, ble5HandlerState.common.phyFeatures);
2403 
2404                         if(!RCL_Handler_BLE5_updateAuxPtr(&ble5HandlerState.common.auxPtrInfo, pktDuration, 0, false))
2405                         {
2406                             startTimeStatus = RCL_CommandStatus_Error_Param;
2407                         }
2408                     }
2409                     if (startTimeStatus >= RCL_CommandStatus_Finished)
2410                     {
2411                         cmd->status = startTimeStatus;
2412                         rclEvents.lastCmdDone = 1;
2413                     }
2414                     else
2415                     {
2416                         HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_ADVCFG) = advCfg;
2417                         HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_OPCFG) = 0;
2418                         uint16_t whitenInit = RCL_Handler_BLE5_findWhitenInit(channel);
2419                         HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_WHITEINIT) = whitenInit;
2420                         if (ble5HandlerState.common.accessAddressModification)
2421                         {
2422                             HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_MDMSYNCA) = perAdvCmd->ctx->accessAddress ^ (whitenInit << 24);
2423                         }
2424 
2425                         /* Enable interrupts */
2426                         LRF_enableHwInterrupt(LRF_EventOpDone.value | LRF_EventOpError.value);
2427 
2428                         LRF_waitForTopsmReady();
2429 
2430                         /* Deallocate TX FIFO. Writing to FCMD is safe because PBE is finished, ref. RCL-367 */
2431                         HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_FCMD) = (LRFDPBE_FCMD_DATA_TXFIFO_DEALLOC >> LRFDPBE_FCMD_DATA_S);
2432 
2433                         /* Post cmd */
2434                         Log_printf(RclCore, Log_VERBOSE, "Sending AuxChain on channel %1d (access address %08X)", channel, perAdvCmd->ctx->accessAddress);
2435                         HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_API) = PBE_BLE5_REGDEF_API_OP_ADV;
2436 
2437                         /* Free up the TxBuffer and notify caller with an RCL event */
2438                         RCL_Buffer_TxBuffer *txBuffer;
2439                         txBuffer = RCL_TxBuffer_get(&perAdvCmd->ctx->txBuffers);
2440                         if (txBuffer == NULL)
2441                         {
2442                             /* Error */
2443                             ble5HandlerState.common.endStatus = RCL_CommandStatus_Error_TxBufferCorruption;
2444                         }
2445                         txBuffer->state = RCL_BufferStateFinished;
2446                         if (txBuffer == ble5HandlerState.common.txBufferInfo.lastEnteredTxBuffer)
2447                         {
2448                             ble5HandlerState.common.txBufferInfo.lastEnteredTxBuffer = NULL;
2449                         }
2450                         rclEvents.txBufferFinished = 1;
2451                     }
2452                 }
2453             }
2454         }
2455         if (rclEvents.lastCmdDone != 0)
2456         {
2457             RCL_Handler_BLE5_updateAdvScanInitStats(perAdvCmd->stats, rclSchedulerState.actualStartTime);
2458         }
2459     }
2460     if (rclEvents.lastCmdDone != 0)
2461     {
2462         LRF_disable();
2463         LRF_disableSynthRefsys();
2464     }
2465     return rclEvents;
2466 }
2467 
2468 /*
2469  *  ======== RCL_Handler_BLE5_scan_init ========
2470  */
RCL_Handler_BLE5_scan_init(RCL_Command * cmd,LRF_Events lrfEvents,RCL_Events rclEventsIn)2471 RCL_Events RCL_Handler_BLE5_scan_init(RCL_Command *cmd, LRF_Events lrfEvents, RCL_Events rclEventsIn)
2472 {
2473     RCL_CmdBle5Scanner *scanCmd = (RCL_CmdBle5Scanner *) cmd;
2474     RCL_CmdBle5Initiator *initCmd = (RCL_CmdBle5Initiator *) cmd;
2475     uint32_t rfFreq;
2476     RCL_Events rclEvents = RCL_EventNone;
2477     RCL_CtxScanInit *ctx;
2478     RCL_StatsAdvScanInit *stats;
2479     bool followAuxPtr = false;
2480     RCL_ConnParams *connParams;
2481 
2482     if (rclEventsIn.setup != 0)
2483     {
2484         uint32_t earliestStartTime;
2485         RCL_Ble5Channel channel;
2486         uint32_t interval = 0;
2487         RCL_Command_TxPower txPower;
2488         bool acceptLegacy;
2489         bool acceptExtended;
2490 
2491         /* Start by enabling refsys */
2492         earliestStartTime = LRF_enableSynthRefsys();
2493 
2494         HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_MDMSYNCA) = ADV_ACCESS_ADDRESS;
2495 
2496         /* 32-bit access to also write CRCINITH */
2497         HWREG_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_CRCINITL) = ADV_CRC_INIT;
2498 
2499         /* The initial First Rx Timeout depends on the relative gaceful stop time configured for the command */
2500         HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FIRSTRXTIMEOUT) = 0;
2501 
2502         ble5HandlerState.common.fifoCfg = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FIFOCFG);
2503         HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_EXTRABYTES) = RCL_Handler_BLE5_findNumExtraBytes(ble5HandlerState.common.fifoCfg);
2504 
2505         /* Default end status */
2506         ble5HandlerState.common.endStatus = RCL_CommandStatus_Finished;
2507 
2508         if (cmd->cmdId == RCL_CMDID_BLE5_INITIATOR)
2509         {
2510             ble5HandlerState.scanInit.initiator = true;
2511             channel = initCmd->channel;
2512             txPower = initCmd->txPower;
2513             acceptLegacy = initCmd->acceptLegacy;
2514             acceptExtended = initCmd->acceptExtended;
2515         }
2516         else
2517         {
2518             ble5HandlerState.scanInit.initiator = false;
2519             channel = scanCmd->channel;
2520             txPower = scanCmd->txPower;
2521             acceptLegacy = scanCmd->acceptLegacy;
2522             acceptExtended = scanCmd->acceptExtended;
2523         }
2524         ble5HandlerState.scanInit.dynamicWinOffset = false; /* Default */
2525 
2526         RCL_CommandStatus status = RCL_Handler_BLE5_setPhy(cmd->phyFeatures);
2527 
2528         rfFreq = RCL_Handler_BLE5_findRfFreq(channel);
2529         if (rfFreq == 0)
2530         {
2531             status = RCL_CommandStatus_Error_Param;
2532         }
2533         else if (LRF_programTxPower(txPower) != TxPowerResult_Ok)
2534         {
2535             status = RCL_CommandStatus_Error_Param;
2536         }
2537         else if (!acceptLegacy && !acceptExtended)
2538         {
2539             cmd->status = RCL_CommandStatus_Error_Param;
2540         }
2541         else if (acceptLegacy && (cmd->phyFeatures != 0))
2542         {
2543             cmd->status = RCL_CommandStatus_Error_Param;
2544         }
2545         else if (acceptLegacy && !acceptExtended)
2546         {
2547             if (channel != BLE_ADV_CHAN_LO && channel != BLE_ADV_CHAN_MID && channel != BLE_ADV_CHAN_HI)
2548             {
2549                 cmd->status = RCL_CommandStatus_Error_Param;
2550             }
2551         }
2552         if (status == RCL_CommandStatus_Active)
2553         {
2554             /* Program frequency word */
2555             LRF_programFrequency(rfFreq, false);
2556 
2557             /* Enable radio */
2558             LRF_enable();
2559 
2560             RCL_CommandStatus startTimeStatus = RCL_Scheduler_setStartStopTimeEarliestStart(cmd, earliestStartTime);
2561             if (startTimeStatus >= RCL_CommandStatus_Finished)
2562             {
2563                 status = startTimeStatus;
2564             }
2565             else
2566             {
2567                 if (ble5HandlerState.scanInit.initiator)
2568                 {
2569                     ctx = initCmd->ctx;
2570                     stats = initCmd->stats;
2571                 }
2572                 else
2573                 {
2574                     ctx = scanCmd->ctx;
2575                     stats = scanCmd->stats;
2576                 }
2577 
2578                 /* Initialize counters */
2579                 ble5HandlerState.common.activeUpdate = RCL_Handler_BLE5_initAdvScanInitStats(stats,
2580                                                                                             rclSchedulerState.actualStartTime);
2581 
2582                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_OPCFG) = 0;
2583                 uint16_t whitenInit = RCL_Handler_BLE5_findWhitenInit(channel);
2584                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_WHITEINIT) = whitenInit;
2585                 if (ble5HandlerState.common.accessAddressModification)
2586                 {
2587                     HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_MDMSYNCA) = ADV_ACCESS_ADDRESS ^ (whitenInit << 24);
2588                 }
2589 
2590                 /* Configure maximum packet length */
2591                 if (acceptExtended)
2592                 {
2593                     HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_MAXLEN) = BLE_ADV_EXTENDED_MAX_PKT_LEN;
2594                 }
2595                 else
2596                 {
2597                     HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_MAXLEN) = BLE_ADV_LEGACY_MAX_PKT_LEN;
2598                 }
2599 
2600                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_OWNADRL) = ctx->ownA[0];
2601                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_OWNADRM) = ctx->ownA[1];
2602                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_OWNADRH) = ctx->ownA[2];
2603                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_OWNADRTYPE) = ctx->addrType.own;
2604 
2605                 /* Set up sync found capture */
2606                 hal_setup_sync_found_cap();
2607                 /* Initialize RF FIFOs */
2608                 ble5HandlerState.common.rxFifoSz = LRF_prepareRxFifo();
2609                 ble5HandlerState.common.curBuffer = NULL;
2610                 RCL_Handler_BLE5_updateRxCurBufferAndFifo(&ctx->rxBuffers);
2611                 rclEventsIn.rxBufferUpdate = 0;
2612                 ble5HandlerState.common.txFifoSz = LRF_prepareTxFifo();
2613 
2614                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_RPAMODE) = (ctx->rpaModeOwn << PBE_BLE5_RAM_RPAMODE_OWNADR_S) |
2615                                                                               (ctx->rpaModePeer << PBE_BLE5_RAM_RPAMODE_PEERADR_S);
2616 
2617                 ble5HandlerState.common.filterListUpdateIndex = -1;
2618                 /* Make sure status is correctly initialized */
2619                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FLSTAT) = 0;
2620                 if (ble5HandlerState.scanInit.initiator)
2621                 {
2622                     if (ctx->filterPolicy != 0)
2623                     {
2624                         /* Set filter list masks to normal accept list use: */
2625                         /* Bit 0: Consider enable bit */
2626                         /* Bit 1: Consider type bit */
2627                         /* Bit 3: Consider privIgn bit */
2628                         /* Bit 15: Consider match bit (found by PBE) */
2629                         /* Other bits are not checked */
2630                         HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FL2MASK) = PBE_BLE5_RAM_FL2MASK_MATCH_M |
2631                                                                                       PBE_BLE5_RAM_FL2MASK_PRIVIGN_M |
2632                                                                                       PBE_BLE5_RAM_FL2MASK_TYPE_M |
2633                                                                                       PBE_BLE5_RAM_FL2MASK_EN_M;
2634 
2635                         /* Initialize filter list */
2636                         RCL_Handler_BLE5_InitializeFilterList(ctx->filterList, (uint32_t *)(volatile unsigned short*) (LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FL2INFO0), 0);
2637                         ble5HandlerState.common.updatableFilterList = ctx->filterList;
2638                     }
2639                     else
2640                     {
2641                         /* Filter list not used */
2642                         HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FL2MASK) = 0;
2643                         RCL_Handler_BLE5_InitializeFilterList(NULL, (uint32_t *)(volatile unsigned short*) (LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FL2INFO0), 0);
2644                         ble5HandlerState.common.updatableFilterList = NULL;
2645                     }
2646                     HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FL1MASK) = 0;
2647                     ble5HandlerState.scanInit.filterListInvertMask = 0;
2648 
2649                     /* Set legacy/extended acceptance configuration */
2650                     uint16_t aeCfg = (acceptLegacy << PBE_BLE5_RAM_AECFG_LEGACY_S) & PBE_BLE5_RAM_AECFG_LEGACY_M;
2651                     aeCfg |= (acceptExtended << PBE_BLE5_RAM_AECFG_EXTENDED_S) & PBE_BLE5_RAM_AECFG_EXTENDED_M;
2652                     if (acceptExtended)
2653                     {
2654                         /* Accept only connectable/non-scannable advertising modes */
2655                         aeCfg |= PBE_BLE5_RAM_AECFG_ADVMODE1_ACCEPT;
2656 
2657                         /* Inform the PBE about the type of channel that will be used for reception */
2658                         if (channel != BLE_ADV_CHAN_LO && channel != BLE_ADV_CHAN_MID && channel != BLE_ADV_CHAN_HI)
2659                         {
2660                             aeCfg |= PBE_BLE5_RAM_AECFG_CHNL_SECONDARY;
2661                         }
2662                         /* Set backoff (only for connect requests on the secondary advertising physical channel) */
2663                         if (ctx->initialBackoff > 0)
2664                         {
2665                             /* Backoff definition in PBE is one count less than in Bluetooth spec */
2666                             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_BACKOFFCNT) = ctx->initialBackoff - 1;
2667                         }
2668                         else
2669                         {
2670                             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_BACKOFFCNT) = 0;
2671                         }
2672                     }
2673                     HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_AECFG) = aeCfg;
2674 
2675                     /* Set filter policy */
2676                     HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FILTPOLICY) = (ctx->filterPolicy << PBE_BLE5_RAM_FILTPOLICY_INTOR_S) &
2677                                                                                       PBE_BLE5_RAM_FILTPOLICY_INTOR_M;
2678 
2679                     HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_PEERADRL) = ctx->peerA[0];
2680                     HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_PEERADRM) = ctx->peerA[1];
2681                     HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_PEERADRH) = ctx->peerA[2];
2682                     HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_PEERADRTYPE) = ctx->addrType.peer;
2683 
2684                     RCL_Buffer_TxBuffer *txBuffer = RCL_TxBuffer_head(&ctx->txBuffers);
2685                     uint32_t numPad = txBuffer->numPad;
2686                     ble5HandlerState.scanInit.winOffsetFifoPtr =
2687                         (uint16_t *) LRF_getTxFifoWrAddr(offsetof(RCL_Buffer_DataEntry, pad0) + numPad + BLE_HEADER_LENGTH + BLE_WIN_OFFSET_POS);
2688                     ble5HandlerState.scanInit.intervalFifoPtr =
2689                         (uint16_t *) LRF_getTxFifoWrAddr(offsetof(RCL_Buffer_DataEntry, pad0) + numPad + BLE_HEADER_LENGTH + BLE_INTERVAL_POS);
2690 
2691                     if (txBuffer != NULL)
2692                     {
2693                         if (txBuffer->length >= 34)
2694                         {
2695                             ble5HandlerState.scanInit.winOffsetBufferPtr = ((uint16_t *)(txBuffer_dataByte(txBuffer, BLE_HEADER_LENGTH + BLE_WIN_OFFSET_POS)));
2696                             ble5HandlerState.scanInit.transmitWindowOffset = HWREGH_READ_LRF(ble5HandlerState.scanInit.winOffsetBufferPtr);
2697 
2698                             interval = *((uint16_t *)(txBuffer_dataByte(txBuffer, BLE_HEADER_LENGTH + BLE_INTERVAL_POS)));
2699                         }
2700                         else
2701                         {
2702                             ble5HandlerState.scanInit.transmitWindowOffset = 0;
2703                         }
2704                         if (initCmd->dynamicWinOffset)
2705                         {
2706                             if (interval == 0)
2707                             {
2708                                 status = RCL_CommandStatus_Error_Param;
2709                             }
2710                             else
2711                             {
2712                                 ble5HandlerState.scanInit.dynamicWinOffset = true;
2713                                 /* Set WinSize to 2 */
2714                                 *txBuffer_dataByte(txBuffer, BLE_HEADER_LENGTH + BLE_WIN_SIZE_POS) = 2;
2715 
2716                                 /* TODO: See RCL-346 */
2717                                 HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_TIMPER1) = RCL_BLE5_CONNECT_SUB_INT - 1;
2718 
2719                                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_WINMOD) = RCL_BLE5_CONNECT_INT_SUB_DIV * interval + RCL_BLE5_CONNECT_INT_SUB_DIV - 1;
2720 
2721                                 ble5HandlerState.scanInit.connectInterval = interval;
2722                             }
2723                         }
2724                         else
2725                         {
2726                             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_WINMOD) = 0;
2727                         }
2728                     }
2729                     /* Enter CONNECT_IND or AUX_CONNECT_REQ */
2730                     ble5HandlerState.common.txBufferInfo = (RCL_TxBufferInfo) { 0 };
2731                     if (RCL_Handler_BLE5_updateTxBuffers(&ctx->txBuffers, 1, &ble5HandlerState.common.txBufferInfo, false) == 0)
2732                     {
2733                         status = RCL_CommandStatus_Error_MissingTxBuffer;
2734                     }
2735                 }
2736                 else
2737                 {
2738                     if (ctx->filterPolicy != 0)
2739                     {
2740                         /* Set filter list masks to normal accept list use: */
2741                         /* Bit 0: Consider enable bit */
2742                         /* Bit 1: Consider type bit */
2743                         /* Bit 2: Consider duplicateIgn bit */
2744                         /* Bit 3: Consider privIgn bit */
2745                         /* Bit 15: Consider match bit (found by PBE) */
2746                         /* Other bits are not checked */
2747                         HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FL1MASK) = 0x800F;
2748                         HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FL1MASK) = PBE_BLE5_RAM_FL1MASK_MATCH_M |
2749                                                                                       PBE_BLE5_RAM_FL1MASK_PRIVIGN_M |
2750                                                                                       PBE_BLE5_RAM_FL1MASK_DUPLICATEIGN_M |
2751                                                                                       PBE_BLE5_RAM_FL1MASK_TYPE_M |
2752                                                                                       PBE_BLE5_RAM_FL1MASK_EN_M;
2753                         ble5HandlerState.scanInit.filterListInvertMask = 0;
2754                     }
2755                     else
2756                     {
2757                         /* Set filter list masks to duplicate address filtering: */
2758                         /* Bit 1: Consider type bit */
2759                         /* Bit 2: Consider duplicateIgn bit */
2760                         /* Bit 15: Consider match bit (found by PBE) */
2761                         /* Other bits are not checked */
2762                         HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FL1MASK) = PBE_BLE5_RAM_FL1MASK_MATCH_M |
2763                                                                                       PBE_BLE5_RAM_FL1MASK_DUPLICATEIGN_M |
2764                                                                                       PBE_BLE5_RAM_FL1MASK_TYPE_M;
2765                         ble5HandlerState.scanInit.filterListInvertMask = PBE_BLE5_RAM_FL1MASK_DUPLICATEIGN_M;
2766                     }
2767                     RCL_Handler_BLE5_InitializeFilterList(ctx->filterList, (uint32_t *)(volatile unsigned short*) (LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FL1INFO0),
2768                                                           ble5HandlerState.scanInit.filterListInvertMask);
2769                     HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FL2MASK) = 0;
2770                     ble5HandlerState.common.updatableFilterList = ctx->filterList;
2771 
2772                     /* Set active/passive scanner configuration */
2773                     uint16_t scanCfg = (scanCmd->activeScan << PBE_BLE5_RAM_SCANCFG_ACTPASS_S) & PBE_BLE5_RAM_SCANCFG_ACTPASS_M;
2774                     HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_SCANCFG) = scanCfg;
2775 
2776                     /* Set legacy/extended acceptance configuration */
2777                     uint16_t aeCfg = (acceptLegacy << PBE_BLE5_RAM_AECFG_LEGACY_S) & PBE_BLE5_RAM_AECFG_LEGACY_M;
2778                     aeCfg |= (acceptExtended << PBE_BLE5_RAM_AECFG_EXTENDED_S) & PBE_BLE5_RAM_AECFG_EXTENDED_M;
2779                     if (acceptExtended)
2780                     {
2781                         /* Scanner should accept all packets but only respond to scannable advertisements */
2782                         aeCfg |= PBE_BLE5_RAM_AECFG_ADVMODE0_ACCEPT;
2783                         aeCfg |= PBE_BLE5_RAM_AECFG_ADVMODE1_ACCEPT;
2784                         aeCfg |= PBE_BLE5_RAM_AECFG_ADVMODE2_ACCEPT;
2785 
2786                         /* Inform the PBE about the type of channel that will be used for reception */
2787                         if (channel != BLE_ADV_CHAN_LO && channel != BLE_ADV_CHAN_MID && channel != BLE_ADV_CHAN_HI)
2788                         {
2789                             aeCfg |= PBE_BLE5_RAM_AECFG_CHNL_SECONDARY;
2790                         }
2791                     }
2792                     HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_AECFG) = aeCfg;
2793 
2794                     /* Set filter policy */
2795                     // TODO: When available, enable SyncInfo filter policy
2796                     // HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FILTPOLICY) = ((ctx->filterPolicy << PBE_BLE5_RAM_FILTPOLICY_SCANNER_S) |
2797                     //                                                                  (ctx->scanExtFilterPolicy << PBE_BLE5_RAM_FILTPOLICY_EXTSCANNER_S) |
2798                     //                                                                  (ctx->periodicSyncEstablishment << PBE_BLE5_RAM_FILTPOLICY_SYNCINFO_S)) &
2799                     //                                                                  (PBE_BLE5_RAM_FILTPOLICY_SCANNER_M | PBE_BLE5_RAM_FILTPOLICY_EXTSCANNER_M |
2800                     //                                                                   PBE_BLE5_RAM_FILTPOLICY_SYNCINFO_M);
2801                     HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FILTPOLICY) = ((ctx->filterPolicy << PBE_BLE5_RAM_FILTPOLICY_SCANNER_S) |
2802                                                                                      (ctx->scanExtFilterPolicy << PBE_BLE5_RAM_FILTPOLICY_EXTSCANNER_S)) &
2803                                                                                      (PBE_BLE5_RAM_FILTPOLICY_SCANNER_M | PBE_BLE5_RAM_FILTPOLICY_EXTSCANNER_M);
2804 
2805 
2806                     /* Set backoff */
2807                     if (ctx->initialBackoff > 0)
2808                     {
2809                         HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_BACKOFFCNT) = ctx->initialBackoff - 1;  /* Backoff definition in PBE is one less than in Bluetooth spec */
2810                     }
2811                     else
2812                     {
2813                         HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_BACKOFFCNT) = 0;
2814                     }
2815                 }
2816 
2817                 if (status == RCL_CommandStatus_Active)
2818                 {
2819                     uint16_t fifoCfg = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FIFOCFG);
2820                     LRF_enableHwInterrupt(RCL_Handler_BLE5_maskEventsByFifoConf(LRF_EventOpDone.value | LRF_EventOpError.value |
2821                                                                                 LRF_EventRxOk.value | LRF_EventRxIgnored.value |
2822                                                                                 LRF_EventRxNok.value | LRF_EventRxBufFull.value,
2823                                                                                 fifoCfg, ble5HandlerState.common.activeUpdate));
2824 
2825                     if (ble5HandlerState.scanInit.initiator)
2826                     {
2827                         Log_printf(RclCore, Log_VERBOSE, "Starting initiator");
2828                         LRF_waitForTopsmReady();
2829                         RCL_Profiling_eventHook(RCL_ProfilingEvent_PreprocStop);
2830                         /* Post cmd */
2831                         HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_API) = PBE_BLE5_REGDEF_API_OP_INITIATOR;
2832 
2833                         if (ble5HandlerState.scanInit.dynamicWinOffset)
2834                         {
2835                             /* Calculate initial winOffset while radio is starting */
2836                             if (acceptExtended && !acceptLegacy)
2837                             {
2838                                /*
2839                                 * For extended advertising, a new referenceTime will be calculated once the initiator has moved to a
2840                                 * secondary advertising channel.
2841                                 */
2842                                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_WINOFFSET) = 0;
2843                                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_WINMOD) = 0;
2844                             }
2845                             else
2846                             {
2847                                 /*
2848                                  * Calculate initial winOffset while radio is starting. Use the actual start time of the command as initial reference,
2849                                  * and consider that the transmit window starts after the end of the packet containing the AUX_CONNECT_REQ.
2850                                  */
2851                                 uint32_t referenceTime = rclSchedulerState.actualStartTime +
2852                                     RCL_Handler_BLE5_findPacketDuration(BLE_CONNECT_MSG_LEN, ble5HandlerState.common.phyFeatures) +
2853                                     BLE_TRANSMIT_WINDOW_DELAY_LEGACY + 3 * RCL_BLE5_CONNECT_SUB_INT;
2854 
2855                                 /*
2856                                  * Use the reference time and the requested connect time to calculate an appropriate value for the winOffset.
2857                                  * The winOffset value is initially set to hit the next window start by considering the desired connect interval,
2858                                  * but the PBE adjusts it based on the length of the window (WINMOD).
2859                                  */
2860                                 uint32_t initialWinOffset = RCL_Handler_BLE5_prepareConnectTime(&initCmd->connectTime, referenceTime, interval);
2861                                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_WINOFFSET) = initialWinOffset;
2862                             }
2863                         }
2864                     }
2865                     else
2866                     {
2867                         Log_printf(RclCore, Log_VERBOSE, "Starting scanner");
2868                         LRF_waitForTopsmReady();
2869                         RCL_Profiling_eventHook(RCL_ProfilingEvent_PreprocStop);
2870                         /* Post cmd */
2871                         HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_API) = PBE_BLE5_REGDEF_API_OP_SCAN;
2872                     }
2873                 }
2874             }
2875         }
2876         /* Set status */
2877         cmd->status = status;
2878         if (status >= RCL_CommandStatus_Finished)
2879         {
2880             rclEvents.lastCmdDone = 1;
2881         }
2882     }
2883     else
2884     {
2885         bool updateStats = false;
2886         if (lrfEvents.rxOk != 0 || lrfEvents.rxNok != 0 || lrfEvents.rxIgnored != 0 || lrfEvents.rxBufFull != 0)
2887         {
2888             /* Copy received packet from PBE FIFO to buffer */
2889             /* First, check that there is actually a buffer available */
2890             while (HWREG_READ_LRF(LRFDPBE_BASE + LRFDPBE_O_RXFREADABLE) >= 4)
2891             {
2892                 /* Check length of received buffer by peeking */
2893                 uint32_t fifoWord = LRF_peekRxFifo(0);
2894                 uint32_t wordLength = RCL_Buffer_DataEntry_paddedLen(fifoWord & 0xFFFF) / 4;
2895                 if (wordLength > 0)
2896                 {
2897                     RCL_MultiBuffer *curBuffer;
2898                     curBuffer = RCL_MultiBuffer_getBuffer(ble5HandlerState.common.curBuffer,
2899                                                           wordLength * 4);
2900                     if (curBuffer != ble5HandlerState.common.curBuffer)
2901                     {
2902                         rclEvents.rxBufferFinished = 1;
2903                         ble5HandlerState.common.curBuffer = curBuffer;
2904                     }
2905                     if (curBuffer == NULL)
2906                     {
2907                         /* Error */
2908                         ble5HandlerState.common.endStatus = RCL_CommandStatus_Error_RxBufferCorruption;
2909                         /* Send abort */
2910                         HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_API) = PBE_BLE5_REGDEF_API_OP_STOP;
2911                         /* Do not check for more packets from the RX FIFO */
2912                         break;
2913                     }
2914                     else
2915                     {
2916                         uint32_t *data32;
2917                         data32 = (uint32_t *)RCL_MultiBuffer_getNextWritableByte(curBuffer);
2918                         LRF_readRxFifoWords(data32, wordLength);
2919                         if(lrfEvents.rxOk && wordLength > 1)
2920                         {
2921                             uint32_t header = data32[1] >> 16;
2922                             uint32_t type = (header & BLE_PDU_TYPE_BM);
2923 
2924                             if (type == BLE_PDU_ADV_EXTENDED)
2925                             {
2926                                 /* Attempt to extract an AuxPtr from the received packet */
2927                                 RCL_Handler_BLE5_readAuxPtrFromRxBuffer(data32, &ble5HandlerState.common.auxPtrInfo);
2928                                 if (ble5HandlerState.common.auxPtrInfo.auxPtrPresent)
2929                                 {
2930                                     /* Check auxPhy and request PHY change if needed */
2931                                     if (ble5HandlerState.common.channel == BLE_ADV_CHAN_LO ||
2932                                         ble5HandlerState.common.channel == BLE_ADV_CHAN_MID ||
2933                                         ble5HandlerState.common.channel == BLE_ADV_CHAN_HI)
2934                                     {
2935                                         if ((cmd->phyFeatures & 0x03) != ble5HandlerState.common.auxPtrInfo.auxPhy)
2936                                         {
2937                                             ble5HandlerState.scanInit.switchPhy = true;
2938                                         }
2939                                     }
2940                                     else
2941                                     {
2942                                         ble5HandlerState.scanInit.switchPhy = false;
2943                                     }
2944                                     ble5HandlerState.scanInit.followAuxPtr = true;
2945                                 }
2946                                 else
2947                                 {
2948                                     ble5HandlerState.scanInit.followAuxPtr = false;
2949                                 }
2950                                 ble5HandlerState.scanInit.isExtAdv = true;
2951                             }
2952                             else if (type == BLE_PDU_AUX_CONNECT_RSP && ble5HandlerState.scanInit.initiator)
2953                             {
2954                                 /* No auxiliary PDU is expected after receiving an AUX_CONNECT_RSP */
2955                                 ble5HandlerState.scanInit.followAuxPtr = false;
2956                                 ble5HandlerState.scanInit.isExtAdv = true;
2957                             }
2958                             else
2959                             {
2960                                 /* Handle all other legacy PDU types */
2961                                 if (ble5HandlerState.scanInit.initiator)
2962                                 {
2963                                     /* Store BLE packet length if this was an accepted connectable advertiser message */
2964                                     if (type == BLE_PDU_ADV_IND || type == BLE_PDU_ADV_DIRECT_IND)
2965                                     {
2966                                         ble5HandlerState.scanInit.advPktLen = header >> 8;
2967                                     }
2968                                 }
2969                                 ble5HandlerState.scanInit.switchPhy = false;
2970                                 ble5HandlerState.scanInit.isExtAdv = false;
2971                                 ble5HandlerState.scanInit.followAuxPtr = false;
2972                             }
2973                         }
2974                         RCL_Handler_BLE5_commitPacket(curBuffer, wordLength * 4);
2975                         /* Raise event */
2976                         rclEvents.rxEntryAvail = 1;
2977                         /* Adjust effective FIFO size */
2978                         ctx = (ble5HandlerState.scanInit.initiator) ? initCmd->ctx : scanCmd->ctx;
2979                         RCL_Handler_BLE5_updateRxCurBufferAndFifo(&ctx->rxBuffers);
2980                         rclEventsIn.rxBufferUpdate = 0;
2981                     }
2982                 }
2983             }
2984             if (ble5HandlerState.common.activeUpdate)
2985             {
2986                 updateStats = true;
2987             }
2988         }
2989         if (rclEventsIn.timerStart != 0)
2990         {
2991             rclEvents.cmdStarted = 1;
2992         }
2993 
2994         if (lrfEvents.opDone != 0 || lrfEvents.opError != 0)
2995         {
2996             uint16_t endCause = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_COMMON_RAM_O_ENDCAUSE);
2997             if (lrfEvents.opError == 0 && (endCause == PBE_COMMON_RAM_ENDCAUSE_STAT_ENDOK ||
2998                                            endCause == PBE_COMMON_RAM_ENDCAUSE_STAT_RXERR ||
2999                                            endCause == PBE_COMMON_RAM_ENDCAUSE_STAT_NOSYNC))
3000             {
3001                 /* Backoff updates are handled differently depending on whether it's a scanner or an initiator */
3002                 ctx = (ble5HandlerState.scanInit.initiator) ? initCmd->ctx : scanCmd->ctx;
3003 
3004                 if (endCause == PBE_COMMON_RAM_ENDCAUSE_STAT_ENDOK ||
3005                     endCause == PBE_COMMON_RAM_ENDCAUSE_STAT_RXERR ||
3006                     endCause == PBE_COMMON_RAM_ENDCAUSE_STAT_NOSYNC)
3007                 {
3008                     if (!ble5HandlerState.scanInit.initiator)
3009                     {
3010                         if (ble5HandlerState.scanInit.isExtAdv)
3011                         {
3012                             /* Only update backoff related variables for the extended usecase after an AUX_SCAN_REQ has been sent. */
3013                             uint16_t chCfg = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_AECFG) & PBE_BLE5_RAM_AECFG_CHNL_M;
3014                             if (ble5HandlerState.scanInit.isExtAdv && (chCfg == PBE_BLE5_RAM_AECFG_CHNL_SECONDARY))
3015                             {
3016                                 // TODO: Ensure that the backoff procedure is only executed when receiving AUX_SCAN_RSP PDUs and not for subsequent AUX_CHAIN_IND PDUs.
3017                                 RCL_Handler_BLE5_updateBackoffParams(ctx, endCause);
3018                             }
3019                             /* Follow AuxPtr if needed and schedule new listening window */
3020                             if (ble5HandlerState.scanInit.followAuxPtr && (endCause == PBE_COMMON_RAM_ENDCAUSE_STAT_ENDOK))
3021                             {
3022                                 /* Turn off LRF to allow new synth programming */
3023                                 LRF_disable();
3024                                 if (ble5HandlerState.scanInit.switchPhy)
3025                                 {
3026                                     /* Update phyFeatures while keeping the code rate selection intact. Raise a partialSetup event to handle the PHY switch. */
3027                                     rclSchedulerState.requestedPhyFeatures = ble5HandlerState.common.auxPtrInfo.auxPhy | (cmd->phyFeatures & 0x04);
3028                                     rclEvents.partialSetup = 1;
3029                                     followAuxPtr = false;
3030                                 }
3031                                 else
3032                                 {
3033                                     /* No need to handle a PHY switch. Proceed with the operation. */
3034                                     rclSchedulerState.requestedPhyFeatures = cmd->phyFeatures;
3035                                     followAuxPtr = true;
3036                                 }
3037                             }
3038                             else
3039                             {
3040                                 followAuxPtr = false;
3041                                 rclEvents.lastCmdDone = 1;
3042                                 cmd->status = RCL_CommandStatus_Finished;
3043                             }
3044                         }
3045                         else
3046                         {
3047                             /* Always update the various variables associated with the backoff procedure for legacy advertising */
3048                             RCL_Handler_BLE5_updateBackoffParams(ctx, endCause);
3049 
3050                             /* Receiving on a primary channel. Restart scanner unless timed out */
3051                             /* Set to start immediately */
3052                             RCL_CommandStatus startTimeStatus = RCL_Scheduler_setNewStartNow();
3053                             if (startTimeStatus >= RCL_CommandStatus_Finished)
3054                             {
3055                                 cmd->status = startTimeStatus;
3056                                 rclEvents.lastCmdDone = 1;
3057                             }
3058                             else
3059                             {
3060                                 if (!(rclSchedulerState.hardStopInfo.apiStopEnabled || rclSchedulerState.gracefulStopInfo.apiStopEnabled))
3061                                 {
3062                                     Log_printf(RclCore, Log_VERBOSE, "Restarting scanner");
3063                                     /* Reset TXFIFO - needed due to LPRF_PHY-511 */
3064                                     /* Writing to FCMD is safe because PBE is finished, ref. RCL-367 */
3065                                     HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_FCMD) = (LRFDPBE_FCMD_DATA_TXFIFO_RESET >> LRFDPBE_FCMD_DATA_S);
3066                                     /* Post cmd */
3067                                     HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_API) = PBE_BLE5_REGDEF_API_OP_SCAN;
3068                                     if (ble5HandlerState.common.activeUpdate)
3069                                     {
3070                                         updateStats = true;
3071                                     }
3072                                 }
3073                             }
3074                         }
3075                     }
3076                     else /* Initiator */
3077                     {
3078                         RCL_CommandStatus endStatus = ble5HandlerState.common.endStatus;
3079 
3080                         if (endCause == PBE_COMMON_RAM_ENDCAUSE_STAT_ENDOK)
3081                         {
3082                             if (ble5HandlerState.scanInit.isExtAdv && ble5HandlerState.scanInit.followAuxPtr)
3083                             {
3084                                 /* Turn off LRF to allow new synth programming  */
3085                                 LRF_disable();
3086                                 /*  Check if a PHY switch was requested */
3087                                 if (ble5HandlerState.scanInit.switchPhy)
3088                                 {
3089                                     /* Update phyFeatures while keeping the code rate selection intact. Raise a partialSetup event to handle the PHY switch. */
3090                                     rclSchedulerState.requestedPhyFeatures = ble5HandlerState.common.auxPtrInfo.auxPhy | (cmd->phyFeatures & 0x04);
3091                                     rclEvents.partialSetup = 1;
3092                                     followAuxPtr = false;
3093                                 }
3094                                 else
3095                                 {
3096                                     rclSchedulerState.requestedPhyFeatures = cmd->phyFeatures;
3097                                     followAuxPtr = true;
3098                                 }
3099                             }
3100                             else
3101                             {
3102                                 endStatus = RCL_CommandStatus_Connect;
3103                                 /* Find connect time */
3104                                 uint32_t transmitWindowOffset;
3105                                 /* 32-bit acccess to also read LASTTIMESTAMPH */
3106                                 uint32_t eventTime = HWREG_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_LASTTIMESTAMPL) - ble5HandlerState.common.timestampAdjust;
3107                                 uint32_t connectTime;
3108                                 if (ble5HandlerState.scanInit.dynamicWinOffset)
3109                                 {
3110                                     transmitWindowOffset = HWREGH_READ_LRF(ble5HandlerState.scanInit.winOffsetFifoPtr);
3111                                     /* Write back to transmit buffer */
3112                                     HWREGH_WRITE_LRF(ble5HandlerState.scanInit.winOffsetBufferPtr) = transmitWindowOffset;
3113                                 }
3114                                 else
3115                                 {
3116                                     transmitWindowOffset = ble5HandlerState.scanInit.transmitWindowOffset;
3117                                 }
3118                                 Log_printf(RclCore, Log_VERBOSE, "Connection formed, transmit window offset %1d", transmitWindowOffset);
3119 
3120                                 /* Find the connect time and report it to the caller */
3121                                 uint32_t referenceTime = eventTime;
3122                                 if (ble5HandlerState.scanInit.isExtAdv && !ble5HandlerState.scanInit.followAuxPtr)
3123                                 {
3124                                     /*
3125                                      * The transmit window starts after the end of the packet containing the AUX_CONNECT_REQ, but evenTime corresponds to the time at which
3126                                      * the AUX_CONNECT_RSP was received. Account for this by substracting the T_IFS.
3127                                      */
3128                                     referenceTime -= BLE_T_IFS;
3129                                     referenceTime += transmitWindowOffset * BLE_CONNECT_INT_UNIT;
3130                                     /* For extended advertising, PHY needs to be considered when calculating the transmit window delay */
3131                                     referenceTime += ((ble5HandlerState.common.phyFeatures & BLE_PHY_FEATURE_PHY_MASK) == BLE_PHY_FEATURE_PHY_CODED) ?
3132                                                       BLE_TRANSMIT_WINDOW_DELAY_EXT_CODED : BLE_TRANSMIT_WINDOW_DELAY_EXT_UNCODED;
3133                                 }
3134                                 else
3135                                 {
3136                                     referenceTime += RCL_Handler_BLE5_findPacketDuration(ble5HandlerState.scanInit.advPktLen, ble5HandlerState.common.phyFeatures) +
3137                                                      BLE_T_IFS + RCL_Handler_BLE5_findPacketDuration(BLE_CONNECT_MSG_LEN, ble5HandlerState.common.phyFeatures) +
3138                                                      BLE_TRANSMIT_WINDOW_DELAY_LEGACY + transmitWindowOffset * BLE_CONNECT_INT_UNIT;
3139                                 }
3140 
3141                                 if (ble5HandlerState.scanInit.dynamicWinOffset)
3142                                 {
3143                                     connectTime = RCL_Handler_BLE5_findConnectTime(initCmd->connectTime, referenceTime, ble5HandlerState.scanInit.connectInterval);
3144                                     /* Check that the connect time is within the bounds expected; if not (due to timer drift), report a different connect time */
3145                                     if (connectTime > referenceTime + 2 * BLE_CONNECT_INT_UNIT)
3146                                     {
3147                                         Log_printf(RclCore, Log_WARNING, "Transmitted window offset did not match requested transmit time. Reporting a different connect time");
3148                                         connectTime = referenceTime + BLE_CONNECT_INT_UNIT / 2;
3149                                     }
3150                                     else
3151                                     {
3152                                         Log_printf(RclCore, Log_DEBUG, "Margins: %1d us and %1d us", (connectTime - referenceTime + 2)/4, (referenceTime + 2 * BLE_CONNECT_INT_UNIT - connectTime + 2)/4);
3153                                     }
3154                                 }
3155                                 else
3156                                 {
3157                                     connectTime = referenceTime + BLE_CONNECT_INT_UNIT / 2;
3158                                 }
3159                                 initCmd->connectTime = connectTime;
3160                                 followAuxPtr = false;
3161                                 rclEvents.lastCmdDone = 1;
3162                                 cmd->status = endStatus;
3163                             }
3164 
3165                             /* Only update backOff related variables for the extended usecase after an AUX_CONNECT_REQ has been sent */
3166                             uint16_t chCfg = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_AECFG) & PBE_BLE5_RAM_AECFG_CHNL_M;
3167                             if (ble5HandlerState.scanInit.isExtAdv && chCfg == PBE_BLE5_RAM_AECFG_CHNL_SECONDARY)
3168                             {
3169                                 RCL_Handler_BLE5_updateBackoffParams(ctx, endCause);
3170                             }
3171                         }
3172                     }
3173                 }
3174             }
3175             else
3176             {
3177                 RCL_CommandStatus endStatus = ble5HandlerState.common.endStatus;
3178                 if (lrfEvents.opError != 0 && endStatus == RCL_CommandStatus_Finished)
3179                 {
3180                     endStatus = RCL_Handler_BLE5_findPbeErrorEndStatus(endCause);
3181                     followAuxPtr = false;
3182                     rclEvents.lastCmdDone = 1;
3183                     cmd->status = endStatus;
3184 
3185                 }
3186                 else if (endCause == PBE_COMMON_RAM_ENDCAUSE_STAT_EOPSTOP)
3187                 {
3188                     endStatus = RCL_Scheduler_findStopStatus(RCL_StopType_Graceful);
3189                     followAuxPtr = false;
3190                     rclEvents.lastCmdDone = 1;
3191                     cmd->status = endStatus;
3192                 }
3193                 else if (rclSchedulerState.hardStopInfo.apiStopEnabled && endCause == PBE_COMMON_RAM_ENDCAUSE_STAT_ENDOK)
3194                 {
3195                     endStatus = RCL_Scheduler_findStopStatus(RCL_StopType_Hard);
3196 
3197                     followAuxPtr = false;
3198                     rclEvents.lastCmdDone = 1;
3199                     cmd->status = endStatus;
3200                 }
3201                 else if (rclSchedulerState.gracefulStopInfo.apiStopEnabled && endCause == PBE_COMMON_RAM_ENDCAUSE_STAT_ENDOK)
3202                 {
3203                     endStatus = RCL_Scheduler_findStopStatus(RCL_StopType_Graceful);
3204                     followAuxPtr = false;
3205                     rclEvents.lastCmdDone = 1;
3206                     cmd->status = endStatus;
3207                 }
3208                 else
3209                 {
3210                     /* No change of status */
3211                 }
3212             }
3213         }
3214         else
3215         {
3216             /* Other events need to be handled unconditionally */
3217         }
3218 
3219         if (rclEvents.lastCmdDone != 0)
3220         {
3221             /* Write back backoff count */
3222             if (!ble5HandlerState.scanInit.initiator)
3223             {
3224                 scanCmd->ctx->initialBackoff = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_BACKOFFCNT) + 1; /* Backoff definition in PBE is one less than in Bluetooth spec */
3225             }
3226             if (ble5HandlerState.scanInit.initiator && ble5HandlerState.scanInit.isExtAdv)
3227             {
3228                 initCmd->ctx->initialBackoff = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_BACKOFFCNT) + 1; /* Backoff definition in PBE is one less than in Bluetooth spec */
3229             }
3230             updateStats = true;
3231         }
3232         if (updateStats)
3233         {
3234             RCL_Handler_BLE5_updateAdvScanInitStats((ble5HandlerState.scanInit.initiator) ? initCmd->stats : scanCmd->stats,
3235                                                     rclSchedulerState.actualStartTime);
3236         }
3237     }
3238 
3239     if (cmd->status == RCL_CommandStatus_Active)
3240     {
3241         if (rclEventsIn.rxBufferUpdate != 0)
3242         {
3243             ctx = (ble5HandlerState.scanInit.initiator) ? initCmd->ctx : scanCmd->ctx;
3244             RCL_Handler_BLE5_updateRxCurBufferAndFifo(&ctx->rxBuffers);
3245             rclEventsIn.rxBufferUpdate = 0;
3246         }
3247         if (rclEventsIn.handlerCmdUpdate != 0)
3248         {
3249             if (ble5HandlerState.scanInit.followAuxPtr && ble5HandlerState.scanInit.switchPhy)
3250             {
3251                 /* PHY change concluded successfully. Proceed with the scanner restart */
3252                 followAuxPtr = true;
3253             }
3254             else
3255             {
3256                 followAuxPtr = false;
3257             }
3258             if (ble5HandlerState.common.updatableFilterList != NULL && ble5HandlerState.common.filterListUpdateIndex >= 0)
3259             {
3260                 uint32_t index = (uint32_t) ble5HandlerState.common.filterListUpdateIndex;
3261                 uint32_t *targetPtr = (uint32_t *) (ble5HandlerState.scanInit.initiator ? (volatile unsigned short*) (LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FL2INFO0) : (volatile unsigned short*) (LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FL1INFO0));
3262 
3263                 RCL_Handler_BLE5_updateFilterListEntry(ble5HandlerState.common.updatableFilterList,
3264                     targetPtr,
3265                     ble5HandlerState.scanInit.filterListInvertMask, index);
3266                 ble5HandlerState.common.filterListUpdateIndex = -1;
3267             }
3268         }
3269         if (followAuxPtr)
3270         {
3271             uint32_t maxAuxPtrWaitTime = (ble5HandlerState.scanInit.initiator) ? initCmd->maxAuxPtrWaitTime : scanCmd->maxAuxPtrWaitTime;
3272             uint32_t auxOffsetUs = ble5HandlerState.common.auxPtrInfo.offsetUnits ? (ble5HandlerState.common.auxPtrInfo.auxOffset * BLE_AUX_OFFSET_300_US) :
3273                                                                                     (ble5HandlerState.common.auxPtrInfo.auxOffset * BLE_AUX_OFFSET_30_US);
3274 
3275             /* Switch to the channel indicated by the auxPtr */
3276             RCL_Ble5Channel nextChannel = (RCL_Ble5Channel) ble5HandlerState.common.auxPtrInfo.chIndex;
3277             rfFreq = RCL_Handler_BLE5_findRfFreq(nextChannel);
3278 
3279             if ((maxAuxPtrWaitTime != 0) && (maxAuxPtrWaitTime < auxOffsetUs))
3280             {
3281                 cmd->status = RCL_CommandStatus_MaxAuxWaitTimeExceeded;
3282                 rclEvents.lastCmdDone = 1;
3283             }
3284             else if (rfFreq == 0)
3285             {
3286                 cmd->status = RCL_CommandStatus_Error_Param;
3287                 rclEvents.lastCmdDone = 1;
3288             }
3289             else
3290             {
3291                 if (ble5HandlerState.scanInit.initiator)
3292                 {
3293                     connParams = initCmd->ctx->connParams;
3294                     if (initCmd->ctx->connParams != NULL)
3295                     {
3296                         /* Check received AuxPhy to determine if connection parameters need to be updated */
3297                         if (ble5HandlerState.common.auxPtrInfo.auxPhy == BLE_PHY_FEATURE_PHY_2MBPS)
3298                         {
3299                             /* Retry TX FIFO and point to the correct AUX_CONNECT_REQ. Writing to FCMD is safe because PBE is finished, ref. RCL-367 */
3300                             HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_FCMD) = (LRFDPBE_FCMD_DATA_TXFIFO_RETRY >> LRFDPBE_FCMD_DATA_S);
3301 
3302                             /* Update parameters. Use position of Interval field as reference for other connection parameters */
3303                             HWREGH_WRITE_LRF(ble5HandlerState.scanInit.intervalFifoPtr) = connParams->ble2M.interval;
3304                             HWREGH_WRITE_LRF(((uintptr_t) ble5HandlerState.scanInit.intervalFifoPtr) + (BLE_LATENCY_POS - BLE_INTERVAL_POS)) = connParams->ble2M.latency;
3305                             HWREGH_WRITE_LRF(((uintptr_t) ble5HandlerState.scanInit.intervalFifoPtr) + (BLE_TIMEOUT_POS - BLE_INTERVAL_POS)) = connParams->ble2M.timeout;
3306                         }
3307                         else if (ble5HandlerState.common.auxPtrInfo.auxPhy == BLE_PHY_FEATURE_PHY_CODED)
3308                         {
3309                             /* Retry TX FIFO and point to the correct AUX_CONNECT_REQ. Writing to FCMD is safe because PBE is finished, ref. RCL-367 */
3310                             HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_FCMD) = (LRFDPBE_FCMD_DATA_TXFIFO_RETRY >> LRFDPBE_FCMD_DATA_S);
3311 
3312                             /* Update parameters. Use position of Interval field as reference for other connection parameters */
3313                             HWREGH_WRITE_LRF(ble5HandlerState.scanInit.intervalFifoPtr) = connParams->bleCoded.interval;
3314                             HWREGH_WRITE_LRF(((uintptr_t) ble5HandlerState.scanInit.intervalFifoPtr) + (BLE_LATENCY_POS - BLE_INTERVAL_POS)) = connParams->bleCoded.latency;
3315                             HWREGH_WRITE_LRF(((uintptr_t) ble5HandlerState.scanInit.intervalFifoPtr) + (BLE_TIMEOUT_POS - BLE_INTERVAL_POS)) = connParams->bleCoded.timeout;
3316                         }
3317                         else
3318                         {
3319                             /* No need to update connection parameters for LE 1M PHY */
3320                         }
3321                     }
3322                     else
3323                     {
3324                         /* No change of the connection parameters regardless of the PHY */
3325                     }
3326                 }
3327 
3328                 /* Begin the start time calculation of the receive window by getting the time of the last sync plus the aux offset given in the AuxPtr */
3329                 /* 32-bit access to also read LASTTIMESTAMPH */
3330                 uint32_t startTime = HWREG_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_LASTTIMESTAMPL) - ble5HandlerState.common.timestampAdjust;
3331 
3332                 /* Update timestamps for the next packet if there was been a PHY change */
3333                 if (ble5HandlerState.scanInit.switchPhy)
3334                 {
3335                     RCL_Handler_BLE5_setPhy(rclSchedulerState.requestedPhyFeatures);
3336                     ble5HandlerState.scanInit.switchPhy = false;
3337                 }
3338 
3339                 uint32_t offset = RCL_SCHEDULER_SYSTIM_US(ble5HandlerState.common.auxPtrInfo.offsetUnits ?
3340                                                           ble5HandlerState.common.auxPtrInfo.auxOffset * BLE_AUX_OFFSET_300_US :
3341                                                           ble5HandlerState.common.auxPtrInfo.auxOffset * BLE_AUX_OFFSET_30_US);
3342                 startTime += offset;
3343 
3344                 /* Use the local and remote clock accuracies to find the clock error contribution */
3345                 uint16_t localClkAccuracy = RCL_SCHEDULER_SYSTIM_US(ble5HandlerState.scanInit.initiator ?
3346                                                                     initCmd->ctx->localClockAccuracy :
3347                                                                     scanCmd->ctx->localClockAccuracy);
3348                 uint16_t remoteClkAccuracy = RCL_SCHEDULER_SYSTIM_US(ble5HandlerState.common.auxPtrInfo.offsetUnits ?
3349                                                                      BLE_SCALED_CLK_ACCURACY_500PPM :
3350                                                                      BLE_SCALED_CLK_ACCURACY_50PPM);
3351 
3352                 /* Find clock error contribution. Add 1 us (4 systim units) to correct for rounding down. Also consider the sleep/active clock adjustments */
3353                 uint16_t remoteClkError = (uint16_t)((((offset * remoteClkAccuracy) >> BLE_CLK_ACCURACY_SCALE_FACTOR)) + 4 + RCL_SCHEDULER_SYSTIM_US(2));
3354                 uint16_t localClkError = (uint16_t)((((offset * localClkAccuracy) >> BLE_CLK_ACCURACY_SCALE_FACTOR)) + 4 + RCL_SCHEDULER_SYSTIM_US(16));
3355 
3356                 /* Calculate the needed window widening. Consider the allowed deviations for active clock accuracy and sleep clock accuracy */
3357                 uint16_t windowWidening = remoteClkError + localClkError;
3358 
3359                 /* Add some additional time to the window widening due to missing constants describing the Rx Start Overhead. See RCL-513. */
3360                 startTime -= (windowWidening + RX_START_OVERHEAD);
3361 
3362                 /* Begin the timeout calculation by considering that the end of receive window occurs one offset unit after startTime */
3363                 uint16_t endTime = RCL_SCHEDULER_SYSTIM_US(ble5HandlerState.common.auxPtrInfo.offsetUnits ? BLE_AUX_OFFSET_300_US : BLE_AUX_OFFSET_30_US);
3364                 uint16_t timeout = windowWidening + endTime + windowWidening;
3365 
3366 #ifdef DeviceFamily_CC27XX
3367                 startTime -= RCL_SCHEDULER_SYSTIM_US(100);
3368                 timeout += RCL_SCHEDULER_SYSTIM_US(200);
3369 #endif
3370                 /* Set timeout by writing to FIRSTRXTIMEOUT. Consider the necessary Rx sync Overhead. See RCL-513. */
3371                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FIRSTRXTIMEOUT) = timeout + RCL_Handler_BLE5_findRxSyncOverhead(ble5HandlerState.common.phyFeatures);
3372 
3373                 /* Program frequency word */
3374                 LRF_programFrequency(rfFreq, false);
3375                 /* Enable radio */
3376                 LRF_enable();
3377 
3378                 uint16_t whitenInit = RCL_Handler_BLE5_findWhitenInit(nextChannel);
3379                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_WHITEINIT) = whitenInit;
3380 
3381                 /* Inform the PBE that we have moved to a secondary channel */
3382                 uint16_t aeCfg = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_AECFG) | PBE_BLE5_RAM_AECFG_CHNL_SECONDARY;
3383                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_AECFG) = aeCfg;
3384 
3385                 if (ble5HandlerState.common.accessAddressModification)
3386                 {
3387                     HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_MDMSYNCA) = ADV_ACCESS_ADDRESS ^ (whitenInit << 24);
3388                 }
3389 
3390                 if (ble5HandlerState.scanInit.dynamicWinOffset)
3391                 {
3392                     HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_WINMOD) = RCL_BLE5_CONNECT_INT_SUB_DIV * ble5HandlerState.scanInit.connectInterval + RCL_BLE5_CONNECT_INT_SUB_DIV - 1;
3393                 }
3394 
3395                 /* Set new start time */
3396                 RCL_CommandStatus startTimeStatus = RCL_Scheduler_setNewStartAbsTime(startTime, true);
3397                 if (startTimeStatus >= RCL_CommandStatus_Finished)
3398                 {
3399                     cmd->status = startTimeStatus;
3400                     rclEvents.lastCmdDone = 1;
3401                 }
3402                 else
3403                 {
3404                     cmd->status = RCL_CommandStatus_Active;
3405                     /* Set up sync found capture */
3406                     hal_setup_sync_found_cap();
3407 
3408                     uint16_t fifoCfg = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FIFOCFG);
3409                     LRF_enableHwInterrupt(RCL_Handler_BLE5_maskEventsByFifoConf(LRF_EventOpDone.value | LRF_EventOpError.value |
3410                                                                                 LRF_EventRxOk.value | LRF_EventRxIgnored.value |
3411                                                                                 LRF_EventRxNok.value | LRF_EventRxBufFull.value,
3412                                                                                 fifoCfg, ble5HandlerState.common.activeUpdate));
3413                     Log_printf(RclCore, Log_VERBOSE, "Following AuxPointer on channel: %d", nextChannel);
3414                     LRF_waitForTopsmReady();
3415 
3416                     if (!ble5HandlerState.scanInit.initiator)
3417                     {
3418                         /* Post cmd */
3419                         HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_API) = PBE_BLE5_REGDEF_API_OP_SCAN;
3420                     }
3421                     else
3422                     {
3423                         /* Post cmd */
3424                         HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_API) = PBE_BLE5_REGDEF_API_OP_INITIATOR;
3425 
3426                         if (ble5HandlerState.scanInit.dynamicWinOffset)
3427                         {
3428                             /*
3429                              * Calculate initial winOffset while radio is starting. Use the actual start time of the command as initial reference,
3430                              * and consider that the transmit window starts after the end of the packet containing the AUX_CONNECT_REQ.
3431                              */
3432                             uint32_t referenceTime = rclSchedulerState.actualStartTime +
3433                                 RCL_Handler_BLE5_findPacketDuration(BLE_CONNECT_MSG_LEN, ble5HandlerState.common.phyFeatures) +
3434                                 3 * RCL_BLE5_CONNECT_SUB_INT;
3435                             /* The transmitWindowDelay needs to take into account the type of PHY in use */
3436                             referenceTime += ((ble5HandlerState.common.phyFeatures & BLE_PHY_FEATURE_PHY_MASK) == BLE_PHY_FEATURE_PHY_CODED) ?
3437                                               BLE_TRANSMIT_WINDOW_DELAY_EXT_CODED : BLE_TRANSMIT_WINDOW_DELAY_EXT_UNCODED;
3438 
3439                             /*
3440                              * Use the reference time and the requested connect time to calculate an appropriate value for the winOffset.
3441                              * The winOffset value is initially set to hit the next window start by considering the desired connect interval,
3442                              * but the PBE adjusts it based on the length of the window (WINMOD).
3443                              */
3444                             uint32_t initialWinOffset = RCL_Handler_BLE5_prepareConnectTime(&initCmd->connectTime, referenceTime,
3445                                                                                             ble5HandlerState.scanInit.connectInterval);
3446                             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_WINOFFSET) = initialWinOffset;
3447                         }
3448                     }
3449 
3450                     if (ble5HandlerState.common.activeUpdate)
3451                     {
3452                         RCL_Handler_BLE5_updateAdvScanInitStats((ble5HandlerState.scanInit.initiator) ? initCmd->stats : scanCmd->stats,
3453                                                                  rclSchedulerState.actualStartTime);
3454 
3455                     }
3456                 }
3457             }
3458         }
3459     }
3460 
3461     if (rclEvents.lastCmdDone != 0)
3462     {
3463         ble5HandlerState.common.updatableFilterList = NULL;
3464         LRF_disable();
3465         LRF_disableSynthRefsys();
3466     }
3467     return rclEvents;
3468 }
3469 
3470 /*
3471  *  ======== RCL_Handler_BLE5_periodicScan ========
3472  */
RCL_Handler_BLE5_periodicScan(RCL_Command * cmd,LRF_Events lrfEvents,RCL_Events rclEventsIn)3473 RCL_Events RCL_Handler_BLE5_periodicScan(RCL_Command *cmd, LRF_Events lrfEvents, RCL_Events rclEventsIn)
3474 {
3475     RCL_CmdBle5PeriodicScanner *perScanCmd = (RCL_CmdBle5PeriodicScanner *) cmd;
3476     uint32_t rfFreq;
3477     RCL_Events rclEvents = RCL_EventNone;
3478     bool followAuxPtr = false;
3479 
3480     if (rclEventsIn.setup != 0)
3481     {
3482         uint32_t earliestStartTime;
3483         RCL_Ble5Channel channel;
3484         RCL_Command_TxPower txPower;
3485 
3486         /* Start by enabling refsys */
3487         earliestStartTime = LRF_enableSynthRefsys();
3488 
3489         HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_MDMSYNCA) = perScanCmd->ctx->accessAddress;
3490 
3491         /* 32-bit access to also write CRCINITH */
3492         HWREG_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_CRCINITL) = perScanCmd->ctx->crcInit << 8;
3493 
3494         /* The initial First Rx Timeout depends on the relative gaceful stop time configured for the command */
3495         HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FIRSTRXTIMEOUT) = 0;
3496 
3497         ble5HandlerState.common.fifoCfg = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FIFOCFG);
3498         HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_EXTRABYTES) = RCL_Handler_BLE5_findNumExtraBytes(ble5HandlerState.common.fifoCfg);
3499 
3500         /* Default end status */
3501         ble5HandlerState.common.endStatus = RCL_CommandStatus_Finished;
3502 
3503         channel = perScanCmd->channel;
3504         txPower = perScanCmd->txPower;
3505 
3506         RCL_CommandStatus status = RCL_Handler_BLE5_setPhy(cmd->phyFeatures);
3507 
3508         rfFreq = RCL_Handler_BLE5_findRfFreq(channel);
3509         if (rfFreq == 0)
3510         {
3511             status = RCL_CommandStatus_Error_Param;
3512         }
3513         else if (LRF_programTxPower(txPower) != TxPowerResult_Ok)
3514         {
3515             status = RCL_CommandStatus_Error_Param;
3516         }
3517         else if (channel != BLE_ADV_CHAN_LO && channel != BLE_ADV_CHAN_MID && channel != BLE_ADV_CHAN_HI)
3518         {
3519             cmd->status = RCL_CommandStatus_Error_Param;
3520         }
3521 
3522         if (status == RCL_CommandStatus_Active)
3523         {
3524             /* Program frequency word */
3525             LRF_programFrequency(rfFreq, false);
3526 
3527             /* Enable radio */
3528             LRF_enable();
3529 
3530             RCL_CommandStatus startTimeStatus = RCL_Scheduler_setStartStopTimeEarliestStart(cmd, earliestStartTime);
3531             if (startTimeStatus >= RCL_CommandStatus_Finished)
3532             {
3533                 status = startTimeStatus;
3534             }
3535             else
3536             {
3537                 /* Initialize counters */
3538                 ble5HandlerState.common.activeUpdate = RCL_Handler_BLE5_initAdvScanInitStats(perScanCmd->stats,
3539                                                                                              rclSchedulerState.actualStartTime);
3540 
3541                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_OPCFG) = 0;
3542 
3543                 /* Only accept non-connectable/non-scannable extended PDUs coming on a secondary channel */
3544                 uint16_t aeCfg = PBE_BLE5_RAM_AECFG_EXTENDED_EN | PBE_BLE5_RAM_AECFG_ADVMODE0_ACCEPT | PBE_BLE5_RAM_AECFG_CHNL_SECONDARY;
3545 
3546                 uint16_t whitenInit = RCL_Handler_BLE5_findWhitenInit(channel);
3547                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_WHITEINIT) = whitenInit;
3548 
3549                 if (ble5HandlerState.common.accessAddressModification)
3550                 {
3551                     HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_MDMSYNCA) = perScanCmd->ctx->accessAddress ^ (whitenInit << 24);
3552                 }
3553 
3554                 /* Configure maximum packet length */
3555                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_MAXLEN) = BLE_ADV_EXTENDED_MAX_PKT_LEN;
3556 
3557                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_OWNADRL) = 0;
3558                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_OWNADRM) = 0;
3559                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_OWNADRH) = 0;
3560                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_OWNADRTYPE) = 0;
3561 
3562                 /* Set up sync found capture */
3563                 hal_setup_sync_found_cap();
3564                 /* Initialize RF FIFOs */
3565                 ble5HandlerState.common.rxFifoSz = LRF_prepareRxFifo();
3566                 ble5HandlerState.common.curBuffer = NULL;
3567                 RCL_Handler_BLE5_updateRxCurBufferAndFifo(&perScanCmd->ctx->rxBuffers);
3568                 rclEventsIn.rxBufferUpdate = 0;
3569 
3570                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_RPAMODE) = 0;
3571 
3572                 ble5HandlerState.common.filterListUpdateIndex = -1;
3573                 /* Make sure status is correctly initialized */
3574                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FLSTAT) = 0;
3575 
3576                 /* Set filter list masks to duplicate address filtering: */
3577                 /* Bit 1: Consider type bit */
3578                 /* Bit 2: Consider duplicateIgn bit */
3579                 /* Bit 15: Consider match bit (found by PBE) */
3580                 /* Other bits are not checked */
3581                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FL1MASK) = PBE_BLE5_RAM_FL1MASK_MATCH_M |
3582                                                                               PBE_BLE5_RAM_FL1MASK_DUPLICATEIGN_M |
3583                                                                               PBE_BLE5_RAM_FL1MASK_TYPE_M;
3584                 ble5HandlerState.scanInit.filterListInvertMask = PBE_BLE5_RAM_FL1MASK_DUPLICATEIGN_M;
3585 
3586                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FL2MASK) = 0;
3587 
3588                 /* Set passive scanner configuration. No scan requests are sent */
3589                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_SCANCFG) = 0;
3590 
3591                 /* Set acceptance configuration */
3592                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_AECFG) = aeCfg;
3593 
3594                 /* Set filter policy */
3595                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FILTPOLICY) = 0;
3596 
3597                 if (status == RCL_CommandStatus_Active)
3598                 {
3599                     uint16_t fifoCfg = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FIFOCFG);
3600                     LRF_enableHwInterrupt(RCL_Handler_BLE5_maskEventsByFifoConf(LRF_EventOpDone.value | LRF_EventOpError.value |
3601                                                                                 LRF_EventRxOk.value | LRF_EventRxIgnored.value |
3602                                                                                 LRF_EventRxNok.value | LRF_EventRxBufFull.value,
3603                                                                                 fifoCfg, ble5HandlerState.common.activeUpdate));
3604 
3605                     Log_printf(RclCore, Log_VERBOSE, "Starting periodic scanner");
3606                     LRF_waitForTopsmReady();
3607                     RCL_Profiling_eventHook(RCL_ProfilingEvent_PreprocStop);
3608                     /* Post cmd */
3609                     HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_API) = PBE_BLE5_REGDEF_API_OP_SCAN;
3610 
3611                 }
3612             }
3613         }
3614         /* Set status */
3615         cmd->status = status;
3616         if (status >= RCL_CommandStatus_Finished)
3617         {
3618             rclEvents.lastCmdDone = 1;
3619         }
3620     }
3621     else
3622     {
3623         bool updateStats = false;
3624         if (lrfEvents.rxOk != 0 || lrfEvents.rxNok != 0 || lrfEvents.rxIgnored != 0 || lrfEvents.rxBufFull != 0)
3625         {
3626             /* Copy received packet from PBE FIFO to buffer */
3627             /* First, check that there is actually a buffer available */
3628             while (HWREG_READ_LRF(LRFDPBE_BASE + LRFDPBE_O_RXFREADABLE) >= 4)
3629             {
3630                 /* Check length of received buffer by peeking */
3631                 uint32_t fifoWord = LRF_peekRxFifo(0);
3632                 uint32_t wordLength = RCL_Buffer_DataEntry_paddedLen(fifoWord & 0xFFFF) / 4;
3633                 if (wordLength > 0)
3634                 {
3635                     RCL_MultiBuffer *curBuffer;
3636                     curBuffer = RCL_MultiBuffer_getBuffer(ble5HandlerState.common.curBuffer,
3637                                                           wordLength * 4);
3638                     if (curBuffer != ble5HandlerState.common.curBuffer)
3639                     {
3640                         rclEvents.rxBufferFinished = 1;
3641                         ble5HandlerState.common.curBuffer = curBuffer;
3642                     }
3643                     if (curBuffer == NULL)
3644                     {
3645                         /* Error */
3646                         ble5HandlerState.common.endStatus = RCL_CommandStatus_Error_RxBufferCorruption;
3647                         /* Send abort */
3648                         HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_API) = PBE_BLE5_REGDEF_API_OP_STOP;
3649                         /* Do not check for more packets from the RX FIFO */
3650                         break;
3651                     }
3652                     else
3653                     {
3654                         uint32_t *data32;
3655                         data32 = (uint32_t *)RCL_MultiBuffer_getNextWritableByte(curBuffer);
3656                         LRF_readRxFifoWords(data32, wordLength);
3657                         if(lrfEvents.rxOk && wordLength > 1)
3658                         {
3659                             uint32_t header = data32[1] >> 16;
3660                             uint32_t type = (header & BLE_PDU_TYPE_BM);
3661 
3662                             if (type == BLE_PDU_ADV_EXTENDED)
3663                             {
3664                                 /* Attempt to extract an AuxPtr from the received packet */
3665                                 RCL_Handler_BLE5_readAuxPtrFromRxBuffer(data32, &ble5HandlerState.common.auxPtrInfo);
3666                                 if (ble5HandlerState.common.auxPtrInfo.auxPtrPresent)
3667                                 {
3668                                     ble5HandlerState.perScan.followAuxPtr = true;
3669                                 }
3670                                 else
3671                                 {
3672                                     ble5HandlerState.perScan.followAuxPtr = false;
3673                                 }
3674                                 RCL_Handler_BLE5_commitPacket(curBuffer, wordLength * 4);
3675                                 /* Raise event */
3676                                 rclEvents.rxEntryAvail = 1;
3677                                 /* Adjust effective FIFO size */
3678                                 RCL_Handler_BLE5_updateRxCurBufferAndFifo(&perScanCmd->ctx->rxBuffers);
3679                                 rclEventsIn.rxBufferUpdate = 0;
3680                             }
3681                             else
3682                             {
3683                                 rclEvents.lastCmdDone = 1;
3684                                 cmd->status = RCL_CommandStatus_Error_RxBufferCorruption;
3685                             }
3686                         }
3687                     }
3688                 }
3689             }
3690             if (ble5HandlerState.common.activeUpdate)
3691             {
3692                 updateStats = true;
3693             }
3694         }
3695         if (rclEventsIn.timerStart != 0)
3696         {
3697             rclEvents.cmdStarted = 1;
3698         }
3699 
3700         if (lrfEvents.opDone != 0 || lrfEvents.opError != 0)
3701         {
3702             uint16_t endCause = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_COMMON_RAM_O_ENDCAUSE);
3703             if (lrfEvents.opError == 0 && (endCause == PBE_COMMON_RAM_ENDCAUSE_STAT_ENDOK ||
3704                                            endCause == PBE_COMMON_RAM_ENDCAUSE_STAT_RXERR ||
3705                                            endCause == PBE_COMMON_RAM_ENDCAUSE_STAT_NOSYNC))
3706             {
3707                 if (endCause == PBE_COMMON_RAM_ENDCAUSE_STAT_ENDOK && ble5HandlerState.perScan.followAuxPtr)
3708                 {
3709                     /* Turn off LRF to allow new synth programming */
3710                     LRF_disable();
3711                     followAuxPtr = true;
3712                 }
3713                 else
3714                 {
3715                     followAuxPtr = false;
3716                     rclEvents.lastCmdDone = 1;
3717                     cmd->status = RCL_CommandStatus_Finished;
3718                 }
3719             }
3720             else
3721             {
3722                 RCL_CommandStatus endStatus = ble5HandlerState.common.endStatus;
3723                 if (lrfEvents.opError != 0 && endStatus == RCL_CommandStatus_Finished)
3724                 {
3725                     endStatus = RCL_Handler_BLE5_findPbeErrorEndStatus(endCause);
3726                     followAuxPtr = false;
3727                     rclEvents.lastCmdDone = 1;
3728                     cmd->status = endStatus;
3729 
3730                 }
3731                 else if (endCause == PBE_COMMON_RAM_ENDCAUSE_STAT_EOPSTOP)
3732                 {
3733                     endStatus = RCL_Scheduler_findStopStatus(RCL_StopType_Graceful);
3734                     followAuxPtr = false;
3735                     rclEvents.lastCmdDone = 1;
3736                     cmd->status = endStatus;
3737                 }
3738                 else if (rclSchedulerState.hardStopInfo.apiStopEnabled && endCause == PBE_COMMON_RAM_ENDCAUSE_STAT_ENDOK)
3739                 {
3740                     endStatus = RCL_Scheduler_findStopStatus(RCL_StopType_Hard);
3741 
3742                     followAuxPtr = false;
3743                     rclEvents.lastCmdDone = 1;
3744                     cmd->status = endStatus;
3745                 }
3746                 else if (rclSchedulerState.gracefulStopInfo.apiStopEnabled && endCause == PBE_COMMON_RAM_ENDCAUSE_STAT_ENDOK)
3747                 {
3748                     endStatus = RCL_Scheduler_findStopStatus(RCL_StopType_Graceful);
3749                     followAuxPtr = false;
3750                     rclEvents.lastCmdDone = 1;
3751                     cmd->status = endStatus;
3752                 }
3753                 else
3754                 {
3755                     /* No change of status */
3756                 }
3757             }
3758         }
3759         else
3760         {
3761             /* Other events need to be handled unconditionally */
3762         }
3763 
3764         if (rclEvents.lastCmdDone != 0)
3765         {
3766             updateStats = true;
3767         }
3768         if (updateStats)
3769         {
3770             RCL_Handler_BLE5_updateAdvScanInitStats(perScanCmd->stats, rclSchedulerState.actualStartTime);
3771         }
3772     }
3773 
3774     if (cmd->status == RCL_CommandStatus_Active)
3775     {
3776         if (rclEventsIn.rxBufferUpdate != 0)
3777         {
3778             RCL_Handler_BLE5_updateRxCurBufferAndFifo(&perScanCmd->ctx->rxBuffers);
3779             rclEventsIn.rxBufferUpdate = 0;
3780         }
3781         if (followAuxPtr)
3782         {
3783             uint32_t maxAuxPtrWaitTime = perScanCmd->maxAuxPtrWaitTime;
3784             uint32_t auxOffsetUs = ble5HandlerState.common.auxPtrInfo.offsetUnits ? (ble5HandlerState.common.auxPtrInfo.auxOffset * BLE_AUX_OFFSET_300_US) :
3785                                                                                     (ble5HandlerState.common.auxPtrInfo.auxOffset * BLE_AUX_OFFSET_30_US);
3786 
3787             /* Switch to the channel indicated by the auxPtr */
3788             RCL_Ble5Channel nextChannel = (RCL_Ble5Channel) ble5HandlerState.common.auxPtrInfo.chIndex;
3789             rfFreq = RCL_Handler_BLE5_findRfFreq(nextChannel);
3790 
3791             if (maxAuxPtrWaitTime < auxOffsetUs)
3792             {
3793                 cmd->status = RCL_CommandStatus_MaxAuxWaitTimeExceeded;
3794                 rclEvents.lastCmdDone = 1;
3795             }
3796             else if (rfFreq == 0)
3797             {
3798                 cmd->status = RCL_CommandStatus_Error_Param;
3799                 rclEvents.lastCmdDone = 1;
3800             }
3801             else
3802             {
3803                 /* Begin the start time calculation of the receive window by getting the time of the last sync plus the aux offset given in the AuxPtr */
3804                 /* 32-bit access to also read LASTTIMESTAMPH */
3805                 uint32_t startTime = HWREG_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_LASTTIMESTAMPL) - ble5HandlerState.common.timestampAdjust;
3806                 uint32_t offset = RCL_SCHEDULER_SYSTIM_US(ble5HandlerState.common.auxPtrInfo.offsetUnits ?
3807                                                           ble5HandlerState.common.auxPtrInfo.auxOffset * BLE_AUX_OFFSET_300_US :
3808                                                           ble5HandlerState.common.auxPtrInfo.auxOffset * BLE_AUX_OFFSET_30_US);
3809                 startTime += offset;
3810 
3811                 /* Use the local and remote clock accuracies to find the clock error contribution */
3812                 uint16_t localClkAccuracy = RCL_SCHEDULER_SYSTIM_US(perScanCmd->ctx->localClockAccuracy);
3813                 uint16_t remoteClkAccuracy = RCL_SCHEDULER_SYSTIM_US(ble5HandlerState.common.auxPtrInfo.offsetUnits ?
3814                                                                      BLE_SCALED_CLK_ACCURACY_500PPM :
3815                                                                      BLE_SCALED_CLK_ACCURACY_50PPM);
3816 
3817                 /* Find clock error contribution. Add 1 us (4 systim units) to correct for rounding down. Also consider the sleep/active clock adjustments */
3818                 uint16_t remoteClkError = (uint16_t)((((offset * remoteClkAccuracy) >> BLE_CLK_ACCURACY_SCALE_FACTOR)) + 4 + RCL_SCHEDULER_SYSTIM_US(2));
3819                 uint16_t localClkError = (uint16_t)((((offset * localClkAccuracy) >> BLE_CLK_ACCURACY_SCALE_FACTOR)) + 4 + RCL_SCHEDULER_SYSTIM_US(16));
3820 
3821                 /* Calculate the needed window widening. Consider the allowed deviations for active clock accuracy and sleep clock accuracy */
3822                 uint16_t windowWidening = remoteClkError + localClkError;
3823 
3824                 /* Add some additional time to the window widening due to missing constants describing the Rx Start Overhead. See RCL-513. */
3825                 startTime -= (windowWidening + RX_START_OVERHEAD);
3826 
3827                 /* Begin the timeout calculation by considering that the end of receive window occurs one offset unit after startTime */
3828                 uint16_t endTime = RCL_SCHEDULER_SYSTIM_US(ble5HandlerState.common.auxPtrInfo.offsetUnits ? BLE_AUX_OFFSET_300_US : BLE_AUX_OFFSET_30_US);
3829                 uint16_t timeout = windowWidening + endTime + windowWidening;
3830 
3831 #ifdef DeviceFamily_CC27XX
3832                 startTime -= RCL_SCHEDULER_SYSTIM_US(100);
3833                 timeout += RCL_SCHEDULER_SYSTIM_US(200);
3834 #endif
3835                 /* Set timeout by writing to FIRSTRXTIMEOUT. Consider the necessary Rx sync Overhead. See RCL-513. */
3836                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FIRSTRXTIMEOUT) = timeout + RCL_Handler_BLE5_findRxSyncOverhead(ble5HandlerState.common.phyFeatures);
3837 
3838                 /* Program frequency word */
3839                 LRF_programFrequency(rfFreq, false);
3840                 /* Enable radio */
3841                 LRF_enable();
3842 
3843                 uint16_t whitenInit = RCL_Handler_BLE5_findWhitenInit(nextChannel);
3844                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_WHITEINIT) = whitenInit;
3845 
3846                 if (ble5HandlerState.common.accessAddressModification)
3847                 {
3848                     HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_MDMSYNCA) = perScanCmd->ctx->accessAddress ^ (whitenInit << 24);
3849                 }
3850 
3851                 /* Set new start time */
3852                 RCL_CommandStatus startTimeStatus = RCL_Scheduler_setNewStartAbsTime(startTime, true);
3853                 if (startTimeStatus >= RCL_CommandStatus_Finished)
3854                 {
3855                     cmd->status = startTimeStatus;
3856                     rclEvents.lastCmdDone = 1;
3857                 }
3858                 else
3859                 {
3860                     cmd->status = RCL_CommandStatus_Active;
3861                     /* Set up sync found capture */
3862                     hal_setup_sync_found_cap();
3863 
3864                     uint16_t fifoCfg = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FIFOCFG);
3865                     LRF_enableHwInterrupt(RCL_Handler_BLE5_maskEventsByFifoConf(LRF_EventOpDone.value | LRF_EventOpError.value |
3866                                                                                 LRF_EventRxOk.value | LRF_EventRxIgnored.value |
3867                                                                                 LRF_EventRxNok.value | LRF_EventRxBufFull.value,
3868                                                                                 fifoCfg, ble5HandlerState.common.activeUpdate));
3869                     Log_printf(RclCore, Log_VERBOSE, "Following AuxPointer on channel: %d", nextChannel);
3870                     LRF_waitForTopsmReady();
3871 
3872                     /* Post cmd */
3873                     HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_API) = PBE_BLE5_REGDEF_API_OP_SCAN;
3874 
3875                     if (ble5HandlerState.common.activeUpdate)
3876                     {
3877                         RCL_Handler_BLE5_updateAdvScanInitStats(perScanCmd->stats, rclSchedulerState.actualStartTime);
3878                     }
3879                 }
3880             }
3881         }
3882     }
3883 
3884     if (rclEvents.lastCmdDone != 0)
3885     {
3886         ble5HandlerState.common.updatableFilterList = NULL;
3887         LRF_disable();
3888         LRF_disableSynthRefsys();
3889     }
3890     return rclEvents;
3891 }
3892 
3893 /*
3894  *  ======== RCL_Handler_BLE5_conn ========
3895  */
RCL_Handler_BLE5_conn(RCL_Command * cmd,LRF_Events lrfEvents,RCL_Events rclEventsIn)3896 RCL_Events RCL_Handler_BLE5_conn(RCL_Command *cmd, LRF_Events lrfEvents, RCL_Events rclEventsIn)
3897 {
3898     uint32_t rfFreq;
3899     RCL_CmdBle5Connection *connCmd = (RCL_CmdBle5Connection *) cmd;
3900     RCL_Events rclEvents = {.value = 0};
3901 
3902     if (rclEventsIn.setup != 0)
3903     {
3904         uint32_t earliestStartTime;
3905 
3906         /* Start by enabling refsys */
3907         earliestStartTime = LRF_enableSynthRefsys();
3908 
3909         uint32_t startDelay = 0;
3910         RCL_CtxConnection *ctx = connCmd->ctx;
3911         uint32_t crcInit = ctx->crcInit;
3912         uint32_t accessAddress = ctx->accessAddress;
3913 
3914         HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_MDMSYNCA) = accessAddress;
3915 
3916         /* 32-bit access to also write CRCINITH */
3917         HWREG_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_CRCINITL) = crcInit << 8;
3918 
3919         ble5HandlerState.common.fifoCfg = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FIFOCFG);
3920         HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_EXTRABYTES) = RCL_Handler_BLE5_findNumExtraBytes(ble5HandlerState.common.fifoCfg);
3921 
3922         HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_MDCFG) = 0;
3923 
3924         HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_SEQSTAT) = ctx->seqStat;
3925 
3926         /* Default end status */
3927         ble5HandlerState.common.endStatus = RCL_CommandStatus_Finished;
3928 
3929         RCL_CommandStatus status = RCL_Handler_BLE5_setPhy(cmd->phyFeatures);
3930         rfFreq = RCL_Handler_BLE5_findRfFreq(connCmd->channel);
3931         if (rfFreq == 0)
3932         {
3933             status = RCL_CommandStatus_Error_Param;
3934         }
3935         else if (LRF_programTxPower(connCmd->txPower) != TxPowerResult_Ok)
3936         {
3937             status = RCL_CommandStatus_Error_Param;
3938         }
3939 
3940         if (status == RCL_CommandStatus_Active)
3941         {
3942             /* Program frequency word */
3943             LRF_programFrequency(rfFreq, !ctx->isPeripheral);
3944 
3945             /* Enable radio */
3946             LRF_enable();
3947 
3948             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_OPCFG) = 0;
3949             uint16_t whitenInit = RCL_Handler_BLE5_findWhitenInit(connCmd->channel);
3950             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_WHITEINIT) = whitenInit;
3951             if (ble5HandlerState.common.accessAddressModification)
3952             {
3953                 HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_MDMSYNCA) = accessAddress ^ (whitenInit << 24);
3954             }
3955 
3956             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_MAXLEN) = BLE_MAX_PKT_LEN;
3957             /* Set up timers */
3958 
3959             RCL_CommandStatus startTimeStatus = RCL_Scheduler_setStartStopTimeEarliestStart(cmd, earliestStartTime);
3960             if (startTimeStatus >= RCL_CommandStatus_Finished)
3961             {
3962                 status = startTimeStatus;
3963             }
3964             else
3965             {
3966                 /* Initialize counters */
3967                 ble5HandlerState.common.activeUpdate = RCL_Handler_BLE5_initConnStats(connCmd->stats, rclSchedulerState.actualStartTime);
3968                 if (cmd->scheduling == RCL_Schedule_AbsTime)
3969                 {
3970                     startDelay = rclSchedulerState.actualStartTime - cmd->timing.absStartTime;
3971                 }
3972                 /* Set up sync found capture */
3973                 hal_setup_sync_found_cap();
3974                 /* Initialize RF FIFOs */
3975                 ble5HandlerState.common.rxFifoSz = LRF_prepareRxFifo();
3976                 ble5HandlerState.common.curBuffer = NULL;
3977                 RCL_Handler_BLE5_updateRxCurBufferAndFifo(&connCmd->ctx->rxBuffers);
3978                 rclEventsIn.rxBufferUpdate = 0;
3979                 ble5HandlerState.common.txFifoSz = LRF_prepareTxFifo();
3980 
3981                 /* Enter TX payload - maximum two packets in the beginning */
3982                 bool retransPossible = ctx->isPeripheral &&
3983                     ((ctx->seqStat & (PBE_BLE5_RAM_SEQSTAT_EMPTY_M | PBE_BLE5_RAM_SEQSTAT_FIRSTPKT_M)) == 0);
3984                 ble5HandlerState.common.txBufferInfo = (RCL_TxBufferInfo) { .isConnBuffer = true };
3985                 RCL_Handler_BLE5_updateTxBuffers(&ctx->txBuffers, 2,
3986                                                  &ble5HandlerState.common.txBufferInfo, retransPossible);
3987 
3988                 uint16_t fifoCfg = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FIFOCFG);
3989                 LRF_enableHwInterrupt(RCL_Handler_BLE5_maskEventsByFifoConf(LRF_EventOpDone.value | LRF_EventOpError.value |
3990                                                                             LRF_EventRxOk.value | LRF_EventRxIgnored.value |
3991                                                                             LRF_EventRxNok.value | LRF_EventRxEmpty.value |
3992                                                                             LRF_EventRxBufFull.value | LRF_EventTxDone.value,
3993                                                                             fifoCfg, ble5HandlerState.common.activeUpdate));
3994                 if (ctx->isPeripheral)
3995                 {
3996                     int32_t relRxTimeoutTime = connCmd->relRxTimeoutTime;
3997                     if (relRxTimeoutTime != 0)
3998                     {
3999                         relRxTimeoutTime -= startDelay;
4000 
4001                         if (relRxTimeoutTime <= 0)
4002                         {
4003                             status = RCL_CommandStatus_RxTimeout;
4004                         }
4005                     }
4006 
4007                     if (status == RCL_CommandStatus_Active)
4008                     {
4009                         /* Set timeout */
4010                         HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FIRSTRXTIMEOUT) = relRxTimeoutTime;
4011 
4012                         Log_printf(RclCore, Log_VERBOSE, "Starting peripheral");
4013                         LRF_waitForTopsmReady();
4014                         RCL_Profiling_eventHook(RCL_ProfilingEvent_PreprocStop);
4015                         /* Post cmd */
4016                         HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_API) = PBE_BLE5_REGDEF_API_OP_PERIPHERAL;
4017                     }
4018                 }
4019                 else
4020                 {
4021                     Log_printf(RclCore, Log_VERBOSE, "Starting central");
4022                     LRF_waitForTopsmReady();
4023                     RCL_Profiling_eventHook(RCL_ProfilingEvent_PreprocStop);
4024                     /* Post cmd */
4025                     HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_API) = PBE_BLE5_REGDEF_API_OP_CENTRAL;
4026                 }
4027                 if (status == RCL_CommandStatus_Active)
4028                 {
4029                     /* Insert any more TX payload that can fit */
4030                     RCL_Handler_BLE5_updateTxBuffers(&ctx->txBuffers,
4031                                                     UINT32_MAX,
4032                                                     &ble5HandlerState.common.txBufferInfo,
4033                                                     false);
4034                 }
4035             }
4036         }
4037         /* Set status */
4038         cmd->status = status;
4039         if (status >= RCL_CommandStatus_Finished)
4040         {
4041             rclEvents.lastCmdDone = 1;
4042         }
4043     }
4044     else
4045     {
4046         if (lrfEvents.rxOk != 0 || lrfEvents.rxNok != 0 || lrfEvents.rxEmpty != 0 || lrfEvents.rxIgnored != 0 || lrfEvents.rxBufFull != 0)
4047         {
4048             /* Copy received packet from PBE FIFO to buffer */
4049             /* First, check that there is actually a buffer available */
4050             while (HWREG_READ_LRF(LRFDPBE_BASE + LRFDPBE_O_RXFREADABLE) >= 4)
4051             {
4052                 /* Check length of received buffer by peeking */
4053                 uint32_t fifoWord = LRF_peekRxFifo(0);
4054                 uint32_t wordLength = RCL_Buffer_DataEntry_paddedLen(fifoWord & 0xFFFF) / 4;
4055                 if (wordLength > 0)
4056                 {
4057                     RCL_MultiBuffer *curBuffer;
4058                     curBuffer = RCL_MultiBuffer_getBuffer(ble5HandlerState.common.curBuffer,
4059                                                           wordLength * 4);
4060                     if (curBuffer != ble5HandlerState.common.curBuffer)
4061                     {
4062                         rclEvents.rxBufferFinished = 1;
4063                         ble5HandlerState.common.curBuffer = curBuffer;
4064                     }
4065 
4066                     if (curBuffer == NULL)
4067                     {
4068                         /* Error */
4069                         ble5HandlerState.common.endStatus = RCL_CommandStatus_Error_RxBufferCorruption;
4070                         /* Send abort */
4071                         HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_API) = PBE_BLE5_REGDEF_API_OP_STOP;
4072                         /* Do not check for more packets from the RX FIFO */
4073                         break;
4074                     }
4075                     else
4076                     {
4077                         uint32_t *data32;
4078                         data32 = (uint32_t *)RCL_MultiBuffer_getNextWritableByte(curBuffer);
4079                         LRF_readRxFifoWords(data32, wordLength);
4080                         RCL_Handler_BLE5_commitPacket(curBuffer, wordLength * 4);
4081                         /* Raise event */
4082                         rclEvents.rxEntryAvail = 1;
4083                         /* Adjust effective FIFO size */
4084                         RCL_Handler_BLE5_updateRxCurBufferAndFifo(&connCmd->ctx->rxBuffers);
4085                         rclEventsIn.rxBufferUpdate = 0;
4086                     }
4087                 }
4088             }
4089             if (ble5HandlerState.common.activeUpdate)
4090             {
4091                 RCL_Handler_BLE5_updateConnStats(connCmd->stats, rclSchedulerState.actualStartTime);
4092             }
4093         }
4094         if (lrfEvents.txDone != 0)
4095         {
4096             /* Free up finished tx buffers */
4097             uint32_t bytesWritten = ble5HandlerState.common.txFifoSz - LRF_getTxFifoWritable();
4098             uint32_t numBytes = ble5HandlerState.common.txBufferInfo.numBytes;
4099             int32_t numBuffers = ble5HandlerState.common.txBufferInfo.numBuffers;
4100             if (bytesWritten < numBytes)
4101             {
4102                 RCL_Buffer_TxBuffer *txBuffer;
4103                 do
4104                 {
4105                     uint32_t entryBytes;
4106                     txBuffer = RCL_TxBuffer_get(&connCmd->ctx->txBuffers);
4107                     if (txBuffer == NULL)
4108                     {
4109                         /* Error */
4110                         break;
4111                     }
4112                     txBuffer->state = RCL_BufferStateFinished;
4113                     numBuffers--;
4114                     entryBytes = RCL_Buffer_DataEntry_paddedLen(txBuffer->length);
4115                     numBytes -= entryBytes;
4116                     if (txBuffer == ble5HandlerState.common.txBufferInfo.lastEnteredTxBuffer)
4117                     {
4118                         ble5HandlerState.common.txBufferInfo.lastEnteredTxBuffer = NULL;
4119                         ble5HandlerState.common.txBufferInfo.lastTxHdr = NULL;
4120                     }
4121 
4122                 } while (bytesWritten < numBytes);
4123 
4124                 /* Check consistency */
4125                 if (numBytes != bytesWritten || numBuffers < 0)
4126                 {
4127                     /* Error */
4128                     ble5HandlerState.common.endStatus = RCL_CommandStatus_Error_TxBufferCorruption;
4129                     /* Send abort */
4130                     HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_API) = PBE_BLE5_REGDEF_API_OP_STOP;
4131                 }
4132                 else
4133                 {
4134                     ble5HandlerState.common.txBufferInfo.numBytes = numBytes;
4135                     ble5HandlerState.common.txBufferInfo.numBuffers = numBuffers;
4136                     rclEvents.txBufferFinished = 1;
4137                 }
4138                 /* Set flag to insert more data if possible */
4139                 rclEventsIn.txBufferUpdate = 1;
4140             }
4141         }
4142         if (rclEventsIn.timerStart != 0)
4143         {
4144             rclEvents.cmdStarted = 1;
4145         }
4146 
4147         if (lrfEvents.opDone != 0 || lrfEvents.opError != 0)
4148         {
4149             RCL_Profiling_eventHook(RCL_ProfilingEvent_PostprocStart);
4150             RCL_CommandStatus endStatus;
4151             connCmd->ctx->seqStat = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_SEQSTAT);
4152             /* Disable radio */
4153 
4154             rclEvents.lastCmdDone = 1;
4155             endStatus = ble5HandlerState.common.endStatus;
4156             if (endStatus == RCL_CommandStatus_Finished)
4157             {
4158                 uint16_t pbeEndcause = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_COMMON_RAM_O_ENDCAUSE);
4159                 /* Check if we need to change status */
4160                 if (lrfEvents.opError != 0)
4161                 {
4162                     endStatus = RCL_Handler_BLE5_findPbeErrorEndStatus(pbeEndcause);
4163                 }
4164                 else
4165                 {
4166                     if (pbeEndcause == PBE_COMMON_RAM_ENDCAUSE_STAT_RXTIMEOUT)
4167                     {
4168                         endStatus = RCL_CommandStatus_RxTimeout;
4169                     }
4170                     else if (pbeEndcause == PBE_COMMON_RAM_ENDCAUSE_STAT_EOPSTOP)
4171                     {
4172                         endStatus = RCL_Scheduler_findStopStatus(RCL_StopType_Graceful);
4173                     }
4174                     else if (pbeEndcause == PBE_COMMON_RAM_ENDCAUSE_STAT_NOSYNC)
4175                     {
4176                         endStatus = RCL_CommandStatus_NoSync;
4177                     }
4178                     else if (pbeEndcause == PBE_COMMON_RAM_ENDCAUSE_STAT_RXERR)
4179                     {
4180                             endStatus = RCL_CommandStatus_RxErr;
4181                     }
4182                     else if (pbeEndcause == PBE_COMMON_RAM_ENDCAUSE_STAT_MAXNAK)
4183                     {
4184                         endStatus = RCL_CommandStatus_MaxNak;
4185                     }
4186                     else
4187                     {
4188                         /* No change of status */
4189                     }
4190                 }
4191             }
4192             cmd->status = endStatus;
4193         }
4194         else
4195         {
4196             /* Other events need to be handled unconditionally */
4197         }
4198         if (rclEvents.lastCmdDone != 0)
4199         {
4200             RCL_Handler_BLE5_updateConnStats(connCmd->stats, rclSchedulerState.actualStartTime);
4201         }
4202     }
4203 
4204     if (cmd->status == RCL_CommandStatus_Active)
4205     {
4206         if (rclEventsIn.rxBufferUpdate != 0)
4207         {
4208             RCL_Handler_BLE5_updateRxCurBufferAndFifo(&connCmd->ctx->rxBuffers);
4209             rclEventsIn.rxBufferUpdate = 0;
4210         }
4211         if (rclEventsIn.txBufferUpdate != 0)
4212         {
4213             /* Insert any more TX payload that can fit */
4214             RCL_Handler_BLE5_updateTxBuffers(&connCmd->ctx->txBuffers,
4215                                              UINT32_MAX,
4216                                              &ble5HandlerState.common.txBufferInfo,
4217                                              false);
4218             rclEventsIn.txBufferUpdate = 0;
4219         }
4220     }
4221 
4222     if (rclEvents.lastCmdDone != 0)
4223     {
4224         LRF_disable();
4225         LRF_disableSynthRefsys();
4226     }
4227 
4228     return rclEvents;
4229 }
4230 
4231 /*
4232  *  ======== RCL_Handler_BLE5_dtmTx ========
4233  */
RCL_Handler_BLE5_dtmTx(RCL_Command * cmd,LRF_Events lrfEvents,RCL_Events rclEventsIn)4234 RCL_Events RCL_Handler_BLE5_dtmTx(RCL_Command *cmd, LRF_Events lrfEvents, RCL_Events rclEventsIn)
4235 {
4236     RCL_CmdBle5DtmTx *txCmd = (RCL_CmdBle5DtmTx *) cmd;
4237     RCL_Events rclEvents = {.value = 0};
4238 
4239     if (rclEventsIn.setup != 0)
4240     {
4241         uint32_t earliestStartTime;
4242         RCL_Ble5Channel channel;
4243         uint8_t byteVal;
4244         uint32_t whitenPoly;
4245         uint32_t whitenSeed;
4246         uint32_t rfFreq;
4247 
4248         /* Start by enabling refsys */
4249         earliestStartTime = LRF_enableSynthRefsys();
4250 
4251         HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_MDMSYNCA) = DTM_ACCESS_ADDRESS;
4252         /* 32-bit access to also write CRCINITH */
4253         HWREG_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_CRCINITL) = ADV_CRC_INIT;
4254         /* Set PBE timer 1 prescaler to use 1 us ticks */
4255         uint16_t timPre = HWREG_READ_LRF(LRFDPBE_BASE + LRFDPBE_O_TIMPRE);
4256         ble5HandlerState.dtmTx.storedPbeTimPre = timPre;
4257         HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_TIMPRE) = (timPre & ~LRFDPBE_TIMPRE_PRE1_M) | ((LRF_CLOCK_TICKS_PER_US - 1) << LRFDPBE_TIMPRE_PRE1_S);
4258 
4259         HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_RFINTERVAL) = txCmd->periodUs;
4260         HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NTXTARGET) = txCmd->numPackets;
4261 
4262         /* Default end status */
4263         ble5HandlerState.common.endStatus = RCL_CommandStatus_Finished;
4264 
4265         channel = txCmd->channel;
4266 
4267         RCL_CommandStatus status = RCL_Handler_BLE5_setPhy(cmd->phyFeatures);
4268         rfFreq = RCL_Handler_BLE5_findRfFreq(channel);
4269         if (rfFreq == 0)
4270         {
4271             status = RCL_CommandStatus_Error_Param;
4272         }
4273         else if (LRF_programTxPower(txCmd->txPower) != TxPowerResult_Ok)
4274         {
4275             status = RCL_CommandStatus_Error_Param;
4276         }
4277 
4278         if (status == RCL_CommandStatus_Active)
4279         {
4280             /* Program frequency word */
4281             LRF_programFrequency(rfFreq, false);
4282 
4283             /* Enable radio */
4284             LRF_enable();
4285 
4286             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_OPCFG) = (PBE_BLE5_RAM_OPCFG_REPEAT_YES) |
4287                                                                         (PBE_BLE5_RAM_OPCFG_TXPATTERN_NO) |
4288                                                                         (PBE_BLE5_RAM_OPCFG_TXFCMD_RETRY) |
4289                                                                         (PBE_BLE5_RAM_OPCFG_RFINTERVAL_EN);
4290 
4291             /* Initialize RF FIFOs */
4292             ble5HandlerState.common.txFifoSz = LRF_prepareTxFifo();
4293 
4294             /* Prepare payload */
4295             switch (txCmd->pduHeader & 0x0F)
4296             {
4297             case BLE_DTM_PAYLOAD_TYPE_PRBS9:
4298                 byteVal = 0;
4299                 whitenPoly = RCL_HANDLER_BLE5_PRBS9_POLY;
4300                 whitenSeed = RCL_HANDLER_BLE5_PRBS9_INIT;
4301                 break;
4302             case BLE_DTM_PAYLOAD_TYPE_11110000:
4303                 byteVal = 0x0F; /* 11110000... in transmission order */
4304                 whitenPoly = 0;
4305                 whitenSeed = 0;
4306                 break;
4307             case BLE_DTM_PAYLOAD_TYPE_10101010:
4308                 byteVal = 0x55; /* 10101010... in transmission order */
4309                 whitenPoly = 0;
4310                 whitenSeed = 0;
4311                 break;
4312             case BLE_DTM_PAYLOAD_TYPE_PRBS15:
4313                 byteVal = 0;
4314                 whitenPoly = RCL_HANDLER_BLE5_PRBS15_POLY;
4315                 whitenSeed = RCL_HANDLER_BLE5_PRBS15_INIT;
4316                 break;
4317             case BLE_DTM_PAYLOAD_TYPE_11111111:
4318                 byteVal = 0xFF; /* All ones */
4319                 whitenPoly = 0;
4320                 whitenSeed = 0;
4321                 break;
4322             case BLE_DTM_PAYLOAD_TYPE_00000000:
4323                 byteVal = 0x00; /* All zeros */
4324                 whitenPoly = 0;
4325                 whitenSeed = 0;
4326                 break;
4327             case BLE_DTM_PAYLOAD_TYPE_00001111:
4328                 byteVal = 0xF0; /* 00001111... in transmission order */
4329                 whitenPoly = 0;
4330                 whitenSeed = 0;
4331                 break;
4332             case BLE_DTM_PAYLOAD_TYPE_01010101:
4333                 byteVal = 0xAA; /* 01010101... in transmission order */
4334                 whitenPoly = 0;
4335                 whitenSeed = 0;
4336                 break;
4337             default:
4338                 status = RCL_CommandStatus_Error_Param;
4339                 whitenSeed = 0;
4340                 whitenPoly = 0;
4341                 byteVal = 0;
4342                 break;
4343             }
4344             if (status == RCL_CommandStatus_Active)
4345             {
4346                 /* Enter length field and padding length in FIFO */
4347                 HWREG_WRITE_LRF(LRFDTXF_BASE + LRFDTXF_O_TXD) = (txCmd->pduLength + 6) | (3 << 16);
4348                 /* Enter header in FIFO */
4349                 HWREG_WRITE_LRF(LRFDTXF_BASE + LRFDTXF_O_TXD) = (txCmd->pduLength << 24) | (txCmd->pduHeader << 16);
4350 
4351                 if (whitenSeed == 0)
4352                 {
4353                     uint32_t txWord = byteVal | (byteVal << 8) | (byteVal << 16) | (byteVal << 24);
4354                     for (int i = 0; i < RCL_Buffer_bytesToWords(txCmd->pduLength); i++)
4355                     {
4356                         HWREG_WRITE_LRF(LRFDTXF_BASE + LRFDTXF_O_TXD) = txWord;
4357                     }
4358                 }
4359                 else
4360                 {
4361                     /* Re-use PBE whitener for generating PRBS payload */
4362                     /* Save existing polynomial, which is part of the setup */
4363                     uint32_t whitenPolySave = HWREG_READ_LRF(LRFDPBE32_BASE + LRFDPBE32_O_POLY0);
4364                     /* Configure stand-alone whitening in PRBS0 of the PHA */
4365                     HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_PHACFG) = (LRFDPBE_PHACFG_MODE0_WHITE) |
4366                                                              (LRFDPBE_PHACFG_MODE1_INDEP);
4367                     /* Set the polynomial of the configured PRBS sequence */
4368                     HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_POLY0) = whitenPoly;
4369                     /* Seed the PRBS */
4370                     HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_LFSR0BR) = whitenSeed;
4371                     /* Set byte accesses */
4372                     HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_LFSR0N) = 7;
4373                     /* Write the configured byte value into the whitener for the first byte */
4374                     HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_LFSR0INL) = byteVal;
4375                     for (int i = 0; i < RCL_Buffer_bytesToWords(txCmd->pduLength); i++)
4376                     {
4377                         /* Initialize combined 4-byte word */
4378                         uint32_t txWord = 0;
4379                         for (int j = 0; j < 4; j++)
4380                         {
4381                             /* Wait for PHA to be done whiteneing the byte */
4382                             while ((HWREG_READ_LRF(LRFDPBE_BASE + LRFDPBE_O_PHASTA) & LRFDPBE_PHASTA_BUSY_M) != 0)
4383                             {}
4384                             /* Read whitened byte */
4385                             uint8_t txByte = HWREG_READ_LRF(LRFDPBE_BASE + LRFDPBE_O_PHAOUT0);
4386                             /* Enter next byte */
4387                             HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_LFSR0INL) = byteVal;
4388                             /* Insert byte into word */
4389                             txWord |= txByte << (j * 8);
4390                         }
4391                         /* Write word to TX FIFO. If the packet length does not divide 4, there will be some extra non-zero bytes,
4392                         but they will be ignored by the radio, making the transmitted packet correct */
4393                         HWREG_WRITE_LRF(LRFDTXF_BASE + LRFDTXF_O_TXD) = txWord;
4394                     }
4395                     /* Restore whitener polynomial */
4396                     HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_POLY0) = whitenPolySave;
4397                 }
4398 
4399                 RCL_CommandStatus startTimeStatus = RCL_Scheduler_setStartStopTimeEarliestStart(cmd, earliestStartTime);
4400                 if (startTimeStatus >= RCL_CommandStatus_Finished)
4401                 {
4402                     status = startTimeStatus;
4403                 }
4404                 else
4405                 {
4406                     LRF_enableHwInterrupt(LRF_EventOpDone.value | LRF_EventOpError.value);
4407                     HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_WHITEINIT) = 0;
4408                     if (ble5HandlerState.common.accessAddressModification)
4409                     {
4410                         uint16_t whitenInit = RCL_Handler_BLE5_findWhitenInit(channel);
4411                         HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_MDMSYNCA) = DTM_ACCESS_ADDRESS ^ (whitenInit << 24);
4412                     }
4413                     Log_printf(RclCore, Log_VERBOSE, "Starting DTM TX");
4414                     LRF_waitForTopsmReady();
4415                     /* Post cmd */
4416                     HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_API) = PBE_BLE5_REGDEF_API_OP_TXRAW;
4417                 }
4418             }
4419         }
4420         /* Set status */
4421         cmd->status = status;
4422         if (status >= RCL_CommandStatus_Finished)
4423         {
4424             rclEvents.lastCmdDone = 1;
4425         }
4426     }
4427 
4428     if (cmd->status == RCL_CommandStatus_Active)
4429     {
4430         if (rclEventsIn.timerStart != 0)
4431         {
4432             Log_printf(RclCore, Log_VERBOSE, "DTM TX started");
4433             rclEvents.cmdStarted = 1;
4434         }
4435         if (lrfEvents.opDone != 0 || lrfEvents.opError != 0)
4436         {
4437             Log_printf(RclCore, Log_VERBOSE, "TX raw done");
4438             RCL_CommandStatus endStatus = ble5HandlerState.common.endStatus;
4439             if (endStatus == RCL_CommandStatus_Finished && lrfEvents.opError != 0)
4440             {
4441                 cmd->status = RCL_Handler_BLE5_findPbeErrorEndStatus(HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_COMMON_RAM_O_ENDCAUSE));
4442             }
4443             else
4444             {
4445                 if (HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_COMMON_RAM_O_ENDCAUSE) == PBE_COMMON_RAM_ENDCAUSE_STAT_EOPSTOP)
4446                 {
4447                     endStatus = RCL_Scheduler_findStopStatus(RCL_StopType_Graceful);
4448                 }
4449 
4450                 cmd->status = endStatus;
4451             }
4452             rclEvents.lastCmdDone = 1;
4453         }
4454         else
4455         {
4456             /* Other events need to be handled unconditionally */
4457         }
4458     }
4459     if (rclEvents.lastCmdDone != 0)
4460     {
4461         LRF_disable();
4462         LRF_disableSynthRefsys();
4463         /* Restore PBE timer 1 prescaler */
4464         HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_TIMPRE) = ble5HandlerState.dtmTx.storedPbeTimPre;
4465     }
4466     return rclEvents;
4467 }
4468 
4469 
4470 /*
4471  *  ======== RCL_Handler_BLE5_genericRx ========
4472  */
RCL_Handler_BLE5_genericRx(RCL_Command * cmd,LRF_Events lrfEvents,RCL_Events rclEventsIn)4473 RCL_Events RCL_Handler_BLE5_genericRx(RCL_Command *cmd, LRF_Events lrfEvents, RCL_Events rclEventsIn)
4474 {
4475     RCL_CmdBle5GenericRx *rxCmd = (RCL_CmdBle5GenericRx *) cmd;
4476     uint32_t rfFreq;
4477     RCL_Events rclEvents = RCL_EventNone;
4478     RCL_CtxGenericRx *ctx = rxCmd->ctx;
4479 
4480     if (rclEventsIn.setup != 0)
4481     {
4482         uint32_t earliestStartTime;
4483         RCL_Ble5Channel channel;
4484 
4485         /* Start by enabling refsys */
4486         earliestStartTime = LRF_enableSynthRefsys();
4487 
4488         uint32_t crcInit = ctx->crcInit;
4489         uint32_t accessAddress = ctx->accessAddress;
4490 
4491         HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_MDMSYNCA) = accessAddress;
4492         /* 32-bit access to also write CRCINITH */
4493         HWREG_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_CRCINITL) = crcInit << 8;
4494 
4495         ble5HandlerState.common.fifoCfg = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FIFOCFG);
4496         HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_EXTRABYTES) = RCL_Handler_BLE5_findNumExtraBytes(ble5HandlerState.common.fifoCfg);
4497 
4498         /* Default end status */
4499         ble5HandlerState.common.endStatus = RCL_CommandStatus_Finished;
4500 
4501         channel = rxCmd->channel;
4502 
4503         RCL_CommandStatus status = RCL_Handler_BLE5_setPhy(cmd->phyFeatures);
4504         rfFreq = RCL_Handler_BLE5_findRfFreq(channel);
4505         if (rfFreq == 0)
4506         {
4507             status = RCL_CommandStatus_Error_Param;
4508         }
4509 
4510         if (status == RCL_CommandStatus_Active)
4511         {
4512             /* Program frequency word */
4513             LRF_programFrequency(rfFreq, false);
4514 
4515             /* Enable radio */
4516             LRF_enable();
4517 
4518             RCL_CommandStatus startTimeStatus = RCL_Scheduler_setStartStopTimeEarliestStart(cmd, earliestStartTime);
4519             if (startTimeStatus >= RCL_CommandStatus_Finished)
4520             {
4521                 status = startTimeStatus;
4522             }
4523             else
4524             {
4525                 /* Initialize counters */
4526                 ble5HandlerState.common.activeUpdate = RCL_Handler_BLE5_initGenericRxStats(rxCmd->stats,
4527                                                                                         rclSchedulerState.actualStartTime);
4528 
4529                 uint16_t whitenInit = RCL_Handler_BLE5_findWhitenInit(channel);
4530                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_WHITEINIT) = whitenInit;
4531 
4532                 if (ble5HandlerState.common.accessAddressModification)
4533                 {
4534                     HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_MDMSYNCA) = accessAddress ^ (whitenInit << 24);
4535                 }
4536 
4537                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_MAXLEN) = ctx->maxPktLen;
4538                 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_OPCFG) = ctx->config.repeated << PBE_BLE5_RAM_OPCFG_REPEAT_S;
4539 
4540                 if (ctx->config.disableSync != 0)
4541                 {
4542                     uint16_t demc1be0 = HWREG_READ_LRF(LRFDMDM_BASE + LRFDMDM_O_DEMC1BE0);
4543                     uint16_t demc1be1 = HWREG_READ_LRF(LRFDMDM_BASE + LRFDMDM_O_DEMC1BE1);
4544                     uint16_t demc1be2 = HWREG_READ_LRF(LRFDMDM_BASE + LRFDMDM_O_DEMC1BE2);
4545 #ifdef DeviceFamily_CC27XX
4546                     uint16_t demc1be12 = HWREG_READ_LRF(LRFDMDM_BASE + LRFDMDM_O_DEMC1BE12);
4547 #endif
4548                     ble5HandlerState.genericRx.restoreThresh = true;
4549                     ble5HandlerState.genericRx.demc1be0 = demc1be0;
4550                     ble5HandlerState.genericRx.demc1be1 = demc1be1;
4551                     ble5HandlerState.genericRx.demc1be2 = demc1be2;
4552 #ifdef DeviceFamily_CC27XX
4553                     ble5HandlerState.genericRx.demc1be12 = demc1be12;
4554 #endif
4555                     demc1be0 |= LRFDMDM_DEMC1BE0_MASKA_M | LRFDMDM_DEMC1BE0_MASKB_M;
4556                     demc1be1 = (0x7F << LRFDMDM_DEMC1BE1_THRESHOLDA_S) | (0x7F << LRFDMDM_DEMC1BE1_THRESHOLDB_S);
4557                     demc1be2 = (demc1be2 & ~LRFDMDM_DEMC1BE2_THRESHOLDC_M) | (0x7F << LRFDMDM_DEMC1BE2_THRESHOLDC_S);
4558 #ifdef DeviceFamily_CC27XX
4559                     demc1be12 = (demc1be12 & ~LRFDMDM_DEMC1BE12_THRESHOLDG_M) | (0x7F << LRFDMDM_DEMC1BE12_THRESHOLDG_S);
4560 #endif
4561                     HWREG_WRITE_LRF(LRFDMDM_BASE + LRFDMDM_O_DEMC1BE0) = demc1be0;
4562                     HWREG_WRITE_LRF(LRFDMDM_BASE + LRFDMDM_O_DEMC1BE1) = demc1be1;
4563                     HWREG_WRITE_LRF(LRFDMDM_BASE + LRFDMDM_O_DEMC1BE2) = demc1be2;
4564 #ifdef DeviceFamily_CC27XX
4565                     HWREG_WRITE_LRF(LRFDMDM_BASE + LRFDMDM_O_DEMC1BE12) = demc1be12;
4566 #endif
4567                 }
4568                 else
4569                 {
4570                     ble5HandlerState.genericRx.restoreThresh = false;
4571                 }
4572 
4573                 /* Set up sync found capture */
4574                 hal_setup_sync_found_cap();
4575                 /* Initialize RF FIFOs */
4576                 ble5HandlerState.common.rxFifoSz = LRF_prepareRxFifo();
4577                 ble5HandlerState.common.curBuffer = NULL;
4578                 if (ctx->config.discardRxPackets == 0)
4579                 {
4580                     RCL_Handler_BLE5_updateRxCurBufferAndFifo(&ctx->rxBuffers);
4581                     rclEventsIn.rxBufferUpdate = 0;
4582                 }
4583                 else
4584                 {
4585                     /* Set FIFO size to maximum */
4586                     LRF_setRxFifoEffSz(ble5HandlerState.common.rxFifoSz);
4587                 }
4588 
4589                 if (status == RCL_CommandStatus_Active)
4590                 {
4591                     uint16_t fifoCfg = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FIFOCFG);
4592                     LRF_enableHwInterrupt(RCL_Handler_BLE5_maskEventsByFifoConf(LRF_EventOpDone.value | LRF_EventOpError.value |
4593                                                                                 LRF_EventRxOk.value | LRF_EventRxIgnored.value |
4594                                                                                 LRF_EventRxNok.value | LRF_EventRxBufFull.value,
4595                                                                                 fifoCfg, ble5HandlerState.common.activeUpdate));
4596 
4597                     Log_printf(RclCore, Log_VERBOSE, "Starting generic RX");
4598                     LRF_waitForTopsmReady();
4599                     /* Post cmd */
4600                     HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_API) = PBE_BLE5_REGDEF_API_OP_RXRAW;
4601                 }
4602             }
4603         }
4604         /* Set status */
4605         cmd->status = status;
4606         if (status >= RCL_CommandStatus_Finished)
4607         {
4608             rclEvents.lastCmdDone = 1;
4609         }
4610     }
4611     else
4612     {
4613         if (lrfEvents.rxOk != 0 || lrfEvents.rxNok != 0 || lrfEvents.rxIgnored != 0 || lrfEvents.rxBufFull != 0)
4614         {
4615             /* Copy received packet from PBE FIFO to buffer */
4616             /* First, check that there is actually a buffer available */
4617             while (HWREG_READ_LRF(LRFDPBE_BASE + LRFDPBE_O_RXFREADABLE) >= 4)
4618             {
4619                 /* Check length of received buffer by peeking */
4620                 uint32_t fifoWord = LRF_peekRxFifo(0);
4621                 uint32_t wordLength = RCL_Buffer_DataEntry_paddedLen(fifoWord & 0xFFFF) / 4;
4622                 if (wordLength > 0)
4623                 {
4624                     if (ctx->config.discardRxPackets == 0)
4625                     {
4626                         RCL_MultiBuffer *curBuffer;
4627                         curBuffer = RCL_MultiBuffer_getBuffer(ble5HandlerState.common.curBuffer,
4628                                                             wordLength * 4);
4629                         if (curBuffer != ble5HandlerState.common.curBuffer)
4630                         {
4631                             rclEvents.rxBufferFinished = 1;
4632                             ble5HandlerState.common.curBuffer = curBuffer;
4633                         }
4634                         if (curBuffer == NULL)
4635                         {
4636                             /* Error */
4637                             ble5HandlerState.common.endStatus = RCL_CommandStatus_Error_RxBufferCorruption;
4638                             /* Send abort */
4639                             HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_API) = PBE_BLE5_REGDEF_API_OP_STOP;
4640                             /* Do not check for more packets from the RX FIFO */
4641                             break;
4642                         }
4643                         else
4644                         {
4645                             uint32_t *data32;
4646                             data32 = (uint32_t *)RCL_MultiBuffer_getNextWritableByte(curBuffer);
4647                             LRF_readRxFifoWords(data32, wordLength);
4648                             RCL_Handler_BLE5_commitPacket(curBuffer, wordLength * 4);
4649                             /* Raise event */
4650                             rclEvents.rxEntryAvail = 1;
4651                             /* Adjust effective FIFO size */
4652                             RCL_Handler_BLE5_updateRxCurBufferAndFifo(&ctx->rxBuffers);
4653                             rclEventsIn.rxBufferUpdate = 0;
4654                         }
4655                     }
4656                     else
4657                     {
4658                         LRF_discardRxFifoWords(wordLength);
4659                     }
4660                 }
4661             }
4662             if (ble5HandlerState.common.activeUpdate)
4663             {
4664                 RCL_Handler_BLE5_updateGenericRxStats(rxCmd->stats, rclSchedulerState.actualStartTime);
4665             }
4666         }
4667         if (rclEventsIn.timerStart != 0)
4668         {
4669             Log_printf(RclCore, Log_VERBOSE, "Generic RX started");
4670             rclEvents.cmdStarted = 1;
4671         }
4672         if (lrfEvents.opDone != 0 || lrfEvents.opError != 0)
4673         {
4674             uint16_t endCause = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_COMMON_RAM_O_ENDCAUSE);
4675             /* Disable radio */
4676             RCL_CommandStatus endStatus = ble5HandlerState.common.endStatus;
4677             rclEvents.lastCmdDone = 1;
4678             if (lrfEvents.opError != 0 && endStatus == RCL_CommandStatus_Finished)
4679             {
4680                 endStatus = RCL_Handler_BLE5_findPbeErrorEndStatus(endCause);
4681             }
4682             else if (endCause == PBE_COMMON_RAM_ENDCAUSE_STAT_EOPSTOP)
4683             {
4684                 endStatus = RCL_Scheduler_findStopStatus(RCL_StopType_Graceful);
4685             }
4686             else
4687             {
4688                 /* No change of status */
4689             }
4690             cmd->status = endStatus;
4691         }
4692         else
4693         {
4694             /* Other events need to be handled unconditionally */
4695         }
4696 
4697         if (rclEvents.lastCmdDone != 0)
4698         {
4699             RCL_Handler_BLE5_updateGenericRxStats(rxCmd->stats, rclSchedulerState.actualStartTime);
4700         }
4701     }
4702 
4703     if (cmd->status == RCL_CommandStatus_Active)
4704     {
4705         if ( rclEventsIn.rxBufferUpdate != 0)
4706         {
4707             RCL_Handler_BLE5_updateRxCurBufferAndFifo(&ctx->rxBuffers);
4708             rclEventsIn.rxBufferUpdate = 0;
4709         }
4710     }
4711     if (rclEvents.lastCmdDone != 0)
4712     {
4713         if (ble5HandlerState.genericRx.restoreThresh)
4714         {
4715             HWREG_WRITE_LRF(LRFDMDM_BASE + LRFDMDM_O_DEMC1BE0) = ble5HandlerState.genericRx.demc1be0;
4716             HWREG_WRITE_LRF(LRFDMDM_BASE + LRFDMDM_O_DEMC1BE1) = ble5HandlerState.genericRx.demc1be1;
4717             HWREG_WRITE_LRF(LRFDMDM_BASE + LRFDMDM_O_DEMC1BE2) = ble5HandlerState.genericRx.demc1be2;
4718 #ifdef DeviceFamily_CC27XX
4719             HWREG_WRITE_LRF(LRFDMDM_BASE + LRFDMDM_O_DEMC1BE12) = ble5HandlerState.genericRx.demc1be12;
4720 #endif
4721         }
4722 
4723         LRF_disable();
4724         LRF_disableSynthRefsys();
4725     }
4726     return rclEvents;
4727 }
4728 
4729 /*
4730  *  ======== RCL_Handler_BLE5_genericTx ========
4731  */
RCL_Handler_BLE5_genericTx(RCL_Command * cmd,LRF_Events lrfEvents,RCL_Events rclEventsIn)4732 RCL_Events RCL_Handler_BLE5_genericTx(RCL_Command *cmd, LRF_Events lrfEvents, RCL_Events rclEventsIn)
4733 {
4734     uint32_t rfFreq;
4735     RCL_CmdBle5GenericTx *txCmd = (RCL_CmdBle5GenericTx *) cmd;
4736     RCL_Events rclEvents = {.value = 0};
4737 
4738     if (rclEventsIn.setup != 0)
4739     {
4740         uint32_t earliestStartTime;
4741         RCL_Ble5Channel channel;
4742 
4743         /* Start by enabling refsys */
4744         earliestStartTime = LRF_enableSynthRefsys();
4745 
4746         RCL_CtxGenericTx *ctx = txCmd->ctx;
4747         uint32_t crcInit = ctx->crcInit;
4748         uint32_t accessAddress = ctx->accessAddress;
4749 
4750         HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_MDMSYNCA) = accessAddress;
4751         /* 32-bit access to also write CRCINITH */
4752         HWREG_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_CRCINITL) = crcInit << 8;
4753 
4754         /* Default end status */
4755         ble5HandlerState.common.endStatus = RCL_CommandStatus_Finished;
4756 
4757         channel = txCmd->channel;
4758 
4759         RCL_CommandStatus status = RCL_Handler_BLE5_setPhy(cmd->phyFeatures);
4760         rfFreq = RCL_Handler_BLE5_findRfFreq(channel);
4761         if (rfFreq == 0)
4762         {
4763             status = RCL_CommandStatus_Error_Param;
4764         }
4765         else if (LRF_programTxPower(txCmd->txPower) != TxPowerResult_Ok)
4766         {
4767             status = RCL_CommandStatus_Error_Param;
4768         }
4769 
4770         if (status == RCL_CommandStatus_Active)
4771         {
4772             /* Program frequency word */
4773             LRF_programFrequency(rfFreq, false);
4774 
4775             /* Enable radio */
4776             LRF_enable();
4777 
4778             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_OPCFG) = PBE_BLE5_RAM_OPCFG_TXFCMD_DEALLOC;
4779             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NTXTARGET) = 0;
4780 
4781             /* Initialize RF FIFOs */
4782             ble5HandlerState.common.txFifoSz = LRF_prepareTxFifo();
4783 
4784             /* Enter payload */
4785             uint32_t nBuffer = RCL_Handler_BLE5_updateTxBuffers(&txCmd->ctx->txBuffers, 1, NULL, false);
4786             if (nBuffer == 0)
4787             {
4788                 status = RCL_CommandStatus_Error_MissingTxBuffer;
4789             }
4790             else
4791             {
4792                 RCL_CommandStatus startTimeStatus = RCL_Scheduler_setStartStopTimeEarliestStart(cmd, earliestStartTime);
4793                 if (startTimeStatus >= RCL_CommandStatus_Finished)
4794                 {
4795                     status = startTimeStatus;
4796                 }
4797                 else
4798                 {
4799                     LRF_enableHwInterrupt(LRF_EventOpDone.value | LRF_EventOpError.value);
4800                     uint16_t whitenInit = RCL_Handler_BLE5_findWhitenInit(channel);
4801                     HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_WHITEINIT) = whitenInit;
4802                     if (ble5HandlerState.common.accessAddressModification)
4803                     {
4804                         HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_MDMSYNCA) = accessAddress ^ (whitenInit << 24);
4805                     }
4806                     Log_printf(RclCore, Log_VERBOSE, "Starting generic TX");
4807                     LRF_waitForTopsmReady();
4808                     /* Post cmd */
4809                     HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_API) = PBE_BLE5_REGDEF_API_OP_TXRAW;
4810                 }
4811             }
4812         }
4813         /* Set status */
4814         cmd->status = status;
4815         if (status >= RCL_CommandStatus_Finished)
4816         {
4817             rclEvents.lastCmdDone = 1;
4818         }
4819     }
4820 
4821     if (cmd->status == RCL_CommandStatus_Active)
4822     {
4823         if (rclEventsIn.timerStart != 0)
4824         {
4825             rclEvents.cmdStarted = 1;
4826         }
4827         if (lrfEvents.opDone != 0 || lrfEvents.opError != 0)
4828         {
4829             Log_printf(RclCore, Log_VERBOSE, "TX raw done");
4830             RCL_CommandStatus endStatus = ble5HandlerState.common.endStatus;
4831             if (endStatus == RCL_CommandStatus_Finished && lrfEvents.opError != 0)
4832             {
4833                 cmd->status = RCL_Handler_BLE5_findPbeErrorEndStatus(HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_COMMON_RAM_O_ENDCAUSE));
4834             }
4835             else
4836             {
4837                 cmd->status = endStatus;
4838                 /* Pop transmitted packet */
4839                 RCL_Buffer_TxBuffer *txBuffer;
4840                 txBuffer = RCL_TxBuffer_get(&txCmd->ctx->txBuffers);
4841                 if (txBuffer != NULL)
4842                 {
4843                     txBuffer->state = RCL_BufferStateFinished;
4844                 }
4845             }
4846             rclEvents.lastCmdDone = 1;
4847         }
4848         else
4849         {
4850             /* Other events need to be handled unconditionally */
4851         }
4852     }
4853     if (rclEvents.lastCmdDone != 0)
4854     {
4855         LRF_disable();
4856         LRF_disableSynthRefsys();
4857     }
4858     return rclEvents;
4859 }
4860 
4861 /*
4862  *  ======== RCL_Handler_Ble5_txTest ========
4863  */
RCL_Handler_Ble5_txTest(RCL_Command * cmd,LRF_Events lrfEvents,RCL_Events rclEventsIn)4864 RCL_Events RCL_Handler_Ble5_txTest(RCL_Command *cmd, LRF_Events lrfEvents, RCL_Events rclEventsIn)
4865 {
4866     RCL_CmdBle5TxTest *txCmd = (RCL_CmdBle5TxTest *) cmd;
4867     RCL_Events rclEvents = {.value = 0};
4868 
4869     if (rclEventsIn.setup != 0)
4870     {
4871         uint32_t earliestStartTime;
4872 
4873         /* Start by enabling refsys */
4874         earliestStartTime = LRF_enableSynthRefsys();
4875         ble5HandlerState.txTest.restoreSelector = RCL_HANDLER_BLE5_RESTORE_NONE;
4876         HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_OPCFG) = PBE_BLE5_RAM_OPCFG_TXPATTERN_M;
4877 
4878         /* Default end status */
4879         ble5HandlerState.common.endStatus = RCL_CommandStatus_Finished;
4880 
4881         RCL_Ble5Channel channel = txCmd->channel;
4882 
4883         RCL_CommandStatus status = RCL_Handler_BLE5_setPhy(cmd->phyFeatures);
4884         uint32_t rfFreq = RCL_Handler_BLE5_findRfFreq(channel);
4885         if (rfFreq == 0)
4886         {
4887             status = RCL_CommandStatus_Error_Param;
4888         }
4889         else if (LRF_programTxPower(txCmd->txPower) != TxPowerResult_Ok)
4890         {
4891             status = RCL_CommandStatus_Error_Param;
4892         }
4893 
4894         if (status == RCL_CommandStatus_Active)
4895         {
4896             /* Program frequency word */
4897             LRF_programFrequency(rfFreq, false);
4898 
4899             /* Enter configuration */
4900             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_PATTERN) = txCmd->txWord;
4901             if (txCmd->config.sendCw != 0)
4902             {
4903                 HWREG_WRITE_LRF(LRFDMDM_BASE + LRFDMDM_O_MODCTRL) = HWREG_READ_LRF(LRFDMDM_BASE + LRFDMDM_O_MODCTRL) | LRFDMDM_MODCTRL_TONEINSERT_M;
4904                 ble5HandlerState.txTest.restoreSelector = RCL_HANDLER_BLE5_RESTORE_MODCTRL;
4905             }
4906             else
4907             {
4908                 uint32_t whitenMode = txCmd->config.whitenMode;
4909                 /* Configure whitening */
4910                 /* Use pseudo-random sync word (not necessarily matching selected PRBS) */
4911                 HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_MDMSYNCA) = RCL_HANDLER_BLE5_PRBS_SYNC;
4912                 if (whitenMode == RCL_CMD_BLE5_WH_MODE_DEFAULT)
4913                 {
4914                     uint16_t whitenInit = RCL_Handler_BLE5_findWhitenInit(txCmd->channel);
4915                     HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_WHITEINIT) = whitenInit;
4916                     if (whitenInit == 0)
4917                     {
4918                         /* Use pattern as sync word */
4919                         HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_MDMSYNCA) = txCmd->txWord | (txCmd->txWord << 16);
4920                     }
4921                 }
4922                 else
4923                 {
4924                     ble5HandlerState.txTest.restoreSelector = RCL_HANDLER_BLE5_RESTORE_WHITEN_POLY;
4925                     ble5HandlerState.txTest.storedWhitenPoly = HWREG_READ_LRF(LRFDPBE32_BASE + LRFDPBE32_O_POLY0);
4926                     if (whitenMode == RCL_CMD_BLE5_WH_MODE_PRBS9)
4927                     {
4928                         HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_POLY0) = RCL_HANDLER_BLE5_PRBS9_POLY;
4929                         HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_WHITEINIT) = RCL_HANDLER_BLE5_PRBS9_INIT;
4930                     }
4931                     else if (whitenMode == RCL_CMD_BLE5_WH_MODE_PRBS15)
4932                     {
4933                         HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_POLY0) = RCL_HANDLER_BLE5_PRBS15_POLY;
4934                         HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_WHITEINIT) = RCL_HANDLER_BLE5_PRBS15_INIT;
4935                     }
4936                     else
4937                     {
4938                         HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_POLY0) = RCL_HANDLER_BLE5_PRBS32_POLY;
4939                         HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_WHITEINIT) = RCL_HANDLER_BLE5_PRBS32_INIT;
4940                     }
4941                 }
4942             }
4943 
4944             /* Enable radio */
4945             LRF_enable();
4946 
4947             RCL_CommandStatus startTimeStatus = RCL_Scheduler_setStartStopTimeEarliestStart(cmd, earliestStartTime);
4948             if (startTimeStatus >= RCL_CommandStatus_Finished)
4949             {
4950                 status = startTimeStatus;
4951             }
4952             else
4953             {
4954                 /* Enable interrupts */
4955                 LRF_enableHwInterrupt(LRF_EventOpDone.value | LRF_EventOpError.value);
4956 
4957                 /* Post cmd */
4958                 Log_printf(RclCore, Log_VERBOSE, "Starting BLE5 infinite TX");
4959 
4960                 LRF_waitForTopsmReady();
4961                 HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_API) = PBE_BLE5_REGDEF_API_OP_TXRAW;
4962             }
4963         }
4964         /* Set status */
4965         cmd->status = status;
4966         if (status >= RCL_CommandStatus_Finished)
4967         {
4968             rclEvents.lastCmdDone = 1;
4969         }
4970     }
4971 
4972     if (cmd->status == RCL_CommandStatus_Active)
4973     {
4974         if (rclEventsIn.timerStart != 0)
4975         {
4976             rclEvents.cmdStarted = 1;
4977         }
4978         if (lrfEvents.opDone != 0)
4979         {
4980             cmd->status = ble5HandlerState.common.endStatus;
4981             rclEvents.lastCmdDone = 1;
4982         }
4983         else if (lrfEvents.opError != 0)
4984         {
4985             RCL_CommandStatus endStatus = ble5HandlerState.common.endStatus;
4986             if (endStatus == RCL_CommandStatus_Finished)
4987             {
4988                 cmd->status = RCL_Handler_BLE5_findPbeErrorEndStatus(HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_COMMON_RAM_O_ENDCAUSE));
4989             }
4990             else
4991             {
4992                 cmd->status = endStatus;
4993             }
4994             rclEvents.lastCmdDone = 1;
4995         }
4996         else
4997         {
4998             /* Other events need to be handled unconditionally */
4999         }
5000     }
5001 
5002     if (rclEvents.lastCmdDone != 0)
5003     {
5004         if ((ble5HandlerState.txTest.restoreSelector & RCL_HANDLER_BLE5_RESTORE_MODCTRL) != 0)
5005         {
5006             HWREG_WRITE_LRF(LRFDMDM_BASE + LRFDMDM_O_MODCTRL) = HWREG_READ_LRF(LRFDMDM_BASE + LRFDMDM_O_MODCTRL) & (~LRFDMDM_MODCTRL_TONEINSERT_M);
5007         }
5008         if ((ble5HandlerState.txTest.restoreSelector & RCL_HANDLER_BLE5_RESTORE_WHITEN_POLY) != 0)
5009         {
5010             HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_POLY0) = ble5HandlerState.txTest.storedWhitenPoly;
5011         }
5012         LRF_disable();
5013         LRF_disableSynthRefsys();
5014     }
5015 
5016     return rclEvents;
5017 }
5018 
5019 /*
5020  *  ======== RCL_BLE5_updateFilterList ========
5021  */
RCL_BLE5_updateFilterList(const RCL_FL_Entry * newEntry,RCL_FilterList * filterList,uint32_t index)5022 RCL_BLE5_FilterListUpdateResult RCL_BLE5_updateFilterList(const RCL_FL_Entry *newEntry, RCL_FilterList *filterList, uint32_t index)
5023 {
5024     if (filterList == NULL)
5025     {
5026         return RCL_BLE5_FilterListUpdateIndexError;
5027     }
5028     else if (index >= filterList->numEntries || index >= PBE_NUM_FILTER_ENTRIES)
5029     {
5030         return RCL_BLE5_FilterListUpdateIndexError;
5031     }
5032     else
5033     {
5034         /* Run in protected region to avoid race conditions */
5035         uintptr_t key = HwiP_disable();
5036         /* Insert updated entry */
5037         filterList->entries[index] = *newEntry;
5038         /* Check if handler should be notified */
5039         if (ble5HandlerState.common.updatableFilterList == filterList)
5040         {
5041             /* Set index */
5042             ble5HandlerState.common.filterListUpdateIndex = index;
5043             /* Send event to running command */
5044             RCL_Scheduler_postEvent(rclSchedulerState.currCmd, RCL_EventHandlerCmdUpdate);
5045         }
5046         HwiP_restore(key);
5047 
5048         return RCL_BLE5_FilterListUpdateOk;
5049     }
5050 }
5051 
5052 /*
5053  *  ======== RCL_BLE5_setDefaultRfFrequency ========
5054  */
RCL_BLE5_setDefaultRfFrequency(uint32_t rfFrequency)5055 void RCL_BLE5_setDefaultRfFrequency(uint32_t rfFrequency)
5056 {
5057     ble5HandlerState.common.defaultRfFrequency = rfFrequency;
5058 }
5059 
5060 /*
5061  *  ======== RCL_BLE5_getRxStatus ========
5062  */
RCL_BLE5_getRxStatus(const RCL_Buffer_DataEntry * rxEntry)5063 RCL_Ble5_RxPktStatus RCL_BLE5_getRxStatus(const RCL_Buffer_DataEntry *rxEntry)
5064 {
5065     uint16_t fifoCfg = ble5HandlerState.common.fifoCfg;
5066 
5067     if ((fifoCfg & PBE_BLE5_RAM_FIFOCFG_APPENDSTATUS_M) != 0)
5068     {
5069         /* Find number of bytes in status and the appended bytes after that */
5070         uint32_t positionFromEnd = RCL_Handler_BLE5_findNumExtraBytes(fifoCfg &
5071                                                                      (PBE_BLE5_RAM_FIFOCFG_APPENDSTATUS_M |
5072                                                                      PBE_BLE5_RAM_FIFOCFG_APPENDLQI_M |
5073                                                                      PBE_BLE5_RAM_FIFOCFG_APPENDFREQEST_M |
5074                                                                      PBE_BLE5_RAM_FIFOCFG_APPENDRSSI_M |
5075                                                                      PBE_BLE5_RAM_FIFOCFG_APPENDTIMESTAMP_M));
5076         int32_t offset = rxEntry->length - sizeof(rxEntry->numPad) - sizeof(rxEntry->pad0) - positionFromEnd;
5077 
5078         if (offset < 0)
5079         {
5080             return  (RCL_Ble5_RxPktStatus) {.value = RCL_BLE5_RX_PKT_STATUS_INVALID};
5081         }
5082         else
5083         {
5084             const RCL_Ble5_RxPktStatus *statusPtr = (const RCL_Ble5_RxPktStatus *) (rxEntry->data + offset);
5085 
5086             return *statusPtr;
5087         }
5088     }
5089     else
5090     {
5091         return (RCL_Ble5_RxPktStatus) {.value = RCL_BLE5_RX_PKT_STATUS_INVALID};
5092     }
5093 }
5094 
5095 /*
5096  *  ======== RCL_BLE5_getRxRssi ========
5097  */
RCL_BLE5_getRxRssi(const RCL_Buffer_DataEntry * rxEntry)5098 int8_t RCL_BLE5_getRxRssi(const RCL_Buffer_DataEntry *rxEntry)
5099 {
5100     uint16_t fifoCfg = ble5HandlerState.common.fifoCfg;
5101 
5102     if ((fifoCfg & PBE_BLE5_RAM_FIFOCFG_APPENDRSSI_M) != 0)
5103     {
5104         /* Find number of bytes in RSSI and the appended bytes after that */
5105         uint32_t positionFromEnd = RCL_Handler_BLE5_findNumExtraBytes(fifoCfg &
5106                                                                      (PBE_BLE5_RAM_FIFOCFG_APPENDRSSI_M |
5107                                                                      PBE_BLE5_RAM_FIFOCFG_APPENDTIMESTAMP_M));
5108         int32_t offset = rxEntry->length - sizeof(rxEntry->numPad) - sizeof(rxEntry->pad0) - positionFromEnd;
5109 
5110         if (offset < 0)
5111         {
5112             return LRF_RSSI_INVALID;
5113         }
5114         else
5115         {
5116             const int8_t *rssiPtr = (const int8_t *) (rxEntry->data + offset);
5117 
5118             return *rssiPtr;
5119         }
5120     }
5121     else
5122     {
5123         return LRF_RSSI_INVALID;
5124     }
5125 }
5126 
5127 /*
5128  *  ======== RCL_BLE5_getRxTimestamp ========
5129  */
RCL_BLE5_getRxTimestamp(const RCL_Buffer_DataEntry * rxEntry)5130 uint32_t RCL_BLE5_getRxTimestamp(const RCL_Buffer_DataEntry *rxEntry)
5131 {
5132     uint16_t fifoCfg = ble5HandlerState.common.fifoCfg;
5133 
5134     if ((fifoCfg & PBE_BLE5_RAM_FIFOCFG_APPENDTIMESTAMP_M) != 0)
5135     {
5136         uint32_t timestamp;
5137         /* If status not appended; assume 1 Mbps */
5138         uint32_t timestampAdjust = TIMESTAMP_ADJUST_1MBPS;
5139         int32_t offset = (rxEntry->length - sizeof(rxEntry->numPad) - sizeof(rxEntry->pad0) - sizeof(timestamp));
5140         if (offset < 0)
5141         {
5142             return 0;
5143         }
5144         else
5145         {
5146             const uint8_t *dataPtr = rxEntry->data + offset;
5147             timestamp = dataPtr[0] | (dataPtr[1] << 8) | (dataPtr[2] << 16) | (dataPtr[3] << 24);
5148             if (fifoCfg & PBE_BLE5_RAM_FIFOCFG_APPENDSTATUS_M)
5149             {
5150                 /* Find number of bytes in status and the appended bytes between status and timesptamp */
5151                 uint32_t positionFromTimestamp = RCL_Handler_BLE5_findNumExtraBytes(fifoCfg &
5152                                                                                    (PBE_BLE5_RAM_FIFOCFG_APPENDSTATUS_M |
5153                                                                                    PBE_BLE5_RAM_FIFOCFG_APPENDLQI_M |
5154                                                                                    PBE_BLE5_RAM_FIFOCFG_APPENDFREQEST_M |
5155                                                                                    PBE_BLE5_RAM_FIFOCFG_APPENDRSSI_M));
5156                 offset -= positionFromTimestamp;
5157                 if (offset < 0)
5158                 {
5159                     return 0;
5160                 }
5161                 else
5162                 {
5163                     const RCL_Ble5_RxPktStatus *statusPtr = (const RCL_Ble5_RxPktStatus *) (rxEntry->data + offset);
5164                     switch (statusPtr->phy)
5165                     {
5166                         case RCL_Ble5_RxPhy1Mbps:
5167                         default:
5168                             timestampAdjust = TIMESTAMP_ADJUST_1MBPS;
5169                             break;
5170                         case RCL_Ble5_RxPhy2Mbps:
5171                             timestampAdjust = TIMESTAMP_ADJUST_2MBPS;
5172                             break;
5173                         case RCL_Ble5_RxPhyCodedS8:
5174                         case RCL_Ble5_RxPhyCodedS2:
5175                             timestampAdjust = TIMESTAMP_ADJUST_CODED;
5176                             break;
5177                     }
5178                 }
5179             }
5180         }
5181         return timestamp - timestampAdjust;
5182     }
5183     else
5184     {
5185         return 0;
5186     }
5187 }
5188 
5189 /*
5190  *  ======== RCL_BLE5_getAuxAdvStartTimeDelta ========
5191  */
RCL_BLE5_getAuxAdvStartTimeDelta(uint16_t phyFeatures,uint8_t chMap,uint8_t advPayloadLen)5192 uint32_t RCL_BLE5_getAuxAdvStartTimeDelta(uint16_t phyFeatures, uint8_t chMap, uint8_t advPayloadLen)
5193 {
5194     uint8_t numPrimaryChPackets = (chMap & 1) + ((chMap >> 1) & 1) + ((chMap >> 2) & 1);
5195     uint32_t advPayloadLenInOffsetUnits = BLE_convertSystimUnitsToOffsetUnits(RCL_Handler_BLE5_findPacketDuration(advPayloadLen, phyFeatures), BLE_AUX_OFFSET_30_US);
5196 
5197     return (RCL_SCHEDULER_SYSTIM_US((advPayloadLenInOffsetUnits * BLE_AUX_OFFSET_30_US) + EXT_ADV_INTERVAL_US) * numPrimaryChPackets);
5198 }
5199 
5200 /*
5201  *  ======== RCL_BLE5_setAccessAddressModification ========
5202  */
5203 /* This function should be secret, so no prototype is given in the .h file */
RCL_BLE5_setAccessAddressModification(bool enable)5204 void RCL_BLE5_setAccessAddressModification(bool enable)
5205 {
5206     ble5HandlerState.common.accessAddressModification = enable;
5207 }
5208 
5209 /*
5210  *  ======== RCL_Handler_BLE5_random ========
5211  */
RCL_Handler_BLE5_getRandomNumber(void)5212 __attribute__((weak)) uint32_t RCL_Handler_BLE5_getRandomNumber(void)
5213 {
5214     return Random_getNumber();
5215 }
5216 
5217 /*
5218  *  ======== RCL_Handler_BLE5_updateRxCurBufferAndFifo ========
5219  */
RCL_Handler_BLE5_updateRxCurBufferAndFifo(List_List * rxBuffers)5220 static void RCL_Handler_BLE5_updateRxCurBufferAndFifo(List_List *rxBuffers)
5221 {
5222     RCL_MultiBuffer *curBuffer = ble5HandlerState.common.curBuffer;
5223 
5224     if (curBuffer == NULL)
5225     {
5226         curBuffer = RCL_MultiBuffer_findFirstWritableBuffer((RCL_MultiBuffer *)rxBuffers->head);
5227     }
5228     ble5HandlerState.common.curBuffer = curBuffer;
5229 
5230     uint32_t rxSpace =
5231         RCL_MultiBuffer_findAvailableRxSpace(curBuffer);
5232 
5233     LRF_setRxFifoEffSz(rxSpace);
5234 }
5235 
5236 /*
5237  *  ======== RCL_Handler_BLE5_findWhitenInit ========
5238  */
RCL_Handler_BLE5_findWhitenInit(RCL_Ble5Channel channel)5239 static uint16_t RCL_Handler_BLE5_findWhitenInit(RCL_Ble5Channel channel)
5240 {
5241     uint16_t whitenInit;
5242 
5243     if ((channel & BLE_CUSTOM_FREQ_BM) == 0)
5244     {
5245         if (channel < BLE_PHY_CHAN_MIN)
5246         {
5247             /* Standard channel - set bit as BLE standard requires */
5248             whitenInit = channel | 0x40;
5249         }
5250         else
5251         {
5252             /* PHY channel - no whitening */
5253             whitenInit = 0;
5254         }
5255     }
5256     else
5257     {
5258         /* Custom channel - use remaining bits as whitening initialization */
5259         whitenInit = channel & ~BLE_CUSTOM_FREQ_BM;
5260     }
5261     return whitenInit;
5262 }
5263 
5264 /*
5265  *  ======== RCL_Handler_BLE5_findRfFreq ========
5266  */
RCL_Handler_BLE5_findRfFreq(RCL_Ble5Channel channel)5267 static uint32_t RCL_Handler_BLE5_findRfFreq(RCL_Ble5Channel channel)
5268 {
5269     uint32_t rfFreq;
5270 
5271     ble5HandlerState.common.channel = channel;
5272     if (channel <= BLE_DATA_CHAN_MAX)
5273     {
5274         /*  Data channel */
5275         rfFreq = channel * BLE_CHAN_SPACE + BLE_DATA_CHAN_BASE;
5276         if (rfFreq >= BLE_ADV_CHAN_MID_FREQ)
5277         {
5278             rfFreq += BLE_CHAN_SPACE;
5279         }
5280     }
5281     else if (channel == BLE_ADV_CHAN_LO)
5282     {
5283         rfFreq = BLE_ADV_CHAN_LO_FREQ;
5284     }
5285     else if (channel == BLE_ADV_CHAN_MID)
5286     {
5287         rfFreq = BLE_ADV_CHAN_MID_FREQ;
5288     }
5289     else if (channel == BLE_ADV_CHAN_HI)
5290     {
5291         rfFreq = BLE_ADV_CHAN_HI_FREQ;
5292     }
5293     else if (channel >= BLE_PHY_CHAN_MIN && channel <= BLE_PHY_CHAN_MAX)
5294     {
5295         rfFreq = BLE_ADV_CHAN_LO_FREQ + ((channel - BLE_PHY_CHAN_MIN) * BLE_CHAN_SPACE);
5296     }
5297     else if ((channel & BLE_CUSTOM_FREQ_BM) != 0)
5298     {
5299         rfFreq = ble5HandlerState.common.defaultRfFrequency;
5300     }
5301     else
5302     {
5303         /* error */
5304         rfFreq = 0;
5305     }
5306 
5307     return rfFreq;
5308 }
5309 
5310 /*
5311  *  ======== RCL_Handler_BLE5_findAdvChannel ========
5312  */
RCL_Handler_BLE5_findAdvChannel(uint32_t advMap,uint32_t order)5313 static RCL_Ble5Channel RCL_Handler_BLE5_findAdvChannel(uint32_t advMap, uint32_t order)
5314 {
5315     RCL_Ble5Channel channel;
5316     if ((advMap & BLE_CUSTOM_FREQ_BM) != 0)
5317     {
5318         channel = advMap;
5319     }
5320     else
5321     {
5322         if (order >= 6)
5323         {
5324             /* Error, but handle */
5325             order = 0;
5326         }
5327         switch (advMap & 0x07)
5328         {
5329         case 1:
5330             channel = 37;
5331             break;
5332 
5333         case 2:
5334             channel = 38;
5335             break;
5336 
5337         case 3:
5338             channel = ((order & 1) == 0) ? 37 : 38;
5339             break;
5340 
5341         case 4:
5342             channel = 39;
5343             break;
5344 
5345         case 5:
5346             channel = ((order & 1) == 0) ? 37 : 39;
5347             break;
5348 
5349         case 6:
5350             channel = ((order & 1) == 0) ? 38 : 39;
5351             break;
5352 
5353         case 7:
5354             channel = (order >> 1) + 37;
5355             break;
5356 
5357         default:
5358             channel = 37; /* Error, but handle */
5359             break;
5360         }
5361     }
5362 
5363     return channel;
5364 }
5365 
5366 /*
5367  *  ======== RCL_Handler_BLE5_setPhy ========
5368  */
RCL_Handler_BLE5_setPhy(uint16_t phyFeatures)5369 static RCL_CommandStatus RCL_Handler_BLE5_setPhy(uint16_t phyFeatures)
5370 {
5371     switch (phyFeatures & BLE_PHY_FEATURE_PHY_MASK)
5372     {
5373         case BLE_PHY_FEATURE_PHY_1MBPS:
5374             ble5HandlerState.common.timestampAdjust = TIMESTAMP_ADJUST_1MBPS;
5375             break;
5376 
5377         case BLE_PHY_FEATURE_PHY_2MBPS:
5378             ble5HandlerState.common.timestampAdjust = TIMESTAMP_ADJUST_2MBPS;
5379             break;
5380 
5381         case BLE_PHY_FEATURE_PHY_CODED:
5382             ble5HandlerState.common.timestampAdjust = TIMESTAMP_ADJUST_CODED;
5383             break;
5384 
5385         default:
5386             return RCL_CommandStatus_Error_Param;
5387     }
5388 
5389     ble5HandlerState.common.phyFeatures = phyFeatures;
5390 
5391     return RCL_CommandStatus_Active;
5392 }
5393 
5394 /*
5395  *  ======== RCL_Handler_BLE5_findPbeErrorEndStatus ========
5396  */
RCL_Handler_BLE5_findPbeErrorEndStatus(uint16_t pbeEndStatus)5397 static RCL_CommandStatus RCL_Handler_BLE5_findPbeErrorEndStatus(uint16_t pbeEndStatus)
5398 {
5399     RCL_CommandStatus status;
5400     switch (pbeEndStatus)
5401     {
5402     case PBE_COMMON_RAM_ENDCAUSE_STAT_ERR_RXF:
5403         status = RCL_CommandStatus_Error_RxFifo;
5404         break;
5405     case PBE_COMMON_RAM_ENDCAUSE_STAT_ERR_TXF:
5406         status = RCL_CommandStatus_Error_TxFifo;
5407         break;
5408     case PBE_COMMON_RAM_ENDCAUSE_STAT_ERR_SYNTH:
5409         Log_printf(RclCore, Log_ERROR, "Synth error. RFEMSGBOX = %04X", HWREG_READ_LRF(LRFDRFE_BASE + LRFDRFE_O_MSGBOX));
5410         status = RCL_CommandStatus_Error_Synth;
5411         break;
5412     case PBE_COMMON_RAM_ENDCAUSE_STAT_ERR_STOP:
5413         status = RCL_Scheduler_findStopStatus(RCL_StopType_Hard);
5414         break;
5415      case PBE_COMMON_RAM_ENDCAUSE_STAT_ERR_PAR:
5416         status = RCL_CommandStatus_Error_Param;
5417         break;
5418     case PBE_COMMON_RAM_ENDCAUSE_STAT_ERR_BADOP:
5419         status = RCL_CommandStatus_Error_UnknownOp;
5420         break;
5421     default:
5422         Log_printf(RclCore, Log_ERROR, "Unexpected error 0x%04X from PBE", pbeEndStatus);
5423         status = RCL_CommandStatus_Error;
5424         break;
5425     }
5426     return status;
5427 }
5428 
5429 /*
5430  *  ======== RCL_Handler_BLE5_updateTxBuffers ========
5431  */
RCL_Handler_BLE5_updateTxBuffers(List_List * txBuffers,uint32_t maxBuffers,RCL_TxBufferInfo * txBufferInfo,bool retransPossible)5432 static uint32_t RCL_Handler_BLE5_updateTxBuffers(List_List *txBuffers,
5433                                           uint32_t maxBuffers,
5434                                           RCL_TxBufferInfo *txBufferInfo,
5435                                           bool retransPossible)
5436 {
5437     uint32_t nWords = 0;
5438     uint32_t nBuffers = 0;
5439     RCL_Buffer_TxBuffer *nextTxBuffer;
5440     RCL_Buffer_TxBuffer *txBuffer = NULL;
5441     uint8_t *lastTxHdr = NULL;
5442     bool isConnBuffer = false;
5443 
5444     if (txBufferInfo != NULL)
5445     {
5446         txBuffer = txBufferInfo->lastEnteredTxBuffer;
5447         lastTxHdr = txBufferInfo->lastTxHdr;
5448         isConnBuffer = txBufferInfo->isConnBuffer;
5449     }
5450 
5451     if (txBuffer == NULL)
5452     {
5453         nextTxBuffer = RCL_TxBuffer_head(txBuffers);
5454     }
5455     else
5456     {
5457         nextTxBuffer = RCL_TxBuffer_next(txBuffer);
5458     }
5459 
5460     if (nextTxBuffer != NULL && lastTxHdr != NULL && isConnBuffer)
5461     {
5462         /* Set MD = 1 */
5463         HWREGB_WRITE_LRF(lastTxHdr) = HWREGB_READ_LRF(lastTxHdr) | 0x10;
5464         lastTxHdr = NULL;
5465     }
5466 
5467     while (nextTxBuffer != NULL && nBuffers < maxBuffers)
5468     {
5469 
5470         uint32_t length = nextTxBuffer->length;
5471         /* Number of words including length field and end padding */
5472         uint32_t wordLength = RCL_Buffer_DataEntry_paddedLen(length) / 4;
5473         if (wordLength > LRF_getTxFifoWritable() / 4)
5474         {
5475             /* Packet will not fit */
5476             break;
5477         }
5478         txBuffer = nextTxBuffer;
5479         txBuffer->state = RCL_BufferStateInUse;
5480 
5481         uint32_t *data32 = (uint32_t *) &(txBuffer->length);
5482 
5483         if (txBufferInfo != NULL && isConnBuffer)
5484         {
5485             lastTxHdr = LRF_getTxFifoWrAddr(txBuffer->numPad + 3);
5486         }
5487         /* TODO: See RCL-347 */
5488         /* Copy packet into FIFO */
5489         LRF_writeTxFifoWords(data32, wordLength);
5490         nextTxBuffer = RCL_TxBuffer_next(txBuffer);
5491         if (nextTxBuffer != NULL && lastTxHdr != NULL && isConnBuffer)
5492         {
5493             /* Set MD = 1 */
5494             HWREGB_WRITE_LRF(lastTxHdr) = HWREGB_READ_LRF(lastTxHdr) | 0x10;
5495             lastTxHdr = NULL;
5496         }
5497 
5498         nBuffers++;
5499         nWords += wordLength;
5500         /* If the first packet is a possible retransmission, move the read pointer behind it */
5501         if (retransPossible)
5502         {
5503             LRF_skipTxFifoWords(wordLength);
5504             retransPossible = false;
5505         }
5506     }
5507 
5508     if (txBufferInfo != NULL)
5509     {
5510         txBufferInfo->lastEnteredTxBuffer = txBuffer;
5511         txBufferInfo->lastTxHdr = lastTxHdr;
5512         txBufferInfo->numBytes += nWords * 4;
5513         txBufferInfo->numBuffers += nBuffers;
5514     }
5515 
5516     return nBuffers;
5517 }
5518 
5519 /*
5520  *  ======== RCL_Handler_BLE5_commitPacket ========
5521  */
RCL_Handler_BLE5_commitPacket(RCL_MultiBuffer * curBuffer,uint32_t numBytes)5522 static void RCL_Handler_BLE5_commitPacket(RCL_MultiBuffer *curBuffer, uint32_t numBytes)
5523 {
5524     /* Write channel into receive buffer entry - pad0 field is always part of the padding in BLE */
5525     RCL_Buffer_DataEntry *entry = (RCL_Buffer_DataEntry *) RCL_MultiBuffer_getNextWritableByte(curBuffer);
5526     entry->pad0 = ble5HandlerState.common.channel;
5527 
5528     /* Commit packet */
5529     RCL_MultiBuffer_commitBytes(curBuffer, numBytes);
5530 }
5531 
5532 
5533 /*
5534  *  ======== RCL_Handler_BLE5_maskEventsByFifoConf ========
5535  */
RCL_Handler_BLE5_maskEventsByFifoConf(uint32_t mask,uint16_t fifoConfVal,bool activeUpdate)5536 static uint32_t RCL_Handler_BLE5_maskEventsByFifoConf(uint32_t mask, uint16_t fifoConfVal, bool activeUpdate)
5537 {
5538     /* Remove events that will not give an entry in the RX FIFO, based on FIFOCFG, unless active update is used */
5539     if (!activeUpdate)
5540     {
5541         mask &= ~(((fifoConfVal & PBE_BLE5_RAM_FIFOCFG_AUTOFLUSHIGN_M) ? LRF_EventRxIgnored.value : 0) |
5542             ((fifoConfVal & PBE_BLE5_RAM_FIFOCFG_AUTOFLUSHCRC_M) ? LRF_EventRxNok.value : 0) |
5543             ((fifoConfVal & PBE_BLE5_RAM_FIFOCFG_AUTOFLUSHEMPTY_M) ? LRF_EventRxEmpty.value : 0) |
5544             LRF_EventRxBufFull.value);
5545     }
5546 
5547     return mask;
5548 }
5549 
5550 /*
5551  *  ======== RCL_Handler_BLE5_updateAdvScanInitStats ========
5552  */
RCL_Handler_BLE5_updateAdvScanInitStats(RCL_StatsAdvScanInit * stats,uint32_t startTime)5553 static void RCL_Handler_BLE5_updateAdvScanInitStats(RCL_StatsAdvScanInit *stats, uint32_t startTime)
5554 {
5555     if (stats != NULL)
5556     {
5557         /* 32-bit access to also read LASTTIMESTAMPH */
5558         uint32_t lastTimestamp = HWREG_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_LASTTIMESTAMPL);
5559         /* Check if a new value is found in the first timestamp */
5560         if (lastTimestamp == startTime)
5561         {
5562             stats->timestampValid = false;
5563         }
5564         else
5565         {
5566             stats->timestampValid = true;
5567             stats->lastTimestamp = lastTimestamp - ble5HandlerState.common.timestampAdjust;
5568         }
5569         stats->lastRssi = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_LASTRSSI);
5570         stats->nRxNok = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NRXNOK);
5571         stats->nRxIgnored = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NRXIGNORED);
5572         stats->nRxFifoFull = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NRXFIFOFULL);
5573         stats->nRxOk = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NRXOK);
5574         stats->nTx = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NTX);
5575     }
5576 }
5577 
5578 /*
5579  *  ======== RCL_Handler_BLE5_initAdvScanInitStats ========
5580  */
RCL_Handler_BLE5_initAdvScanInitStats(RCL_StatsAdvScanInit * stats,uint32_t startTime)5581 static bool RCL_Handler_BLE5_initAdvScanInitStats(RCL_StatsAdvScanInit *stats, uint32_t startTime)
5582 {
5583     if (stats != NULL)
5584     {
5585         /* Set timestamp to start time of command (will not occur again) to know if a valid value has been found */
5586         /* 32-bit access to also write LASTTIMESTAMPH */
5587         HWREG_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_LASTTIMESTAMPL) = startTime;
5588 
5589         stats->timestampValid = false;
5590         stats->lastRssi = LRF_RSSI_INVALID;
5591         if (stats->config.accumulate != 0)
5592         {
5593             /* Copy existing values into PBE */
5594             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NRXNOK) = stats->nRxNok;
5595             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NRXIGNORED) = stats->nRxIgnored;
5596             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NRXFIFOFULL) = stats->nRxFifoFull;
5597             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NRXOK) = stats->nRxOk;
5598             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NTX) = stats->nTx;
5599         }
5600         else
5601         {
5602             /* Reset existing values in PBE */
5603             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NRXNOK) = 0;
5604             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NRXIGNORED) = 0;
5605             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NRXFIFOFULL) = 0;
5606             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NRXOK) = 0;
5607             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NTX) = 0;
5608 
5609             stats->nRxNok = 0;
5610             stats->nRxIgnored = 0;
5611             stats->nRxFifoFull = 0;
5612             stats->nRxOk = 0;
5613             stats->nTx = 0;
5614         }
5615         return stats->config.activeUpdate;
5616     }
5617     else
5618     {
5619         return false;
5620     }
5621 }
5622 
5623 /*
5624  *  ======== RCL_Handler_BLE5_initConnStats ========
5625  */
RCL_Handler_BLE5_initConnStats(RCL_StatsConnection * stats,uint32_t startTime)5626 static bool RCL_Handler_BLE5_initConnStats(RCL_StatsConnection *stats, uint32_t startTime)
5627 {
5628     if (stats != NULL)
5629     {
5630         /* Set timestamp to start time of command (will not occur again) to know if a valid value has been found */
5631         /* 32-bit access to also write FIRSTTIMESTAMPH */
5632         HWREG_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FIRSTTIMESTAMPL) = startTime;
5633 
5634         stats->anchorValid = false;
5635         stats->lastRssi = LRF_RSSI_INVALID;
5636         if (stats->config.accumulate != 0)
5637         {
5638             /* Copy existing values into PBE */
5639             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NTXDONE) = stats->nTxDone;
5640             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NTXACK) = stats->nTxAck;
5641             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NTXCTLACK) = stats->nTxCtlAck;
5642             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NTXCTL) = stats->nTxCtl;
5643             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NTXRETRANS) = stats->nTxRetrans;
5644             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NRXNOK) = stats->nRxNok;
5645             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NRXIGNORED) = stats->nRxIgnored;
5646             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NRXEMPTY) = stats->nRxEmpty;
5647             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NRXFIFOFULL) = stats->nRxFifoFull;
5648             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NRXOK) = stats->nRxOk;
5649             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NTX) = stats->nTx;
5650             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NRXCTL) = stats->nRxCtl;
5651             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NRXCTLACK) = stats->nRxCtlAck;
5652         }
5653         else
5654         {
5655             /* Reset existing values in PBE */
5656             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NTXDONE) = 0;
5657             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NTXACK) = 0;
5658             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NTXCTLACK) = 0;
5659             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NTXCTL) = 0;
5660             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NTXRETRANS) = 0;
5661             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NRXNOK) = 0;
5662             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NRXIGNORED) = 0;
5663             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NRXEMPTY) = 0;
5664             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NRXFIFOFULL) = 0;
5665             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NRXOK) = 0;
5666             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NTX) = 0;
5667             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NRXCTL) = 0;
5668             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NRXCTLACK) = 0;
5669 
5670             stats->nTxDone = 0;
5671             stats->nTxAck = 0;
5672             stats->nTxCtlAck = 0;
5673             stats->nTxCtl = 0;
5674             stats->nTxRetrans = 0;
5675             stats->nRxNok = 0;
5676             stats->nRxIgnored = 0;
5677             stats->nRxEmpty = 0;
5678             stats->nRxFifoFull = 0;
5679             stats->nRxOk = 0;
5680             stats->nTx = 0;
5681             stats->nRxCtl = 0;
5682             stats->nRxCtlAck = 0;
5683         }
5684         return stats->config.activeUpdate;
5685     }
5686     else
5687     {
5688         return false;
5689     }
5690 }
5691 
5692 /*
5693  *  ======== RCL_Handler_BLE5_updateConnStats ========
5694  */
RCL_Handler_BLE5_updateConnStats(RCL_StatsConnection * stats,uint32_t startTime)5695 static void RCL_Handler_BLE5_updateConnStats(RCL_StatsConnection *stats, uint32_t startTime)
5696 {
5697     if (stats != NULL)
5698     {
5699         /* 32-bit access to also read FIRSTTIMESTAMPH */
5700         uint32_t anchorPoint = HWREG_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FIRSTTIMESTAMPL);
5701 
5702         /* Check if a new value is found in the first timestamp */
5703         if (anchorPoint == startTime)
5704         {
5705             stats->anchorValid = false;
5706         }
5707         else
5708         {
5709             stats->anchorValid = true;
5710             stats->anchorPoint = anchorPoint - ble5HandlerState.common.timestampAdjust;
5711         }
5712         stats->lastRssi = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_LASTRSSI);
5713         stats->nTxDone = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NTXDONE);
5714         stats->nTxAck = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NTXACK);
5715         stats->nTxCtlAck = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NTXCTLACK);
5716         stats->nTxCtl = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NTXCTL);
5717         stats->nTxRetrans = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NTXRETRANS);
5718         stats->nRxNok = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NRXNOK);
5719         stats->nRxIgnored = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NRXIGNORED);
5720         stats->nRxEmpty = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NRXEMPTY);
5721         stats->nRxFifoFull = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NRXFIFOFULL);
5722         stats->nRxOk = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NRXOK);
5723         stats->nTx = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NTX);
5724         stats->nRxCtl = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NRXCTL);
5725         stats->nRxCtlAck = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NRXCTLACK);
5726     }
5727 }
5728 
5729 /*
5730  *  ======== RCL_Handler_BLE5_initGenericRxStats ========
5731  */
RCL_Handler_BLE5_initGenericRxStats(RCL_StatsGenericRx * stats,uint32_t startTime)5732 static bool RCL_Handler_BLE5_initGenericRxStats(RCL_StatsGenericRx *stats, uint32_t startTime)
5733 {
5734     if (stats != NULL)
5735     {
5736         /* Set timestamp to start time of command (will not occur again) to know if a valid value has been found */
5737         /* 32-bit access to also write LASTIMESTAMPH */
5738         HWREG_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_LASTTIMESTAMPL) = startTime;
5739 
5740         stats->timestampValid = false;
5741         stats->lastRssi = LRF_RSSI_INVALID;
5742         if (stats->config.accumulate != 0)
5743         {
5744             /* Copy existing values into PBE */
5745             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NRXNOK) = stats->nRxNok;
5746             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NRXFIFOFULL) = stats->nRxFifoFull;
5747             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NRXOK) = stats->nRxOk;
5748         }
5749         else
5750         {
5751             /* Reset existing values in PBE */
5752             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NRXNOK) = 0;
5753             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NRXFIFOFULL) = 0;
5754             HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NRXOK) = 0;
5755 
5756             stats->nRxNok = 0;
5757             stats->nRxFifoFull = 0;
5758             stats->nRxOk = 0;
5759         }
5760         return stats->config.activeUpdate;
5761     }
5762     else
5763     {
5764         return false;
5765     }
5766 }
5767 
5768 /*
5769  *  ======== RCL_Handler_BLE5_updateGenericRxStats ========
5770  */
RCL_Handler_BLE5_updateGenericRxStats(RCL_StatsGenericRx * stats,uint32_t startTime)5771 static void RCL_Handler_BLE5_updateGenericRxStats(RCL_StatsGenericRx *stats, uint32_t startTime)
5772 {
5773     if (stats != NULL)
5774     {
5775         /* 32-bit access to also read LASTTIMESTAMPH */
5776         uint32_t lastTimestamp = HWREG_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_LASTTIMESTAMPL);
5777 
5778         /* Check if a new value is found in the first timestamp */
5779         if (lastTimestamp == startTime)
5780         {
5781             stats->timestampValid = false;
5782         }
5783         else
5784         {
5785             stats->timestampValid = true;
5786             stats->lastTimestamp = lastTimestamp - ble5HandlerState.common.timestampAdjust;
5787         }
5788         stats->lastRssi = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_LASTRSSI);
5789         stats->nRxNok = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NRXNOK);
5790         stats->nRxFifoFull = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NRXFIFOFULL);
5791         stats->nRxOk = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_NRXOK);
5792     }
5793 }
5794 
5795 /*
5796  *  ======== RCL_Handler_BLE5_InitializeFilterList ========
5797  */
RCL_Handler_BLE5_InitializeFilterList(RCL_FilterList * filterList,uint32_t * pbeFilterList,uint32_t invertMask)5798 static void RCL_Handler_BLE5_InitializeFilterList(RCL_FilterList *filterList, uint32_t *pbeFilterList, uint32_t invertMask)
5799 {
5800     uint32_t numEntries;
5801     uint32_t *targetPtr = pbeFilterList;
5802 
5803     if (filterList == NULL)
5804     {
5805         numEntries = 0;
5806     }
5807     else
5808     {
5809         uint32_t *sourcePtr;
5810 
5811         numEntries = filterList->numEntries;
5812         sourcePtr = (uint32_t *) filterList->entries;
5813         if (numEntries > PBE_NUM_FILTER_ENTRIES)
5814         {
5815             numEntries = PBE_NUM_FILTER_ENTRIES;
5816         }
5817 
5818         /* [RCL-515 WORKAROUND]: Protect the first memory write on BLE High PG1.x due to the hardware bugs */
5819 #ifdef DeviceFamily_CC27XX
5820         ASM_4_NOPS();
5821 #endif //DeviceFamily_CC27XX
5822 
5823         /* Set info of unused entries to be ignored */
5824         for (int i = 0; i < numEntries; i++)
5825         {
5826             uint32_t entry0 = *sourcePtr++;
5827             uint32_t entry1 = *sourcePtr++;
5828             entry0 ^= invertMask;
5829             *targetPtr++ = entry0;
5830             *targetPtr++ = entry1;
5831         }
5832     }
5833 
5834         /* [RCL-515 WORKAROUND]: Protect the first memory write on BLE High PG1.x due to the hardware bugs */
5835 #ifdef DeviceFamily_CC27XX
5836         ASM_4_NOPS();
5837 #endif //DeviceFamily_CC27XX
5838 
5839     /* Set info of unused entries to be ignored */
5840     for (int i = numEntries; i < PBE_NUM_FILTER_ENTRIES; i++)
5841     {
5842         *targetPtr = invertMask;
5843         targetPtr += 2;
5844     }
5845 }
5846 
5847 /*
5848  *  ======== RCL_Handler_BLE5_updateFilterListEntry ========
5849  */
RCL_Handler_BLE5_updateFilterListEntry(RCL_FilterList * filterList,uint32_t * pbeFilterList,uint32_t invertMask,uint32_t index)5850 static void RCL_Handler_BLE5_updateFilterListEntry(RCL_FilterList *filterList, uint32_t *pbeFilterList, uint32_t invertMask, uint32_t index)
5851 {
5852     if (filterList != NULL)
5853     {
5854         uint32_t *sourcePtr;
5855         sourcePtr = (uint32_t *) &filterList->entries[index];
5856         volatile uint32_t *targetPtr = pbeFilterList + 2 * index;
5857 
5858         /* [RCL-515 WORKAROUND]: Protect the first memory write on BLE High PG1.x due to the hardware bugs */
5859 #ifdef DeviceFamily_CC27XX
5860         ASM_4_NOPS();
5861 #endif //DeviceFamily_CC27XX
5862 
5863         /* Disable given entry and remove any match if set up */
5864         targetPtr[0] = invertMask;
5865         /* TOPsm uses read-modify-write on this entry. Write several times to ensure it is not overwritten */
5866         targetPtr[0] = invertMask;
5867         targetPtr[0] = invertMask;
5868         targetPtr[0] = invertMask;
5869         targetPtr[0] = invertMask;
5870 
5871         /* Read updated entry */
5872         uint32_t entry0 = sourcePtr[0];
5873         uint32_t entry1 = sourcePtr[1];
5874         /* Apply invert mask */
5875         entry0 ^= invertMask;
5876 
5877         uint32_t flstat = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FLSTAT);
5878         /* Check if matching algorithm is running */
5879         if (flstat == 0)
5880         {
5881             /* If not, set match bit */
5882             entry0 |= PBE_BLE5_RAM_FL1MASK_MATCH_M;
5883         }
5884 
5885         /* Write back, making sure to write info last */
5886         targetPtr[1] = entry1;
5887         targetPtr[0] = entry0;
5888         /* TOPsm uses read-modify-write on this entry. Write several times to ensure it is not overwritten */
5889         targetPtr[0] = entry0;
5890         targetPtr[0] = entry0;
5891         targetPtr[0] = entry0;
5892         targetPtr[0] = entry0;
5893 
5894         /* Check if matching algorithm has started during this operation */
5895         if (flstat == 0 && HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_FLSTAT) != 0)
5896         {
5897             /* If so, clear match bit */
5898             entry0 &= ~PBE_BLE5_RAM_FL1MASK_MATCH_M;
5899             /* Update entry so no match is found by error */
5900             targetPtr[0] = entry0;
5901             /* TOPsm uses read-modify-write on this entry. Write several times to ensure it is not overwritten */
5902             targetPtr[0] = entry0;
5903             targetPtr[0] = entry0;
5904             targetPtr[0] = entry0;
5905             targetPtr[0] = entry0;
5906         }
5907     }
5908 }
5909 
5910 /*
5911  *  ======== RCL_Handler_BLE5_prepareConnectTime ========
5912  */
RCL_Handler_BLE5_prepareConnectTime(uint32_t * connectTime,uint32_t referenceTime,uint32_t interval)5913 static uint32_t RCL_Handler_BLE5_prepareConnectTime(uint32_t *connectTime, uint32_t referenceTime, uint32_t interval)
5914 {
5915     uint32_t initialConnectTime = *connectTime;
5916     uint32_t newConnectTime;
5917 
5918     /* Always allow 2 sub-periods extra to ensure that subIntervalStart is in the range [2, (2 * interval)] */
5919     newConnectTime = RCL_Handler_BLE5_findConnectTime(initialConnectTime, referenceTime + BLE_CONNECT_INT_UNIT, interval);
5920     *connectTime = newConnectTime;
5921 
5922     uint32_t subIntervalStart = ((newConnectTime - referenceTime) / RCL_BLE5_CONNECT_SUB_INT);
5923     Log_printf(RclCore, Log_DEBUG, "subIntervalStart = %d", subIntervalStart);
5924     return subIntervalStart;
5925 }
5926 
5927 /*
5928  *  ======== RCL_Handler_BLE5_findConnectTime ========
5929  */
RCL_Handler_BLE5_findConnectTime(uint32_t initialConnectTime,uint32_t referenceTime,uint32_t interval)5930 static uint32_t RCL_Handler_BLE5_findConnectTime(uint32_t initialConnectTime, uint32_t referenceTime, uint32_t interval)
5931 {
5932     uint32_t connectTime;
5933     uint32_t timeDiff = initialConnectTime - referenceTime;
5934     if (timeDiff < 0x80000000)
5935     {
5936         /* initialConnectTime >= referenceTime */
5937         uint32_t intervalAdjust = timeDiff / (interval * BLE_CONNECT_INT_UNIT);
5938         connectTime = initialConnectTime - intervalAdjust * (interval * BLE_CONNECT_INT_UNIT);
5939     }
5940     else
5941     {
5942         /* Result was negative; turn it around */
5943         timeDiff = referenceTime - initialConnectTime;
5944         uint32_t intervalAdjust = (timeDiff + (interval * BLE_CONNECT_INT_UNIT) - 1) / (interval * BLE_CONNECT_INT_UNIT);
5945         connectTime = initialConnectTime + intervalAdjust * (interval * BLE_CONNECT_INT_UNIT);
5946     }
5947     Log_printf(RclCore, Log_DEBUG, "referenceTime = 0x%08X, connectTime = 0x%08X", referenceTime, connectTime);
5948 
5949     return connectTime;
5950 }
5951 
5952 /*
5953  *  ======== RCL_Handler_BLE5_findPacketDuration ========
5954  */
RCL_Handler_BLE5_findPacketDuration(uint32_t length,uint16_t phyFeatures)5955 static uint32_t RCL_Handler_BLE5_findPacketDuration(uint32_t length, uint16_t phyFeatures)
5956 {
5957     uint32_t duration;
5958     switch (phyFeatures & BLE_PHY_FEATURE_PHY_MASK)
5959     {
5960         case BLE_PHY_FEATURE_PHY_1MBPS:
5961         default:
5962             duration = BLE_1MBPS_PACKET_BASE_TIME + BLE_1MBPS_TIME_PER_BYTE * length;
5963             break;
5964 
5965         case BLE_PHY_FEATURE_PHY_2MBPS:
5966             duration = BLE_2MBPS_PACKET_BASE_TIME + BLE_2MBPS_TIME_PER_BYTE * length;
5967             break;
5968 
5969         case BLE_PHY_FEATURE_PHY_CODED:
5970             if ((phyFeatures & 0x0004) == BLE_PHY_FEATURE_CODING_S8)
5971             {
5972                 duration = BLE_CODED_S8_PACKET_BASE_TIME + BLE_CODED_S8_TIME_PER_BYTE * length;
5973             }
5974             else
5975             {
5976                 duration = BLE_CODED_S2_PACKET_BASE_TIME + BLE_CODED_S2_TIME_PER_BYTE * length;
5977             }
5978             break;
5979     }
5980     return duration;
5981 }
5982 
5983 /*
5984  *  ======== RCL_Handler_BLE5_findNumExtraBytes ========
5985  */
RCL_Handler_BLE5_findNumExtraBytes(uint32_t fifoCfg)5986 static uint32_t RCL_Handler_BLE5_findNumExtraBytes(uint32_t fifoCfg)
5987 {
5988     uint32_t numExtraBytes = 0;
5989     if (fifoCfg & PBE_BLE5_RAM_FIFOCFG_APPENDCRC_M)
5990     {
5991         numExtraBytes += BLE_CRC_LENGTH;
5992     }
5993     if (fifoCfg & PBE_BLE5_RAM_FIFOCFG_APPENDSTATUS_M)
5994     {
5995         numExtraBytes += 1;
5996     }
5997     if (fifoCfg & PBE_BLE5_RAM_FIFOCFG_APPENDLQI_M)
5998     {
5999         numExtraBytes += 1;
6000     }
6001     if (fifoCfg & PBE_BLE5_RAM_FIFOCFG_APPENDFREQEST_M)
6002     {
6003         numExtraBytes += 1;
6004     }
6005     if (fifoCfg & PBE_BLE5_RAM_FIFOCFG_APPENDRSSI_M)
6006     {
6007         numExtraBytes += 1;
6008     }
6009     if (fifoCfg & PBE_BLE5_RAM_FIFOCFG_APPENDTIMESTAMP_M)
6010     {
6011         numExtraBytes += sizeof(uint32_t);
6012     }
6013 
6014     return numExtraBytes;
6015 }
6016 
6017 /*
6018  *  ======== RCL_Handler_BLE5_findRxSyncOverhead ========
6019  */
RCL_Handler_BLE5_findRxSyncOverhead(uint16_t phyFeatures)6020 static uint16_t RCL_Handler_BLE5_findRxSyncOverhead(uint16_t phyFeatures)
6021 {
6022     uint16_t overhead;
6023     switch (phyFeatures & BLE_PHY_FEATURE_PHY_MASK)
6024     {
6025         case BLE_PHY_FEATURE_PHY_1MBPS:
6026         default:
6027             overhead = RX_SYNC_OVERHEAD_1MBPS;
6028             break;
6029 
6030         case BLE_PHY_FEATURE_PHY_2MBPS:
6031             overhead = RX_SYNC_OVERHEAD_2MBPS;
6032             break;
6033 
6034         case BLE_PHY_FEATURE_PHY_CODED:
6035             overhead = RX_SYNC_OVERHEAD_CODED;
6036             break;
6037     }
6038     return overhead;
6039 }
6040 
6041 /*
6042  *  ======== RCL_Handler_BLE5_updateBackoffParams ========
6043  */
RCL_Handler_BLE5_updateBackoffParams(RCL_CtxScanInit * ctx,uint16_t endCause)6044 static void RCL_Handler_BLE5_updateBackoffParams(RCL_CtxScanInit *ctx, uint16_t endCause)
6045 {
6046     if (endCause == PBE_COMMON_RAM_ENDCAUSE_STAT_ENDOK)
6047     {
6048         /* SCAN_RSP, AUX_SCAN_RSP, AUX_CONNECT_RSP received OK */
6049         ctx->backoffStatus.backOffLastFail = 0;
6050         if (ctx->backoffStatus.backOffLastSucceed != 0)
6051         {
6052             /* Decrement backoffUpper */
6053             if (ctx->backoffUpper > 0)
6054             {
6055                 ctx->backoffUpper--;
6056             }
6057             ctx->backoffStatus.backOffLastSucceed = 0;
6058         }
6059         else
6060         {
6061             ctx->backoffStatus.backOffLastSucceed = 1;
6062         }
6063     }
6064     else
6065     {
6066         /* SCAN_RSP, AUX_SCAN_RSP or AUX_CONNECT_RSP not received OK */
6067         ctx->backoffStatus.backOffLastSucceed = 0;
6068         if (ctx->backoffStatus.backOffLastFail != 0)
6069         {
6070             /* Increment backoffUpper */
6071             if (ctx->backoffUpper < BACKOFF_UPPER_MAX)
6072             {
6073                 ctx->backoffUpper++;
6074             }
6075             ctx->backoffStatus.backOffLastFail = 0;
6076         }
6077         else
6078         {
6079             ctx->backoffStatus.backOffLastFail = 1;
6080         }
6081     }
6082     /* Set new backoff count */
6083     /* Backoff definition in PBE is one less count than in Bluetooth spec */
6084     /* This gives value from 0 to (2^backoffUpper - 1) */
6085     HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_BLE5_RAM_O_BACKOFFCNT) = (RCL_Handler_BLE5_getRandomNumber() & ((1 << ctx->backoffUpper) - 1));
6086 }
6087 
6088 /*
6089  *  ======== RCL_Handler_BLE5_getAuxPtrFromTxBuffer ========
6090  */
RCL_Handler_BLE5_getAuxPtrFromTxBuffer(RCL_Buffer_TxBuffer * curBuffer,RCL_AuxPtrInfo * auxPtrInfo,uint8_t offset)6091 static void RCL_Handler_BLE5_getAuxPtrFromTxBuffer(RCL_Buffer_TxBuffer *curBuffer, RCL_AuxPtrInfo *auxPtrInfo, uint8_t offset)
6092 {
6093     uint8_t payloadIndex = curBuffer->numPad - 1 + BLE_HEADER_LENGTH;
6094     uint8_t pktLen = curBuffer->data[payloadIndex - 1];
6095     uint8_t extHdrFlags = curBuffer->data[payloadIndex + 1];
6096 
6097     uint8_t auxPtrIndex = RCL_Handler_BLE5_checkExtHdrField(extHdrFlags, BLE_EXTENDED_HEADER_AUXPTR_BM);
6098 
6099     if (auxPtrIndex != 0)
6100     {
6101         /*
6102          * Consider that the extended header takes 2 bytes, one for the extended header length
6103          * and one for the header flags.
6104          */
6105         auxPtrIndex += payloadIndex + 2;
6106 
6107         /* Determine Tx FIFO pointer to the auxOffset */
6108         auxPtrInfo->auxChCaOffsetUnitsFifoPtr = LRF_getTxFifoWrAddr(offset + payloadIndex + auxPtrIndex);
6109         auxPtrInfo->auxOffsetLowFifoPtr = LRF_getTxFifoWrAddr(offset + payloadIndex + auxPtrIndex + 1);
6110         auxPtrInfo->auxOffsetHighFifoPtr = LRF_getTxFifoWrAddr(offset + payloadIndex + auxPtrIndex + 2);
6111 
6112         /* Extract AuxPtr information from Tx Buffer */
6113         auxPtrInfo->pktLen = pktLen;
6114         auxPtrInfo->ptrIndex = auxPtrIndex;
6115         auxPtrInfo->chIndex = curBuffer->data[auxPtrIndex] & 0x3F;
6116         auxPtrInfo->ca = ((curBuffer->data[auxPtrIndex] & 0x40) >> 6);
6117         auxPtrInfo->offsetUnits = (curBuffer->data[auxPtrIndex] >> 7);
6118         auxPtrInfo->auxOffset = ((uint16_t)(curBuffer->data[auxPtrIndex + 2] & 0x1F) << 8) | (uint16_t)(curBuffer->data[auxPtrIndex + 1]);
6119         auxPtrInfo->auxPhy = curBuffer->data[auxPtrIndex + 2] >> 5;
6120         auxPtrInfo->auxPtrPresent = true;
6121     }
6122     else
6123     {
6124         auxPtrInfo->pktLen = pktLen;
6125         auxPtrInfo->ptrIndex = 0;
6126         auxPtrInfo->chIndex = 0;
6127         auxPtrInfo->offsetUnits = 0;
6128         auxPtrInfo->auxOffset = 0;
6129         auxPtrInfo->ca = 0;
6130         auxPtrInfo->auxPhy = 0;
6131         auxPtrInfo->auxChCaOffsetUnitsFifoPtr = NULL;
6132         auxPtrInfo->auxOffsetLowFifoPtr = NULL;
6133         auxPtrInfo->auxOffsetHighFifoPtr = NULL;
6134         auxPtrInfo->auxPtrPresent = false;
6135     }
6136 }
6137 
6138 /*
6139  *  ======== RCL_Handler_BLE5_checkExtHdrField ========
6140  */
RCL_Handler_BLE5_checkExtHdrField(uint8_t extHdrFlags,uint8_t fieldMask)6141 static uint8_t RCL_Handler_BLE5_checkExtHdrField(uint8_t extHdrFlags, uint8_t fieldMask)
6142 {
6143     uint8_t fieldIndex = 0;
6144 
6145     /* Check extended header flags to determine the index of the desired field (if present) */
6146     if (extHdrFlags & fieldMask)
6147     {
6148         if (extHdrFlags & BLE_EXTENDED_HEADER_ADVA_BM)
6149         {
6150             fieldIndex += BLE_EXTENDED_HEADER_ADVA_LEN;
6151         }
6152         if (extHdrFlags & BLE_EXTENDED_HEADER_TARGETA_BM)
6153         {
6154             fieldIndex += BLE_EXTENDED_HEADER_TARGETA_LEN;
6155         }
6156         if (extHdrFlags & BLE_EXTENDED_HEADER_CTEINFO_BM)
6157         {
6158             fieldIndex += BLE_EXTENDED_HEADER_CTEINFO_LEN;
6159         }
6160         if (extHdrFlags & BLE_EXTENDED_HEADER_ADI_BM)
6161         {
6162             fieldIndex += BLE_EXTENDED_HEADER_ADI_LEN;
6163         }
6164         if ((extHdrFlags & BLE_EXTENDED_HEADER_AUXPTR_BM) && (fieldMask == BLE_EXTENDED_HEADER_SYNCINFO_BM))
6165         {
6166             fieldIndex += BLE_EXTENDED_HEADER_AUXPTR_LEN;
6167         }
6168     }
6169 
6170     return fieldIndex;
6171 }
6172 
6173 /*
6174  *  ======== RCL_Handler_BLE5_readAuxPtrFromRxBuffer ========
6175  */
RCL_Handler_BLE5_readAuxPtrFromRxBuffer(uint32_t * data32,RCL_AuxPtrInfo * auxPtrInfo)6176 static void RCL_Handler_BLE5_readAuxPtrFromRxBuffer(uint32_t *data32, RCL_AuxPtrInfo *auxPtrInfo)
6177 {
6178     uint8_t *data8;
6179     data8 = (uint8_t*) data32;
6180     uint8_t payloadIndex = 6 + BLE_HEADER_LENGTH;
6181     uint8_t extHdrFlags = data8[payloadIndex + 1];
6182 
6183     /* Check advertising type */
6184     if (extHdrFlags & BLE_EXTENDED_HEADER_AUXPTR_BM)
6185     {
6186         /* Extract AuxPtr information */
6187         uint8_t auxPtrIndex = payloadIndex + 2;
6188 
6189         if (extHdrFlags & BLE_EXTENDED_HEADER_ADVA_BM)
6190         {
6191             auxPtrIndex += BLE_EXTENDED_HEADER_ADVA_LEN;
6192         }
6193         if (extHdrFlags & BLE_EXTENDED_HEADER_TARGETA_BM)
6194         {
6195             auxPtrIndex += BLE_EXTENDED_HEADER_TARGETA_LEN;
6196         }
6197         if (extHdrFlags & BLE_EXTENDED_HEADER_CTEINFO_BM)
6198         {
6199             auxPtrIndex += BLE_EXTENDED_HEADER_CTEINFO_LEN;
6200         }
6201         if (extHdrFlags & BLE_EXTENDED_HEADER_ADI_BM)
6202         {
6203             auxPtrIndex += BLE_EXTENDED_HEADER_ADI_LEN;
6204         }
6205 
6206         auxPtrInfo->auxOffset = ((uint16_t)(data8[auxPtrIndex + 2] & 0x1F) << 8) | (uint16_t)(data8[auxPtrIndex + 1]);
6207         auxPtrInfo->ca = ((data8[auxPtrIndex] & 0x40) >> 6);
6208         auxPtrInfo->offsetUnits = data8[auxPtrIndex] >> 7;
6209         auxPtrInfo->chIndex = data8[auxPtrIndex] & 0x3F;
6210         auxPtrInfo->auxPhy = data8[auxPtrIndex + 2] >> 5;
6211         auxPtrInfo->ptrIndex = auxPtrIndex;
6212         auxPtrInfo->pktLen = data8[payloadIndex - 1];
6213 
6214         auxPtrInfo->auxChCaOffsetUnitsFifoPtr = NULL;
6215         auxPtrInfo->auxOffsetHighFifoPtr = NULL;
6216         auxPtrInfo->auxOffsetLowFifoPtr = NULL;
6217         auxPtrInfo->auxPtrPresent = true;
6218     }
6219     else
6220     {
6221         auxPtrInfo->pktLen = 0;
6222         auxPtrInfo->ptrIndex = 0;
6223         auxPtrInfo->chIndex = 0;
6224         auxPtrInfo->offsetUnits = 0;
6225         auxPtrInfo->auxOffset = 0;
6226         auxPtrInfo->ca = 0;
6227         auxPtrInfo->auxPhy = 0;
6228         auxPtrInfo->auxChCaOffsetUnitsFifoPtr = NULL;
6229         auxPtrInfo->auxOffsetLowFifoPtr = NULL;
6230         auxPtrInfo->auxOffsetHighFifoPtr = NULL;
6231         auxPtrInfo->auxPtrPresent = false;
6232     }
6233 }
6234 
6235 /*
6236  *  ======== RCL_Handler_BLE5_updateAuxPtr ========
6237  */
RCL_Handler_BLE5_updateAuxPtr(RCL_AuxPtrInfo * auxPtr,uint32_t packetDuration,uint8_t chanMap,bool switchPhy)6238 static bool RCL_Handler_BLE5_updateAuxPtr(RCL_AuxPtrInfo *auxPtr, uint32_t packetDuration, uint8_t chanMap, bool switchPhy)
6239 {
6240     uint16_t auxOffsetUs;
6241     uint16_t auxOffset;
6242     uint8_t  auxChCaOffsetUnits;
6243     uint8_t  auxOffsetLow;
6244     uint8_t  auxOffsetHigh;
6245     bool status = true;
6246 
6247     uint8_t primaryChPacketsLeft = (chanMap & 1) + ((chanMap >> 1) & 1) + ((chanMap >> 2) & 1);
6248 
6249     /*
6250      * First calculate the packet duration in terms of 30 us offset units. Then round up to avoid being too late.
6251      * Note: Packet Duration is given in systim units [250 ns], so divide by 4 to get value in microseconds.
6252      */
6253     uint32_t pktDurationInOffsetUnits = BLE_convertSystimUnitsToOffsetUnits(packetDuration, BLE_AUX_OFFSET_30_US);
6254      /*
6255       * Automatic calculation of the AuxPtr.
6256       * All primary advertising channel packets must point to the same time. Since they have the same duration,
6257       * the packet duration can be used to calculate the auxPtr.
6258       */
6259     if ((auxPtr->offsetUnits == 1) && (auxPtr->auxOffset == 0))
6260     {
6261         if (primaryChPacketsLeft == 0)
6262         {
6263             auxOffsetUs = (pktDurationInOffsetUnits * BLE_AUX_OFFSET_30_US) + EXT_ADV_INTERVAL_US;
6264         }
6265         else
6266         {
6267             auxOffsetUs = primaryChPacketsLeft * ((pktDurationInOffsetUnits * BLE_AUX_OFFSET_30_US) + EXT_ADV_INTERVAL_US);
6268         }
6269 
6270         /* Consider the time that it takes to handle the PHY switching */
6271         if (switchPhy)
6272         {
6273             auxOffsetUs += EXT_ADV_PHY_SWITCHING_DELAY_US;
6274         }
6275 
6276         /* Calculate the auxOffset in 30 us offset units  */
6277         auxOffset = auxOffsetUs / BLE_AUX_OFFSET_30_US;
6278 
6279         /* Use 30 [us] offset units. Keep the rest of the AuxPtr information intact */
6280         auxChCaOffsetUnits = (auxPtr->chIndex | (auxPtr->ca << 6));
6281     }
6282     /*
6283      * If valid, use existing AuxPtr to send the first primary advertising channel packet, and derive the
6284      * correct value for the rest of the primary advertising channel packets.
6285      */
6286     else
6287     {
6288         uint32_t minReqOffsetUs;
6289         auxOffsetUs = auxPtr->offsetUnits ? (auxPtr->auxOffset * BLE_AUX_OFFSET_300_US) : (auxPtr->auxOffset * BLE_AUX_OFFSET_30_US);
6290 
6291         if (primaryChPacketsLeft == 0)
6292         {
6293             /* No need to recalculate auxOffset. All primary advertising channel packets sent or start from secondary channel. */
6294             minReqOffsetUs = (pktDurationInOffsetUnits * BLE_AUX_OFFSET_30_US) + EXT_ADV_INTERVAL_US;
6295 
6296             if (auxOffsetUs < minReqOffsetUs)
6297             {
6298                 /* Invalid initial auxOffset. Deadline can't be met. */
6299                 status = false;
6300             }
6301         }
6302         else
6303         {
6304             /* Derive correct auxOffset value based on the number of primary channel packets sent. */
6305             minReqOffsetUs = primaryChPacketsLeft * ((pktDurationInOffsetUnits * BLE_AUX_OFFSET_30_US) + EXT_ADV_INTERVAL_US);
6306 
6307             if (auxOffsetUs < minReqOffsetUs)
6308             {
6309                 /* Invalid initial auxOffset. Deadline can't be met. */
6310                 status = false;
6311             }
6312             else
6313             {
6314                 auxOffsetUs -= (auxPtr->numPrimaryChPackets - primaryChPacketsLeft) * ((pktDurationInOffsetUnits * BLE_AUX_OFFSET_30_US) + EXT_ADV_INTERVAL_US);
6315             }
6316         }
6317 
6318         /* Consider the time that it takes to handle the PHY switching */
6319         if (switchPhy)
6320         {
6321             auxOffsetUs += EXT_ADV_PHY_SWITCHING_DELAY_US;
6322         }
6323 
6324         /* Calculate the auxOffset in offset units (i.e. 30 us or 300 us) */
6325         auxOffset = auxPtr->offsetUnits ? (auxOffsetUs / BLE_AUX_OFFSET_300_US) : (auxOffsetUs / BLE_AUX_OFFSET_30_US);
6326 
6327         /* Keep the AuxPtr information intact */
6328         auxChCaOffsetUnits = (auxPtr->chIndex | (auxPtr->ca << 6) | (auxPtr->offsetUnits << 7));
6329     }
6330 
6331     auxOffsetLow = auxOffset & 0xFF;
6332     auxOffsetHigh = (auxOffset >> 8) & 0x1F;
6333     Log_printf(RclCore, Log_VERBOSE, "Start of next auxiliary packet in %d [us] or %d [offset units]", auxOffsetUs, auxOffset);
6334 
6335     /* Update Tx FIFO */
6336     *auxPtr->auxChCaOffsetUnitsFifoPtr = auxChCaOffsetUnits;
6337     *auxPtr->auxOffsetLowFifoPtr = auxOffsetLow;
6338     *auxPtr->auxOffsetHighFifoPtr = auxOffsetHigh | (auxPtr->auxPhy << 5);
6339 
6340     return status;
6341 }
6342