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