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