PRSDK-8534: migration to sysbios 6.82
[keystone-rtos/edma3_lld.git] / packages / ti / sdo / edma3 / drv / sample / src / sample_arm_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 - 2019 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 #if defined (BUILD_A8)
43 #include <ti/sysbios/family/arm/a8/Cache.h>
44 #elif defined (BUILD_A15)
45 #include <ti/sysbios/family/arm/a15/Cache.h>
46 #else
47 #include <ti/sysbios/hal/Cache.h>
48 #endif
50 #include <ti/sysbios/hal/Hwi.h>
51 #include <ti/sysbios/knl/Task.h>
52 #include <ti/sysbios/knl/Semaphore.h>
54 #include <ti/sdo/edma3/drv/sample/bios6_edma3_drv_sample.h>
56 extern uint32_t ccXferCompInt[EDMA3_MAX_EDMA3_INSTANCES][EDMA3_MAX_REGIONS];
57 extern uint32_t ccErrorInt[EDMA3_MAX_EDMA3_INSTANCES];
58 extern uint32_t tcErrorInt[EDMA3_MAX_EDMA3_INSTANCES][EDMA3_MAX_TC];
60 /**
61  * Shadow Region on which the executable is running. Its value is
62  * populated with the DSP Instance Number here in this case.
63  */
64 extern uint32_t region_id;
66 /**
67  * \brief   EDMA3 OS Protect Entry
68  *
69  *      This function saves the current state of protection in 'intState'
70  *      variable passed by caller, if the protection level is
71  *      EDMA3_OS_PROTECT_INTERRUPT. It then applies the requested level of
72  *      protection.
73  *      For EDMA3_OS_PROTECT_INTERRUPT_XFER_COMPLETION and
74  *      EDMA3_OS_PROTECT_INTERRUPT_CC_ERROR, variable 'intState' is ignored,
75  *      and the requested interrupt is disabled.
76  *      For EDMA3_OS_PROTECT_INTERRUPT_TC_ERROR, '*intState' specifies the
77  *      Transfer Controller number whose interrupt needs to be disabled.
78  *
79  * \param   level is numeric identifier of the desired degree of protection.
80  * \param   intState is memory location where current state of protection is
81  *      saved for future use while restoring it via edma3OsProtectExit() (Only
82  *      for EDMA3_OS_PROTECT_INTERRUPT protection level).
83  * \return  None
84  */
85 void edma3OsProtectEntry (uint32_t edma3InstanceId,
86                             int32_t level, uint32_t *intState)
87     {
88     if (((level == EDMA3_OS_PROTECT_INTERRUPT)
89         || (level == EDMA3_OS_PROTECT_INTERRUPT_TC_ERROR))
90         && (intState == NULL))
91         {
92             /* Nothing to be done here */
93         }
94     else
95         {
96         switch (level)
97             {
98             /* Disable all (global) interrupts */
99             case EDMA3_OS_PROTECT_INTERRUPT :
100                 *intState = Hwi_disable();
101                 break;
103             /* Disable scheduler */
104             case EDMA3_OS_PROTECT_SCHEDULER :
105                         Task_disable();
106                 break;
108             /* Disable EDMA3 transfer completion interrupt only */
109             case EDMA3_OS_PROTECT_INTERRUPT_XFER_COMPLETION :
110                 Hwi_disableInterrupt(ccXferCompInt[edma3InstanceId][region_id]);
111                 break;
113             /* Disable EDMA3 CC error interrupt only */
114             case EDMA3_OS_PROTECT_INTERRUPT_CC_ERROR :
115                 Hwi_disableInterrupt(ccErrorInt[edma3InstanceId]);
116                 break;
118             /* Disable EDMA3 TC error interrupt only */
119             case EDMA3_OS_PROTECT_INTERRUPT_TC_ERROR :
120                 switch (*intState)
121                     {
122                     case 0:
123                     case 1:
124                     case 2:
125                     case 3:
126                     case 4:
127                     case 5:
128                     case 6:
129                     case 7:
130                         /* Fall through... */
131                         /* Disable the corresponding interrupt */
132                         Hwi_disableInterrupt(tcErrorInt[edma3InstanceId][*intState]);
133                         break;
135                      default:
136                         break;
137                     }
139                 break;
141             default:
142                 break;
143             }
144         }
145         return;
146     }
149 /**
150  * \brief   EDMA3 OS Protect Exit
151  *
152  *      This function undoes the protection enforced to original state
153  *      as is specified by the variable 'intState' passed, if the protection
154  *      level is EDMA3_OS_PROTECT_INTERRUPT.
155  *      For EDMA3_OS_PROTECT_INTERRUPT_XFER_COMPLETION and
156  *      EDMA3_OS_PROTECT_INTERRUPT_CC_ERROR, variable 'intState' is ignored,
157  *      and the requested interrupt is enabled.
158  *      For EDMA3_OS_PROTECT_INTERRUPT_TC_ERROR, 'intState' specifies the
159  *      Transfer Controller number whose interrupt needs to be enabled.
160  * \param   level is numeric identifier of the desired degree of protection.
161  * \param   intState is original state of protection at time when the
162  *      corresponding edma3OsProtectEntry() was called (Only
163  *      for EDMA3_OS_PROTECT_INTERRUPT protection level).
164  * \return  None
165  */
166 void edma3OsProtectExit (uint32_t edma3InstanceId,
167                         int32_t level, uint32_t intState)
168     {
169     switch (level)
170         {
171         /* Enable all (global) interrupts */
172         case EDMA3_OS_PROTECT_INTERRUPT :
173             Hwi_restore(intState);
174             break;
176         /* Enable scheduler */
177         case EDMA3_OS_PROTECT_SCHEDULER :
178             Task_enable();
179             break;
181         /* Enable EDMA3 transfer completion interrupt only */
182         case EDMA3_OS_PROTECT_INTERRUPT_XFER_COMPLETION :
183             Hwi_enableInterrupt(ccXferCompInt[edma3InstanceId][region_id]);
184             break;
186         /* Enable EDMA3 CC error interrupt only */
187         case EDMA3_OS_PROTECT_INTERRUPT_CC_ERROR :
188             Hwi_enableInterrupt(ccErrorInt[edma3InstanceId]);
189             break;
191         /* Enable EDMA3 TC error interrupt only */
192         case EDMA3_OS_PROTECT_INTERRUPT_TC_ERROR :
193             switch ((int32_t)intState)
194                 {
195                 case 0:
196                 case 1:
197                 case 2:
198                 case 3:
199                 case 4:
200                 case 5:
201                 case 6:
202                 case 7:
203                     /* Fall through... */
204                     /* Enable the corresponding interrupt */
205                     Hwi_enableInterrupt(tcErrorInt[edma3InstanceId][intState]);
206                     break;
208                  default:
209                     break;
210                 }
212             break;
214         default:
215             break;
216         }
217     }
220 /**
221  *  \brief   EDMA3 Cache Invalidate
222  *
223  *  This function invalidates the D cache.
224  *
225  *  \param  mem_start_ptr [IN]      Starting address of memory.
226  *                                  Please note that this should be
227  *                                  aligned according to the cache line size.
228  *  \param  num_bytes [IN]          length of buffer
229  *  \return  EDMA3_DRV_SOK if success, else error code in case of error
230  *          or non-alignment of buffers.
231  *
232  * Note: This function is required if the buffer is in DDR.
233  * For other cases, where buffer is NOT in DDR, user
234  * may or may not require the below implementation and
235  * should modify it according to her need.
236  */
237 EDMA3_DRV_Result Edma3_CacheInvalidate(uint32_t mem_start_ptr,
238                            uint32_t    num_bytes)
239     {
240     EDMA3_DRV_Result cacheInvResult = EDMA3_DRV_SOK;
242     /* Verify whether the start address is cache aligned or not */
243     if((mem_start_ptr & (EDMA3_CACHE_LINE_SIZE_IN_BYTES-1U))    !=    0)
244         {
245 #ifdef EDMA3_DRV_DEBUG
246         EDMA3_DRV_PRINTF("\r\n Cache : Memory is not %d bytes alinged\r\n",
247                             EDMA3_CACHE_LINE_SIZE_IN_BYTES);
248 #endif
249         cacheInvResult = EDMA3_NON_ALIGNED_BUFFERS_ERROR;
250         }
251     else
252         {
253             Cache_inv((Ptr)mem_start_ptr, num_bytes, Cache_Type_ALL, (Bool)TRUE);
254         }
256     return cacheInvResult;
261 /**
262  * \brief   EDMA3 Cache Flush
263  *
264  *  This function flushes (cleans) the Cache
265  *
266  *  \param  mem_start_ptr [IN]      Starting address of memory.
267  *                                  Please note that this should be
268  *                                  aligned according to the cache line size.
269  *  \param  num_bytes [IN]          length of buffer
270  *  \return  EDMA3_DRV_SOK if success, else error code in case of error
271  *          or non-alignment of buffers.
272  *
273  * Note: This function is required if the buffer is in DDR.
274  * For other cases, where buffer is NOT in DDR, user
275  * may or may not require the below implementation and
276  * should modify it according to her need.
277  */
278 EDMA3_DRV_Result Edma3_CacheFlush(uint32_t mem_start_ptr,
279                       uint32_t num_bytes)
280     {
281     EDMA3_DRV_Result cacheFlushResult = EDMA3_DRV_SOK;
283     /* Verify whether the start address is cache aligned or not */
284     if((mem_start_ptr & (EDMA3_CACHE_LINE_SIZE_IN_BYTES-1U))    !=    0)
285         {
286 #ifdef EDMA3_DRV_DEBUG
287         EDMA3_DRV_PRINTF("\r\n Cache : Memory is not %d bytes alinged\r\n",
288                             EDMA3_CACHE_LINE_SIZE_IN_BYTES);
289 #endif
290         cacheFlushResult = EDMA3_NON_ALIGNED_BUFFERS_ERROR;
291         }
292     else
293         {
294             Cache_wb((Ptr)mem_start_ptr, num_bytes, Cache_Type_ALL, (Bool)TRUE);
295         }
297     return cacheFlushResult;
301 /**
302   * Counting Semaphore related functions (OS dependent) should be
303   * called/implemented by the application. A handle to the semaphore
304   * is required while opening the driver/resource manager instance.
305   */
307 /**
308  * \brief   EDMA3 OS Semaphore Create
309  *
310  *      This function creates a counting semaphore with specified
311  *      attributes and initial value. It should be used to create a semaphore
312  *      with initial value as '1'. The semaphore is then passed by the user
313  *      to the EDMA3 driver/RM for proper sharing of resources.
314  * \param   initVal [IN] is initial value for semaphore
315  * \param   semParams [IN] is the semaphore attributes.
316  * \param   hSem [OUT] is location to recieve the handle to just created
317  *      semaphore
318  * \return  EDMA3_DRV_SOK if succesful, else a suitable error code.
319  */
320 EDMA3_DRV_Result edma3OsSemCreate(int32_t initVal,
321                                                         const Semaphore_Params *semParams,
322                                 EDMA3_OS_Sem_Handle *hSem)
323     {
324     EDMA3_DRV_Result semCreateResult = EDMA3_DRV_SOK;
326     if(NULL == hSem)
327         {
328         semCreateResult = EDMA3_DRV_E_INVALID_PARAM;
329         }
330     else
331         {
332         *hSem = (EDMA3_OS_Sem_Handle)Semaphore_create(initVal, semParams, NULL);
333         if ( (*hSem) == NULL )
334             {
335             semCreateResult = EDMA3_DRV_E_SEMAPHORE;
336             }
337         }
339     return semCreateResult;
340     }
343 /**
344  * \brief   EDMA3 OS Semaphore Delete
345  *
346  *      This function deletes or removes the specified semaphore
347  *      from the system. Associated dynamically allocated memory
348  *      if any is also freed up.
349  * \param   hSem [IN] handle to the semaphore to be deleted
350  * \return  EDMA3_DRV_SOK if succesful else a suitable error code
351  */
352 EDMA3_DRV_Result edma3OsSemDelete(EDMA3_OS_Sem_Handle hSem)
353     {
354     EDMA3_DRV_Result semDeleteResult = EDMA3_DRV_SOK;
356     if(NULL == hSem)
357         {
358         semDeleteResult = EDMA3_DRV_E_INVALID_PARAM;
359         }
360     else
361         {
362                 Semaphore_delete((Semaphore_Handle *)&hSem);
363         }
365     return semDeleteResult;
366     }
369 /**
370  * \brief   EDMA3 OS Semaphore Take
371  *
372  *      This function takes a semaphore token if available.
373  *      If a semaphore is unavailable, it blocks currently
374  *      running thread in wait (for specified duration) for
375  *      a free semaphore.
376  * \param   hSem [IN] is the handle of the specified semaphore
377  * \param   mSecTimeout [IN] is wait time in milliseconds
378  * \return  EDMA3_Result if successful else a suitable error code
379  */
380 EDMA3_Result edma3OsSemTake(EDMA3_OS_Sem_Handle hSem, int32_t mSecTimeout)
381     {
382     EDMA3_Result semTakeResult = EDMA3_DRV_SOK;
384     if(NULL == hSem)
385         {
386         semTakeResult = EDMA3_DRV_E_INVALID_PARAM;
387         }
388     else
389         {
390         if((Semaphore_pend((Semaphore_Handle)hSem, (uint32_t)mSecTimeout)) == FALSE)
391             {
392             semTakeResult = EDMA3_DRV_E_SEMAPHORE;
393             }
394         }
396     return semTakeResult;
397     }
400 /**
401  * \brief   EDMA3 OS Semaphore Give
402  *
403  *      This function gives or relinquishes an already
404  *      acquired semaphore token
405  * \param   hSem [IN] is the handle of the specified semaphore
406  * \return  EDMA3_Result if successful else a suitable error code
407  */
408 EDMA3_Result edma3OsSemGive(EDMA3_OS_Sem_Handle hSem)
409     {
410     EDMA3_Result semGiveResult = EDMA3_DRV_SOK;
412     if(NULL == hSem)
413         {
414         semGiveResult = EDMA3_DRV_E_INVALID_PARAM;
415         }
416     else
417         {
418                 Semaphore_post((Semaphore_Handle)hSem);
419         }
421     return semGiveResult;
422     }
424 /* End of File */