Fixed Jenkins daily build error in adcbuf and cbuff driver files.
[processor-sdk/pdk.git] / packages / ti / drv / cbuff / src / cbuff.c
1 /*
2  *  Copyright (c) Texas Instruments Incorporated 2021
3  *
4  *  Redistribution and use in source and binary forms, with or without
5  *  modification, are permitted provided that the following conditions
6  *  are met:
7  *
8  *    Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  *
11  *    Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the
14  *    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
21  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
33 /**
34  *  \file cbuff.c
35  *
36  *  \brief The file implements the CBUFF Driver.
37  *
38  */
40 /* ========================================================================== */
41 /*                             Include Files                                  */
42 /* ========================================================================== */
43 #include <stddef.h>
44 #include <stdint.h>
45 #include <string.h>
46 #include <ti/csl/soc.h>
47 #include <ti/drv/cbuff/cbuff.h>
48 #include <ti/osal/DebugP.h>
49 #include <ti/osal/MemoryP.h>
50 #include <ti/osal/HwiP.h>
51 #include <ti/drv/cbuff/src/cbuff_internal.h>
52 #include <ti/csl/cslr_cbuff.h>
53 #include <ti/csl/arch/csl_arch.h>
54 #include <ti/osal/osal.h>
55 #include <ti/csl/hw_types.h>
57 /* ========================================================================== */
58 /*                          Function Declarations                             */
59 /* ========================================================================== */
61 /* CBUFF Register Read/Write API: */
62 static void CBUFF_reset          (CSL_CbuffRegs* ptrCBUFFReg);
63 static void CBUFF_releaseReset   (CSL_CbuffRegs* ptrCBUFFReg);
64 static void CBUFF_enableErrorInt (CSL_CbuffRegs* ptrCBUFFReg);
65 static void CBUFF_disableErrorInt(CSL_CbuffRegs* ptrCBUFFReg);
66 static void CBUFF_disableFrameDoneInt (CSL_CbuffRegs* ptrCBUFFReg);
67 static void CBUFF_enableFrameDoneInt (CSL_CbuffRegs* ptrCBUFFReg);
68 static void CBUFF_disableChirpDoneInt (CSL_CbuffRegs* ptrCBUFFReg);
69 static void CBUFF_enableChirpDoneInt (CSL_CbuffRegs* ptrCBUFFReg);
70 static void CBUFF_setECC         (CSL_CbuffRegs* ptrCBUFFReg, uint8_t ecc);
71 static void CBUFF_getStatus      (CSL_CbuffRegs* ptrCBUFFReg, uint8_t* isFrameDone, uint8_t* isChirpDone);
72 static void CBUFF_clearStatus    (CSL_CbuffRegs* ptrCBUFFReg, uint8_t isFrameDone, uint8_t isChirpDone);
73 static void CBUFF_setFrameStartSWTrigger (CSL_CbuffRegs* ptrCBUFFReg, uint32_t enableSW);
74 static void CBUFF_setChirpAvailableSWTrigger (CSL_CbuffRegs* ptrCBUFFReg, uint32_t enableSW);
75 static void CBUFF_triggerFrameStart (CSL_CbuffRegs* ptrCBUFFReg);
76 static void CBUFF_triggerChirpAvailable (CSL_CbuffRegs* ptrCBUFFReg);
77 static void CBUFF_clearLLEntry (CSL_CbuffRegs* ptrCBUFFReg, uint8_t listIndex);
78 static void CBUFF_setLLEntry (CSL_CbuffRegs* ptrCBUFFReg, uint8_t listIndex, CBUFF_LinkListParams* ptrLLParams);
79 static void CBUFF_setNumberChirps (CSL_CbuffRegs* ptrCBUFFReg, uint32_t numChirps);
81 /* CBUFF Driver Internal API: */
82 static CBUFF_InterfaceFxn* CBUFF_isIfSupported (CBUFF_Interface interface);
83 static int32_t CBUFF_validateBufferCfg (CBUFF_BufferCfg* ptrUserBuffer, int32_t* errCode);
85 /* CBUFF Session Management API: */
86 static int32_t CBUFF_validateHWSessionCfg (CBUFF_Session* ptrSession, int32_t* errCode);
87 static int32_t CBUFF_validateSWSessionCfg (CBUFF_Session* ptrSession, int32_t* errCode);
88 static CBUFF_Session* CBUFF_allocateSession (CBUFF_DriverMCB* ptrDriverMCB);
89 static void CBUFF_freeSession (CBUFF_Session* ptrSession);
91 /* CBUFF Frame Done Management API: */
92 static void CBUFF_registerFrameDone (CBUFF_DriverMCB* ptrDriverMCB);
93 static void CBUFF_deregisterFrameDone (CBUFF_DriverMCB* ptrDriverMCB);
95 /**************************************************************************
96  * CBUFF ISR:
97  **************************************************************************/
98 static void CBUFF_ISR (uintptr_t arg);
99 static void CBUFF_ErrorISR (uintptr_t arg);
100 static void CBUFF_FrameStartISR (uintptr_t arg);
102 /* ========================================================================== */
103 /*                          Function Definitions                              */
104 /* ========================================================================== */
106 /**
107  *  @b Description
108  *  @n
109  *      The function is used to reset the CBUFF module.
110  *
111  *  @param[in]  ptrCBUFFReg
112  *      Pointer to the CBUFF Register space
113  *
114  *  \ingroup CBUFF_DRIVER_INTERNAL_FUNCTION
115  *
116  *  @retval
117  *      Not applicable
118  */
119 static void CBUFF_reset (CSL_CbuffRegs* ptrCBUFFReg)
121     ptrCBUFFReg->CONFIG_REG_0 = CSL_FINSR (ptrCBUFFReg->CONFIG_REG_0, 27U, 27U, 1U);
124 /**
125  *  @b Description
126  *  @n
127  *      The function is used to release the reset of the CBUFF module.
128  *
129  *  @param[in]  ptrCBUFFReg
130  *      Pointer to the CBUFF Register space
131  *
132  *  \ingroup CBUFF_DRIVER_INTERNAL_FUNCTION
133  *
134  *  @retval
135  *      Not applicable
136  */
137 static void CBUFF_releaseReset (CSL_CbuffRegs* ptrCBUFFReg)
139     ptrCBUFFReg->CONFIG_REG_0 = CSL_FINSR (ptrCBUFFReg->CONFIG_REG_0, 27U, 27U, 0U);
142 /**
143  *  @b Description
144  *  @n
145  *      The function is used to setup the ECC
146  *
147  *  @param[in]  ptrCBUFFReg
148  *      Pointer to the CBUFF Register space
149  *  @param[in]  ecc
150  *      Flag to enable/disable ECC
151  *
152  *  \ingroup CBUFF_DRIVER_INTERNAL_FUNCTION
153  *
154  *  @retval
155  *      Not applicable
156  */
157 static void CBUFF_setECC (CSL_CbuffRegs* ptrCBUFFReg, uint8_t ecc)
159     ptrCBUFFReg->CONFIG_REG_0 = CSL_FINSR (ptrCBUFFReg->CONFIG_REG_0, 1U, 1U, (uint32_t)ecc);
162 /**
163  *  @b Description
164  *  @n
165  *      The function is used to disable the frame done interrupts
166  *
167  *  @param[in]  ptrCBUFFReg
168  *      Pointer to the CBUFF Register space
169  *
170  *  \ingroup CBUFF_DRIVER_INTERNAL_FUNCTION
171  *
172  *  @retval
173  *      Not applicable
174  */
175 static void CBUFF_disableFrameDoneInt (CSL_CbuffRegs* ptrCBUFFReg)
177     /* Disable Frame Done:
178      *  - Interrupts are disabled by writing a 1 to the corresponding bits */
179     ptrCBUFFReg->CFG_MASK_REG0 = CSL_FINSR (ptrCBUFFReg->CFG_MASK_REG0,
180                                             STAT_CBUFF_REG0_S_FRAME_DONE_BIT_START,
181                                             STAT_CBUFF_REG0_S_FRAME_DONE_BIT_START,
182                                             1U);
185 /**
186  *  @b Description
187  *  @n
188  *      The function is used to enable the chirp done interrupt
189  *
190  *  @param[in]  ptrCBUFFReg
191  *      Pointer to the CBUFF Register space
192  *
193  *  \ingroup CBUFF_DRIVER_INTERNAL_FUNCTION
194  *
195  *  @retval
196  *      Not applicable
197  */
198 static void CBUFF_enableFrameDoneInt (CSL_CbuffRegs* ptrCBUFFReg)
200     /* Enable Frame Done:
201      *  - Interrupts are enabled by writing a 0 to the corresponding bits */
202     ptrCBUFFReg->CFG_MASK_REG0 = CSL_FINSR (ptrCBUFFReg->CFG_MASK_REG0,
203                                             STAT_CBUFF_REG0_S_FRAME_DONE_BIT_START,
204                                             STAT_CBUFF_REG0_S_FRAME_DONE_BIT_START,
205                                             0U);
208 /**
209  *  @b Description
210  *  @n
211  *      The function is used to disable the chirp done interrupts
212  *
213  *  @param[in]  ptrCBUFFReg
214  *      Pointer to the CBUFF Register space
215  *
216  *  \ingroup CBUFF_DRIVER_INTERNAL_FUNCTION
217  *
218  *  @retval
219  *      Not applicable
220  */
221 static void CBUFF_disableChirpDoneInt (CSL_CbuffRegs* ptrCBUFFReg)
223     /* Disable Chirp Done:
224      *  - Interrupts are disabled by writing a 1 to the corresponding bits */
225     ptrCBUFFReg->CFG_MASK_REG0 = CSL_FINSR (ptrCBUFFReg->CFG_MASK_REG0,
226                                             STAT_CBUFF_REG0_S_CHIRP_DONE_BIT_START,
227                                             STAT_CBUFF_REG0_S_CHIRP_DONE_BIT_START,
228                                             1U);
231 /**
232  *  @b Description
233  *  @n
234  *      The function is used to enable the chirp done interrupt
235  *
236  *  @param[in]  ptrCBUFFReg
237  *      Pointer to the CBUFF Register space
238  *
239  *  \ingroup CBUFF_DRIVER_INTERNAL_FUNCTION
240  *
241  *  @retval
242  *      Not applicable
243  */
244 static void CBUFF_enableChirpDoneInt (CSL_CbuffRegs* ptrCBUFFReg)
246     /* Enable Chirp Done:
247      *  - Interrupts are enabled by writing a 0 to the corresponding bits */
248     ptrCBUFFReg->CFG_MASK_REG0 = CSL_FINSR (ptrCBUFFReg->CFG_MASK_REG0,
249                                             STAT_CBUFF_REG0_S_CHIRP_DONE_BIT_START,
250                                             STAT_CBUFF_REG0_S_CHIRP_DONE_BIT_START,
251                                             0U);
254 /**
255  *  @b Description
256  *  @n
257  *      The function is used to enable the error interrupts associated with the
258  *      CBUFF Module
259  *
260  *  @param[in]  ptrCBUFFReg
261  *      Pointer to the CBUFF Register space
262  *
263  *  \ingroup CBUFF_DRIVER_INTERNAL_FUNCTION
264  *
265  *  @retval
266  *      Not applicable
267  */
268 static void CBUFF_enableErrorInt (CSL_CbuffRegs* ptrCBUFFReg)
270     /* Enable Frame Start Error & Chirp Error:
271      *  - Interrupts are enabled by writing a 0 to the corresponding bits */
272     ptrCBUFFReg->CFG_MASK_REG1 = CSL_FINSR (ptrCBUFFReg->CFG_MASK_REG1,
273                                             STAT_CBUFF_REG1_S_FRAME_ERR_BIT_START,
274                                             STAT_CBUFF_REG1_S_FRAME_ERR_BIT_START,
275                                             0U);
276     ptrCBUFFReg->CFG_MASK_REG1 = CSL_FINSR (ptrCBUFFReg->CFG_MASK_REG1,
277                                             STAT_CBUFF_REG1_S_CHIRP_ERR_BIT_START,
278                                             STAT_CBUFF_REG1_S_CHIRP_ERR_BIT_START,
279                                             0U);
282 /**
283  *  @b Description
284  *  @n
285  *      The function is used to disable the error interrupts associated with the
286  *      CBUFF Module
287  *
288  *  @param[in]  ptrCBUFFReg
289  *      Pointer to the CBUFF Register space
290  *
291  *  \ingroup CBUFF_DRIVER_INTERNAL_FUNCTION
292  *
293  *  @retval
294  *      Not applicable
295  */
296 static void CBUFF_disableErrorInt(CSL_CbuffRegs* ptrCBUFFReg)
298     /* Enable Frame Start Error & Chirp Error:
299      *  - Interrupts are disabled by writing a 1 to the corresponding bits */
300     ptrCBUFFReg->CFG_MASK_REG1 = CSL_FINSR (ptrCBUFFReg->CFG_MASK_REG1,
301                                             STAT_CBUFF_REG1_S_FRAME_ERR_BIT_START,
302                                             STAT_CBUFF_REG1_S_FRAME_ERR_BIT_START,
303                                             1U);
304     ptrCBUFFReg->CFG_MASK_REG1 = CSL_FINSR (ptrCBUFFReg->CFG_MASK_REG1,
305                                             STAT_CBUFF_REG1_S_CHIRP_ERR_BIT_START,
306                                             STAT_CBUFF_REG1_S_CHIRP_ERR_BIT_START,
307                                             1U);
310 /**
311  *  @b Description
312  *  @n
313  *      The function is used to get the CBUFF status.
314  *
315  *  @param[in]  ptrCBUFFReg
316  *      Pointer to the CBUFF Register space
317  *  @param[out]  isFrameDone
318  *      Set to 1 to indicate that the frame has been done
319  *  @param[out]  isChirpDone
320  *      Set to 1 to indicate that the chirp has been done
321  *
322  *  \ingroup CBUFF_DRIVER_INTERNAL_FUNCTION
323  *
324  *  @retval
325  *      Not applicable
326  */
327 static void CBUFF_getStatus (CSL_CbuffRegs* ptrCBUFFReg, uint8_t* isFrameDone, uint8_t* isChirpDone)
329     *isFrameDone = (uint8_t)CSL_FEXTR (ptrCBUFFReg->STAT_CBUFF_REG0, 12U, 12U);
330     *isChirpDone = (uint8_t)CSL_FEXTR (ptrCBUFFReg->STAT_CBUFF_REG0, 11U, 11U);
333 /**
334  *  @b Description
335  *  @n
336  *      The function is used to clear the CBUFF status.
337  *
338  *  @param[in]  ptrCBUFFReg
339  *      Pointer to the CBUFF Register space
340  *  @param[in]  isFrameDone
341  *      Set to 1 to clear the Frame Done Status
342  *  @param[out]  isChirpDone
343  *      Set to 1 to clear the Chirp Done Status
344  *
345  *  \ingroup CBUFF_DRIVER_INTERNAL_FUNCTION
346  *
347  *  @retval
348  *      Not applicable
349  */
350 static void CBUFF_clearStatus (CSL_CbuffRegs* ptrCBUFFReg, uint8_t isFrameDone, uint8_t isChirpDone)
352     ptrCBUFFReg->CLR_CBUFF_REG0 = CSL_FINSR (ptrCBUFFReg->CLR_CBUFF_REG0, 12U, 12U, (uint32_t)isFrameDone);
353     ptrCBUFFReg->CLR_CBUFF_REG0 = CSL_FINSR (ptrCBUFFReg->CLR_CBUFF_REG0, 11U, 11U, (uint32_t)isChirpDone);
356 /**
357  *  @b Description
358  *  @n
359  *      The function is used to set the software triggerring capability of the frame start
360  *
361  *  @param[in]  ptrCBUFFReg
362  *      Pointer to the CBUFF Register space
363  *  @param[in]  enableSW
364  *      Set to 1 to enable the triggering be done by the SW else set to 0
365  *
366  *  \ingroup CBUFF_DRIVER_INTERNAL_FUNCTION
367  *
368  *  @retval
369  *      Not applicable
370  */
371 static void CBUFF_setFrameStartSWTrigger (CSL_CbuffRegs* ptrCBUFFReg, uint32_t enableSW)
373     ptrCBUFFReg->CONFIG_REG_0 = CSL_FINSR (ptrCBUFFReg->CONFIG_REG_0, 2U, 2U, enableSW);
376 /**
377  *  @b Description
378  *  @n
379  *      The function is used to set the software triggerring capability of the chirp available
380  *
381  *  @param[in]  ptrCBUFFReg
382  *      Pointer to the CBUFF Register space
383  *  @param[in]  enableSW
384  *      Set to 1 to enable the triggering be done by the SW else set to 0
385  *
386  *  \ingroup CBUFF_DRIVER_INTERNAL_FUNCTION
387  *
388  *  @retval
389  *      Not applicable
390  */
391 static void CBUFF_setChirpAvailableSWTrigger (CSL_CbuffRegs* ptrCBUFFReg, uint32_t enableSW)
393     ptrCBUFFReg->CONFIG_REG_0 = CSL_FINSR (ptrCBUFFReg->CONFIG_REG_0, 3U, 3U, enableSW);
396 /**
397  *  @b Description
398  *  @n
399  *      The function is used to trigger the frame start. This function should only be
400  *      invoked if the software has assumed the responsibility for triggering the frame
401  *      start
402  *
403  *  @param[in]  ptrCBUFFReg
404  *      Pointer to the CBUFF Register space
405  *
406  *  \ingroup CBUFF_DRIVER_INTERNAL_FUNCTION
407  *
408  *  @retval
409  *      Not applicable
410  */
411 static void CBUFF_triggerFrameStart (CSL_CbuffRegs* ptrCBUFFReg)
413     ptrCBUFFReg->CONFIG_REG_0 = CSL_FINSR (ptrCBUFFReg->CONFIG_REG_0, 25U, 25U, 1U);
416 /**
417  *  @b Description
418  *  @n
419  *      The function is used to trigger the chirp available. This function should only be
420  *      invoked if the software has assumed the responsibility for triggering the chirp
421  *      available
422  *
423  *  @param[in]  ptrCBUFFReg
424  *      Pointer to the CBUFF Register space
425  *
426  *  \ingroup CBUFF_DRIVER_INTERNAL_FUNCTION
427  *
428  *  @retval
429  *      Not applicable
430  */
431 static void CBUFF_triggerChirpAvailable (CSL_CbuffRegs* ptrCBUFFReg)
433     ptrCBUFFReg->CONFIG_REG_0 = CSL_FINSR (ptrCBUFFReg->CONFIG_REG_0, 24U, 24U, 1U);
436 /**
437  *  @b Description
438  *  @n
439  *      The function is used to set the number of chirps
440  *
441  *  @param[in]  ptrCBUFFReg
442  *      Pointer to the CBUFF Register space
443  *  @param[in]  numChirps
444  *      Number of chirps to be configured
445  *
446  *  \ingroup CBUFF_DRIVER_INTERNAL_FUNCTION
447  *
448  *  @retval
449  *      Not applicable
450  */
451 static void CBUFF_setNumberChirps (CSL_CbuffRegs* ptrCBUFFReg, uint32_t numChirps)
453     ptrCBUFFReg->CFG_CHIRPS_PER_FRAME = numChirps;
456 /**
457  *  @b Description
458  *  @n
459  *      The function is used to clear the linked list entry in the CBUFF IP
460  *
461  *  @param[in]  ptrCBUFFReg
462  *      Pointer to the CBUFF Register space
463  *  @param[in]  listIndex
464  *      Linked List index to be cleared.
465  *
466  *  \ingroup CBUFF_DRIVER_INTERNAL_FUNCTION
467  *
468  *  @retval
469  *      Not applicable
470  */
471 static void CBUFF_clearLLEntry (CSL_CbuffRegs* ptrCBUFFReg, uint8_t listIndex)
473     /* Reset the LL to the default values. */
474     ptrCBUFFReg->LL_ENTRY[listIndex].CFG_DATA_LL           = 0U;
475     ptrCBUFFReg->LL_ENTRY[listIndex].CFG_DATA_LL_LPHDR_VAL = 0U;
476     ptrCBUFFReg->LL_ENTRY[listIndex].CFG_DATA_LL_THRESHOLD = CSL_FMKR (14U, 8U, 0x3FU);
479 /**
480  *  @b Description
481  *  @n
482  *      The function is used to set the linked list entry in the CBUFF IP
483  *
484  *  @param[in]  ptrCBUFFReg
485  *      Pointer to the CBUFF Register space
486  *  @param[in]  listIndex
487  *      Linked List index to be configured.
488  *  @param[in]  ptrLLParams
489  *      Pointer to the Linked list params used to set the LL entry
490  *
491  *  \ingroup CBUFF_DRIVER_INTERNAL_FUNCTION
492  *
493  *  @retval
494  *      Not applicable
495  */
496 static void CBUFF_setLLEntry (CSL_CbuffRegs* ptrCBUFFReg, uint8_t listIndex, CBUFF_LinkListParams* ptrLLParams)
498     /* Sanity Check: This should never occur and the transfer size should always be within the IP Limits */
499     DebugP_assert (ptrLLParams->transferSize <= CBUFF_MAX_TRANSFER_SIZE_CBUFF_UNITS);
501     /* Setup the linked list data:
502      *  - CRC Enable as per the specified configuration
503      *  - LP Header as per the specified configuration
504      *  - Wait for Packet sent is enabled
505      *  - Size as per the specified configuration
506      *  - Data Formating of the incoming data sources [128bit(0) or 96bit (1)]
507      *  - Data Format map applicable only for LVDS.
508      *  - LVDS/CSI2 Output format i.e. 16bit, 14bit or 12bit
509      *  - Number of the virtual channel
510      *  - Horizontal Sync Start as per the specified configuration
511      *  - Horizontal Sync End as per the specified configuration
512      *  - Linked List entry is valid */
513     ptrCBUFFReg->LL_ENTRY[listIndex].CFG_DATA_LL =
514              CSL_FMKR (28U, 28U, ptrLLParams->crcEnable)        |
515              CSL_FMKR (27U, 27U, ptrLLParams->lpHdrEn)          |
516              CSL_FMKR (22U, 9U,  ptrLLParams->transferSize)     |
517              CSL_FMKR (8U,  8U,  ptrLLParams->align96)          |
518              CSL_FMKR (7U,  7U,  ptrLLParams->dataFmtMap)       |
519              CSL_FMKR (6U,  5U,  ptrLLParams->outputDataFmt)    |
520              CSL_FMKR (4U,  3U,  ptrLLParams->vcNum)            |
521              CSL_FMKR (2U,  2U,  ptrLLParams->hsyncStart)       |
522              CSL_FMKR (1U,  1U,  ptrLLParams->hsyncEnd)         |
523              CSL_FMKR (0U,  0U,  1U);
525     /* Set the Long Packet Header & Thresholds: */
526     ptrCBUFFReg->LL_ENTRY[listIndex].CFG_DATA_LL_LPHDR_VAL = ptrLLParams->lpHeaderValue;
527     ptrCBUFFReg->LL_ENTRY[listIndex].CFG_DATA_LL_THRESHOLD = ptrLLParams->threshold;
530 /**
531  *  @b Description
532  *  @n
533  *      The function is used to configure the VSYNC parameters for a specific
534  *      virtual channel.
535  *
536  *  @param[in]  ptrCBUFFReg
537  *      Pointer to the CBUFF Register space
538  *  @param[in]  vc
539  *      Virtual channel [Valid from 0 to 3]
540  *  @param[in]  vcStart
541  *      Flag to enable/disable the VSYNC Start
542  *  @param[in]  vcEnd
543  *      Flag to enable/disable the VSYNC End
544  *
545  *  \ingroup CBUFF_DRIVER_INTERNAL_FUNCTION
546  *
547  *  @retval
548  *      Not applicable
549  */
550 void CBUFF_setVC (CSL_CbuffRegs* ptrCBUFFReg, uint8_t vc, uint8_t vcStart, uint8_t vcEnd)
552     switch (vc)
553     {
554         case 0U:
555         {
556             ptrCBUFFReg->CONFIG_REG_0 = CSL_FINSR (ptrCBUFFReg->CONFIG_REG_0, 10U, 10U, (uint32_t)vcStart);
557             ptrCBUFFReg->CONFIG_REG_0 = CSL_FINSR (ptrCBUFFReg->CONFIG_REG_0, 11U, 11U, (uint32_t)vcEnd);
558             break;
559         }
560         case 1U:
561         {
562             ptrCBUFFReg->CONFIG_REG_0 = CSL_FINSR (ptrCBUFFReg->CONFIG_REG_0, 12U, 12U, (uint32_t)vcStart);
563             ptrCBUFFReg->CONFIG_REG_0 = CSL_FINSR (ptrCBUFFReg->CONFIG_REG_0, 13U, 13U, (uint32_t)vcEnd);
564             break;
565         }
566         case 2U:
567         {
568             ptrCBUFFReg->CONFIG_REG_0 = CSL_FINSR (ptrCBUFFReg->CONFIG_REG_0, 14U, 14U, (uint32_t)vcStart);
569             ptrCBUFFReg->CONFIG_REG_0 = CSL_FINSR (ptrCBUFFReg->CONFIG_REG_0, 15U, 15U, (uint32_t)vcEnd);
570             break;
571         }
572         case 3U:
573         {
574             ptrCBUFFReg->CONFIG_REG_0 = CSL_FINSR (ptrCBUFFReg->CONFIG_REG_0, 16U, 16U, (uint32_t)vcStart);
575             ptrCBUFFReg->CONFIG_REG_0 = CSL_FINSR (ptrCBUFFReg->CONFIG_REG_0, 17U, 17U, (uint32_t)vcEnd);
576             break;
577         }
578         default:
579         {
580             DebugP_assert (0);
581             break;
582         }
583     }
586 /**
587  *  @b Description
588  *  @n
589  *      This is the function which is used to validate the buffers
590  *      configuration. User buffers passed by the applications for
591  *      either the header *OR* data buffers need to be placed into
592  *      the EDMA address space.
593  *
594  *  @param[in]  ptrUserBuffer
595  *      Pointer to the user buffer which needs to be validated
596  *  @param[out] errCode
597  *      Error code populated on the error
598  *
599  *  \ingroup CBUFF_DRIVER_INTERNAL_FUNCTION
600  *
601  *  @retval
602  *      Success -   0
603  *  @retval
604  *      Error   -   <0
605  */
606 static int32_t CBUFF_validateBufferCfg (CBUFF_BufferCfg* ptrUserBuffer, int32_t* errCode)
608     int32_t     retVal = -1;
609     
610     /* Sanity Check: Ensure that the size does not exceed the MAXIMUM CBUFF IP Size */
611     if (ptrUserBuffer->size > CBUFF_MAX_TRANSFER_SIZE_CBUFF_UNITS)
612     {
613         /* Error: Invalid size exceeds the max which the IP block can support */
614         *errCode = CBUFF_ELIMIT;
615         return retVal;
616     }
618     /* Is the address specified? */
619     if (ptrUserBuffer->size != 0U)
620     {
621         /* YES: Translate to the EDMA space */
622         /* Update the configuration with the EDMA Address: This is what we will be using to
623          * setup the EDMA Transfers */
624         ptrUserBuffer->address = CSL_locToGlobAddr (ptrUserBuffer->address);
625     }
627     /* User buffers have been validated: */
628     retVal = 0;
630     return retVal;
633 /**
634  *  @b Description
635  *  @n
636  *      The function is the registered ISR for the CBUFF to handle the CBUFF
637  *      completion status
638  *
639  *  @param[in]  arg
640  *      Pointer to the CBUFF Driver MCB
641  *
642  *  \ingroup CBUFF_DRIVER_INTERNAL_FUNCTION
643  *
644  *  @retval
645  *      Not applicable
646  */
647 static void CBUFF_ISR (uintptr_t arg)
649     CBUFF_DriverMCB*        ptrDriverMCB;
650     uint8_t                 isFrameDone;
651     uint8_t                 isChirpDone;
652     CBUFF_Session*          ptrSession;
654     /* Get the pointer to the driver MCB: */
655     ptrDriverMCB = (CBUFF_DriverMCB*)arg;
657     /* Sanity Check: */
658     DebugP_assert (ptrDriverMCB != NULL);
660     /* Get the CBUFF Status: */
661     CBUFF_getStatus (ptrDriverMCB->ptrCBUFFReg, &isFrameDone, &isChirpDone);
663     /* Clear the CBUFF Status: */
664     CBUFF_clearStatus (ptrDriverMCB->ptrCBUFFReg, isFrameDone, isChirpDone);
666     /* Get the currently active session: */
667     ptrSession = ptrDriverMCB->ptrCurrentActiveSession;
668     if (ptrSession == NULL)
669     {
670         /* Record the number of the interrupts. */
671         ptrDriverMCB->totalNumNonActiveSessionInterrupts++;
672         return;
673     }
675     /* Was the frame processed? */
676     if (isFrameDone == 1U)
677     {
678         /* YES: The frame was processed. Increment the statistics */
679         ptrDriverMCB->totalNumFrameDone++;
681         /* Increment the statistics for the session */
682         ptrSession->numFrameDone++;
684         /* Do we need to invoke the callback function? */
685         if (ptrSession->sessionCfg.frameDoneCallbackFxn != NULL)
686         {
687             /* YES: Notify the callback function that the frame done was received for the
688              * active session. */
689             ptrSession->sessionCfg.frameDoneCallbackFxn ((CBUFF_SessionHandle)ptrSession);
690         }
691     }
693     /* Are we operating in debug mode? */
694     if (ptrDriverMCB->initCfg.enableDebugMode == true)
695     {
696         /* Was the chirp processed? */
697         if (isChirpDone == 1U)
698         {
699             /* YES: The chirp was handled. Increment the statistics */
700             ptrDriverMCB->totalNumChirpDone++;
702             /* Increment the statistics for the session */
703             ptrSession->numChirpDone++;
704         }
705     }
707     return;
710 /**
711  *  @b Description
712  *  @n
713  *      The function is the registered ISR for the CBUFF to handle the
714  *      CBUFF errors
715  *
716  *  @param[in]  arg
717  *      Pointer to the CBUFF Driver MCB
718  *
719  *  \ingroup CBUFF_DRIVER_INTERNAL_FUNCTION
720  *
721  *  @retval
722  *      Not applicable
723  */
724 static void CBUFF_ErrorISR (uintptr_t arg)
726     CBUFF_DriverMCB*        ptrDriverMCB;
728     /* Get the pointer to the driver MCB: */
729     ptrDriverMCB = (CBUFF_DriverMCB*)arg;
731     /* Sanity Check: */
732     DebugP_assert (ptrDriverMCB != NULL);
734     /* Increment the error counter */
735     ptrDriverMCB->totalNumErrorInterrupts++;
736     return;
739 /**
740  *  @b Description
741  *  @n
742  *      The function is the registered ISR for the CBUFF to handle
743  *      the start of the frame
744  *
745  *  @param[in]  arg
746  *      Pointer to the CBUFF Driver MCB
747  *
748  *  \ingroup CBUFF_DRIVER_INTERNAL_FUNCTION
749  *
750  *  @retval
751  *      Not applicable
752  */
753 static void CBUFF_FrameStartISR (uintptr_t arg)
755     CBUFF_DriverMCB*        ptrDriverMCB;
757     /* Get the pointer to the driver MCB: */
758     ptrDriverMCB = (CBUFF_DriverMCB*)arg;
760     /* Sanity Check: */
761     DebugP_assert (ptrDriverMCB != NULL);
763     /* Increment the frame start counter */
764     ptrDriverMCB->totalNumFrameStart++;
765     return;
768 /**
769  *  @b Description
770  *  @n
771  *      The function is used to validate the high speed interface with the platform
772  *      supplied interface table.
773  *
774  *  @param[in]  interface
775  *      Interface to be verified
776  *
777  *  \ingroup CBUFF_DRIVER_INTERNAL_FUNCTION
778  *
779  *  @retval
780  *      Success     - Supported interface function block
781  *  @retval
782  *      Error       - NULL
783  */
784 static CBUFF_InterfaceFxn* CBUFF_isIfSupported (CBUFF_Interface interface)
786     uint8_t             ifIndex = 0U;
787     CBUFF_InterfaceFxn* ptrInterfaceFxn;
788     int32_t             done = 0;
790     /* Initialize the interface function to the platform supplied definition */
791     while (done == 0)
792     {
793         /* Get the interface block: */
794         ptrInterfaceFxn = &gCBUFFInterfaceFxn[ifIndex];
796         /* Is this a valid interface or the end of the table? */
797         if (ptrInterfaceFxn->initFxn != NULL)
798         {
799             /* YES: Do we have a match on the interface? */
800             if (interface == ptrInterfaceFxn->interface)
801             {
802                 /* YES: We have found a match. */
803                 done = 1;
804             }
805             else
806             {
807                 /* NO: Skip to the next entry in the platform table */
808                 ifIndex++;
809             }
810         }
811         else
812         {
813             /* NO: We have reached the end of the platform table and have not found a match. */
814             ptrInterfaceFxn = NULL;
815             done = 1;
816         }
817     }
818     return ptrInterfaceFxn;
821 /**
822  *  @b Description
823  *  @n
824  *      The function is used to free an allocated session
825  *
826  *  @param[in]  ptrSession
827  *      Pointer to the session to be freed up
828  *
829  *  \ingroup CBUFF_DRIVER_INTERNAL_FUNCTION
830  *
831  *  @retval
832  *      Not applicable
833  */
834 static void CBUFF_freeSession (CBUFF_Session* ptrSession)
836     CBUFF_DriverMCB*    ptrDriverMCB;
837     uint8_t             dmaNum;
839     /* Keep a local copy of the session information */
840     ptrDriverMCB = ptrSession->ptrDriverMCB;
841     dmaNum       = ptrSession->dmaNum;
843     /* Reset the contents of the session memory: */
844     memset ((void*)ptrSession, 0, sizeof(CBUFF_Session));
846     /* Update session back: */
847     ptrSession->ptrDriverMCB = ptrDriverMCB;
848     ptrSession->dmaNum       = dmaNum;
851 /**
852  *  @b Description
853  *  @n
854  *      The function is used to allocate a session block
855  *
856  *  @param[in]  ptrDriverMCB
857  *      Pointer to the driver MCB
858  *
859  *  \ingroup CBUFF_DRIVER_INTERNAL_FUNCTION
860  *
861  *  @retval
862  *      Success - Allocated session handle
863  *  @retval
864  *      Error   - NULL
865  */
866 static CBUFF_Session* CBUFF_allocateSession (CBUFF_DriverMCB* ptrDriverMCB)
868     uint8_t         sessionIndex;
869     CBUFF_Session*  ptrSession;
870     uintptr_t       key;
872     /* Disable the interrupts: The session table is a critical resource which needs
873      * to be protected against concurrent access from multiple threads. */
874     key = HwiP_disable();
876     /* Cycle through all the sessions: */
877     for (sessionIndex = 0U; sessionIndex < ptrDriverMCB->initCfg.maxSessions; sessionIndex++)
878     {
879         /* Get the session: */
880         ptrSession = &ptrDriverMCB->ptrSessionTable[sessionIndex];
882         /* Is the session valid and in use? */
883         if (ptrSession->isValid == false)
884         {
885             /* NO: Session is free and can be used. */
886             ptrSession->isValid = true;
887             break;
888         }
889     }
891     /* Were we able to allocate a session? */
892     if (sessionIndex == ptrDriverMCB->initCfg.maxSessions)
893     {
894         /* NO: Reached the end of the table and unable to find a free slot */
895         ptrSession = NULL;
896     }
898     /* Restore the interrupts: Session allocation has been completed. */
899     HwiP_restore (key);
901     /* Return the session: */
902     return ptrSession;
905 /**
906  *  @b Description
907  *  @n
908  *      The function is used to register the frame done interrupts.
909  *      If applications are executing only one session we dont want
910  *      to overwhelm the processor with frame done interrupts. Frame
911  *      done interrupts should only be used if there are multiple
912  *      sessions which are getting activated and the application has
913  *      registered for callback functions.
914  *
915  *  @param[in]  ptrDriverMCB
916  *      Pointer to the driver MCB
917  *
918  *  \ingroup CBUFF_DRIVER_INTERNAL_FUNCTION
919  *
920  *  @retval
921  *      Not applicable
922  */
923 static void CBUFF_registerFrameDone (CBUFF_DriverMCB* ptrDriverMCB)
925     uint8_t         sessionIndex;
926     CBUFF_Session*  ptrSession;
928     /* Is the debug mode enabled? */
929     if (ptrDriverMCB->initCfg.enableDebugMode == true)
930     {
931         /* YES: Frame done interrupts are already registered. There is no need
932          * to perform any other actions. */
933         return;
934     }
936     /* Cycle through all the sessions: */
937     for (sessionIndex = 0U; sessionIndex < ptrDriverMCB->initCfg.maxSessions; sessionIndex++)
938     {
939         /* Get the session: */
940         ptrSession = &ptrDriverMCB->ptrSessionTable[sessionIndex];
942         /* Is the session valid and does it need the frame done callback? */
943         if ((ptrSession->isValid == true) && (ptrSession->sessionCfg.frameDoneCallbackFxn != NULL))
944         {
945             /* YES: Frame Done interrupt notifications are required. */
946             CBUFF_enableFrameDoneInt (ptrDriverMCB->ptrCBUFFReg);
947             break;
948         }
949     }
951     return;
954 /**
955  *  @b Description
956  *  @n
957  *      The function is used to deregister the frame done interrupts.
958  *      If there are no active sessions which require this functionality
959  *      then we can deregister this interrupt and not take a performance
960  *      hit for these interrupts.
961  *
962  *  @param[in]  ptrDriverMCB
963  *      Pointer to the driver MCB
964  *
965  *  \ingroup CBUFF_DRIVER_INTERNAL_FUNCTION
966  *
967  *  @retval
968  *      Not applicable
969  */
970 static void CBUFF_deregisterFrameDone (CBUFF_DriverMCB* ptrDriverMCB)
972     uint8_t         sessionIndex;
973     CBUFF_Session*  ptrSession;
974     uint8_t         isFrameDone;
975     uint8_t         isChirpDone;
977     /* Is the debug mode enabled? */
978     if (ptrDriverMCB->initCfg.enableDebugMode == true)
979     {
980         /* YES: Executing in debug mode. There is no need to perform any deregisteration
981          * We need to keep the interrupts always registered. */
982         return;
983     }
985     /* Cycle through all the sessions: */
986     for (sessionIndex = 0U; sessionIndex < ptrDriverMCB->initCfg.maxSessions; sessionIndex++)
987     {
988         /* Get the session: */
989         ptrSession = &ptrDriverMCB->ptrSessionTable[sessionIndex];
991         /* Is the session valid and does it need the frame done callback? */
992         if ((ptrSession->isValid == true) && (ptrSession->sessionCfg.frameDoneCallbackFxn != NULL))
993         {
994             break;
995         }
996     }
997     if (sessionIndex == ptrDriverMCB->initCfg.maxSessions)
998     {
999         /* Control comes here indicates that there were no either:-
1000          * (a) No more active sessions  *OR*
1001          * (b) None of the sessions needed the frame done functionality
1002          *
1003          * So we can deregister the ISR and avoid the performance penalty. */
1004         CBUFF_disableFrameDoneInt (ptrDriverMCB->ptrCBUFFReg);
1006         /* We have disabled the interrupts but if there are any pending interrupts
1007          * then these need to be acknowledged here; else we will not get any more
1008          * interrupts. */
1009         CBUFF_getStatus (ptrDriverMCB->ptrCBUFFReg, &isFrameDone, &isChirpDone);
1010         CBUFF_clearStatus (ptrDriverMCB->ptrCBUFFReg, isFrameDone, isChirpDone);
1011     }
1013     return;
1016 /**
1017  *  @b Description
1018  *  @n
1019  *      The function is used to validate the HW Session configuration.
1020  *
1021  *  @param[in]  ptrSession
1022  *      Pointer to the session
1023  *  @param[out] errCode
1024  *      Error code populated on error
1025  *
1026  *  \ingroup CBUFF_DRIVER_INTERNAL_FUNCTION
1027  *
1028  *  @retval
1029  *      Success     - 0
1030  *  @retval
1031  *      Error       - <0
1032  */
1033 static int32_t CBUFF_validateHWSessionCfg (CBUFF_Session* ptrSession, int32_t* errCode)
1035     uint32_t            index;
1036     ADCBufMMWave_CQType cqType;
1037     int32_t             retVal = MINUS_ONE;
1039     /************************************************************************
1040      * Sanity Check: Continuous mode is *NOT* supported for all data formats
1041      ************************************************************************/
1042     if (ptrSession->sessionCfg.u.hwCfg.opMode == CBUFF_OperationalMode_CONTINUOUS)
1043     {
1044         /* Sanity Check: Curently only the ADC Data mode is supported with continuous mode */
1045         if (ptrSession->sessionCfg.u.hwCfg.dataFormat != CBUFF_DataFmt_ADC_DATA)
1046         {
1047             *errCode = CBUFF_ENOTSUP;
1048             return retVal;
1049         }
1051         /* Sanity Check: Ensure that the chirp mode is correctly configured */
1052         if (ptrSession->sessionCfg.u.hwCfg.chirpMode != 0U)
1053         {
1054             *errCode = CBUFF_EINVAL;
1055             return retVal;
1056         }
1057     }
1058     else
1059     {
1060         /* Sanity Check: Validate the range. (Single or Multiple Chirp) */
1061         if ((ptrSession->sessionCfg.u.hwCfg.chirpMode < gCBUFFHwAttribute.chirpModeStartIndex) ||
1062             (ptrSession->sessionCfg.u.hwCfg.chirpMode > gCBUFFHwAttribute.chirpModeEndIndex))
1063         {
1064             /* Error: The chirp mode is not within the supported range */
1065             *errCode = CBUFF_EINVAL;
1066             return retVal;
1067         }
1068     }
1070     /************************************************************************
1071      * Sanity Check: Validate the user buffers
1072      ************************************************************************/
1073     if ((ptrSession->sessionCfg.u.hwCfg.dataFormat == CBUFF_DataFmt_ADC_USER) ||
1074         (ptrSession->sessionCfg.u.hwCfg.dataFormat == CBUFF_DataFmt_CP_ADC_CQ_USER))
1075     {
1076         /* User data will be streamed out: */
1077         for (index = 0U; index < CBUFF_MAX_USER_BUFFER; index++)
1078         {
1079             /* Validate the user buffers to make sure these can be streamed out via the CBUFF */
1080             if (CBUFF_validateBufferCfg (&ptrSession->sessionCfg.u.hwCfg.userBufferInfo[index], errCode) < 0)
1081             {
1082                 /* Error: Invalid user buffer configuration error code is already setup */
1083                 return retVal;
1084             }
1085         }
1086     }
1088     /* Cycle through the configuration and process it */
1089     ptrSession->numActiveADCChannels = 0U;
1090     for (index = 0U; index < NUM_RX_CHANNEL; index++)
1091     {
1092         /* Get the ADCBUF Channel Address from the ADCBUFFF registers */
1093         ptrSession->rxChannelAddress[index] = ADCBuf_getChanBufAddr (ptrSession->sessionCfg.u.hwCfg.adcBufHandle, index, errCode);
1095         if (ptrSession->rxChannelAddress[index] != 0U)
1096         {
1097             /* YES: Increment the number of active ADC channels */
1098             ptrSession->numActiveADCChannels++;
1100             /* Translate the address to EDMA:  */
1101             ptrSession->rxChannelAddress[index] = CSL_locToGlobAddr(ptrSession->rxChannelAddress[index]);
1103             /* Track the cumulative Chirp Parameter Transfer Size */
1104             ptrSession->cpTotalTransferSize = ptrSession->cpTotalTransferSize + CP_SIZE_CBUFF_UNITS;
1105         }
1106     }
1108     /************************************************************************
1109      * Sanity Check: ADC channels should be configured and be enabled
1110      ************************************************************************/
1111     if (ptrSession->numActiveADCChannels == 0U)
1112     {
1113         /* Error: No ADC channel has been enabled. We cannot calculate the ADC channel address
1114          * and setup the EDMA chains before the ADC is configured. */
1115         *errCode = CBUFF_EINVAL;
1116         return retVal;
1117     }
1119     /************************************************************************
1120      * Sanity Check: Chirp Quality
1121      ************************************************************************/
1122     if ((ptrSession->sessionCfg.u.hwCfg.dataFormat == CBUFF_DataFmt_CP_ADC_CQ) ||
1123         (ptrSession->sessionCfg.u.hwCfg.dataFormat == CBUFF_DataFmt_CP_ADC_CQ_USER))
1124     {
1125         /* Initialize the CQ */
1126         ptrSession->numCQ = 0U;
1128         /* Cycle through all the Chirp Quality: */
1129         for (cqType = ADCBufMMWave_CQType_CQ0; cqType < ADCBufMMWave_CQType_MAX_CQ; cqType++)
1130         {
1131             /* Do we have a valid CQ to be streamed out? */
1132             if (ptrSession->sessionCfg.u.hwCfg.cqSize[cqType] != 0U)
1133             {
1134                 /* YES: Get the CQ Base address from the ADC Driver */
1135                 ptrSession->cqBuffer[ptrSession->numCQ].address = ADCBUF_MMWave_getCQBufAddr(ptrSession->sessionCfg.u.hwCfg.adcBufHandle, 
1136                                                                                              cqType, errCode);
1138                 if (ptrSession->cqBuffer[ptrSession->numCQ].address == 0U)
1139                 {
1140                     /* Error: Unable to get the base address; error code is already setup */
1141                     return retVal;
1142                 }
1144                 /* Translate the address to EDMA: */
1145                 ptrSession->cqBuffer[ptrSession->numCQ].address = CSL_locToGlobAddr(ptrSession->cqBuffer[ptrSession->numCQ].address);
1147                 /* Store the CQn Size: */
1148                 ptrSession->cqBuffer[ptrSession->numCQ].size = ptrSession->sessionCfg.u.hwCfg.cqSize[cqType];
1150                 /* Increment the detected number of CQ: */
1151                 ptrSession->numCQ++;
1152             }
1153         }
1155         /* Sanity Check: Do we have at least 1 CQ to be streamed out. */
1156         if (ptrSession->numCQ == 0U)
1157         {
1158             /* Error: There is no CQ. */
1159             *errCode = CBUFF_EINVAL;
1160             return retVal;
1161         }
1162     }
1164     /* HW Session configuration has been validated */
1165     retVal = 0;
1167     return retVal;
1170 /**
1171  *  @b Description
1172  *  @n
1173  *      The function is used to validate the SW Session configuration.
1174  *
1175  *  @param[in]  ptrSession
1176  *      Pointer to the session
1177  *  @param[out] errCode
1178  *      Error code populated on error
1179  *
1180  *  \ingroup CBUFF_DRIVER_INTERNAL_FUNCTION
1181  *
1182  *  @retval
1183  *      Success     - 0
1184  *  @retval
1185  *      Error       - <0
1186  */
1187 static int32_t CBUFF_validateSWSessionCfg (CBUFF_Session* ptrSession, int32_t* errCode)
1189     uint32_t    index;
1190     int32_t     retVal = MINUS_ONE;
1192     /************************************************************************
1193      * Sanity Check: Validate the user buffers
1194      ************************************************************************/
1195     for (index = 0U; index < CBUFF_MAX_USER_BUFFER; index++)
1196     {
1197         /* Validate the user buffers to make sure these can be streamed out via the CBUFF */
1198         if (CBUFF_validateBufferCfg (&ptrSession->sessionCfg.u.swCfg.userBufferInfo[index], errCode) < 0)
1199         {
1200             /* Error: Invalid user buffer configuration error code is already setup */
1201             return retVal;
1202         }
1203     }
1205     /* SW Session configuration has been validated */
1206     retVal = 0;
1208     return retVal;
1211 /**
1212  *  @b Description
1213  *  @n
1214  *      The function is used to deactivate the session.
1215  *
1216  *  @param[in]  sessionHandle
1217  *      Handle to the session to be activated
1218  *  @param[out] errCode
1219  *      Error code populated on error
1220  *
1221  *  \ingroup CBUFF_DRIVER_EXTERNAL_FUNCTION
1222  *
1223  *  @retval
1224  *      Success     - 0
1225  *  @retval
1226  *      Error       - <0
1227  */
1228 int32_t CBUFF_deactivateSession (CBUFF_SessionHandle sessionHandle, int32_t* errCode)
1230     int32_t             retVal = MINUS_ONE;
1231     CBUFF_DriverMCB*    ptrDriverMCB;
1232     CBUFF_Session*      ptrSession;
1233     uint8_t             index;
1235     /* Get the pointer to the session: */
1236     ptrSession = (CBUFF_Session*)sessionHandle;
1237     if (ptrSession == NULL)
1238     {
1239         *errCode = CBUFF_EINVAL;
1240         return retVal;
1241     }
1243     /* Sanity Check: Ensure that there exists a back pointer to the CBUFF Driver */
1244     ptrDriverMCB = ptrSession->ptrDriverMCB;
1245     DebugP_assert (ptrDriverMCB != NULL);
1247     /* Sanity Check: Ensure that the session is currently active. If this is not active
1248      * we cannot deactivate it because we will cause random behavior. */
1249     if (ptrDriverMCB->ptrCurrentActiveSession != ptrSession)
1250     {
1251         *errCode = CBUFF_EINVAL;
1252         return retVal;
1253     }
1255     /* Clear out all the linked list entries in the CBUFF IP */
1256     for (index = 0U; index < CBUFF_MAX_LINKED_LIST_SIZE; index++)
1257     {
1258         CBUFF_clearLLEntry (ptrDriverMCB->ptrCBUFFReg, index);
1259     }
1261     /* Default State: The triggers are always owned by the software. Frame Starts from
1262      * the BSS can cause the CBUFF IP to falsely kickstart the state machine especially
1263      * if there is no active session */
1264     CBUFF_setFrameStartSWTrigger (ptrDriverMCB->ptrCBUFFReg, 1U);
1265     CBUFF_setChirpAvailableSWTrigger (ptrDriverMCB->ptrCBUFFReg, 1U);
1267     /* Close the high speed interface (HSI) for the session: */
1268     DebugP_assert (ptrDriverMCB->interfaceFxn->closeFxn (ptrSession, errCode) == 0);
1270     /* The session is no longer active: */
1271     ptrDriverMCB->ptrCurrentActiveSession = NULL;
1273     /* Session has been deactivated successfully */
1274     retVal = 0;
1276     return retVal;
1279 int32_t CBUFF_activateSession (CBUFF_SessionHandle sessionHandle, int32_t* errCode)
1281     int32_t             retVal = MINUS_ONE;
1282     CBUFF_DriverMCB*    ptrDriverMCB;
1283     CBUFF_Session*      ptrSession;
1284     uint8_t             index;
1286     /* Get the pointer to the session: */
1287     ptrSession = (CBUFF_Session*)sessionHandle;
1288     if (ptrSession == NULL)
1289     {
1290         *errCode = CBUFF_EINVAL;
1291         return retVal;
1292     }
1294     /* Sanity Check: Ensure that there exists a back pointer to the CBUFF Driver */
1295     ptrDriverMCB = ptrSession->ptrDriverMCB;
1296     DebugP_assert (ptrDriverMCB != NULL);
1298     /* Is there a current session which is already active? */
1299     if (ptrDriverMCB->ptrCurrentActiveSession != NULL)
1300     {
1301         /* YES: Let the application deactivate it explicitly. */
1302         *errCode = CBUFF_EINUSE;
1303         return retVal;
1304     }
1306     /* The Linked List entries are already configured in the session. */
1307     for (index = 0U; index < ptrSession->linkListIndex; index++)
1308     {
1309         /* Configure the CBUFF IP Linked List Entry. */
1310         CBUFF_setLLEntry (ptrDriverMCB->ptrCBUFFReg, index, &ptrSession->linkedListTracker[index]);
1311     }
1313     /* Process the session configuration on the basis of the execution mode: */
1314     if (ptrSession->sessionCfg.executionMode == CBUFF_SessionExecuteMode_HW)
1315     {
1316         /* Hardware Triggered Execution Mode: Are we operating in chirp *or* continuous mode? */
1317         if (ptrSession->sessionCfg.u.hwCfg.opMode == CBUFF_OperationalMode_CONTINUOUS)
1318         {
1319             /* The Frame start needs to be triggered by the driver. */
1320             CBUFF_setFrameStartSWTrigger (ptrDriverMCB->ptrCBUFFReg, 1U);
1321             CBUFF_setChirpAvailableSWTrigger (ptrDriverMCB->ptrCBUFFReg, 0U);
1322         }
1323         else
1324         {
1325             /* HW Trigger Chirp Mode: The triggers are owned by the HW */
1326             CBUFF_setFrameStartSWTrigger (ptrDriverMCB->ptrCBUFFReg, 0U);
1327             CBUFF_setChirpAvailableSWTrigger (ptrDriverMCB->ptrCBUFFReg, 0U);
1328         }
1329     }
1330     else
1331     {
1332         /* Software Triggered Execution Mode: The chirp available & frame start needs to be triggered
1333          * by the driver. */
1334         CBUFF_setFrameStartSWTrigger (ptrDriverMCB->ptrCBUFFReg, 1U);
1335         CBUFF_setChirpAvailableSWTrigger (ptrDriverMCB->ptrCBUFFReg, 1U);
1336     }
1338     /* Setup the number of chirps per frame: */
1339     CBUFF_setNumberChirps (ptrDriverMCB->ptrCBUFFReg, ptrSession->numChirpsPerFrame);
1341     /* The session is now active and can be used. */
1342     ptrDriverMCB->ptrCurrentActiveSession = ptrSession;
1344     /* Open the high speed interface (HSI) for the session: */
1345     DebugP_assert (ptrDriverMCB->interfaceFxn->openFxn (ptrSession, errCode) == 0);
1347     /* We need to determine if we need to do the manual trigger sending of the packet.
1348      * This has to be done in the following cases:-
1349      *  (1) Hardware Triggerred Mode: Handle the continuous operational mode
1350      *  (2) Software Triggerred Mode */
1351     if (ptrSession->sessionCfg.executionMode == CBUFF_SessionExecuteMode_HW)
1352     {
1353         /* Are we operationg in continuous mode? */
1354         if (ptrSession->sessionCfg.u.hwCfg.opMode == CBUFF_OperationalMode_CONTINUOUS)
1355         {
1356             /* YES: We need to trigger the frame start manually for the first time only. */
1357             CBUFF_triggerFrameStart (ptrDriverMCB->ptrCBUFFReg);
1358         }
1359     }
1360     else
1361     {
1362         /* In Software Triggered mode: We need to trigger the frame start & chirp available */
1363         CBUFF_triggerFrameStart (ptrDriverMCB->ptrCBUFFReg);
1364         CBUFF_triggerChirpAvailable (ptrDriverMCB->ptrCBUFFReg);
1365     }
1367     /* Session has been activated: */
1368     retVal = 0;
1370     return retVal;
1373 /**
1374  *  @b Description
1375  *  @n
1376  *      The function is used to get/set information from the CBUFF Driver
1377  *
1378  *  @param[in]  cBuffHandle
1379  *      Handle to the driver
1380  *  @param[in]  cmd
1381  *      CBUFF command
1382  *  @param[in]  arg
1383  *      Command specified pointer to the argument
1384  *  @param[in]  argLen
1385  *      Length of the argument
1386  *  @param[out] errCode
1387  *      Error code populated on error
1388  *
1389  *  \ingroup CBUFF_DRIVER_EXTERNAL_FUNCTION
1390  *
1391  *  @retval
1392  *      Success     - 0
1393  *  @retval
1394  *      Error       - <0
1395  */
1396 int32_t CBUFF_control
1398     CBUFF_Handle    cBuffHandle,
1399     CBUFF_Command   cmd,
1400     void*           arg,
1401     uint32_t        argLen,
1402     int32_t*        errCode
1405     CBUFF_DriverMCB*    ptrDriverMCB;
1406     int32_t             retVal = MINUS_ONE;
1408     /* Sanity Check: Validate the arguments */
1409     ptrDriverMCB = (CBUFF_DriverMCB*)cBuffHandle;
1410     if (ptrDriverMCB == NULL)
1411     {
1412         *errCode = CBUFF_EINVAL;
1413         return retVal;
1414     }
1416     /* Process the command: */
1417     switch (cmd)
1418     {
1419         case CBUFF_Command_GET_CBUFF_STATS:
1420         {
1421             CBUFF_Stats*    ptrStats;
1422             uint32_t        stats;
1424             /* Sanity Check: Validate the command specific arguments */
1425             if ((arg == NULL) || (argLen != sizeof (CBUFF_Stats)))
1426             {
1427                 *errCode = CBUFF_EINVAL;
1428                 return retVal;
1429             }
1431             /* Get the pointer to the statistics: */
1432             ptrStats = (CBUFF_Stats*)arg;
1434             /* Read the statistics register */
1435             stats = ptrDriverMCB->ptrCBUFFReg->STAT_CBUFF_REG1;
1437             /* Populate the statistics: */
1438             ptrStats->frameStartError = CSL_FEXTR(stats, 17U, 17U);
1439             ptrStats->chirpError      = CSL_FEXTR(stats, 16U, 16U);
1441             /* Copy over the CBUFF statistics: */
1442             ptrStats->numFrameStart      = ptrDriverMCB->totalNumFrameStart;
1443             ptrStats->numFrameDone       = ptrDriverMCB->totalNumFrameDone;
1444             ptrStats->numChirpDone       = ptrDriverMCB->totalNumChirpDone;
1445             ptrStats->numErrorInterrupts = ptrDriverMCB->totalNumErrorInterrupts;
1447             /* Command executed successfully */
1448             retVal = 0;
1449             break;
1450         }
1451         case CBUFF_Command_CLEAR_CBUFF_STATS:
1452         {
1453             /* Reset the statistics: */
1454             ptrDriverMCB->totalNumFrameStart      = 0U;
1455             ptrDriverMCB->totalNumFrameDone       = 0U;
1456             ptrDriverMCB->totalNumChirpDone       = 0U;
1457             ptrDriverMCB->totalNumErrorInterrupts = 0U;
1459             /* Command executed successfully */
1460             retVal = 0;
1461             break;
1462         }
1463         case CBUFF_Command_GET_ACTIVE_SESSION:
1464         {
1465             CBUFF_SessionHandle* ptrActiveSessionHandle;
1467             /* Sanity Check: Validate the command specific arguments */
1468             if ((arg == NULL) || (argLen != sizeof (CBUFF_SessionHandle)))
1469             {
1470                 *errCode = CBUFF_EINVAL;
1471                 return retVal;
1472             }
1474             /* Get the pointer to the argument which is to be populated */
1475             ptrActiveSessionHandle = (CBUFF_SessionHandle*)arg;
1477             /* Return the active session handle back */
1478             *ptrActiveSessionHandle = (CBUFF_SessionHandle)ptrDriverMCB->ptrCurrentActiveSession;
1480             /* Command executed successfully */
1481             retVal = 0;
1482             break;
1483         }
1484         default:
1485         {
1486             /* Error: This is not a valid command. */
1487             *errCode = CBUFF_EINVAL;
1488             break;
1489         }
1490     }
1492     return retVal;
1495 CBUFF_Handle CBUFF_init (CBUFF_InitCfg* ptrInitCfg, int32_t* errCode)
1497     CBUFF_Handle            retHandle = NULL;
1498     CBUFF_DriverMCB*        ptrDriverMCB = NULL;
1499     OsalRegisterIntrParams_t    intrPrms;
1500     SOC_SysIntListenerCfg   listenerCfg;
1501     int32_t                 tmpErrCode;
1502     uint8_t                 index;
1503     CBUFF_Session*          ptrSession;
1504     uint32_t                priority;
1506     /* Initialize the error code: */
1507     *errCode = 0;
1509     /* Sanity Check: Validate the arguments */
1510     if (ptrInitCfg == NULL)
1511     {
1512         /* Error: Invalid configuration */
1513         *errCode = CBUFF_EINVAL;
1514         return retHandle;
1515     }
1517     /* Allocate memory for the CBUFF Driver: */
1518     ptrDriverMCB = (CBUFF_DriverMCB*)MemoryP_ctrlAlloc (sizeof(CBUFF_DriverMCB), 0);
1519     if (ptrDriverMCB == NULL)
1520     {
1521         /* Error: Out of memory */
1522         *errCode = CBUFF_ENOMEM;
1523         /* Deinitialize and shutdown the driver.
1524         * - We use a temporary error code because we dont want to hide the real
1525         *   reason for the failure. */
1526         CBUFF_deinit (ptrDriverMCB, &tmpErrCode);
1528         return retHandle;
1529     }
1531     /* Initialize the allocated memory: */
1532     memset ((void *)ptrDriverMCB, 0, sizeof(CBUFF_DriverMCB));
1534     /* Allocate memory for the sessions: */
1535     ptrDriverMCB->ptrSessionTable = (CBUFF_Session*) MemoryP_ctrlAlloc ((sizeof(CBUFF_Session) * ptrInitCfg->maxSessions), 0);
1536     if (ptrDriverMCB->ptrSessionTable == NULL)
1537     {
1538         /* Error: Out of memory */
1539         *errCode = CBUFF_ENOMEM;
1540         return retHandle;
1541     }
1543     /* Initialize the allocated memory: */
1544     memset ((void *)ptrDriverMCB->ptrSessionTable, 0, (sizeof(CBUFF_Session) * ptrInitCfg->maxSessions));
1546     /* Populate the driver block: Copy over the initialization configuration */
1547     memcpy ((void *)&ptrDriverMCB->initCfg, (void*)ptrInitCfg, sizeof(CBUFF_InitCfg));
1549     /* Sanity Check: Ensure that the high speed interface is supported or not? */
1550     ptrDriverMCB->interfaceFxn = CBUFF_isIfSupported (ptrDriverMCB->initCfg.interface);
1551     if (ptrDriverMCB->interfaceFxn == NULL)
1552     {
1553         /* NO: High speed interface is not supported. This seems to be an invalid configuration */
1554         *errCode = CBUFF_EINVAL;
1555         return retHandle;
1556     }
1558     /* Initialize and configure the driver MCB: */
1559     ptrDriverMCB->ptrCBUFFReg = (CSL_CbuffRegs*)gCBUFFHwAttribute.baseAddress;
1561     /* Reset the CBUFF Module: */
1562     CBUFF_reset (ptrDriverMCB->ptrCBUFFReg);
1564 #if defined(_TMS320C6X)
1565     priority = (~((uint32_t) 0U));
1566 #else
1567     priority = 0x1U;
1568 #endif
1570     Osal_RegisterInterrupt_initParams(&intrPrms);
1572     /* Populate the interrupt parameters */
1573     intrPrms.corepacConfig.arg              = (uintptr_t) ptrDriverMCB;
1574     intrPrms.corepacConfig.isrRoutine       = CBUFF_ISR;
1575     intrPrms.corepacConfig.priority         = priority;
1576     intrPrms.corepacConfig.name             = (char *)("CBUFF ISR");
1578     #if defined (_TMS320C6X)
1579     /* On C66x, we use Event Combiner to map the interrupt to the CPU Intc.  To
1580         * do this, OSAL expects that event number holds the interrupt number and we
1581         * use the macro for interrupt number to specify we wish to use Event
1582         * Combiner.
1583         */
1584     intrPrms.corepacConfig.corepacEventNum  = (int32_t) gCBUFFHwAttribute.cbuffInterrupt;
1585     intrPrms.corepacConfig.intVecNum        = OSAL_REGINT_INTVEC_EVENT_COMBINER;
1586     #else
1587     /* Other (non-C66x) CPUs don't use event number and interrupt number is
1588         * passed in and programmed to CPU Intc directly.
1589         */
1590     intrPrms.corepacConfig.corepacEventNum  = (int32_t) 0;
1591     intrPrms.corepacConfig.intVecNum        = (int32_t) gCBUFFHwAttribute.cbuffInterrupt;
1592     #endif
1594     /* Register interrupts */
1595     if(OSAL_INT_SUCCESS != Osal_RegisterInterrupt(&intrPrms, &(ptrDriverMCB->hwiISRHandle)))
1596     {
1597         ptrDriverMCB->hwiISRHandle = NULL;
1598         *errCode = CBUFF_EINVAL;
1599         return retHandle;
1600     }
1602     Osal_RegisterInterrupt_initParams(&intrPrms);
1604     /* Populate the interrupt parameters */
1605     intrPrms.corepacConfig.arg              = (uintptr_t) ptrDriverMCB;
1606     intrPrms.corepacConfig.isrRoutine       = CBUFF_ErrorISR;
1607     intrPrms.corepacConfig.priority         = priority;
1608     intrPrms.corepacConfig.name             = (char *)("CBUFF ERROR ISR");
1610     #if defined (_TMS320C6X)
1611     /* On C66x, we use Event Combiner to map the interrupt to the CPU Intc.  To
1612         * do this, OSAL expects that event number holds the interrupt number and we
1613         * use the macro for interrupt number to specify we wish to use Event
1614         * Combiner.
1615         */
1616     intrPrms.corepacConfig.corepacEventNum  = (int32_t) gCBUFFHwAttribute.errorInterrupt;
1617     intrPrms.corepacConfig.intVecNum        = OSAL_REGINT_INTVEC_EVENT_COMBINER;
1618     #else
1619     /* Other (non-C66x) CPUs don't use event number and interrupt number is
1620         * passed in and programmed to CPU Intc directly.
1621         */
1622     intrPrms.corepacConfig.corepacEventNum  = (int32_t) 0;
1623     intrPrms.corepacConfig.intVecNum        = (int32_t) gCBUFFHwAttribute.errorInterrupt;
1624     #endif
1626     /* Register interrupts */
1627     if(OSAL_INT_SUCCESS != Osal_RegisterInterrupt(&intrPrms, &(ptrDriverMCB->hwiErrorISRHandle)))
1628     {
1629         ptrDriverMCB->hwiErrorISRHandle = NULL;
1630         *errCode = CBUFF_EINVAL;
1631         return retHandle;
1632     }
1634     /* Enable all error interrupts: */
1635     CBUFF_enableErrorInt (ptrDriverMCB->ptrCBUFFReg);
1637     /* Register the CBUFF & Frame Start Interrupt Handlers only if the debug mode is enabled.
1638      * We do not want to overwhelm the system with a large number of interrupts. */
1639      if (ptrDriverMCB->initCfg.enableDebugMode == true)
1640      {
1641         /* Register the CBUFF Frame Start Listener: */
1642         memset ((void*)&listenerCfg, 0, sizeof(SOC_SysIntListenerCfg));
1643         listenerCfg.systemInterrupt = gCBUFFHwAttribute.frameStartInterrupt;
1644         listenerCfg.listenerFxn     = &CBUFF_FrameStartISR;
1645         listenerCfg.arg             = (uintptr_t)ptrDriverMCB;
1646         if (ptrDriverMCB->frameStartListener == NULL)
1647         {
1648             /* Error: Unable to register the frame start listener. Error code is already setup.*/
1649             return retHandle;
1650         }
1652         /* Debug Mode: Enable the Chirp & Frame Done Interrupt: */
1653         CBUFF_enableChirpDoneInt (ptrDriverMCB->ptrCBUFFReg);
1654         CBUFF_enableFrameDoneInt (ptrDriverMCB->ptrCBUFFReg);
1655     }
1656     else
1657     {
1658         /* Normal Mode: Disable the chirp & frame done interrupts. */
1659         CBUFF_disableChirpDoneInt (ptrDriverMCB->ptrCBUFFReg);
1660         CBUFF_disableFrameDoneInt (ptrDriverMCB->ptrCBUFFReg);
1661     }
1663      /* Cycle through and initialize the session table: */
1664      for (index = 0U; index < ptrDriverMCB->initCfg.maxSessions; index++)
1665      {
1666          /* Get the session: */
1667          ptrSession = &ptrDriverMCB->ptrSessionTable[index];
1669          /* Initialize the session: */
1670          ptrSession->ptrDriverMCB = ptrDriverMCB;
1671          ptrSession->isValid      = false;
1672          ptrSession->dmaNum       = index;
1673      }
1675      /* Initialize the high speed interface (HSI) on which the CBUFF is operating: */
1676      if (ptrDriverMCB->interfaceFxn->initFxn (ptrDriverMCB, errCode) < 0)
1677      {
1678          /* Error: Unable to initialize the HSI. Error code is already setup */
1679          return retHandle;
1680      }
1682      /* Reset the linked list entries in the CBUFF IP: */
1683      for (index = 0U; index < CBUFF_MAX_LINKED_LIST_SIZE; index++)
1684      {
1685          CBUFF_clearLLEntry (ptrDriverMCB->ptrCBUFFReg, index);
1686      }
1688      /* Setup the ECC: */
1689      CBUFF_setECC (ptrDriverMCB->ptrCBUFFReg, ptrDriverMCB->initCfg.enableECC);
1691      /* Default State: The triggers are always owned by the software */
1692      CBUFF_setFrameStartSWTrigger (ptrDriverMCB->ptrCBUFFReg, 1U);
1693      CBUFF_setChirpAvailableSWTrigger (ptrDriverMCB->ptrCBUFFReg, 1U);
1695      /* Release the reset of the CBUFF Module.  */
1696      CBUFF_releaseReset (ptrDriverMCB->ptrCBUFFReg);
1697      
1698      /* NO. CBUFF Initialization was successful */
1699      retHandle = (CBUFF_Handle)ptrDriverMCB;
1700     
1701     return retHandle;
1704 CBUFF_SessionHandle CBUFF_open (CBUFF_Handle cbuffHandle, CBUFF_SessionCfg* ptrSessionCfg, int32_t* errCode)
1706     CBUFF_DriverMCB*        ptrDriverMCB;
1707     CBUFF_SessionHandle     sessionHandle;
1708     CBUFF_Session*          ptrSession = NULL;
1709     int32_t                 tmpErrCode;
1711     /* Initialize the error code: */
1712     *errCode = 0;
1714     /* Get the driver MCB: */
1715     ptrDriverMCB = (CBUFF_DriverMCB*)cbuffHandle;
1717     /* Sanity Check: Validate the arguments */
1718     if ((ptrDriverMCB == NULL) || (ptrSessionCfg == NULL))
1719     {
1720         /* Error: Invalid configuration */
1721         *errCode = CBUFF_EINVAL;
1722         CBUFF_close ((CBUFF_SessionHandle)ptrSession, &tmpErrCode);
1723         sessionHandle = NULL;
1724         return sessionHandle;
1725     }
1727     /* Sanity Check: Validate the arguments */
1728     if ((ptrSessionCfg->edmaHandle             == NULL) ||
1729         (ptrSessionCfg->allocateEDMAChannelFxn == NULL) ||
1730         (ptrSessionCfg->freeEDMAChannelFxn     == NULL))
1731     {
1732         *errCode = CBUFF_EINVAL;
1733         CBUFF_close ((CBUFF_SessionHandle)ptrSession, &tmpErrCode);
1734         sessionHandle = NULL;
1735         return sessionHandle;
1736     }
1738     /* Allocate a session: */
1739     ptrSession = CBUFF_allocateSession (ptrDriverMCB);
1740     if (ptrSession == NULL)
1741     {
1742         /* Error: Out of sessions. Limit reached. */
1743         *errCode = CBUFF_ELIMIT;
1744         CBUFF_close ((CBUFF_SessionHandle)ptrSession, &tmpErrCode);
1745         sessionHandle = NULL;
1746         return sessionHandle;
1747     }
1749     /* Copy over the session configuration: */
1750     memcpy ((void *)&ptrSession->sessionCfg, (void*)ptrSessionCfg, sizeof (CBUFF_SessionCfg));
1752     /* Do we need to add a header to the stream? */
1753     if (CBUFF_validateBufferCfg (&ptrSession->sessionCfg.header, errCode) < 0)
1754     {
1755         /* Error: Invalid header configuration error code is already setup */
1756         CBUFF_close ((CBUFF_SessionHandle)ptrSession, &tmpErrCode);
1757         sessionHandle = NULL;
1758         return sessionHandle;
1759     }
1761     /* Process the session configuration on the basis of the execution mode: */
1762     if (ptrSession->sessionCfg.executionMode == CBUFF_SessionExecuteMode_HW)
1763     {
1764         /* Sanity Check: Validate the HW Session configuration */
1765         if (CBUFF_validateHWSessionCfg (ptrSession, errCode) < 0)
1766         {
1767             /* Error: Session configuration was invalid. Error code is setup */
1768             CBUFF_close ((CBUFF_SessionHandle)ptrSession, &tmpErrCode);
1769             sessionHandle = NULL;
1770             return sessionHandle;
1771         }
1773         /* Determine the ADC Transfer Size: For Complex Samples we send I/Q */
1774         ptrSession->adcTransferSize = 0U;
1775         if (ptrSession->sessionCfg.dataType == CBUFF_DataType_REAL)
1776         {
1777             /* Real: */
1778             ptrSession->adcTransferSize = ptrSession->sessionCfg.u.hwCfg.numADCSamples;
1779         }
1780         else
1781         {
1782             /* Complex: */
1783             ptrSession->adcTransferSize = ptrSession->sessionCfg.u.hwCfg.numADCSamples * 2;
1784         }
1786         /* Setup the number of chirps per frame: */
1787         if (ptrSession->sessionCfg.u.hwCfg.opMode == CBUFF_OperationalMode_CHIRP)
1788         {
1789             /* Chirp Mode: Use the provided configuration */
1790             ptrSession->numChirpsPerFrame = (ptrSession->sessionCfg.u.hwCfg.numChirpsPerFrame / ptrSession->sessionCfg.u.hwCfg.chirpMode);
1791             ptrSession->adcTransferSize   = ptrSession->adcTransferSize * ptrSession->sessionCfg.u.hwCfg.chirpMode;
1792         }
1793         else
1794         {
1795             /* Continuous Mode: There are infinite chirps per frame. */
1796             ptrSession->numChirpsPerFrame = 0xFFFFFFFFU;
1797         }
1798     }
1799     else
1800     {
1801         /* Sanity Check: Validate the SW Session configuration */
1802         if (CBUFF_validateSWSessionCfg (ptrSession, errCode) < 0)
1803         {
1804             /* Error: Session configuration was invalid. Error code is setup */
1805             CBUFF_close ((CBUFF_SessionHandle)ptrSession, &tmpErrCode);
1806             sessionHandle = NULL;
1807             return sessionHandle;
1808         }
1810         /* There is only 1 chirp per frame. */
1811         ptrSession->numChirpsPerFrame = 1U;
1812     }
1814     /* Setup the transfer: */
1815     if (CBUFF_setupTransfer (ptrSession, errCode) < 0)
1816     {
1817         /*Error: Unable to setup the transfer. Error code is already setup*/
1818         CBUFF_close ((CBUFF_SessionHandle)ptrSession, &tmpErrCode);
1819         sessionHandle = NULL;
1820         return sessionHandle;
1821     }
1823     /* Register for the Frame Done Interrupts */
1824     CBUFF_registerFrameDone (ptrDriverMCB);
1825     
1826     /* NO: Set the session handle */
1827     sessionHandle = (CBUFF_SessionHandle)ptrSession;
1829     return sessionHandle;
1832 int32_t CBUFF_close(CBUFF_SessionHandle sessionHandle, int32_t* errCode)
1834     int32_t             retVal = MINUS_ONE;
1835     CBUFF_DriverMCB*    ptrDriverMCB;
1836     CBUFF_Session*      ptrSession;
1838     *errCode = CBUFF_NO_ERROR;
1840     /* Get the pointer to the session: */
1841     ptrSession = (CBUFF_Session*)sessionHandle;
1842     if (ptrSession == NULL)
1843     {
1844         *errCode = CBUFF_EINVAL;
1845         return retVal;
1846     }
1848     /* Sanity Check: Ensure that there exists a back pointer to the CBUFF Driver */
1849     ptrDriverMCB = ptrSession->ptrDriverMCB;
1850     DebugP_assert (ptrDriverMCB != NULL);
1852     /* Is the session currently active? */
1853     if (ptrDriverMCB->ptrCurrentActiveSession == ptrSession)
1854     {
1855         /* YES: Application needs to deactivate the session before it
1856          * can be deleted. This needs to be done explicitly by the application. */
1857         *errCode = CBUFF_EINUSE;
1858         return retVal;
1859     }
1861     /* Shutdown the transfer: */
1862     if (CBUFF_shutdownTransfer (ptrSession, errCode) < 0)
1863     {
1864         /* Error: Unable to shutdown the transfer. Error code is already setup */
1865         return retVal;
1866     }
1868     /* Free the session: */
1869     CBUFF_freeSession (ptrSession);
1871     /* Deregister for the Frame Done Interrupts */
1872     CBUFF_deregisterFrameDone (ptrDriverMCB);
1874     /* Session has been successfully deleted */
1875     retVal = 0;
1877     return retVal;
1880 /**
1881  *  @b Description
1882  *  @n
1883  *      The function is used to deinitialize and shutdown the CBUFF driver.
1884  *
1885  *  @param[in]  cBuffHandle
1886  *      Handle to the driver
1887  *  @param[out] errCode
1888  *      Error code populated on error
1889  *
1890  *  \ingroup CBUFF_DRIVER_EXTERNAL_FUNCTION
1891  *
1892  *  @retval
1893  *      Success     - 0
1894  *  @retval
1895  *      Error       - <0
1896  */
1897 int32_t CBUFF_deinit (CBUFF_Handle cBuffHandle, int32_t* errCode)
1899     CBUFF_DriverMCB*    ptrDriverMCB;
1900     CBUFF_Session*      ptrSession;
1901     int32_t             retVal = MINUS_ONE;
1902     uint8_t             sessionIndex;
1904     /* Initialize the error code: */
1905     *errCode = 0;
1907     /* Sanity Check: Validate the arguments */
1908     ptrDriverMCB = (CBUFF_DriverMCB*)cBuffHandle;
1909     if (ptrDriverMCB == NULL)
1910     {
1911         *errCode = CBUFF_EINVAL;
1912         return retVal;
1913     }
1915     /* Sanity Check: Ensure that there are no activated sessions. Applications
1916      * should explicitly deactivate them */
1917     if (ptrDriverMCB->ptrCurrentActiveSession != NULL)
1918     {
1919         /* Error: There is already an active session */
1920         *errCode = CBUFF_EINUSE;
1921         return retVal;
1922     }
1924     /* Disable all the interrupts: The driver is going down. */
1925     CBUFF_disableErrorInt (ptrDriverMCB->ptrCBUFFReg);
1926     CBUFF_disableFrameDoneInt (ptrDriverMCB->ptrCBUFFReg);
1927     CBUFF_disableChirpDoneInt (ptrDriverMCB->ptrCBUFFReg);
1929     /* Was the session table created? */
1930     if (ptrDriverMCB->ptrSessionTable != NULL)
1931     {
1932         /* YES: Cycle through and delete all the valid sessions */
1933         for (sessionIndex = 0U; sessionIndex < ptrDriverMCB->initCfg.maxSessions; sessionIndex++)
1934         {
1935             /* Get the session: */
1936             ptrSession = &ptrDriverMCB->ptrSessionTable[sessionIndex];
1938             /* Was the session valid? */
1939             if (ptrSession->isValid == true)
1940             {
1941                 /* YES: Delete the session */
1942                 retVal = CBUFF_close ((CBUFF_SessionHandle)ptrSession, errCode);
1943                 if (retVal < 0)
1944                 {
1945                     /* Error: Unable to delete the session; error code is already populated */
1946                     return retVal;
1947                 }
1948             }
1949         }
1951         /* Cleanup the memory for the allocated session table */
1952         MemoryP_ctrlFree (ptrDriverMCB->ptrSessionTable, (sizeof(CBUFF_Session) * ptrDriverMCB->initCfg.maxSessions));
1953     }
1955     /* Deregister the CBUFF Error ISR Handler only if had been registered */
1956     if (ptrDriverMCB->hwiErrorISRHandle != NULL)
1957     {
1958         HwiP_delete(ptrDriverMCB->hwiErrorISRHandle);
1959     }
1961     /* Deregister the CBUFF Interrupt handlers only if it had been registered */
1962     if (ptrDriverMCB->hwiISRHandle != NULL)
1963     {
1964         HwiP_delete(ptrDriverMCB->hwiISRHandle);
1965     }
1966     
1967     /* Deinitialize the high speed interface: */
1968     if (ptrDriverMCB->interfaceFxn->deinitFxn (ptrDriverMCB, errCode) < 0)
1969     {
1970         /* Error: Unable to deinitialize the HSI. Error code is already setup */
1971         return retVal;
1972     }
1974     /* Cleanup the memory */
1975     MemoryP_ctrlFree (ptrDriverMCB, sizeof(CBUFF_DriverMCB));
1977     /* CBUFF has been deinitialized successfully. */
1978     retVal = 0;
1980     return retVal;