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