7d97f72144ae4abd4bd4ad30cf45c55f633e5af2
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)
120 {
121 ptrCBUFFReg->CONFIG_REG_0 = CSL_FINSR (ptrCBUFFReg->CONFIG_REG_0, 27U, 27U, 1U);
122 }
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)
138 {
139 ptrCBUFFReg->CONFIG_REG_0 = CSL_FINSR (ptrCBUFFReg->CONFIG_REG_0, 27U, 27U, 0U);
140 }
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)
158 {
159 ptrCBUFFReg->CONFIG_REG_0 = CSL_FINSR (ptrCBUFFReg->CONFIG_REG_0, 1U, 1U, (uint32_t)ecc);
160 }
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)
176 {
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);
183 }
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)
199 {
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);
206 }
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)
222 {
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);
229 }
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)
245 {
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);
252 }
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)
269 {
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);
280 }
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)
297 {
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);
308 }
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)
328 {
329 *isFrameDone = (uint8_t)CSL_FEXTR (ptrCBUFFReg->STAT_CBUFF_REG0, 12U, 12U);
330 *isChirpDone = (uint8_t)CSL_FEXTR (ptrCBUFFReg->STAT_CBUFF_REG0, 11U, 11U);
331 }
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)
351 {
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);
354 }
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)
372 {
373 ptrCBUFFReg->CONFIG_REG_0 = CSL_FINSR (ptrCBUFFReg->CONFIG_REG_0, 2U, 2U, enableSW);
374 }
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)
392 {
393 ptrCBUFFReg->CONFIG_REG_0 = CSL_FINSR (ptrCBUFFReg->CONFIG_REG_0, 3U, 3U, enableSW);
394 }
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)
412 {
413 ptrCBUFFReg->CONFIG_REG_0 = CSL_FINSR (ptrCBUFFReg->CONFIG_REG_0, 25U, 25U, 1U);
414 }
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)
432 {
433 ptrCBUFFReg->CONFIG_REG_0 = CSL_FINSR (ptrCBUFFReg->CONFIG_REG_0, 24U, 24U, 1U);
434 }
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)
452 {
453 ptrCBUFFReg->CFG_CHIRPS_PER_FRAME = numChirps;
454 }
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)
472 {
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);
477 }
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)
497 {
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;
528 }
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)
551 {
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 }
584 }
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)
607 {
608 int32_t retVal = -1;
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;
631 }
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)
648 {
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;
708 }
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)
725 {
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;
737 }
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)
754 {
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;
766 }
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)
785 {
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;
819 }
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)
835 {
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;
849 }
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)
867 {
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;
903 }
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)
924 {
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;
952 }
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)
971 {
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;
1014 }
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)
1034 {
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;
1168 }
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)
1188 {
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;
1209 }
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)
1229 {
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;
1277 }
1279 int32_t CBUFF_activateSession (CBUFF_SessionHandle sessionHandle, int32_t* errCode)
1280 {
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;
1371 }
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
1397 (
1398 CBUFF_Handle cBuffHandle,
1399 CBUFF_Command cmd,
1400 void* arg,
1401 uint32_t argLen,
1402 int32_t* errCode
1403 )
1404 {
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;
1493 }
1495 CBUFF_Handle CBUFF_init (CBUFF_InitCfg* ptrInitCfg, int32_t* errCode)
1496 {
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 = 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 = 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 = "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 = "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);
1698 /* NO. CBUFF Initialization was successful */
1699 retHandle = (CBUFF_Handle)ptrDriverMCB;
1701 return retHandle;
1702 }
1704 CBUFF_SessionHandle CBUFF_open (CBUFF_Handle cbuffHandle, CBUFF_SessionCfg* ptrSessionCfg, int32_t* errCode)
1705 {
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);
1826 /* NO: Set the session handle */
1827 sessionHandle = (CBUFF_SessionHandle)ptrSession;
1829 return sessionHandle;
1830 }
1832 int32_t CBUFF_close(CBUFF_SessionHandle sessionHandle, int32_t* errCode)
1833 {
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;
1878 }
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)
1898 {
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 }
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;
1981 }