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 * ======== generic.c ========
34 */
35
36 #include <stdint.h>
37 #include <stdlib.h>
38
39 #include <ti/log/Log.h>
40
41 #include <ti/drivers/rcl/RCL_Command.h>
42 #include <ti/drivers/rcl/RCL_Buffer.h>
43 #include <ti/drivers/rcl/RCL_Scheduler.h>
44 #include <ti/drivers/rcl/RCL_Profiling.h>
45
46 #include <ti/drivers/rcl/hal/hal.h>
47 #include <ti/drivers/rcl/commands/generic.h>
48
49 #include <ti/devices/DeviceFamily.h>
50 #include DeviceFamily_constructPath(inc/hw_lrfdtxf.h)
51 #include DeviceFamily_constructPath(inc/hw_lrfdrxf.h)
52 #include DeviceFamily_constructPath(inc/hw_lrfddbell.h)
53 #include DeviceFamily_constructPath(inc/hw_lrfdpbe.h)
54 #include DeviceFamily_constructPath(inc/hw_lrfdpbe32.h)
55 #include DeviceFamily_constructPath(inc/hw_lrfdmdm.h)
56 #include DeviceFamily_constructPath(inc/hw_lrfdrfe.h)
57 #include DeviceFamily_constructPath(inc/pbe_generic_ram_regs.h)
58 #include DeviceFamily_constructPath(inc/pbe_common_ram_regs.h)
59 #include DeviceFamily_constructPath(inc/pbe_generic_regdef_regs.h)
60
61 /** Polynomial to use for PRBS15 data */
62 #define RCL_HANDLER_GENERIC_PRBS15_POLY 0x80020000
63 /** Polynomial to use for PRBS32 data */
64 #define RCL_HANDLER_GENERIC_PRBS32_POLY 0x00400007
65 #define RCL_HANDLER_GENERIC_PRBS_INIT 0x00005555
66 #define RCL_HANDLER_GENERIC_PRBS_SYNC 0xAB05FA1C
67
68 #define RCL_HANDLER_GENERIC_RESTORE_NONE 0x0000
69 #define RCL_HANDLER_GENERIC_RESTORE_MODCTRL 0x0001
70 #define RCL_HANDLER_GENERIC_RESTORE_WHITEN_INIT 0x0002
71 #define RCL_HANDLER_GENERIC_RESTORE_WHITEN_POLY 0x0004
72
73
74 struct
75 {
76 struct {
77 uint16_t txFifoSize;
78 uint16_t rxFifoSize;
79 RCL_CommandStatus endStatus;
80 bool activeUpdate;
81 bool powerConstraintsSet;
82 RCL_MultiBuffer *curBuffer;
83 } common;
84 union {
85 struct {
86 bool gracefulStopObserved;
87 bool stopFs;
88 uint32_t txCount;
89 uint32_t period;
90 } tx;
91 struct {
92 uint16_t restoreOpt;
93 uint16_t storedWhitenInit;
94 uint32_t storedWhitenPoly;
95 } txTest;
96 struct {
97 uint32_t longOkCount;
98 uint32_t longNokCount;
99 uint16_t demc1be1;
100 uint16_t demc1be2;
101 #ifdef DeviceFamily_CC27XX
102 uint16_t demc1be12;
103 #endif
104 bool restoreThresh;
105 } rx;
106 struct {
107 uint32_t longTxCount;
108 uint32_t longOkCount;
109 uint32_t longNokCount;
110 uint32_t longRxIgnoredCount;
111 uint32_t longRxAddrMismatchCount;
112 uint32_t longRxBufFullCount;
113 } nesb;
114 };
115 } genericHandlerState;
116
117
118 static void RCL_Handler_Generic_setSynthPowerState(bool fsOff);
119 static void RCL_Handler_Generic_updateRxCurBufferAndFifo(List_List *rxBuffers);
120 static RCL_CommandStatus RCL_Handler_Generic_findPbeErrorEndStatus(uint16_t pbeEndStatus);
121 static uint32_t RCL_Handler_Generic_updateTxBuffers(List_List *txBuffers, uint32_t maxBuffers);
122 static uint32_t RCL_Handler_Generic_maskEventsByFifoConf(uint32_t mask, uint16_t fifoConfVal, bool activeUpdate);
123 static void RCL_Handler_Generic_updateRxStats(RCL_StatsGeneric *stats, uint32_t startTime);
124 static void RCL_Handler_Generic_updateLongStats(void);
125 static bool RCL_Handler_Generic_initRxStats(RCL_StatsGeneric *stats, uint32_t startTime);
126 static uint32_t RCL_Handler_Generic_updateSyncWord(uint32_t syncWord);
127 static void RCL_Handler_Nesb_updateHeader(List_List *txBuffers, uint8_t autoRetransmitMode,
128 uint8_t hdrConf, uint8_t seqNumber);
129 static void RCL_Handler_Nesb_updateStats(RCL_StatsNesb *stats, uint32_t startTime);
130 static void RCL_Handler_Nesb_updateLongStats(void);
131 static bool RCL_Handler_Nesb_initStats(RCL_StatsNesb *stats, uint32_t startTime);
132
133 /*
134 * ======== RCL_Handler_Generic_Fs ========
135 */
RCL_Handler_Generic_Fs(RCL_Command * cmd,LRF_Events lrfEvents,RCL_Events rclEventsIn)136 RCL_Events RCL_Handler_Generic_Fs(RCL_Command *cmd, LRF_Events lrfEvents, RCL_Events rclEventsIn)
137 {
138 RCL_CmdGenericFs *fsCmd = (RCL_CmdGenericFs *) cmd;
139 RCL_Events rclEvents = {.value = 0};
140
141 if (rclEventsIn.setup != 0)
142 {
143 uint32_t earliestStartTime;
144
145 /* Start by enabling refsys */
146 earliestStartTime = LRF_enableSynthRefsys();
147
148 /* Program frequency word */
149 LRF_programFrequency(fsCmd->rfFrequency, fsCmd->fsType == RCL_FsType_Tx);
150
151 /* Enable radio */
152 LRF_enable();
153
154 /* Mark as active */
155 cmd->status = RCL_CommandStatus_Active;
156 /* Default end status */
157 genericHandlerState.common.endStatus = RCL_CommandStatus_Finished;
158 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_OPCFG) = 0 << PBE_GENERIC_RAM_OPCFG_START_S;
159
160 RCL_CommandStatus startTimeStatus = RCL_Scheduler_setStartStopTimeEarliestStart(cmd, earliestStartTime);
161 if (startTimeStatus >= RCL_CommandStatus_Finished)
162 {
163 cmd->status = startTimeStatus;
164 rclEvents.lastCmdDone = 1;
165 }
166 else
167 {
168 /* Enable interrupts */
169 LRF_enableHwInterrupt(LRF_EventOpDone.value | LRF_EventOpError.value);
170
171 /* Post cmd */
172 Log_printf(RclCore, Log_VERBOSE, "Starting FS");
173 LRF_waitForTopsmReady();
174 HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_API) = PBE_GENERIC_REGDEF_API_OP_FS;
175 }
176 }
177
178 if (cmd->status == RCL_CommandStatus_Active)
179 {
180 if (rclEventsIn.timerStart != 0)
181 {
182 rclEvents.cmdStarted = 1;
183 }
184 if (lrfEvents.opDone != 0)
185 {
186 cmd->status = genericHandlerState.common.endStatus;
187
188 RCL_Handler_Generic_setSynthPowerState(false);
189
190 /* Set additional power constraints if necessary */
191 if(!genericHandlerState.common.powerConstraintsSet)
192 {
193 genericHandlerState.common.powerConstraintsSet = true;
194 hal_power_set_constraint();
195 }
196 rclEvents.lastCmdDone = 1;
197 }
198 else if (lrfEvents.opError != 0)
199 {
200 RCL_CommandStatus endStatus = genericHandlerState.common.endStatus;
201 if (endStatus == RCL_CommandStatus_Finished)
202 {
203 cmd->status = RCL_Handler_Generic_findPbeErrorEndStatus(HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_COMMON_RAM_O_ENDCAUSE));
204 }
205 else
206 {
207 cmd->status = endStatus;
208 }
209 RCL_Handler_Generic_setSynthPowerState(true);
210 rclEvents.lastCmdDone = 1;
211 }
212 else
213 {
214 /* Other events need to be handled unconditionally */
215 }
216 }
217 if (rclEvents.lastCmdDone != 0)
218 {
219 LRF_disable();
220 }
221 return rclEvents;
222 }
223
224 /*
225 * ======== RCL_Handler_Generic_FsOff ========
226 */
RCL_Handler_Generic_FsOff(RCL_Command * cmd,LRF_Events lrfEvents,RCL_Events rclEventsIn)227 RCL_Events RCL_Handler_Generic_FsOff(RCL_Command *cmd, LRF_Events lrfEvents, RCL_Events rclEventsIn)
228 {
229 RCL_Events rclEvents = {.value = 0};
230
231 if (rclEventsIn.setup != 0)
232 {
233 /* Enable radio */
234 LRF_enable();
235
236 /* Mark as active */
237 cmd->status = RCL_CommandStatus_Active;
238
239 RCL_CommandStatus startTimeStatus = RCL_Scheduler_setCmdStopTimeNoStartTrigger(cmd);
240 if (startTimeStatus >= RCL_CommandStatus_Finished)
241 {
242 cmd->status = startTimeStatus;
243 rclEvents.lastCmdDone = 1;
244 }
245 else
246 {
247 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_OPCFG) = 0;
248
249 /* Enable interrupts */
250 LRF_enableHwInterrupt(LRF_EventOpDone.value | LRF_EventOpError.value);
251
252 /* Post cmd */
253 Log_printf(RclCore, Log_VERBOSE, "Turning off FS");
254 LRF_waitForTopsmReady();
255 HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_API) = PBE_GENERIC_REGDEF_API_OP_STOPFS;
256 }
257 }
258
259 if (cmd->status == RCL_CommandStatus_Active)
260 {
261 if (lrfEvents.opDone != 0)
262 {
263 cmd->status = RCL_CommandStatus_Finished;
264 RCL_Handler_Generic_setSynthPowerState(true);
265 rclEvents.lastCmdDone = 1;
266 }
267 else if (lrfEvents.opError != 0)
268 {
269 cmd->status = RCL_Handler_Generic_findPbeErrorEndStatus(HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_COMMON_RAM_O_ENDCAUSE));
270 rclEvents.lastCmdDone = 1;
271 }
272 else
273 {
274 /* Other events need to be handled unconditionally */
275 }
276 }
277 if (rclEvents.lastCmdDone != 0)
278 {
279 LRF_disable();
280 }
281 return rclEvents;
282 }
283
284 /*
285 * ======== RCL_Handler_Generic_Tx ========
286 */
RCL_Handler_Generic_Tx(RCL_Command * cmd,LRF_Events lrfEvents,RCL_Events rclEventsIn)287 RCL_Events RCL_Handler_Generic_Tx(RCL_Command *cmd, LRF_Events lrfEvents, RCL_Events rclEventsIn)
288 {
289 RCL_CmdGenericTx *txCmd = (RCL_CmdGenericTx *) cmd;
290 RCL_Events rclEvents = {.value = 0};
291
292 if (rclEventsIn.setup != 0)
293 {
294 uint32_t earliestStartTime;
295
296 /* Start by enabling refsys */
297 earliestStartTime = LRF_enableSynthRefsys();
298
299 if ((txCmd->rfFrequency == 0) && ((HWREG_READ_LRF(LRFDRFE_BASE + LRFDRFE_O_SPARE4) & 0x0001) == 0))
300 {
301 /* Synth not to be programmed, but not already locked */
302 cmd->status = RCL_CommandStatus_Error_Synth;
303 rclEvents.lastCmdDone = 1;
304 }
305 else
306 {
307 HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_MDMSYNCA) = RCL_Handler_Generic_updateSyncWord(txCmd->syncWord);
308 uint32_t opCfgVal =
309 (0 << PBE_GENERIC_RAM_OPCFG_TXINFINITE_S) |
310 (0 << PBE_GENERIC_RAM_OPCFG_TXPATTERN_S) |
311 (2 << PBE_GENERIC_RAM_OPCFG_TXFCMD_S) |
312 (0 << PBE_GENERIC_RAM_OPCFG_START_S) |
313 (1 << PBE_GENERIC_RAM_OPCFG_FS_NOCAL_S) |
314 (1 << PBE_GENERIC_RAM_OPCFG_FS_KEEPON_S) |
315 (0 << PBE_GENERIC_RAM_OPCFG_RXREPEATOK_S) |
316 (0 << PBE_GENERIC_RAM_OPCFG_RXREPEATNOK_S) |
317 (0 << PBE_GENERIC_RAM_OPCFG_NEXTOP_S) |
318 (1 << PBE_GENERIC_RAM_OPCFG_SINGLE_S) |
319 (0 << PBE_GENERIC_RAM_OPCFG_IFSPERIOD_S) |
320 (0 << PBE_GENERIC_RAM_OPCFG_RFINTERVAL_S);
321
322 if (txCmd->config.fsOff != 0)
323 {
324 opCfgVal &= ~(PBE_GENERIC_RAM_OPCFG_FS_KEEPON_M);
325 }
326 if (txCmd->rfFrequency != 0)
327 {
328 opCfgVal &= ~(PBE_GENERIC_RAM_OPCFG_FS_NOCAL_M);
329 }
330
331 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_OPCFG) = opCfgVal;
332 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_NESB) = (PBE_GENERIC_RAM_NESB_NESBMODE_OFF);
333
334 /* Mark as active */
335 cmd->status = RCL_CommandStatus_Active;
336 /* Default end status */
337 genericHandlerState.common.endStatus = RCL_CommandStatus_Finished;
338
339 /* Program frequency word */
340 if (txCmd->rfFrequency != 0)
341 {
342 LRF_programFrequency(txCmd->rfFrequency, true);
343 }
344 if (LRF_programTxPower(txCmd->txPower) != TxPowerResult_Ok)
345 {
346 cmd->status = RCL_CommandStatus_Error_Param;
347 rclEvents.lastCmdDone = 1;
348 }
349
350 /* Enable radio */
351 LRF_enable();
352
353 /* Initialize RF FIFO */
354 genericHandlerState.common.txFifoSize = LRF_prepareTxFifo();
355
356 /* Enter payload */
357 uint32_t nBuffer = RCL_Handler_Generic_updateTxBuffers(&txCmd->txBuffers, 1);
358 if (nBuffer == 0)
359 {
360 cmd->status = RCL_CommandStatus_Error_MissingTxBuffer;
361 rclEvents.lastCmdDone = 1;
362 }
363 else
364 {
365 RCL_CommandStatus startTimeStatus = RCL_Scheduler_setStartStopTimeEarliestStart(cmd, earliestStartTime);
366 if (startTimeStatus >= RCL_CommandStatus_Finished)
367 {
368 cmd->status = startTimeStatus;
369 rclEvents.lastCmdDone = 1;
370 }
371 else
372 {
373 /* Enable interrupts */
374 LRF_enableHwInterrupt(LRF_EventOpDone.value | LRF_EventOpError.value);
375
376 /* Post cmd */
377 Log_printf(RclCore, Log_VERBOSE, "Starting TX");
378 LRF_waitForTopsmReady();
379 RCL_Profiling_eventHook(RCL_ProfilingEvent_PreprocStop);
380 HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_API) = PBE_GENERIC_REGDEF_API_OP_TX;
381 }
382 }
383 }
384 }
385
386 if (cmd->status == RCL_CommandStatus_Active)
387 {
388 if (rclEventsIn.timerStart != 0)
389 {
390 rclEvents.cmdStarted = 1;
391 }
392 if (lrfEvents.opDone != 0)
393 {
394 cmd->status = genericHandlerState.common.endStatus;
395 rclEvents.lastCmdDone = 1;
396 /* Pop transmitted packet */
397 RCL_Buffer_TxBuffer *txBuffer;
398 txBuffer = RCL_TxBuffer_get(&txCmd->txBuffers);
399 if (txBuffer != NULL)
400 {
401 txBuffer->state = RCL_BufferStateFinished;
402 }
403 RCL_Profiling_eventHook(RCL_ProfilingEvent_PostprocStart);
404 }
405 else if (lrfEvents.opError != 0)
406 {
407 RCL_CommandStatus endStatus = genericHandlerState.common.endStatus;
408 if (endStatus == RCL_CommandStatus_Finished)
409 {
410 cmd->status = RCL_Handler_Generic_findPbeErrorEndStatus(HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_COMMON_RAM_O_ENDCAUSE));
411 }
412 else
413 {
414 cmd->status = endStatus;
415 }
416 rclEvents.lastCmdDone = 1;
417 }
418 else
419 {
420 /* Other events need to be handled unconditionally */
421 }
422 }
423
424 if (rclEvents.lastCmdDone != 0)
425 {
426 LRF_disable();
427 RCL_Handler_Generic_setSynthPowerState(txCmd->config.fsOff);
428 }
429 return rclEvents;
430 }
431
RCL_Handler_Generic_TxRepeat(RCL_Command * cmd,LRF_Events lrfEvents,RCL_Events rclEventsIn)432 RCL_Events RCL_Handler_Generic_TxRepeat(RCL_Command *cmd, LRF_Events lrfEvents, RCL_Events rclEventsIn)
433 {
434 RCL_CmdGenericTxRepeat *txCmd = (RCL_CmdGenericTxRepeat *) cmd;
435 RCL_Events rclEvents = {.value = 0};
436 bool runTx = false;
437
438 if (rclEventsIn.setup != 0)
439 {
440 uint32_t earliestStartTime;
441
442 /* Start by enabling refsys */
443 earliestStartTime = LRF_enableSynthRefsys();
444
445 if ((txCmd->rfFrequency == 0) && ((HWREG_READ_LRF(LRFDRFE_BASE + LRFDRFE_O_SPARE4) & 0x0001) == 0))
446 {
447 /* Synth not to be programmed, but not already locked */
448 cmd->status = RCL_CommandStatus_Error_Synth;
449 rclEvents.lastCmdDone = 1;
450 }
451 else if ((txCmd->rfFrequency == 0) && (txCmd->config.fsRecal != 0))
452 {
453 /* Synth not to be programmed, recalibration for each packet requested */
454 cmd->status = RCL_CommandStatus_Error_Param;
455 rclEvents.lastCmdDone = 1;
456 }
457 else
458 {
459 HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_MDMSYNCA) = RCL_Handler_Generic_updateSyncWord(txCmd->syncWord);
460 /* Handle FS off in the end, so disable it in PBE */
461 uint32_t opCfgVal =
462 (0 << PBE_GENERIC_RAM_OPCFG_TXINFINITE_S) |
463 (0 << PBE_GENERIC_RAM_OPCFG_TXPATTERN_S) |
464 (1 << PBE_GENERIC_RAM_OPCFG_TXFCMD_S) |
465 (0 << PBE_GENERIC_RAM_OPCFG_START_S) |
466 (1 << PBE_GENERIC_RAM_OPCFG_FS_NOCAL_S) |
467 (1 << PBE_GENERIC_RAM_OPCFG_FS_KEEPON_S) |
468 (0 << PBE_GENERIC_RAM_OPCFG_NEXTOP_S) |
469 (0 << PBE_GENERIC_RAM_OPCFG_RXREPEATOK_S) |
470 (1 << PBE_GENERIC_RAM_OPCFG_SINGLE_S) |
471 (0 << PBE_GENERIC_RAM_OPCFG_IFSPERIOD_S) |
472 (0 << PBE_GENERIC_RAM_OPCFG_RFINTERVAL_S);
473
474 if (txCmd->rfFrequency != 0)
475 {
476 opCfgVal &= ~(PBE_GENERIC_RAM_OPCFG_FS_NOCAL_M);
477 }
478 if (txCmd->config.fsRecal != 0)
479 {
480 opCfgVal &= ~(PBE_GENERIC_RAM_OPCFG_FS_KEEPON_M);
481 }
482 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_OPCFG) = opCfgVal;
483 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_NESB) = (PBE_GENERIC_RAM_NESB_NESBMODE_OFF);
484
485 /* Mark as active */
486 cmd->status = RCL_CommandStatus_Active;
487 /* Default end status */
488 genericHandlerState.common.endStatus = RCL_CommandStatus_Finished;
489 genericHandlerState.tx.stopFs = false;
490 genericHandlerState.tx.txCount = 0;
491
492 /* Program frequency word */
493 if (txCmd->rfFrequency != 0)
494 {
495 LRF_programFrequency(txCmd->rfFrequency, true);
496 }
497 if (LRF_programTxPower(txCmd->txPower) != TxPowerResult_Ok)
498 {
499 cmd->status = RCL_CommandStatus_Error_Param;
500 rclEvents.lastCmdDone = 1;
501 }
502
503 /* Enable radio */
504 LRF_enable();
505
506 /* Initialize RF FIFO */
507 genericHandlerState.common.txFifoSize = LRF_prepareTxFifo();
508
509 /* Enter payload */
510 if (txCmd->txEntry == NULL)
511 {
512 cmd->status = RCL_CommandStatus_Error_MissingTxBuffer;
513 rclEvents.lastCmdDone = 1;
514 }
515 else
516 {
517 uint32_t length = txCmd->txEntry->length;
518 /* Number of words including length field and end padding */
519 uint32_t wordLength = RCL_Buffer_DataEntry_paddedLen(length) / 4;
520 if (wordLength > LRF_getTxFifoWritable() / 4)
521 {
522 /* Packet will not fit */
523 /* TODO: See RCL-348 */
524 cmd->status = RCL_CommandStatus_Error_Param;
525 rclEvents.lastCmdDone = 1;
526 }
527 else {
528 LRF_writeTxFifoWords((uint32_t *) txCmd->txEntry, wordLength);
529
530 RCL_CommandStatus startTimeStatus = RCL_Scheduler_setStartStopTimeEarliestStart(cmd, earliestStartTime);
531 if (startTimeStatus >= RCL_CommandStatus_Finished)
532 {
533 cmd->status = startTimeStatus;
534 rclEvents.lastCmdDone = 1;
535 }
536 else
537 {
538 genericHandlerState.tx.period = txCmd->timePeriod;
539
540 runTx = true; /* Go on */
541 genericHandlerState.tx.gracefulStopObserved = false;
542 if (rclSchedulerState.gracefulStopInfo.cmdStopEnabled || rclSchedulerState.gracefulStopInfo.schedStopEnabled)
543 {
544 /* Enable interrupt to service graceful stop */
545 hal_enable_graceful_stop_time_irq();
546 }
547 }
548 }
549 }
550 }
551 }
552
553 if (cmd->status == RCL_CommandStatus_Active)
554 {
555 if (rclEventsIn.timerStart != 0)
556 {
557 rclEvents.cmdStarted = 1;
558 }
559 if (lrfEvents.systim1 != 0)
560 {
561 genericHandlerState.tx.gracefulStopObserved = true;
562 }
563 if (lrfEvents.opDone != 0)
564 {
565 if (genericHandlerState.tx.stopFs)
566 {
567 runTx = false;
568 }
569 else {
570 /* Retry TX FIFO. Writing to FCMD is safe because PBE is finished, ref. RCL-367 */
571 HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_FCMD) = LRFDPBE_FCMD_DATA_TXFIFO_RETRY;
572
573 if (txCmd->numPackets == 0 || genericHandlerState.tx.txCount < txCmd->numPackets)
574 {
575 /* Reset PBE */
576 HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_INIT) = 1 << LRFDPBE_INIT_TOPSM_S;
577
578 runTx = true;
579 if (rclEventsIn.hardStop != 0)
580 {
581 genericHandlerState.common.endStatus = RCL_Scheduler_findStopStatus(RCL_StopType_Hard);
582 runTx = false;
583 }
584 else if (HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_COMMON_RAM_O_ENDCAUSE) == PBE_COMMON_RAM_ENDCAUSE_STAT_EOPSTOP ||
585 genericHandlerState.tx.gracefulStopObserved ||
586 rclEventsIn.gracefulStop != 0)
587 {
588 genericHandlerState.common.endStatus = RCL_Scheduler_findStopStatus(RCL_StopType_Graceful);
589 runTx = false;
590 }
591 else {
592 RCL_CommandStatus startTimeStatus;
593 if (genericHandlerState.tx.period != 0)
594 {
595 startTimeStatus = RCL_Scheduler_setNewStartRelTime(genericHandlerState.tx.period);
596 }
597 else
598 {
599 startTimeStatus = RCL_Scheduler_setNewStartNow();
600 }
601 if (startTimeStatus >= RCL_CommandStatus_Finished)
602 {
603 genericHandlerState.common.endStatus = startTimeStatus;
604 runTx = false;
605 }
606 }
607 }
608 else
609 {
610 if (HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_COMMON_RAM_O_ENDCAUSE) == PBE_COMMON_RAM_ENDCAUSE_STAT_EOPSTOP)
611 {
612 genericHandlerState.common.endStatus = RCL_Scheduler_findStopStatus(RCL_StopType_Graceful);
613 }
614 runTx = false;
615 }
616 }
617 if (!runTx && cmd->status == RCL_CommandStatus_Active)
618 {
619 if (!genericHandlerState.tx.stopFs && txCmd->config.fsRecal == 0 && txCmd->config.fsOff != 0)
620 {
621 /* Send stop FS */
622 LRF_waitForTopsmReady();
623 HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_API) = PBE_GENERIC_REGDEF_API_OP_STOPFS;
624 genericHandlerState.tx.stopFs = true;
625 }
626 else {
627 cmd->status = genericHandlerState.common.endStatus;
628 rclEvents.lastCmdDone = 1;
629 }
630 }
631 }
632 else if (lrfEvents.opError != 0)
633 {
634 if (genericHandlerState.common.endStatus == RCL_CommandStatus_Finished)
635 {
636 genericHandlerState.common.endStatus = RCL_Handler_Generic_findPbeErrorEndStatus(HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_COMMON_RAM_O_ENDCAUSE));
637 }
638
639 if (!genericHandlerState.tx.stopFs && txCmd->config.fsRecal == 0 && txCmd->config.fsOff != 0 &&
640 (HWREG_READ_LRF(LRFDRFE_BASE + LRFDRFE_O_SPARE4) & 0x01) != 0)
641 {
642 /* Synth was turned on, but should be off. Send stop FS */
643 LRF_waitForTopsmReady();
644 HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_API) = PBE_GENERIC_REGDEF_API_OP_STOPFS;
645 genericHandlerState.tx.stopFs = true;
646 }
647 else
648 {
649 cmd->status = genericHandlerState.common.endStatus;
650 rclEvents.lastCmdDone = 1;
651 }
652 }
653 else
654 {
655 /* Other events need to be handled unconditionally */
656 }
657
658 if (runTx)
659 {
660 uint32_t txCount = genericHandlerState.tx.txCount;
661 if (txCount != 0 && txCmd->config.fsRecal == 0)
662 {
663 /* Frequency programming only for the first packet */
664 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_OPCFG) = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_OPCFG) | PBE_GENERIC_RAM_OPCFG_FS_NOCAL_M;
665 }
666 txCount++;
667 if (txCount != 0)
668 {
669 /* Avoid wraparound */
670 genericHandlerState.tx.txCount = txCount;
671 }
672 /* Enable interrupts */
673 LRF_enableHwInterrupt(LRF_EventOpDone.value | LRF_EventOpError.value);
674
675 /* Post cmd */
676 Log_printf(RclCore, Log_VERBOSE, "Starting TX");
677
678 LRF_waitForTopsmReady();
679 HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_API) = PBE_GENERIC_REGDEF_API_OP_TX;
680 }
681 }
682 if (rclEvents.lastCmdDone != 0)
683 {
684 LRF_disable();
685 RCL_Handler_Generic_setSynthPowerState(txCmd->config.fsOff);
686 }
687
688 return rclEvents;
689 }
690
691 /*
692 * ======== RCL_Handler_Generic_TxTest ========
693 */
RCL_Handler_Generic_TxTest(RCL_Command * cmd,LRF_Events lrfEvents,RCL_Events rclEventsIn)694 RCL_Events RCL_Handler_Generic_TxTest(RCL_Command *cmd, LRF_Events lrfEvents, RCL_Events rclEventsIn)
695 {
696 RCL_CmdGenericTxTest *txCmd = (RCL_CmdGenericTxTest *) cmd;
697 RCL_Events rclEvents = {.value = 0};
698
699 if (rclEventsIn.setup != 0)
700 {
701 uint32_t earliestStartTime;
702
703 /* Start by enabling refsys */
704 earliestStartTime = LRF_enableSynthRefsys();
705 genericHandlerState.txTest.restoreOpt = RCL_HANDLER_GENERIC_RESTORE_NONE;
706 if ((txCmd->rfFrequency == 0) && ((HWREG_READ_LRF(LRFDRFE_BASE + LRFDRFE_O_SPARE4) & 0x0001) == 0))
707 {
708 /* Synth not to be programmed, but not already locked */
709 cmd->status = RCL_CommandStatus_Error_Synth;
710 rclEvents.lastCmdDone = 1;
711 }
712 else
713 {
714 uint32_t opCfgVal =
715 (1 << PBE_GENERIC_RAM_OPCFG_TXINFINITE_S) |
716 (1 << PBE_GENERIC_RAM_OPCFG_TXPATTERN_S) |
717 (0 << PBE_GENERIC_RAM_OPCFG_TXFCMD_S) |
718 (0 << PBE_GENERIC_RAM_OPCFG_START_S) |
719 (1 << PBE_GENERIC_RAM_OPCFG_FS_NOCAL_S) |
720 (1 << PBE_GENERIC_RAM_OPCFG_FS_KEEPON_S) |
721 (0 << PBE_GENERIC_RAM_OPCFG_RXREPEATOK_S) |
722 (0 << PBE_GENERIC_RAM_OPCFG_NEXTOP_S) |
723 (1 << PBE_GENERIC_RAM_OPCFG_SINGLE_S) |
724 (0 << PBE_GENERIC_RAM_OPCFG_IFSPERIOD_S) |
725 (0 << PBE_GENERIC_RAM_OPCFG_RFINTERVAL_S);
726
727 if (txCmd->config.fsOff != 0)
728 {
729 opCfgVal &= ~(PBE_GENERIC_RAM_OPCFG_FS_KEEPON_M);
730 }
731 if (txCmd->rfFrequency != 0)
732 {
733 opCfgVal &= ~(PBE_GENERIC_RAM_OPCFG_FS_NOCAL_M);
734 }
735
736 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_OPCFG) = opCfgVal;
737 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_NESB) = (PBE_GENERIC_RAM_NESB_NESBMODE_OFF);
738
739 /* Mark as active */
740 cmd->status = RCL_CommandStatus_Active;
741 /* Default end status */
742 genericHandlerState.common.endStatus = RCL_CommandStatus_Finished;
743
744 if (LRF_programTxPower(txCmd->txPower) != TxPowerResult_Ok)
745 {
746 cmd->status = RCL_CommandStatus_Error_Param;
747 rclEvents.lastCmdDone = 1;
748 }
749
750 /* Enter configuration */
751 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_PATTERN) = txCmd->config.txWord;
752 if (txCmd->config.sendCw != 0)
753 {
754 HWREG_WRITE_LRF(LRFDMDM_BASE + LRFDMDM_O_MODCTRL) = HWREG_READ_LRF(LRFDMDM_BASE + LRFDMDM_O_MODCTRL) | LRFDMDM_MODCTRL_TONEINSERT_M;
755 genericHandlerState.txTest.restoreOpt = RCL_HANDLER_GENERIC_RESTORE_MODCTRL;
756 }
757 else
758 {
759 uint32_t whitenMode = txCmd->config.whitenMode;
760 /* Configure whitening */
761 if (whitenMode == RCL_CMD_GENERIC_WH_MODE_NONE)
762 {
763 genericHandlerState.txTest.restoreOpt = RCL_HANDLER_GENERIC_RESTORE_WHITEN_INIT;
764 genericHandlerState.txTest.storedWhitenInit = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_WHITEINIT);
765 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_WHITEINIT) = 0;
766 /* Use pattern as sync word */
767 HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_MDMSYNCA) = RCL_Handler_Generic_updateSyncWord(txCmd->config.txWord | (txCmd->config.txWord << 16));
768 }
769 else
770 {
771 if (whitenMode >= RCL_CMD_GENERIC_WH_MODE_PRBS15)
772 {
773 genericHandlerState.txTest.restoreOpt = RCL_HANDLER_GENERIC_RESTORE_WHITEN_POLY | RCL_HANDLER_GENERIC_RESTORE_WHITEN_INIT;
774 genericHandlerState.txTest.storedWhitenPoly = HWREG_READ_LRF(LRFDPBE32_BASE + LRFDPBE32_O_POLY0);
775 genericHandlerState.txTest.storedWhitenInit = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_WHITEINIT);
776 if (whitenMode > RCL_CMD_GENERIC_WH_MODE_PRBS15)
777 {
778 HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_POLY0) = RCL_HANDLER_GENERIC_PRBS15_POLY;
779 }
780 else
781 {
782 HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_POLY0) = RCL_HANDLER_GENERIC_PRBS32_POLY;
783 }
784 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_WHITEINIT) = RCL_HANDLER_GENERIC_PRBS_INIT;
785 }
786 /* Use pseudo-random sync word (not necessarily matching selected PRBS) */
787 HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_MDMSYNCA) = RCL_HANDLER_GENERIC_PRBS_SYNC;
788 }
789 }
790 /* Enable radio */
791 LRF_enable();
792
793 RCL_CommandStatus startTimeStatus = RCL_Scheduler_setStartStopTimeEarliestStart(cmd, earliestStartTime);
794 if (startTimeStatus >= RCL_CommandStatus_Finished)
795 {
796 cmd->status = startTimeStatus;
797 rclEvents.lastCmdDone = 1;
798 }
799 else
800 {
801 if (txCmd->rfFrequency != 0)
802 {
803 /* Program frequency word */
804 LRF_programFrequency(txCmd->rfFrequency, true);
805 }
806
807 /* Enable interrupts */
808 LRF_enableHwInterrupt(LRF_EventOpDone.value | LRF_EventOpError.value);
809
810 /* Post cmd */
811 Log_printf(RclCore, Log_VERBOSE, "Starting infinite TX");
812
813 LRF_waitForTopsmReady();
814 HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_API) = PBE_GENERIC_REGDEF_API_OP_TX;
815 }
816 }
817 }
818
819 if (cmd->status == RCL_CommandStatus_Active)
820 {
821 if (rclEventsIn.timerStart != 0)
822 {
823 rclEvents.cmdStarted = 1;
824 }
825 if (lrfEvents.opDone != 0)
826 {
827 cmd->status = genericHandlerState.common.endStatus;
828 rclEvents.lastCmdDone = 1;
829 }
830 else if (lrfEvents.opError != 0)
831 {
832 RCL_CommandStatus endStatus = genericHandlerState.common.endStatus;
833 if (endStatus == RCL_CommandStatus_Finished)
834 {
835 cmd->status = RCL_Handler_Generic_findPbeErrorEndStatus(HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_COMMON_RAM_O_ENDCAUSE));
836 }
837 else
838 {
839 cmd->status = endStatus;
840 }
841 rclEvents.lastCmdDone = 1;
842 }
843 else
844 {
845 /* Other events need to be handled unconditionally */
846 }
847 }
848
849 if (rclEvents.lastCmdDone != 0)
850 {
851 LRF_disable();
852 RCL_Handler_Generic_setSynthPowerState(txCmd->config.fsOff);
853 if ((genericHandlerState.txTest.restoreOpt & RCL_HANDLER_GENERIC_RESTORE_MODCTRL) != 0) {
854 HWREG_WRITE_LRF(LRFDMDM_BASE + LRFDMDM_O_MODCTRL) = HWREG_READ_LRF(LRFDMDM_BASE + LRFDMDM_O_MODCTRL) & (~LRFDMDM_MODCTRL_TONEINSERT_M);
855 }
856 if ((genericHandlerState.txTest.restoreOpt & RCL_HANDLER_GENERIC_RESTORE_WHITEN_INIT) != 0)
857 {
858 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_WHITEINIT) = genericHandlerState.txTest.storedWhitenInit;
859 }
860 if ((genericHandlerState.txTest.restoreOpt & RCL_HANDLER_GENERIC_RESTORE_WHITEN_POLY) != 0)
861 {
862 HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_POLY0) = genericHandlerState.txTest.storedWhitenPoly;
863 }
864 }
865
866 return rclEvents;
867 }
868
869 /*
870 * ======== RCL_Handler_Generic_Rx ========
871 */
RCL_Handler_Generic_Rx(RCL_Command * cmd,LRF_Events lrfEvents,RCL_Events rclEventsIn)872 RCL_Events RCL_Handler_Generic_Rx(RCL_Command *cmd, LRF_Events lrfEvents, RCL_Events rclEventsIn)
873 {
874 RCL_CmdGenericRx *rxCmd = (RCL_CmdGenericRx *) cmd;
875 RCL_Events rclEvents = RCL_EventNone;
876
877 if (rclEventsIn.setup != 0)
878 {
879 uint32_t earliestStartTime;
880
881 /* Start by enabling refsys */
882 earliestStartTime = LRF_enableSynthRefsys();
883
884 if ((rxCmd->rfFrequency == 0) && ((HWREG_READ_LRF(LRFDRFE_BASE + LRFDRFE_O_SPARE4) & 0x0001) == 0))
885 {
886 /* Synth not to be programmed, but not already locked */
887 cmd->status = RCL_CommandStatus_Error_Synth;
888 rclEvents.lastCmdDone = 1;
889 }
890 else
891 {
892 HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_MDMSYNCA) = RCL_Handler_Generic_updateSyncWord(rxCmd->syncWordA);
893 HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_MDMSYNCB) = RCL_Handler_Generic_updateSyncWord(rxCmd->syncWordB);
894 uint32_t opCfgVal =
895 (0 << PBE_GENERIC_RAM_OPCFG_RXFILTEROP_S) |
896 (1 << PBE_GENERIC_RAM_OPCFG_RXINCLUDEHDR_S) |
897 (1 << PBE_GENERIC_RAM_OPCFG_RXREPEATNOK_S) |
898 (0 << PBE_GENERIC_RAM_OPCFG_START_S) |
899 (1 << PBE_GENERIC_RAM_OPCFG_FS_NOCAL_S) |
900 (1 << PBE_GENERIC_RAM_OPCFG_FS_KEEPON_S) |
901 (1 << PBE_GENERIC_RAM_OPCFG_NEXTOP_S) |
902 (0 << PBE_GENERIC_RAM_OPCFG_SINGLE_S) |
903 (0 << PBE_GENERIC_RAM_OPCFG_IFSPERIOD_S) |
904 (0 << PBE_GENERIC_RAM_OPCFG_RXREPEATOK_S) |
905 (0 << PBE_GENERIC_RAM_OPCFG_RFINTERVAL_S);
906
907 if (rxCmd->config.fsOff != 0)
908 {
909 opCfgVal &= ~(PBE_GENERIC_RAM_OPCFG_FS_KEEPON_M);
910 }
911 if (rxCmd->rfFrequency != 0)
912 {
913 opCfgVal &= ~(PBE_GENERIC_RAM_OPCFG_FS_NOCAL_M);
914 }
915 if (rxCmd->config.repeated)
916 {
917 opCfgVal |= PBE_GENERIC_RAM_OPCFG_RFINTERVAL_M;
918 }
919 else
920 {
921 opCfgVal |= PBE_GENERIC_RAM_OPCFG_SINGLE_M;
922 }
923
924 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_OPCFG) = opCfgVal;
925 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_NESB) = (PBE_GENERIC_RAM_NESB_NESBMODE_OFF);
926 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_MAXLEN) = rxCmd->maxPktLen;
927 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_RXTIMEOUT) = 0; /* No timeout except from SYSTIM */
928 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_FIRSTRXTIMEOUT) = 0; /* No timeout except from SYSTIM */
929
930 /* If needed, configure demodulator correlator engine for syncwordA and syncwordB */
931 if (rxCmd->config.disableSyncA != 0 || rxCmd->config.disableSyncB != 0)
932 {
933 uint16_t demc1be1 = HWREG_READ_LRF(LRFDMDM_BASE + LRFDMDM_O_DEMC1BE1);
934 uint16_t demc1be2 = HWREG_READ_LRF(LRFDMDM_BASE + LRFDMDM_O_DEMC1BE2);
935 #ifdef DeviceFamily_CC27XX
936 uint16_t demc1be12 = HWREG_READ_LRF(LRFDMDM_BASE + LRFDMDM_O_DEMC1BE12);
937 #endif
938 genericHandlerState.rx.restoreThresh = true;
939 genericHandlerState.rx.demc1be1 = demc1be1;
940 genericHandlerState.rx.demc1be2 = demc1be2;
941 #ifdef DeviceFamily_CC27XX
942 genericHandlerState.rx.demc1be12 = demc1be12;
943 #endif
944 if (rxCmd->config.disableSyncA != 0)
945 {
946 demc1be1 = (demc1be1 & ~LRFDMDM_DEMC1BE1_THRESHOLDA_M) | (0x7F << LRFDMDM_DEMC1BE1_THRESHOLDA_S);
947 demc1be2 = (demc1be2 & ~LRFDMDM_DEMC1BE2_THRESHOLDC_M) | (0x7F << LRFDMDM_DEMC1BE2_THRESHOLDC_S);
948 #ifdef DeviceFamily_CC27XX
949 demc1be12 = (demc1be12 & ~LRFDMDM_DEMC1BE12_THRESHOLDG_M) | (0x7F << LRFDMDM_DEMC1BE12_THRESHOLDG_S);
950 #endif
951 }
952 if (rxCmd->config.disableSyncB != 0)
953 {
954 demc1be1 = (demc1be1 & ~LRFDMDM_DEMC1BE1_THRESHOLDB_M) | (0x7F << LRFDMDM_DEMC1BE1_THRESHOLDB_S);
955 }
956 HWREG_WRITE_LRF(LRFDMDM_BASE + LRFDMDM_O_DEMC1BE1) = demc1be1;
957 HWREG_WRITE_LRF(LRFDMDM_BASE + LRFDMDM_O_DEMC1BE2) = demc1be2;
958 #ifdef DeviceFamily_CC27XX
959 HWREG_WRITE_LRF(LRFDMDM_BASE + LRFDMDM_O_DEMC1BE12) = demc1be12;
960 #endif
961 }
962 else
963 {
964 genericHandlerState.rx.restoreThresh = false;
965 }
966
967 /* Mark as active */
968 cmd->status = RCL_CommandStatus_Active;
969 /* Default end status */
970 genericHandlerState.common.endStatus = RCL_CommandStatus_Finished;
971
972 /* Program frequency word */
973 if (rxCmd->rfFrequency != 0)
974 {
975 LRF_programFrequency(rxCmd->rfFrequency, false);
976 }
977
978 /* Enable radio */
979 LRF_enable();
980
981 RCL_CommandStatus startTimeStatus = RCL_Scheduler_setStartStopTimeEarliestStart(cmd, earliestStartTime);
982 if (startTimeStatus >= RCL_CommandStatus_Finished)
983 {
984 cmd->status = startTimeStatus;
985 rclEvents.lastCmdDone = 1;
986 }
987 else {
988 genericHandlerState.common.activeUpdate = RCL_Handler_Generic_initRxStats(rxCmd->stats,
989 rclSchedulerState.actualStartTime);
990 /* Set up sync found capture */
991 hal_setup_sync_found_cap();
992 /* Initialize RF FIFOs */
993 genericHandlerState.common.rxFifoSize = LRF_prepareRxFifo();
994 genericHandlerState.common.curBuffer = NULL;
995 if (rxCmd->config.discardRxPackets == 0)
996 {
997 RCL_Handler_Generic_updateRxCurBufferAndFifo(&rxCmd->rxBuffers);
998 }
999 else
1000 {
1001 /* Set FIFO size to maximum */
1002 LRF_setRxFifoEffSz(genericHandlerState.common.rxFifoSize);
1003 }
1004
1005 /* Enable interrupts */
1006 uint16_t fifoCfg = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_FIFOCFG);
1007 LRF_enableHwInterrupt(RCL_Handler_Generic_maskEventsByFifoConf(LRF_EventOpDone.value | LRF_EventOpError.value |
1008 LRF_EventRxOk.value | LRF_EventRxNok.value |
1009 LRF_EventRxBufFull.value,
1010 fifoCfg, genericHandlerState.common.activeUpdate));
1011
1012 /* Post cmd */
1013 Log_printf(RclCore, Log_VERBOSE, "Starting Rx");
1014 LRF_waitForTopsmReady();
1015 RCL_Profiling_eventHook(RCL_ProfilingEvent_PreprocStop);
1016 HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_API) = PBE_GENERIC_REGDEF_API_OP_RX;
1017 }
1018 }
1019 }
1020 else
1021 {
1022 if (lrfEvents.rxOk != 0 || lrfEvents.rxNok != 0 || lrfEvents.rxBufFull != 0)
1023 {
1024 /* Copy received packet from PBE FIFO to buffer */
1025 /* First, check that there is actually a buffer available */
1026 while (HWREG_READ_LRF(LRFDPBE_BASE + LRFDPBE_O_RXFREADABLE) >= 4)
1027 {
1028 /* Check length of received buffer by peeking */
1029 uint32_t fifoWord = LRF_peekRxFifo(0);
1030 uint32_t wordLength = RCL_Buffer_DataEntry_paddedLen(fifoWord & 0xFFFF) / 4;
1031 if (wordLength > 0)
1032 {
1033 if (rxCmd->config.discardRxPackets == 0)
1034 {
1035 RCL_MultiBuffer *curBuffer;
1036 curBuffer = RCL_MultiBuffer_getBuffer(genericHandlerState.common.curBuffer,
1037 wordLength * 4);
1038 if (curBuffer != genericHandlerState.common.curBuffer) {
1039 rclEvents.rxBufferFinished = 1;
1040 genericHandlerState.common.curBuffer = curBuffer;
1041 }
1042 if (curBuffer == NULL) {
1043 /* Error */
1044 genericHandlerState.common.endStatus = RCL_CommandStatus_Error_RxBufferCorruption;
1045 /* Send abort */
1046 HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_API) = PBE_GENERIC_REGDEF_API_OP_STOP;
1047 /* Do not check for more packets from the RX FIFO */
1048 break;
1049 }
1050 else {
1051 uint32_t *data32;
1052 data32 = (uint32_t *)RCL_MultiBuffer_getNextWritableByte(curBuffer);
1053 LRF_readRxFifoWords(data32, wordLength);
1054 RCL_MultiBuffer_commitBytes(curBuffer, wordLength * 4);
1055 /* Raise event */
1056 rclEvents.rxEntryAvail = 1;
1057 /* Adjust effective FIFO size */
1058 RCL_Handler_Generic_updateRxCurBufferAndFifo(&rxCmd->rxBuffers);
1059 }
1060 }
1061 else
1062 {
1063 LRF_discardRxFifoWords(wordLength);
1064 }
1065 }
1066 }
1067 if (genericHandlerState.common.activeUpdate)
1068 {
1069 RCL_Handler_Generic_updateRxStats(rxCmd->stats, rclSchedulerState.actualStartTime);
1070 }
1071 else
1072 {
1073 RCL_Handler_Generic_updateLongStats();
1074 }
1075 }
1076 if (rclEventsIn.timerStart != 0)
1077 {
1078 rclEvents.cmdStarted = 1;
1079 }
1080 if (lrfEvents.opDone != 0 || lrfEvents.opError != 0)
1081 {
1082 RCL_CommandStatus endStatus = genericHandlerState.common.endStatus;
1083 rclEvents.lastCmdDone = 1;
1084 if (lrfEvents.opError != 0 && endStatus == RCL_CommandStatus_Finished)
1085 {
1086 endStatus = RCL_Handler_Generic_findPbeErrorEndStatus(HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_COMMON_RAM_O_ENDCAUSE));
1087 }
1088 else if (HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_COMMON_RAM_O_ENDCAUSE) == PBE_COMMON_RAM_ENDCAUSE_STAT_EOPSTOP)
1089 {
1090 endStatus = RCL_Scheduler_findStopStatus(RCL_StopType_Graceful);
1091 }
1092 cmd->status = endStatus;
1093 RCL_Profiling_eventHook(RCL_ProfilingEvent_PostprocStart);
1094 }
1095 else
1096 {
1097 /* Other events need to be handled unconditionally */
1098 }
1099 }
1100
1101 if (cmd->status == RCL_CommandStatus_Active)
1102 {
1103 if (rclEventsIn.rxBufferUpdate != 0)
1104 {
1105 RCL_Handler_Generic_updateRxCurBufferAndFifo(&rxCmd->rxBuffers);
1106 }
1107 }
1108
1109 if (rclEvents.lastCmdDone != 0)
1110 {
1111 LRF_disable();
1112 RCL_Handler_Generic_setSynthPowerState(rxCmd->config.fsOff);
1113 RCL_Handler_Generic_updateRxStats(rxCmd->stats, rclSchedulerState.actualStartTime);
1114 /* Restore changed thresholds */
1115 if (genericHandlerState.rx.restoreThresh)
1116 {
1117 HWREG_WRITE_LRF(LRFDMDM_BASE + LRFDMDM_O_DEMC1BE1) = genericHandlerState.rx.demc1be1;
1118 HWREG_WRITE_LRF(LRFDMDM_BASE + LRFDMDM_O_DEMC1BE2) = genericHandlerState.rx.demc1be2;
1119 #ifdef DeviceFamily_CC27XX
1120 HWREG_WRITE_LRF(LRFDMDM_BASE + LRFDMDM_O_DEMC1BE12) = genericHandlerState.rx.demc1be12;
1121 #endif
1122 }
1123 }
1124
1125 return rclEvents;
1126 }
1127
1128 /*
1129 * ======== RCL_Handler_Generic_PbeOperation ========
1130 */
RCL_Handler_Generic_PbeOperation(RCL_Command * cmd,LRF_Events lrfEvents,RCL_Events rclEventsIn)1131 RCL_Events RCL_Handler_Generic_PbeOperation(RCL_Command *cmd, LRF_Events lrfEvents, RCL_Events rclEventsIn)
1132 {
1133 RCL_Events rclEvents = {.value = 0};
1134 RCL_CmdGenericPbeOperation *pbeCmd = (RCL_CmdGenericPbeOperation *) cmd;
1135
1136 if (cmd->status == RCL_CommandStatus_Scheduled)
1137 {
1138 /* Enable radio */
1139 LRF_enable();
1140
1141 /* Mark as active */
1142 cmd->status = RCL_CommandStatus_Active;
1143
1144 RCL_CommandStatus startTimeStatus = RCL_Scheduler_setCmdStopTimeNoStartTrigger(cmd);
1145 if (startTimeStatus >= RCL_CommandStatus_Finished)
1146 {
1147 cmd->status = startTimeStatus;
1148 rclEvents.lastCmdDone = 1;
1149 }
1150 else
1151 {
1152 /* Enable interrupts */
1153 LRF_enableHwInterrupt(LRF_EventOpDone.value | LRF_EventOpError.value);
1154
1155 /* Post cmd */
1156 LRF_waitForTopsmReady();
1157 HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_API) = pbeCmd->pbeOperation;
1158 }
1159 }
1160
1161 if (cmd->status == RCL_CommandStatus_Active)
1162 {
1163 if (lrfEvents.opDone != 0)
1164 {
1165 cmd->status = RCL_CommandStatus_Finished;
1166 rclEvents.lastCmdDone = 1;
1167 }
1168 else if (lrfEvents.opError != 0)
1169 {
1170 cmd->status = RCL_Handler_Generic_findPbeErrorEndStatus(HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_COMMON_RAM_O_ENDCAUSE));
1171 rclEvents.lastCmdDone = 1;
1172 }
1173 else
1174 {
1175 /* Other events need to be handled unconditionally */
1176 }
1177 }
1178 if (rclEvents.lastCmdDone != 0)
1179 {
1180 LRF_disable();
1181 }
1182 return rclEvents;
1183 }
1184
1185
1186 /*
1187 * ======== RCL_Handler_Nesb_Ptx ========
1188 */
RCL_Handler_Nesb_Ptx(RCL_Command * cmd,LRF_Events lrfEvents,RCL_Events rclEventsIn)1189 RCL_Events RCL_Handler_Nesb_Ptx(RCL_Command *cmd, LRF_Events lrfEvents, RCL_Events rclEventsIn)
1190 {
1191 RCL_CmdNesbPtx *txCmd = (RCL_CmdNesbPtx *) cmd;
1192 RCL_Events rclEvents = {.value = 0};
1193 bool runTx = false;
1194 bool listenAck = false;
1195 uint32_t earliestStartTime = 0;
1196
1197 if (rclEventsIn.setup != 0)
1198 {
1199 /* Start by enabling refsys */
1200 earliestStartTime = LRF_enableSynthRefsys();
1201
1202 if ((txCmd->rfFrequency == 0) && ((HWREG_READ_LRF(LRFDRFE_BASE + LRFDRFE_O_SPARE4) & 0x0001) == 0))
1203 {
1204 /* Synth not to be programmed, but not already locked */
1205 cmd->status = RCL_CommandStatus_Error_Synth;
1206 rclEvents.lastCmdDone = 1;
1207 }
1208 else
1209 {
1210 HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_MDMSYNCA) = RCL_Handler_Generic_updateSyncWord(txCmd->syncWord);
1211 HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_MDMSYNCB) = RCL_Handler_Generic_updateSyncWord(txCmd->syncWord);
1212
1213 uint32_t opCfgVal = (PBE_GENERIC_RAM_OPCFG_NEXTOP_SWITCH) |
1214 (PBE_GENERIC_RAM_OPCFG_TXFCMD_NONE) |
1215 (PBE_GENERIC_RAM_OPCFG_FS_NOCAL_NOCAL) |
1216 (PBE_GENERIC_RAM_OPCFG_FS_KEEPON_YES) |
1217 (PBE_GENERIC_RAM_OPCFG_IFSPERIOD_EN) |
1218 (PBE_GENERIC_RAM_OPCFG_RXREPEATNOK_YES) |
1219 (PBE_GENERIC_RAM_OPCFG_RXREPEATOK_YES) |
1220 (PBE_GENERIC_RAM_OPCFG_RFINTERVAL_DIS) |
1221 (PBE_GENERIC_RAM_OPCFG_SINGLE_DIS) |
1222 (PBE_GENERIC_RAM_OPCFG_RXINCLUDEHDR_YES);
1223
1224 if (txCmd->config.fsOff != 0)
1225 {
1226 opCfgVal &= ~(PBE_GENERIC_RAM_OPCFG_FS_KEEPON_M);
1227 }
1228 if (txCmd->rfFrequency != 0)
1229 {
1230 opCfgVal &= ~(PBE_GENERIC_RAM_OPCFG_FS_NOCAL_M);
1231 }
1232 if (txCmd->config.autoRetransmitMode != 0)
1233 {
1234 opCfgVal |= (PBE_GENERIC_RAM_OPCFG_TXFCMD_RETRY);
1235 }
1236 else
1237 {
1238 opCfgVal |= (PBE_GENERIC_RAM_OPCFG_TXFCMD_DEALLOC);
1239 }
1240
1241 /* Enable NESB mode */
1242 uint32_t nesbVal = (PBE_GENERIC_RAM_NESB_NESBMODE_ON);
1243
1244 uint32_t seqStat0Val = (txCmd->config.autoRetransmitMode << PBE_GENERIC_RAM_SEQSTAT0_STOPAUTO_S)
1245 & PBE_GENERIC_RAM_SEQSTAT0_STOPAUTO_M;
1246
1247 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_FIRSTRXTIMEOUT) = 2500;
1248 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_RXTIMEOUT) = 800;
1249 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_MAXLEN) = 255;
1250 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_OPCFG) = opCfgVal;
1251 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_NESB) = nesbVal;
1252 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_SEQSTAT0) = seqStat0Val;
1253
1254 /* Mark as active */
1255 cmd->status = RCL_CommandStatus_Active;
1256
1257 /* Default end status */
1258 genericHandlerState.common.endStatus = RCL_CommandStatus_Finished;
1259 genericHandlerState.tx.txCount = 0;
1260
1261 /* Program frequency word */
1262 if (txCmd->rfFrequency != 0)
1263 {
1264 LRF_programFrequency(txCmd->rfFrequency, true);
1265 }
1266 if (LRF_programTxPower(txCmd->txPower) != TxPowerResult_Ok)
1267 {
1268 cmd->status = RCL_CommandStatus_Error_Param;
1269 rclEvents.lastCmdDone = 1;
1270 }
1271
1272 /* Enable radio */
1273 LRF_enable();
1274
1275 /* Initialize Tx FIFO */
1276 genericHandlerState.common.txFifoSize = LRF_prepareTxFifo();
1277
1278 /* Enter header and get ACK configuration */
1279 RCL_Handler_Nesb_updateHeader(&txCmd->txBuffers,
1280 txCmd->config.autoRetransmitMode,
1281 txCmd->config.hdrConf,
1282 txCmd->seqNo);
1283
1284 /* Configure Rx if necessary */
1285 if (txCmd->config.autoRetransmitMode != PBE_GENERIC_RAM_SEQSTAT0_STOPAUTO_ALWAYS)
1286 {
1287 /* Initialize Rx FIFO */
1288 genericHandlerState.common.rxFifoSize = LRF_prepareRxFifo();
1289 genericHandlerState.common.curBuffer = NULL;
1290
1291 /* Request notification on RX buffer updates */
1292 RCL_Handler_Generic_updateRxCurBufferAndFifo(&txCmd->rxBuffers);
1293 listenAck = true;
1294 }
1295
1296 /* Enter payload */
1297 uint32_t nBuffer = RCL_Handler_Generic_updateTxBuffers(&txCmd->txBuffers, 1);
1298 if (nBuffer == 0)
1299 {
1300 cmd->status = RCL_CommandStatus_Error_MissingTxBuffer;
1301 rclEvents.lastCmdDone = 1;
1302 }
1303 else
1304 {
1305 RCL_CommandStatus startTimeStatus = RCL_Scheduler_setStartStopTimeEarliestStart(cmd, earliestStartTime);
1306 if (startTimeStatus >= RCL_CommandStatus_Finished)
1307 {
1308 cmd->status = startTimeStatus;
1309 rclEvents.lastCmdDone = 1;
1310 }
1311 else
1312 {
1313 genericHandlerState.common.activeUpdate = RCL_Handler_Nesb_initStats(txCmd->stats,
1314 rclSchedulerState.actualStartTime);
1315 runTx = true;
1316 }
1317 }
1318 }
1319 }
1320
1321 if (cmd->status == RCL_CommandStatus_Active)
1322 {
1323 /* We only get an Rx LRF event if an Acknowledge is expected */
1324 if (lrfEvents.rxOk != 0 || lrfEvents.rxNok != 0 || lrfEvents.rxIgnored != 0 || lrfEvents.rxBufFull != 0)
1325 {
1326 /* Copy received packet from PBE FIFO to buffer */
1327 /* First, check that there is actually a buffer available */
1328 while (HWREG_READ_LRF(LRFDPBE_BASE + LRFDPBE_O_RXFREADABLE) >= 4)
1329 {
1330 /* Check length of received buffer by peeking */
1331 uint32_t fifoWord = LRF_peekRxFifo(0);
1332 uint32_t numWords = RCL_Buffer_DataEntry_paddedLen(fifoWord & 0xFFFF) / sizeof(uint32_t);
1333 if (numWords > 0)
1334 {
1335 RCL_MultiBuffer *curBuffer;
1336 curBuffer = RCL_MultiBuffer_getBuffer(genericHandlerState.common.curBuffer,
1337 numWords * sizeof(uint32_t));
1338
1339 if (curBuffer != genericHandlerState.common.curBuffer)
1340 {
1341 rclEvents.rxBufferFinished = 1;
1342 genericHandlerState.common.curBuffer = curBuffer;
1343 }
1344
1345 if (curBuffer == NULL)
1346 {
1347 /* Error */
1348 genericHandlerState.common.endStatus = RCL_CommandStatus_Error_RxBufferCorruption;
1349 /* Send abort */
1350 HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_API) = PBE_GENERIC_REGDEF_API_OP_STOP;
1351 /* Do not check for more packets from the RX FIFO */
1352 break;
1353 }
1354 else
1355 {
1356 uint32_t *buffer32 = (uint32_t *)RCL_MultiBuffer_getNextWritableByte(curBuffer);
1357 LRF_readRxFifoWords(buffer32, numWords);
1358 RCL_MultiBuffer_commitBytes(curBuffer, numWords * sizeof(uint32_t));
1359 /* Raise event */
1360 rclEvents.rxEntryAvail = 1;
1361 /* Adjust effective FIFO size */
1362 RCL_Handler_Generic_updateRxCurBufferAndFifo(&txCmd->rxBuffers);
1363 }
1364 }
1365 }
1366 if (genericHandlerState.common.activeUpdate)
1367 {
1368 RCL_Handler_Nesb_updateStats(txCmd->stats, rclSchedulerState.actualStartTime);
1369 }
1370 else
1371 {
1372 RCL_Handler_Nesb_updateLongStats();
1373 }
1374 }
1375 if (rclEventsIn.timerStart != 0)
1376 {
1377 rclEvents.cmdStarted = 1;
1378 }
1379 if (lrfEvents.opDone != 0)
1380 {
1381 /* Retry TX FIFO. Writing to FCMD is safe because PBE is finished, ref. RCL-367 */
1382 HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_FCMD) = LRFDPBE_FCMD_DATA_TXFIFO_RETRY;
1383
1384 uint16_t endCause = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_COMMON_RAM_O_ENDCAUSE);
1385
1386 if (endCause == PBE_COMMON_RAM_ENDCAUSE_STAT_ENDOK)
1387 {
1388 /* Increment the sequence number for next packet */
1389 txCmd->seqNo = (txCmd->seqNo + 1) % 4;
1390
1391 cmd->status = genericHandlerState.common.endStatus;
1392 rclEvents.lastCmdDone = 1;
1393
1394 /* Pop transmitted packet */
1395 RCL_Buffer_TxBuffer *txBuffer;
1396 txBuffer = RCL_TxBuffer_get(&txCmd->txBuffers);
1397 if (txBuffer != NULL)
1398 {
1399 txBuffer->state = RCL_BufferStateFinished;
1400 runTx = false;
1401 }
1402 RCL_Profiling_eventHook(RCL_ProfilingEvent_PostprocStart);
1403 }
1404 /* Handle missed ACKs or ACKs with the wrong address */
1405 else if (endCause == PBE_COMMON_RAM_ENDCAUSE_STAT_NOSYNC)
1406 {
1407 /* Reset PBE */
1408 HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_INIT) = 1 << LRFDPBE_INIT_TOPSM_S;
1409
1410 /* Attempt to retransmit the packet */
1411 if (genericHandlerState.tx.txCount <= txCmd->maxRetrans)
1412 {
1413 Log_printf(RclCore, Log_VERBOSE, "PTX needs to retransmit");
1414
1415 /* Set a new transmit time according to retransDelay. If unattainable, retransmit as soon as possible */
1416 RCL_CommandStatus startTimeStatus = RCL_Scheduler_setNewStartRelTime(txCmd->retransDelay);
1417 if (startTimeStatus >= RCL_CommandStatus_Finished)
1418 {
1419 Log_printf(RclCore, Log_VERBOSE, "Unattainable retranmission delay. Retransmitting as soon as possible");
1420 RCL_Scheduler_setNewStartNow();
1421 }
1422 runTx = true;
1423 }
1424 else /* Finish the command without incrementing the sequence number */
1425 {
1426 genericHandlerState.common.endStatus = RCL_CommandStatus_NoSync;
1427 cmd->status = genericHandlerState.common.endStatus;
1428 rclEvents.lastCmdDone = 1;
1429 runTx = false;
1430 }
1431 }
1432 }
1433 else if (lrfEvents.opError != 0)
1434 {
1435 RCL_CommandStatus endStatus = genericHandlerState.common.endStatus;
1436
1437 if (endStatus == RCL_CommandStatus_Finished)
1438 {
1439 cmd->status = RCL_Handler_Generic_findPbeErrorEndStatus(HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_COMMON_RAM_O_ENDCAUSE));
1440 }
1441 else
1442 {
1443 cmd->status = endStatus;
1444 }
1445 rclEvents.lastCmdDone = 1;
1446 runTx = false;
1447 }
1448 else
1449 {
1450 /* Other events need to be handled unconditionally */
1451 }
1452 if (runTx)
1453 {
1454 uint32_t txCount = genericHandlerState.tx.txCount;
1455 txCount++;
1456 if (txCount != 0)
1457 {
1458 /* Avoid wraparound */
1459 genericHandlerState.tx.txCount = txCount;
1460 }
1461 /* Set up sync found capture */
1462 hal_setup_sync_found_cap();
1463 /* Enable interrupts */
1464 if (listenAck)
1465 {
1466 uint16_t fifoCfg = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_FIFOCFG);
1467 LRF_enableHwInterrupt(RCL_Handler_Generic_maskEventsByFifoConf(LRF_EventOpDone.value | LRF_EventOpError.value |
1468 LRF_EventRxOk.value | LRF_EventRxNok.value |
1469 LRF_EventRxIgnored.value | LRF_EventRxBufFull.value,
1470 fifoCfg, genericHandlerState.common.activeUpdate));
1471 }
1472 else
1473 {
1474 LRF_enableHwInterrupt(LRF_EventOpDone.value | LRF_EventOpError.value);
1475 }
1476 /* Post cmd */
1477 Log_printf(RclCore, Log_VERBOSE, "Start of PTX operation");
1478 LRF_waitForTopsmReady();
1479 RCL_Profiling_eventHook(RCL_ProfilingEvent_PreprocStop);
1480 HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_API) = PBE_GENERIC_REGDEF_API_OP_TX;
1481 }
1482 }
1483 if (rclEvents.lastCmdDone != 0)
1484 {
1485 LRF_disable();
1486 RCL_Handler_Generic_setSynthPowerState(txCmd->config.fsOff);
1487 RCL_Handler_Nesb_updateStats(txCmd->stats, rclSchedulerState.actualStartTime);
1488 }
1489 return rclEvents;
1490 }
1491
1492
1493 /*
1494 * ======== RCL_Handler_Nesb_Prx ========
1495 */
RCL_Handler_Nesb_Prx(RCL_Command * cmd,LRF_Events lrfEvents,RCL_Events rclEventsIn)1496 RCL_Events RCL_Handler_Nesb_Prx(RCL_Command *cmd, LRF_Events lrfEvents, RCL_Events rclEventsIn)
1497 {
1498 RCL_CmdNesbPrx *rxCmd = (RCL_CmdNesbPrx *) cmd;
1499 RCL_Events rclEvents = RCL_EventNone;
1500
1501 if (rclEventsIn.setup != 0)
1502 {
1503 uint32_t earliestStartTime;
1504
1505 /* Start by enabling refsys */
1506 earliestStartTime = LRF_enableSynthRefsys();
1507
1508 if ((rxCmd->rfFrequency == 0) && ((HWREG_READ_LRF(LRFDRFE_BASE + LRFDRFE_O_SPARE4) & 0x0001) == 0))
1509 {
1510 /* Synth not to be programmed, but not already locked */
1511 cmd->status = RCL_CommandStatus_Error_Synth;
1512 rclEvents.lastCmdDone = 1;
1513 }
1514 else
1515 {
1516 HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_MDMSYNCA) = RCL_Handler_Generic_updateSyncWord(rxCmd->syncWordA);
1517 HWREG_WRITE_LRF(LRFDPBE32_BASE + LRFDPBE32_O_MDMSYNCB) = RCL_Handler_Generic_updateSyncWord(rxCmd->syncWordB);
1518
1519 uint32_t opCfgVal = (PBE_GENERIC_RAM_OPCFG_NEXTOP_SWITCH) |
1520 (PBE_GENERIC_RAM_OPCFG_TXFCMD_RETRY) |
1521 (PBE_GENERIC_RAM_OPCFG_FS_NOCAL_NOCAL) |
1522 (PBE_GENERIC_RAM_OPCFG_FS_KEEPON_YES) |
1523 (PBE_GENERIC_RAM_OPCFG_IFSPERIOD_EN) |
1524 (PBE_GENERIC_RAM_OPCFG_RXREPEATNOK_NO) |
1525 (PBE_GENERIC_RAM_OPCFG_RXREPEATOK_NO) |
1526 (PBE_GENERIC_RAM_OPCFG_RFINTERVAL_DIS) |
1527 (PBE_GENERIC_RAM_OPCFG_SINGLE_DIS) |
1528 (PBE_GENERIC_RAM_OPCFG_RXINCLUDEHDR_YES);
1529
1530 if (rxCmd->config.fsOff != 0)
1531 {
1532 opCfgVal &= ~(PBE_GENERIC_RAM_OPCFG_FS_KEEPON_M);
1533 }
1534 if (rxCmd->rfFrequency != 0)
1535 {
1536 opCfgVal &= ~(PBE_GENERIC_RAM_OPCFG_FS_NOCAL_M);
1537 }
1538 if (rxCmd->config.repeatNok != 0)
1539 {
1540 opCfgVal |= PBE_GENERIC_RAM_OPCFG_RXREPEATNOK_M;
1541 }
1542 if (rxCmd->config.repeatOk != 0)
1543 {
1544 opCfgVal &= ~(PBE_GENERIC_RAM_OPCFG_RXREPEATOK_M);
1545 }
1546
1547 /* Enable NESB mode */
1548 uint32_t nesbVal = (PBE_GENERIC_RAM_NESB_NESBMODE_ON);
1549 nesbVal |= (rxCmd->addrLen << PBE_GENERIC_RAM_NESB_PEERADRLEN_S) & PBE_GENERIC_RAM_NESB_PEERADRLEN_M;
1550
1551 /* Configure AutoACK and Seq Status for syncword 0 */
1552 uint32_t seqStat0Val = (rxCmd->syncWord[0].seqValid << PBE_GENERIC_RAM_SEQSTAT0_VALID_S)
1553 & PBE_GENERIC_RAM_SEQSTAT0_VALID_M;
1554
1555 seqStat0Val |= (rxCmd->syncWord[0].autoAckMode << PBE_GENERIC_RAM_SEQSTAT0_STOPAUTO_S)
1556 & PBE_GENERIC_RAM_SEQSTAT0_STOPAUTO_M;
1557
1558 /* Configure AutoACK and Seq Status for syncword 1 */
1559 uint32_t seqStat1Val = (rxCmd->syncWord[1].seqValid << PBE_GENERIC_RAM_SEQSTAT1_VALID_S)
1560 & PBE_GENERIC_RAM_SEQSTAT1_VALID_M;
1561
1562 seqStat1Val |= (rxCmd->syncWord[1].autoAckMode << PBE_GENERIC_RAM_SEQSTAT1_STOPAUTO_S)
1563 & PBE_GENERIC_RAM_SEQSTAT1_STOPAUTO_M;
1564
1565 /* Set the addresses that will be used for address filtering */
1566 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_PEERADR0AL) = (rxCmd->syncWord[0].address & PBE_GENERIC_RAM_PEERADR0AL_VAL_M);
1567 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_PEERADR0AH) = (rxCmd->syncWord[0].address >> 0x10) & PBE_GENERIC_RAM_PEERADR0AH_VAL_M;
1568 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_PEERADR0BL) = (rxCmd->syncWord[1].address & PBE_GENERIC_RAM_PEERADR0BL_VAL_M);
1569 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_PEERADR0BH) = (rxCmd->syncWord[1].address >> 0x10) & PBE_GENERIC_RAM_PEERADR0BH_VAL_M;
1570
1571 /* Set timeouts for the Rx operation */
1572 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_FIRSTRXTIMEOUT) = 0; /* No timeout except from SYSTIM */
1573 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_RXTIMEOUT) = 0; /* No timeout except from SYSTIM */
1574
1575 /* Set remaining configuration registers */
1576 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_OPCFG) = opCfgVal;
1577 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_NESB) = nesbVal;
1578 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_SEQSTAT0) = seqStat0Val;
1579 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_SEQSTAT1) = seqStat1Val;
1580 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_MAXLEN) = 255;
1581
1582 /* If needed, configure demodulator correlator engine for syncwordA and syncwordB */
1583 if (rxCmd->config.disableSyncA != 0 || rxCmd->config.disableSyncB != 0)
1584 {
1585 uint16_t demc1be1 = HWREG_READ_LRF(LRFDMDM_BASE + LRFDMDM_O_DEMC1BE1);
1586 uint16_t demc1be2 = HWREG_READ_LRF(LRFDMDM_BASE + LRFDMDM_O_DEMC1BE2);
1587 genericHandlerState.rx.restoreThresh = true;
1588 genericHandlerState.rx.demc1be1 = demc1be1;
1589 genericHandlerState.rx.demc1be2 = demc1be2;
1590 if (rxCmd->config.disableSyncA != 0)
1591 {
1592 demc1be1 = (demc1be1 & ~LRFDMDM_DEMC1BE1_THRESHOLDA_M) | (0x7F << LRFDMDM_DEMC1BE1_THRESHOLDA_S);
1593 demc1be2 = (demc1be2 & ~LRFDMDM_DEMC1BE2_THRESHOLDC_M) | (0x7F << LRFDMDM_DEMC1BE2_THRESHOLDC_S);
1594 }
1595 if (rxCmd->config.disableSyncB != 0)
1596 {
1597 demc1be1 = (demc1be1 & ~LRFDMDM_DEMC1BE1_THRESHOLDB_M) | (0x7F << LRFDMDM_DEMC1BE1_THRESHOLDB_S);
1598 }
1599 HWREG_WRITE_LRF(LRFDMDM_BASE + LRFDMDM_O_DEMC1BE1) = demc1be1;
1600 HWREG_WRITE_LRF(LRFDMDM_BASE + LRFDMDM_O_DEMC1BE2) = demc1be2;
1601 }
1602 else
1603 {
1604 genericHandlerState.rx.restoreThresh = false;
1605 }
1606
1607 /* Mark as active */
1608 cmd->status = RCL_CommandStatus_Active;
1609 /* Default end status */
1610 genericHandlerState.common.endStatus = RCL_CommandStatus_Finished;
1611
1612 /* Program frequency word */
1613 if (rxCmd->rfFrequency != 0)
1614 {
1615 LRF_programFrequency(rxCmd->rfFrequency, false);
1616 }
1617 if (LRF_programTxPower(rxCmd->txPower) != TxPowerResult_Ok)
1618 {
1619 cmd->status = RCL_CommandStatus_Error_Param;
1620 rclEvents.lastCmdDone = 1;
1621 }
1622
1623 /* Enable radio */
1624 LRF_enable();
1625
1626 RCL_CommandStatus startTimeStatus = RCL_Scheduler_setStartStopTimeEarliestStart(cmd, earliestStartTime);
1627 if (startTimeStatus >= RCL_CommandStatus_Finished)
1628 {
1629 cmd->status = startTimeStatus;
1630 rclEvents.lastCmdDone = 1;
1631 }
1632 else
1633 {
1634 genericHandlerState.common.activeUpdate = RCL_Handler_Nesb_initStats(rxCmd->stats,
1635 rclSchedulerState.actualStartTime);
1636
1637 /* Set up sync found capture */
1638 hal_setup_sync_found_cap();
1639 /* Initialize Rx FIFO */
1640 genericHandlerState.common.rxFifoSize = LRF_prepareRxFifo();
1641 genericHandlerState.common.curBuffer = NULL;
1642
1643 if (rxCmd->config.discardRxPackets == 0)
1644 {
1645 RCL_Handler_Generic_updateRxCurBufferAndFifo(&rxCmd->rxBuffers);
1646 }
1647 else
1648 {
1649 /* Set FIFO size to maximum */
1650 LRF_setRxFifoEffSz(genericHandlerState.common.rxFifoSize);
1651 }
1652
1653 /* If an ACK is required, prepare Tx FIFOs */
1654 if ((rxCmd->syncWord[0].autoAckMode != 0) || (rxCmd->syncWord[1].autoAckMode != 0))
1655 {
1656 genericHandlerState.common.txFifoSize = LRF_prepareTxFifo();
1657 }
1658
1659 /* Enable interrupts */
1660 uint16_t fifoCfg = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_FIFOCFG);
1661 LRF_enableHwInterrupt(RCL_Handler_Generic_maskEventsByFifoConf(LRF_EventOpDone.value | LRF_EventOpError.value |
1662 LRF_EventRxOk.value | LRF_EventRxNok.value |
1663 LRF_EventRxIgnored.value | LRF_EventRxBufFull.value,
1664 fifoCfg, genericHandlerState.common.activeUpdate));
1665 /* Post cmd */
1666 Log_printf(RclCore, Log_VERBOSE, "Starting of PRX operation");
1667 LRF_waitForTopsmReady();
1668 RCL_Profiling_eventHook(RCL_ProfilingEvent_PreprocStop);
1669 HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_API) = PBE_GENERIC_REGDEF_API_OP_RX;
1670 }
1671 }
1672 }
1673 else
1674 {
1675 if (lrfEvents.rxOk != 0 || lrfEvents.rxNok != 0 || lrfEvents.rxIgnored != 0 || lrfEvents.rxBufFull != 0)
1676 {
1677 /* Copy received packet from PBE FIFO to buffer */
1678 /* First, check that there is actually a buffer available */
1679 while (HWREG_READ_LRF(LRFDPBE_BASE + LRFDPBE_O_RXFREADABLE) >= 4)
1680 {
1681 /* Check length of received buffer by peeking */
1682 uint32_t fifoWord = LRF_peekRxFifo(0);
1683 uint32_t numWords = RCL_Buffer_DataEntry_paddedLen(fifoWord & 0xFFFF) / sizeof(uint32_t);
1684 if (numWords > 0)
1685 {
1686 if (rxCmd->config.discardRxPackets == 0)
1687 {
1688 RCL_MultiBuffer *curBuffer;
1689 curBuffer = RCL_MultiBuffer_getBuffer(genericHandlerState.common.curBuffer,
1690 numWords * 4);
1691 if (curBuffer != genericHandlerState.common.curBuffer)
1692 {
1693 rclEvents.rxBufferFinished = 1;
1694 genericHandlerState.common.curBuffer = curBuffer;
1695 }
1696 if (curBuffer == NULL)
1697 {
1698 /* Error */
1699 genericHandlerState.common.endStatus = RCL_CommandStatus_Error_RxBufferCorruption;
1700 /* Send abort */
1701 HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_API) = PBE_GENERIC_REGDEF_API_OP_STOP;
1702 /* Do not check for more packets from the RX FIFO */
1703 break;
1704 }
1705 else
1706 {
1707 uint32_t *buffer32 = (uint32_t *)RCL_MultiBuffer_getNextWritableByte(curBuffer);
1708 LRF_readRxFifoWords(buffer32, numWords);
1709 RCL_MultiBuffer_commitBytes(curBuffer, numWords * sizeof(uint32_t));
1710 /* Raise event */
1711 rclEvents.rxEntryAvail = 1;
1712 /* Adjust effective FIFO size */
1713 RCL_Handler_Generic_updateRxCurBufferAndFifo(&rxCmd->rxBuffers);
1714
1715 /* Update the sequence number to the one from to the last successfully received packet */
1716 rxCmd->syncWord[0].seq = (HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_SEQSTAT0) & PBE_GENERIC_RAM_SEQSTAT0_PID_M) >> PBE_GENERIC_RAM_SEQSTAT0_PID_S;
1717 rxCmd->syncWord[1].seq = (HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_SEQSTAT1) & PBE_GENERIC_RAM_SEQSTAT1_PID_M) >> PBE_GENERIC_RAM_SEQSTAT1_PID_S;
1718
1719 /* Update the CRC value to the one from the last successfully received packet */
1720 rxCmd->syncWord[0].crcVal = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_CRCVAL0);
1721 rxCmd->syncWord[1].crcVal = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_CRCVAL1);
1722 }
1723 }
1724 else
1725 {
1726 LRF_discardRxFifoWords(numWords);
1727 }
1728 }
1729 }
1730 if (genericHandlerState.common.activeUpdate)
1731 {
1732 RCL_Handler_Nesb_updateStats(rxCmd->stats, rclSchedulerState.actualStartTime);
1733 }
1734 else
1735 {
1736 RCL_Handler_Nesb_updateLongStats();
1737 }
1738 }
1739 if (rclEventsIn.timerStart != 0)
1740 {
1741 rclEvents.cmdStarted = 1;
1742 }
1743 if (lrfEvents.opDone != 0 || lrfEvents.opError != 0)
1744 {
1745 RCL_CommandStatus endStatus = genericHandlerState.common.endStatus;
1746
1747 rclEvents.lastCmdDone = 1;
1748 if (lrfEvents.opError != 0 && endStatus == RCL_CommandStatus_Finished)
1749 {
1750 endStatus = RCL_Handler_Generic_findPbeErrorEndStatus(HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_COMMON_RAM_O_ENDCAUSE));
1751 }
1752 else if (HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_COMMON_RAM_O_ENDCAUSE) == PBE_COMMON_RAM_ENDCAUSE_STAT_EOPSTOP)
1753 {
1754 endStatus = RCL_Scheduler_findStopStatus(RCL_StopType_Graceful);
1755 }
1756 cmd->status = endStatus;
1757 RCL_Profiling_eventHook(RCL_ProfilingEvent_PostprocStart);
1758 }
1759 else
1760 {
1761 /* Other events need to be handled unconditionally */
1762 }
1763 }
1764 if (cmd->status == RCL_CommandStatus_Active)
1765 {
1766 if (rclEventsIn.rxBufferUpdate != 0)
1767 {
1768 RCL_Handler_Generic_updateRxCurBufferAndFifo(&rxCmd->rxBuffers);
1769 }
1770 }
1771 if (rclEvents.lastCmdDone != 0)
1772 {
1773 LRF_disable();
1774 RCL_Handler_Generic_setSynthPowerState(rxCmd->config.fsOff);
1775 RCL_Handler_Nesb_updateStats(rxCmd->stats, rclSchedulerState.actualStartTime);
1776 /* Restore changed thresholds */
1777 if (genericHandlerState.rx.restoreThresh)
1778 {
1779 HWREG_WRITE_LRF(LRFDMDM_BASE + LRFDMDM_O_DEMC1BE1) = genericHandlerState.rx.demc1be1;
1780 HWREG_WRITE_LRF(LRFDMDM_BASE + LRFDMDM_O_DEMC1BE2) = genericHandlerState.rx.demc1be2;
1781 }
1782 }
1783
1784 return rclEvents;
1785 }
1786
1787 /*
1788 * ======== RCL_Handler_Generic_setSynthPowerState ========
1789 */
RCL_Handler_Generic_setSynthPowerState(bool fsOff)1790 static void RCL_Handler_Generic_setSynthPowerState(bool fsOff)
1791 {
1792 /* Do power management for synth at the end of a command.
1793 If synth is off, turn off refsys and remove constraint on standby.
1794 If synth is on, keep refsys on and ensure constraint on standby is set */
1795 if (fsOff)
1796 {
1797 LRF_disableSynthRefsys();
1798 /* Release additional power constraints if necessary */
1799 if(genericHandlerState.common.powerConstraintsSet)
1800 {
1801 genericHandlerState.common.powerConstraintsSet = false;
1802 hal_power_release_constraint();
1803 }
1804 }
1805 else
1806 {
1807 /* Set additional power constraints if necessary */
1808 if(!genericHandlerState.common.powerConstraintsSet)
1809 {
1810 genericHandlerState.common.powerConstraintsSet = true;
1811 hal_power_set_constraint();
1812 }
1813 }
1814 }
1815
1816 /*
1817 * ======== RCL_Handler_Generic_updateRxCurBufferAndFifo ========
1818 */
RCL_Handler_Generic_updateRxCurBufferAndFifo(List_List * rxBuffers)1819 static void RCL_Handler_Generic_updateRxCurBufferAndFifo(List_List *rxBuffers)
1820 {
1821 RCL_MultiBuffer *curBuffer = genericHandlerState.common.curBuffer;
1822
1823 if (curBuffer == NULL)
1824 {
1825 curBuffer = RCL_MultiBuffer_findFirstWritableBuffer((RCL_MultiBuffer *)rxBuffers->head);
1826 }
1827 genericHandlerState.common.curBuffer = curBuffer;
1828
1829 uint32_t rxSpace = RCL_MultiBuffer_findAvailableRxSpace(curBuffer);
1830
1831 LRF_setRxFifoEffSz(rxSpace);
1832 }
1833
1834 /*
1835 * ======== RCL_Handler_Generic_findPbeErrorEndStatus ========
1836 */
RCL_Handler_Generic_findPbeErrorEndStatus(uint16_t pbeEndStatus)1837 static RCL_CommandStatus RCL_Handler_Generic_findPbeErrorEndStatus(uint16_t pbeEndStatus)
1838 {
1839 RCL_CommandStatus status;
1840 switch (pbeEndStatus)
1841 {
1842 case PBE_COMMON_RAM_ENDCAUSE_STAT_ERR_RXF:
1843 status = RCL_CommandStatus_Error_RxFifo;
1844 break;
1845 case PBE_COMMON_RAM_ENDCAUSE_STAT_ERR_TXF:
1846 status = RCL_CommandStatus_Error_TxFifo;
1847 break;
1848 case PBE_COMMON_RAM_ENDCAUSE_STAT_ERR_SYNTH:
1849 status = RCL_CommandStatus_Error_Synth;
1850 break;
1851 case PBE_COMMON_RAM_ENDCAUSE_STAT_RXTIMEOUT:
1852 status = RCL_CommandStatus_RxTimeout;
1853 break;
1854 case PBE_COMMON_RAM_ENDCAUSE_STAT_EOPSTOP:
1855 status = RCL_Scheduler_findStopStatus(RCL_StopType_Graceful);
1856 break;
1857 case PBE_COMMON_RAM_ENDCAUSE_STAT_ERR_STOP:
1858 status = RCL_Scheduler_findStopStatus(RCL_StopType_Hard);
1859 break;
1860 case PBE_COMMON_RAM_ENDCAUSE_STAT_ERR_BADOP:
1861 status = RCL_CommandStatus_Error_UnknownOp;
1862 break;
1863 default:
1864 Log_printf(RclCore, Log_ERROR, "Unexpected error 0x%04X from PBE", pbeEndStatus);
1865 status = RCL_CommandStatus_Error;
1866 break;
1867 }
1868 return status;
1869 }
1870
1871 /*
1872 * ======== RCL_Handler_Generic_updateTxBuffers ========
1873 */
RCL_Handler_Generic_updateTxBuffers(List_List * txBuffers,uint32_t maxBuffers)1874 static uint32_t RCL_Handler_Generic_updateTxBuffers(List_List *txBuffers,
1875 uint32_t maxBuffers)
1876 {
1877 uint32_t nBuffers = 0;
1878 RCL_Buffer_TxBuffer *nextTxBuffer;
1879
1880 nextTxBuffer = RCL_TxBuffer_head(txBuffers);
1881
1882 while (nextTxBuffer != NULL && nBuffers < maxBuffers)
1883 {
1884 uint32_t length = nextTxBuffer->length;
1885 /* Number of words including length field and end padding */
1886 uint32_t wordLength = RCL_Buffer_DataEntry_paddedLen(length) / 4;
1887
1888 if (wordLength > LRF_getTxFifoWritable() / 4)
1889 {
1890 /* Packet will not fit */
1891 /* TODO: See RCL-348 */
1892 break;
1893 }
1894 nextTxBuffer->state = RCL_BufferStateInUse;
1895 uint32_t *data32 = (uint32_t *) &(nextTxBuffer->length);
1896
1897 /* Copy packet into FIFO */
1898 LRF_writeTxFifoWords(data32, wordLength);
1899 nextTxBuffer = RCL_TxBuffer_next(nextTxBuffer);
1900
1901 nBuffers++;
1902 }
1903
1904 return nBuffers;
1905 }
1906
1907 /*
1908 * ======== RCL_Handler_Generic_maskEventsByFifoConf ========
1909 */
RCL_Handler_Generic_maskEventsByFifoConf(uint32_t mask,uint16_t fifoConfVal,bool activeUpdate)1910 static uint32_t RCL_Handler_Generic_maskEventsByFifoConf(uint32_t mask, uint16_t fifoConfVal, bool activeUpdate)
1911 {
1912 /* Remove events that will not give an entry in the RX FIFO, based on FIFOCFG, unless active update is used
1913 Note: never remove the CRC error event, as it is needed to update the long CRC error counter */
1914 if (!activeUpdate)
1915 {
1916 mask &= ~(((fifoConfVal & PBE_GENERIC_RAM_FIFOCFG_AUTOFLUSHIGN_M) ? LRF_EventRxIgnored.value : 0) |
1917 LRF_EventRxBufFull.value);
1918 }
1919 return mask;
1920 }
1921
1922 /*
1923 * ======== RCL_Handler_Generic_updateRxStats ========
1924 */
RCL_Handler_Generic_updateRxStats(RCL_StatsGeneric * stats,uint32_t startTime)1925 static void RCL_Handler_Generic_updateRxStats(RCL_StatsGeneric *stats, uint32_t startTime)
1926 {
1927 if (stats != NULL)
1928 {
1929 uint32_t lastTimestamp = HWREG_READ_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_LASTTIMESTAMPL);
1930 /* Check if a new value is found in the first timestamp */
1931 if (lastTimestamp == startTime)
1932 {
1933 stats->timestampValid = false;
1934 }
1935 else {
1936 stats->timestampValid = true;
1937 stats->lastTimestamp = lastTimestamp;
1938 }
1939 stats->lastRssi = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_LASTRSSI);
1940 RCL_Handler_Generic_updateLongStats();
1941 stats->nRxNok = genericHandlerState.rx.longNokCount;
1942 stats->nRxOk = genericHandlerState.rx.longOkCount;
1943 }
1944 }
1945
1946 /*
1947 * ======== RCL_Handler_Generic_updateLongStats ========
1948 */
RCL_Handler_Generic_updateLongStats(void)1949 static void RCL_Handler_Generic_updateLongStats(void)
1950 {
1951 uint32_t oldRxOk = genericHandlerState.rx.longOkCount;
1952 uint32_t oldRxNok = genericHandlerState.rx.longNokCount;
1953 uint32_t newRxOk = (oldRxOk & ~0xFFFF) | HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_NRXOK);
1954 uint32_t newRxNok = (oldRxNok & ~0xFFFF) | HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_NRXNOK);
1955
1956 if (newRxOk < oldRxOk)
1957 {
1958 newRxOk += 0x10000;
1959 }
1960 if (newRxNok < oldRxNok)
1961 {
1962 newRxNok += 0x10000;
1963 }
1964 genericHandlerState.rx.longOkCount = newRxOk;
1965 genericHandlerState.rx.longNokCount = newRxNok;
1966 }
1967
1968 /*
1969 * ======== RCL_Handler_Generic_initRxStats ========
1970 */
RCL_Handler_Generic_initRxStats(RCL_StatsGeneric * stats,uint32_t startTime)1971 static bool RCL_Handler_Generic_initRxStats(RCL_StatsGeneric *stats, uint32_t startTime)
1972 {
1973 if (stats != NULL)
1974 {
1975 /* Set timestamp to start time of command (will not occur again) to know if a valid value has been found */
1976 HWREG_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_LASTTIMESTAMPL) = startTime;
1977 stats->timestampValid = false;
1978 stats->lastRssi = LRF_RSSI_INVALID;
1979 if (stats->config.accumulate != 0)
1980 {
1981 /* Copy existing values into PBE */
1982 genericHandlerState.rx.longNokCount = stats->nRxNok;
1983 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_NRXNOK) = stats->nRxNok & 0xFFFF;
1984 genericHandlerState.rx.longOkCount = stats->nRxOk;
1985 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_NRXOK) = stats->nRxOk & 0xFFFF;
1986 }
1987 else
1988 {
1989 /* Reset existing values in PBE */
1990 genericHandlerState.rx.longNokCount = 0;
1991 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_NRXNOK) = 0;
1992 genericHandlerState.rx.longOkCount = 0;
1993 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_NRXOK) = 0;
1994
1995 stats->nRxNok = 0;
1996 stats->nRxOk = 0;
1997 }
1998 return stats->config.activeUpdate;
1999 }
2000 else
2001 {
2002 /* Reset existing values in PBE */
2003 genericHandlerState.rx.longNokCount = 0;
2004 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_NRXNOK) = 0;
2005 genericHandlerState.rx.longOkCount = 0;
2006 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_NRXOK) = 0;
2007
2008 return false;
2009 }
2010 }
2011
2012 /*
2013 * ======== RCL_Handler_Generic_updateSyncWord ========
2014 */
RCL_Handler_Generic_updateSyncWord(uint32_t syncWord)2015 static uint32_t RCL_Handler_Generic_updateSyncWord(uint32_t syncWord)
2016 {
2017 uint32_t syncWordOut;
2018 /* Check bit ordering of header and follow that */
2019 if ((HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_PKTCFG) & PBE_GENERIC_RAM_PKTCFG_HDRORDER_M) != 0)
2020 {
2021 /* MSb first configured - bit reverse sync word */
2022 HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_PHAOUT0) = syncWord & 0x0000FFFF;
2023 syncWordOut = HWREG_READ_LRF(LRFDPBE_BASE + LRFDPBE_O_PHAOUT0BR) << 16;
2024 HWREG_WRITE_LRF(LRFDPBE_BASE + LRFDPBE_O_PHAOUT0) = syncWord >> 16;
2025 syncWordOut |= HWREG_READ_LRF(LRFDPBE_BASE + LRFDPBE_O_PHAOUT0BR);
2026 /* Check sync word length to see ensure that sync word ends up in least significant bits */
2027 uint32_t syncWordLen = (HWREG_READ_LRF(LRFDMDM_BASE + LRFDMDM_O_DEMSWQU0) & LRFDMDM_DEMSWQU0_REFLEN_M) + 1;
2028 syncWordOut >>= (32 - syncWordLen);
2029 }
2030 else
2031 {
2032 syncWordOut = syncWord;
2033 }
2034
2035 return syncWordOut;
2036 }
2037
2038 /*
2039 * ======== RCL_Handler_Nesb_updateHeader ========
2040 */
RCL_Handler_Nesb_updateHeader(List_List * txBuffers,uint8_t autoRetransmitMode,uint8_t hdrConf,uint8_t seqNumber)2041 static void RCL_Handler_Nesb_updateHeader(List_List *txBuffers, uint8_t autoRetransmitMode,
2042 uint8_t hdrConf, uint8_t seqNumber)
2043 {
2044 uint8_t noAck;
2045 uint8_t seqNo;
2046
2047 RCL_Buffer_TxBuffer *nextTxBuffer;
2048 nextTxBuffer = RCL_TxBuffer_head(txBuffers);
2049 uint8_t indexHeader = nextTxBuffer->numPad - 1;
2050
2051 if (hdrConf == 0)
2052 {
2053 /* Insert NO_ACK field from TX buffer. */
2054 noAck = nextTxBuffer->data[indexHeader] & 0x01;
2055 seqNo = seqNumber;
2056 }
2057 else
2058 {
2059 /* Insert SEQ and NO_ACK field from TX buffer. */
2060 noAck = nextTxBuffer->data[indexHeader] & 0x01;
2061 seqNo = (nextTxBuffer->data[indexHeader] >> 1) & 0x03;
2062 }
2063
2064 /* Update header */
2065 nextTxBuffer->data[indexHeader] = ((nextTxBuffer->data[indexHeader] & 0xF8) | ((seqNo & 0x03) << 1) | noAck);
2066 }
2067
2068 /*
2069 * ======== RCL_Handler_Nesb_updateStats ========
2070 */
RCL_Handler_Nesb_updateStats(RCL_StatsNesb * stats,uint32_t startTime)2071 static void RCL_Handler_Nesb_updateStats(RCL_StatsNesb *stats, uint32_t startTime)
2072 {
2073 if (stats != NULL)
2074 {
2075 uint32_t lastTimestamp = HWREG_READ_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_LASTTIMESTAMPL);
2076 /* Check if a new value is found in the first timestamp */
2077 if (lastTimestamp == startTime)
2078 {
2079 stats->timestampValid = false;
2080 }
2081 else {
2082 stats->timestampValid = true;
2083 stats->lastTimestamp = lastTimestamp;
2084 }
2085 stats->lastRssi = HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_LASTRSSI);
2086 RCL_Handler_Nesb_updateLongStats();
2087 stats->nTx = genericHandlerState.nesb.longTxCount;
2088 stats->nRxOk = genericHandlerState.nesb.longOkCount;
2089 stats->nRxNok = genericHandlerState.nesb.longNokCount;
2090 stats->nRxIgnored = genericHandlerState.nesb.longRxIgnoredCount;
2091 stats->nRxAddrMismatch = genericHandlerState.nesb.longRxAddrMismatchCount;
2092 stats->nRxBufFull = genericHandlerState.nesb.longRxBufFullCount;
2093 }
2094 }
2095
2096 /*
2097 * ======== RCL_Handler_Nesb_updateLongStats ========
2098 */
RCL_Handler_Nesb_updateLongStats(void)2099 static void RCL_Handler_Nesb_updateLongStats(void)
2100 {
2101 uint32_t oldTx = genericHandlerState.nesb.longTxCount;
2102 uint32_t oldRxOk = genericHandlerState.nesb.longOkCount;
2103 uint32_t oldRxNok = genericHandlerState.nesb.longNokCount;
2104 /* TODO: RCL-308: Long counters should not be needed for anything except RX Ok and CRC error */
2105 uint32_t oldRxIgnored = genericHandlerState.nesb.longRxIgnoredCount;
2106 uint32_t oldRxAddrMismatch = genericHandlerState.nesb.longRxAddrMismatchCount;
2107 uint32_t oldRxBufFull = genericHandlerState.nesb.longRxBufFullCount;
2108
2109 uint32_t newTx = (oldTx & ~0xFFFF) | HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_NTX);
2110 uint32_t newRxOk = (oldRxOk & ~0xFFFF) | HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_NRXOK);
2111 uint32_t newRxNok = (oldRxNok & ~0xFFFF) | HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_NRXNOK);
2112 uint32_t newRxIgnored = (oldRxIgnored & ~0xFFFF) | HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_NRXIGNORED);
2113 /* TODO: See RCL-343 */
2114 uint32_t newRxAddrMismatch = (oldRxAddrMismatch & ~0xFFFF) | HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_NRXIGNORED);
2115 uint32_t newRxBufFull = (oldRxBufFull & ~0xFFFF) | HWREGH_READ_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_NRXFIFOFULL);
2116
2117 if (newTx < oldTx)
2118 {
2119 newTx += 0x10000;
2120 }
2121 if (newRxOk < oldRxOk)
2122 {
2123 newRxOk += 0x10000;
2124 }
2125 if (newRxNok < oldRxNok)
2126 {
2127 newRxNok += 0x10000;
2128 }
2129 if (newRxIgnored < oldRxIgnored)
2130 {
2131 newRxIgnored += 0x10000;
2132 }
2133 if (newRxAddrMismatch < oldRxAddrMismatch)
2134 {
2135 newRxAddrMismatch += 0x10000;
2136 }
2137 if (newRxBufFull < oldRxBufFull)
2138 {
2139 newRxBufFull += 0x10000;
2140 }
2141 genericHandlerState.nesb.longTxCount = newTx;
2142 genericHandlerState.nesb.longOkCount = newRxOk;
2143 genericHandlerState.nesb.longNokCount = newRxNok;
2144 genericHandlerState.nesb.longRxIgnoredCount = newRxIgnored;
2145 genericHandlerState.nesb.longRxAddrMismatchCount = newRxAddrMismatch;
2146 genericHandlerState.nesb.longRxBufFullCount = newRxBufFull;
2147 }
2148
2149 /*
2150 * ======== RCL_Handler_Nesb_initStats ========
2151 */
RCL_Handler_Nesb_initStats(RCL_StatsNesb * stats,uint32_t startTime)2152 static bool RCL_Handler_Nesb_initStats(RCL_StatsNesb *stats, uint32_t startTime)
2153 {
2154 if (stats != NULL)
2155 {
2156 /* Set timestamp to start time of command (will not occur again) to know if a valid value has been found */
2157 HWREG_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_LASTTIMESTAMPL) = startTime;
2158 stats->timestampValid = false;
2159 stats->lastRssi = LRF_RSSI_INVALID;
2160 if (stats->config.accumulate != 0)
2161 {
2162 /* Copy existing values into PBE */
2163 genericHandlerState.nesb.longTxCount = stats->nTx;
2164 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_NTX) = stats->nRxOk & 0xFFFF;
2165 genericHandlerState.nesb.longOkCount = stats->nRxOk;
2166 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_NRXOK) = stats->nRxOk & 0xFFFF;
2167 genericHandlerState.nesb.longNokCount = stats->nRxNok;
2168 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_NRXNOK) = stats->nRxNok & 0xFFFF;
2169 genericHandlerState.nesb.longRxIgnoredCount = stats->nRxIgnored;
2170 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_NRXIGNORED) = stats->nRxIgnored & 0xFFFF;
2171 genericHandlerState.nesb.longRxAddrMismatchCount = stats->nRxAddrMismatch;
2172 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_NRXIGNORED) = stats->nRxAddrMismatch & 0xFFFF;
2173 genericHandlerState.nesb.longRxBufFullCount = stats->nRxBufFull;
2174 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_NRXFIFOFULL) = stats->nRxBufFull & 0xFFFF;
2175 }
2176 else
2177 {
2178 /* Reset existing values in PBE */
2179 genericHandlerState.nesb.longTxCount = 0;
2180 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_NTX) = 0;
2181 genericHandlerState.nesb.longOkCount = 0;
2182 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_NRXOK) = 0;
2183 genericHandlerState.nesb.longNokCount = 0;
2184 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_NRXNOK) = 0;
2185 genericHandlerState.nesb.longRxIgnoredCount = 0;
2186 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_NRXIGNORED) = 0;
2187 genericHandlerState.nesb.longRxAddrMismatchCount = 0;
2188 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_NRXIGNORED) = 0;
2189 genericHandlerState.nesb.longRxBufFullCount = 0;
2190 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_NRXFIFOFULL) = 0;
2191
2192 stats->nTx = 0;
2193 stats->nRxOk = 0;
2194 stats->nRxNok = 0;
2195 stats->nRxIgnored = 0;
2196 stats->nRxAddrMismatch = 0;
2197 stats->nRxBufFull = 0;
2198 }
2199 return stats->config.activeUpdate;
2200 }
2201 else
2202 {
2203 /* Reset existing values in PBE */
2204 genericHandlerState.nesb.longTxCount = 0;
2205 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_NTX) = 0;
2206 genericHandlerState.nesb.longOkCount = 0;
2207 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_NRXOK) = 0;
2208 genericHandlerState.nesb.longNokCount = 0;
2209 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_NRXNOK) = 0;
2210 genericHandlerState.nesb.longRxIgnoredCount = 0;
2211 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_NRXIGNORED) = 0;
2212 genericHandlerState.nesb.longRxAddrMismatchCount = 0;
2213 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_NRXIGNORED) = 0;
2214 genericHandlerState.nesb.longRxBufFullCount = 0;
2215 HWREGH_WRITE_LRF(LRFD_BUFRAM_BASE + PBE_GENERIC_RAM_O_NRXFIFOFULL) = 0;
2216
2217 return false;
2218 }
2219 }
2220