PRSDK-3391 Removed unnecessary comments.
[keystone-rtos/edma3_lld.git] / packages / ti / sdo / edma3 / drv / sample / src / sample_cs.c
1 /*
2  * sample_cs.c
3  *
4  * Sample functions showing the implementation of critical section entry/exit
5  * routines and various semaphore related routines (all BIOS6 depenedent).
6  * These implementations MUST be provided by the user / application, using the
7  * EDMA3 driver, for its correct functioning.
8  *
9  * Copyright (C) 2009-2017 Texas Instruments Incorporated - http://www.ti.com/
10  *
11  *
12  *  Redistribution and use in source and binary forms, with or without
13  *  modification, are permitted provided that the following conditions
14  *  are met:
15  *
16  *    Redistributions of source code must retain the above copyright
17  *    notice, this list of conditions and the following disclaimer.
18  *
19  *    Redistributions in binary form must reproduce the above copyright
20  *    notice, this list of conditions and the following disclaimer in the
21  *    documentation and/or other materials provided with the
22  *    distribution.
23  *
24  *    Neither the name of Texas Instruments Incorporated nor the names of
25  *    its contributors may be used to endorse or promote products derived
26  *    from this software without specific prior written permission.
27  *
28  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39  *
40 */
42 #include <ti/sysbios/family/c64p/EventCombiner.h>
43 #include <ti/sysbios/hal/Cache.h>
44 #include <ti/sysbios/hal/Hwi.h>
45 #include <ti/sysbios/knl/Task.h>
46 #include <ti/sysbios/knl/Semaphore.h>
48 #include <ti/sdo/edma3/drv/sample/bios6_edma3_drv_sample.h>
50 extern uint32_t tcErrorInt[EDMA3_MAX_EDMA3_INSTANCES][EDMA3_MAX_TC];
51 extern void enableXferCompInterrupt(uint32_t edma3Id);
52 extern void disableXferCompInterrupt(uint32_t edma3Id);
53 extern void enableErrorInterrupt(uint32_t edma3Id);
54 extern void disableErrorInterrupt(uint32_t edma3Id);
56 /**
57  * Shadow Region on which the executable is running. Its value is
58  * populated with the DSP Instance Number here in this case.
59  */
60 extern uint32_t region_id;
62 /**
63  * \brief   EDMA3 OS Protect Entry
64  *
65  *      This function saves the current state of protection in 'intState'
66  *      variable passed by caller, if the protection level is
67  *      EDMA3_OS_PROTECT_INTERRUPT. It then applies the requested level of
68  *      protection.
69  *      For EDMA3_OS_PROTECT_INTERRUPT_XFER_COMPLETION and
70  *      EDMA3_OS_PROTECT_INTERRUPT_CC_ERROR, variable 'intState' is ignored,
71  *      and the requested interrupt is disabled.
72  *      For EDMA3_OS_PROTECT_INTERRUPT_TC_ERROR, '*intState' specifies the
73  *      Transfer Controller number whose interrupt needs to be disabled.
74  *
75  * \param   level is numeric identifier of the desired degree of protection.
76  * \param   intState is memory location where current state of protection is
77  *      saved for future use while restoring it via edma3OsProtectExit() (Only
78  *      for EDMA3_OS_PROTECT_INTERRUPT protection level).
79  * \return  None
80  */
81 void edma3OsProtectEntry (uint32_t edma3InstanceId,
82                                                         int32_t level, uint32_t *intState)
83     {
84     if (((level == EDMA3_OS_PROTECT_INTERRUPT)
85         || (level == EDMA3_OS_PROTECT_INTERRUPT_TC_ERROR))
86         && (intState == NULL))
87         {
88             /* Nothing to be done here */
89         }
90     else
91         {
92         switch (level)
93             {
94             /* Disable all (global) interrupts */
95             case EDMA3_OS_PROTECT_INTERRUPT :
96                 *intState = Hwi_disable();
97                 break;
99             /* Disable scheduler */
100             case EDMA3_OS_PROTECT_SCHEDULER :
101                                         Task_disable();
102                 break;
104             /* Disable EDMA3 transfer completion interrupt only */
105             case EDMA3_OS_PROTECT_INTERRUPT_XFER_COMPLETION :
106                 disableXferCompInterrupt(edma3InstanceId);
107                 break;
109             /* Disable EDMA3 CC error interrupt only */
110             case EDMA3_OS_PROTECT_INTERRUPT_CC_ERROR :
111                 disableErrorInterrupt(edma3InstanceId);
112                 break;
114             /* Disable EDMA3 TC error interrupt only */
115             case EDMA3_OS_PROTECT_INTERRUPT_TC_ERROR :
116                 switch (*intState)
117                     {
118                     case 0:
119                     case 1:
120                     case 2:
121                     case 3:
122                     case 4:
123                     case 5:
124                     case 6:
125                     case 7:
126                         /* Fall through... */
127                         /* Disable the corresponding interrupt */
128                         EventCombiner_disableEvent(tcErrorInt[edma3InstanceId][*intState]);
129                         break;
131                      default:
132                         break;
133                     }
135                 break;
137             default:
138                 break;
139             }
140         }
141         return;
142         }
145 /**
146  * \brief   EDMA3 OS Protect Exit
147  *
148  *      This function undoes the protection enforced to original state
149  *      as is specified by the variable 'intState' passed, if the protection
150  *      level is EDMA3_OS_PROTECT_INTERRUPT.
151  *      For EDMA3_OS_PROTECT_INTERRUPT_XFER_COMPLETION and
152  *      EDMA3_OS_PROTECT_INTERRUPT_CC_ERROR, variable 'intState' is ignored,
153  *      and the requested interrupt is enabled.
154  *      For EDMA3_OS_PROTECT_INTERRUPT_TC_ERROR, 'intState' specifies the
155  *      Transfer Controller number whose interrupt needs to be enabled.
156  * \param   level is numeric identifier of the desired degree of protection.
157  * \param   intState is original state of protection at time when the
158  *      corresponding edma3OsProtectEntry() was called (Only
159  *      for EDMA3_OS_PROTECT_INTERRUPT protection level).
160  * \return  None
161  */
162 void edma3OsProtectExit (uint32_t edma3InstanceId,
163                         int32_t level, uint32_t intState)
164     {
165     switch (level)
166         {
167         /* Enable all (global) interrupts */
168         case EDMA3_OS_PROTECT_INTERRUPT :
169             Hwi_restore(intState);
170             break;
172         /* Enable scheduler */
173         case EDMA3_OS_PROTECT_SCHEDULER :
174             Task_enable();
175             break;
177         /* Enable EDMA3 transfer completion interrupt only */
178         case EDMA3_OS_PROTECT_INTERRUPT_XFER_COMPLETION :
179             enableXferCompInterrupt(edma3InstanceId);
180             break;
182         /* Enable EDMA3 CC error interrupt only */
183         case EDMA3_OS_PROTECT_INTERRUPT_CC_ERROR :
184             enableErrorInterrupt(edma3InstanceId);
185             break;
187         /* Enable EDMA3 TC error interrupt only */
188         case EDMA3_OS_PROTECT_INTERRUPT_TC_ERROR :
189             switch ((int32_t)intState)
190                 {
191                 case 0:
192                 case 1:
193                 case 2:
194                 case 3:
195                 case 4:
196                 case 5:
197                 case 6:
198                 case 7:
199                     /* Fall through... */
200                     /* Enable the corresponding interrupt */
201                     EventCombiner_enableEvent(tcErrorInt[edma3InstanceId][intState]);
202                     break;
204                  default:
205                     break;
206                 }
208             break;
210         default:
211             break;
212         }
213     }
216 /**
217  *  \brief   EDMA3 Cache Invalidate
218  *
219  *  This function invalidates the D cache.
220  *
221  *  \param  mem_start_ptr [IN]      Starting address of memory.
222  *                                  Please note that this should be
223  *                                  aligned according to the cache line size.
224  *  \param  num_bytes [IN]          length of buffer
225  *  \return  EDMA3_DRV_SOK if success, else error code in case of error
226  *          or non-alignment of buffers.
227  *
228  * Note: This function is required if the buffer is in DDR.
229  * For other cases, where buffer is NOT in DDR, user
230  * may or may not require the below implementation and
231  * should modify it according to her need.
232  */
233 EDMA3_DRV_Result Edma3_CacheInvalidate(uint32_t mem_start_ptr,
234                            uint32_t    num_bytes)
235     {
236     EDMA3_DRV_Result cacheInvResult = EDMA3_DRV_SOK;
238     /* Verify whether the start address is cache aligned or not */
239     if((mem_start_ptr & (EDMA3_CACHE_LINE_SIZE_IN_BYTES-1U))    !=    0)
240         {
241 #ifdef EDMA3_DRV_DEBUG
242         EDMA3_DRV_PRINTF("\r\n Cache : Memory is not %d bytes alinged\r\n",
243                             EDMA3_CACHE_LINE_SIZE_IN_BYTES);
244 #endif
245         cacheInvResult = EDMA3_NON_ALIGNED_BUFFERS_ERROR;
246         }
247     else
248         {
249                 Cache_inv((Ptr)mem_start_ptr, num_bytes, Cache_Type_ALL, (Bool)TRUE);
250         }
252     return cacheInvResult;
257 /**
258  * \brief   EDMA3 Cache Flush
259  *
260  *  This function flushes (cleans) the Cache
261  *
262  *  \param  mem_start_ptr [IN]      Starting address of memory.
263  *                                  Please note that this should be
264  *                                  aligned according to the cache line size.
265  *  \param  num_bytes [IN]          length of buffer
266  *  \return  EDMA3_DRV_SOK if success, else error code in case of error
267  *          or non-alignment of buffers.
268  *
269  * Note: This function is required if the buffer is in DDR.
270  * For other cases, where buffer is NOT in DDR, user
271  * may or may not require the below implementation and
272  * should modify it according to her need.
273  */
274 EDMA3_DRV_Result Edma3_CacheFlush(uint32_t mem_start_ptr,
275                       uint32_t num_bytes)
276     {
277     EDMA3_DRV_Result cacheFlushResult = EDMA3_DRV_SOK;
279     /* Verify whether the start address is cache aligned or not */
280     if((mem_start_ptr & (EDMA3_CACHE_LINE_SIZE_IN_BYTES-1U))    !=    0)
281         {
282 #ifdef EDMA3_DRV_DEBUG
283         EDMA3_DRV_PRINTF("\r\n Cache : Memory is not %d bytes alinged\r\n",
284                             EDMA3_CACHE_LINE_SIZE_IN_BYTES);
285 #endif
286         cacheFlushResult = EDMA3_NON_ALIGNED_BUFFERS_ERROR;
287         }
288     else
289         {
290                 Cache_wb((Ptr)mem_start_ptr, num_bytes, Cache_Type_ALL, (Bool)TRUE);
291         }
293     return cacheFlushResult;
297 /**
298   * Counting Semaphore related functions (OS dependent) should be
299   * called/implemented by the application. A handle to the semaphore
300   * is required while opening the driver/resource manager instance.
301   */
303 /**
304  * \brief   EDMA3 OS Semaphore Create
305  *
306  *      This function creates a counting semaphore with specified
307  *      attributes and initial value. It should be used to create a semaphore
308  *      with initial value as '1'. The semaphore is then passed by the user
309  *      to the EDMA3 driver/RM for proper sharing of resources.
310  * \param   initVal [IN] is initial value for semaphore
311  * \param   semParams [IN] is the semaphore attributes.
312  * \param   hSem [OUT] is location to recieve the handle to just created
313  *      semaphore
314  * \return  EDMA3_DRV_SOK if succesful, else a suitable error code.
315  */
316 EDMA3_DRV_Result edma3OsSemCreate(int32_t initVal,
317                                                         const Semaphore_Params *semParams,
318                                 EDMA3_OS_Sem_Handle *hSem)
319     {
320     EDMA3_DRV_Result semCreateResult = EDMA3_DRV_SOK;
322     if(NULL == hSem)
323         {
324         semCreateResult = EDMA3_DRV_E_INVALID_PARAM;
325         }
326     else
327         {
328         *hSem = (EDMA3_OS_Sem_Handle)Semaphore_create(initVal, semParams, NULL);
329         if ( (*hSem) == NULL )
330             {
331             semCreateResult = EDMA3_DRV_E_SEMAPHORE;
332             }
333         }
335     return semCreateResult;
336     }
339 /**
340  * \brief   EDMA3 OS Semaphore Delete
341  *
342  *      This function deletes or removes the specified semaphore
343  *      from the system. Associated dynamically allocated memory
344  *      if any is also freed up.
345  * \param   hSem [IN] handle to the semaphore to be deleted
346  * \return  EDMA3_DRV_SOK if succesful else a suitable error code
347  */
348 EDMA3_DRV_Result edma3OsSemDelete(EDMA3_OS_Sem_Handle hSem)
349     {
350     EDMA3_DRV_Result semDeleteResult = EDMA3_DRV_SOK;
352     if(NULL == hSem)
353         {
354         semDeleteResult = EDMA3_DRV_E_INVALID_PARAM;
355         }
356     else
357         {
358                 Semaphore_delete((Semaphore_Handle *)&hSem);
359         }
361     return semDeleteResult;
362     }
365 /**
366  * \brief   EDMA3 OS Semaphore Take
367  *
368  *      This function takes a semaphore token if available.
369  *      If a semaphore is unavailable, it blocks currently
370  *      running thread in wait (for specified duration) for
371  *      a free semaphore.
372  * \param   hSem [IN] is the handle of the specified semaphore
373  * \param   mSecTimeout [IN] is wait time in milliseconds
374  * \return  EDMA3_Result if successful else a suitable error code
375  */
376 EDMA3_Result edma3OsSemTake(EDMA3_OS_Sem_Handle hSem, int32_t mSecTimeout)
377     {
378     EDMA3_Result semTakeResult = EDMA3_DRV_SOK;
380     if(NULL == hSem)
381         {
382         semTakeResult = EDMA3_DRV_E_INVALID_PARAM;
383         }
384     else
385         {
386         if((Semaphore_pend(hSem, (uint32_t)mSecTimeout)) == FALSE)
387             {
388             semTakeResult = EDMA3_DRV_E_SEMAPHORE;
389             }
390         }
392     return semTakeResult;
393     }
396 /**
397  * \brief   EDMA3 OS Semaphore Give
398  *
399  *      This function gives or relinquishes an already
400  *      acquired semaphore token
401  * \param   hSem [IN] is the handle of the specified semaphore
402  * \return  EDMA3_Result if successful else a suitable error code
403  */
404 EDMA3_Result edma3OsSemGive(EDMA3_OS_Sem_Handle hSem)
405     {
406     EDMA3_Result semGiveResult = EDMA3_DRV_SOK;
408     if(NULL == hSem)
409         {
410         semGiveResult = EDMA3_DRV_E_INVALID_PARAM;
411         }
412     else
413         {
414                 Semaphore_post(hSem);
415         }
417     return semGiveResult;
418     }
420 /* End of File */