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;
249 }
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;
290 }
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 */