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