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