2 /*
3 Copyright (c) 2016, Texas Instruments Incorporated - http://www.ti.com/
4 All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the
16 * distribution.
17 *
18 * Neither the name of Texas Instruments Incorporated nor the names of
19 * its contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 */
36 /*
37 * sample_cs.c
38 *
39 * Sample functions showing the implementation of critical section entry/exit
40 * routines and various semaphore related routines (all BIOS6 depenedent).
41 * These implementations MUST be provided by the user / application, using the
42 * EDMA3 driver, for its correct functioning.
43 */
45 #include <ti/sysbios/family/c64p/EventCombiner.h>
46 #include <ti/sysbios/hal/Cache.h>
47 #include <ti/sysbios/hal/Hwi.h>
48 #include <ti/sysbios/knl/Task.h>
49 #include <ti/sysbios/knl/Semaphore.h>
51 #include <ti/sdo/edma3/rm/sample/bios6_edma3_rm_sample.h>
52 #include <ti/sdo/edma3/drv/edma3_drv.h>
54 extern unsigned int ccXferCompInt[][EDMA3_MAX_REGIONS];
55 extern unsigned int ccErrorInt[];
56 extern unsigned int tcErrorInt[][EDMA3_MAX_TC];
58 /**
59 * Shadow Region on which the executable is running. Its value is
60 * populated with the DSP Instance Number here in this case.
61 */
62 extern unsigned int region_id;
64 /**
65 * \brief EDMA3 OS Protect Entry
66 *
67 * This function saves the current state of protection in 'intState'
68 * variable passed by caller, if the protection level is
69 * EDMA3_OS_PROTECT_INTERRUPT. It then applies the requested level of
70 * protection.
71 * For EDMA3_OS_PROTECT_INTERRUPT_XFER_COMPLETION and
72 * EDMA3_OS_PROTECT_INTERRUPT_CC_ERROR, variable 'intState' is ignored,
73 * and the requested interrupt is disabled.
74 * For EDMA3_OS_PROTECT_INTERRUPT_TC_ERROR, '*intState' specifies the
75 * Transfer Controller number whose interrupt needs to be disabled.
76 *
77 * \param level is numeric identifier of the desired degree of protection.
78 * \param intState is memory location where current state of protection is
79 * saved for future use while restoring it via edma3OsProtectExit() (Only
80 * for EDMA3_OS_PROTECT_INTERRUPT protection level).
81 * \return None
82 */
83 void edma3OsProtectEntry (unsigned int edma3InstanceId,
84 int level, unsigned int *intState)
85 {
86 if (((level == EDMA3_OS_PROTECT_INTERRUPT)
87 || (level == EDMA3_OS_PROTECT_INTERRUPT_TC_ERROR))
88 && (intState == NULL))
89 {
90 return;
91 }
92 else
93 {
94 switch (level)
95 {
96 /* Disable all (global) interrupts */
97 case EDMA3_OS_PROTECT_INTERRUPT :
98 *intState = Hwi_disable();
99 break;
101 /* Disable scheduler */
102 case EDMA3_OS_PROTECT_SCHEDULER :
103 Task_disable();
104 break;
106 /* Disable EDMA3 transfer completion interrupt only */
107 case EDMA3_OS_PROTECT_INTERRUPT_XFER_COMPLETION :
108 EventCombiner_disableEvent(ccXferCompInt[edma3InstanceId][region_id]);
109 break;
111 /* Disable EDMA3 CC error interrupt only */
112 case EDMA3_OS_PROTECT_INTERRUPT_CC_ERROR :
113 EventCombiner_disableEvent(ccErrorInt[edma3InstanceId]);
114 break;
116 /* Disable EDMA3 TC error interrupt only */
117 case EDMA3_OS_PROTECT_INTERRUPT_TC_ERROR :
118 switch (*intState)
119 {
120 case 0:
121 case 1:
122 case 2:
123 case 3:
124 case 4:
125 case 5:
126 case 6:
127 case 7:
128 /* Fall through... */
129 /* Disable the corresponding interrupt */
130 EventCombiner_disableEvent(tcErrorInt[edma3InstanceId][*intState]);
131 break;
133 default:
134 break;
135 }
137 break;
139 default:
140 break;
141 }
142 }
143 }
146 /**
147 * \brief EDMA3 OS Protect Exit
148 *
149 * This function undoes the protection enforced to original state
150 * as is specified by the variable 'intState' passed, if the protection
151 * level is EDMA3_OS_PROTECT_INTERRUPT.
152 * For EDMA3_OS_PROTECT_INTERRUPT_XFER_COMPLETION and
153 * EDMA3_OS_PROTECT_INTERRUPT_CC_ERROR, variable 'intState' is ignored,
154 * and the requested interrupt is enabled.
155 * For EDMA3_OS_PROTECT_INTERRUPT_TC_ERROR, 'intState' specifies the
156 * Transfer Controller number whose interrupt needs to be enabled.
157 * \param level is numeric identifier of the desired degree of protection.
158 * \param intState is original state of protection at time when the
159 * corresponding edma3OsProtectEntry() was called (Only
160 * for EDMA3_OS_PROTECT_INTERRUPT protection level).
161 * \return None
162 */
163 void edma3OsProtectExit (unsigned int edma3InstanceId,
164 int level, unsigned int intState)
165 {
166 switch (level)
167 {
168 /* Enable all (global) interrupts */
169 case EDMA3_OS_PROTECT_INTERRUPT :
170 Hwi_restore(intState);
171 break;
173 /* Enable scheduler */
174 case EDMA3_OS_PROTECT_SCHEDULER :
175 Task_enable();
176 break;
178 /* Enable EDMA3 transfer completion interrupt only */
179 case EDMA3_OS_PROTECT_INTERRUPT_XFER_COMPLETION :
180 EventCombiner_enableEvent(ccXferCompInt[edma3InstanceId][region_id]);
181 break;
183 /* Enable EDMA3 CC error interrupt only */
184 case EDMA3_OS_PROTECT_INTERRUPT_CC_ERROR :
185 EventCombiner_enableEvent(ccErrorInt[edma3InstanceId]);
186 break;
188 /* Enable EDMA3 TC error interrupt only */
189 case EDMA3_OS_PROTECT_INTERRUPT_TC_ERROR :
190 switch (intState)
191 {
192 case 0:
193 case 1:
194 case 2:
195 case 3:
196 case 4:
197 case 5:
198 case 6:
199 case 7:
200 /* Fall through... */
201 /* Enable the corresponding interrupt */
202 EventCombiner_enableEvent(tcErrorInt[edma3InstanceId][intState]);
203 break;
205 default:
206 break;
207 }
209 break;
211 default:
212 break;
213 }
214 }
217 /**
218 * \brief EDMA3 Cache Invalidate
219 *
220 * This function invalidates the D cache.
221 *
222 * \param mem_start_ptr [IN] Starting address of memory.
223 * Please note that this should be
224 * aligned according to the cache line size.
225 * \param num_bytes [IN] length of buffer
226 * \return EDMA3_DRV_SOK if success, else error code in case of error
227 * or non-alignment of buffers.
228 *
229 * Note: This function is required if the buffer is in DDR.
230 * For other cases, where buffer is NOT in DDR, user
231 * may or may not require the below implementation and
232 * should modify it according to her need.
233 */
234 EDMA3_DRV_Result Edma3_CacheInvalidate(unsigned int mem_start_ptr,
235 unsigned int num_bytes)
236 {
237 EDMA3_DRV_Result cacheInvResult = EDMA3_DRV_SOK;
239 /* Verify whether the start address is cache aligned or not */
240 if((mem_start_ptr & (EDMA3_CACHE_LINE_SIZE_IN_BYTES-1u)) != 0)
241 {
242 #ifdef EDMA3_DRV_DEBUG
243 EDMA3_DRV_PRINTF("\r\n Cache : Memory is not %d bytes alinged\r\n",
244 EDMA3_CACHE_LINE_SIZE_IN_BYTES);
245 #endif
246 cacheInvResult = EDMA3_NON_ALIGNED_BUFFERS_ERROR;
247 }
248 else
249 {
250 Cache_inv((Ptr)mem_start_ptr, num_bytes, Cache_Type_ALL, TRUE);
251 }
253 return cacheInvResult;
254 }
258 /**
259 * \brief EDMA3 Cache Flush
260 *
261 * This function flushes (cleans) the Cache
262 *
263 * \param mem_start_ptr [IN] Starting address of memory.
264 * Please note that this should be
265 * aligned according to the cache line size.
266 * \param num_bytes [IN] length of buffer
267 * \return EDMA3_DRV_SOK if success, else error code in case of error
268 * or non-alignment of buffers.
269 *
270 * Note: This function is required if the buffer is in DDR.
271 * For other cases, where buffer is NOT in DDR, user
272 * may or may not require the below implementation and
273 * should modify it according to her need.
274 */
275 EDMA3_DRV_Result Edma3_CacheFlush(unsigned int mem_start_ptr,
276 unsigned int num_bytes)
277 {
278 EDMA3_DRV_Result cacheFlushResult = EDMA3_DRV_SOK;
280 /* Verify whether the start address is cache aligned or not */
281 if((mem_start_ptr & (EDMA3_CACHE_LINE_SIZE_IN_BYTES-1u)) != 0)
282 {
283 #ifdef EDMA3_DRV_DEBUG
284 EDMA3_DRV_PRINTF("\r\n Cache : Memory is not %d bytes alinged\r\n",
285 EDMA3_CACHE_LINE_SIZE_IN_BYTES);
286 #endif
287 cacheFlushResult = EDMA3_NON_ALIGNED_BUFFERS_ERROR;
288 }
289 else
290 {
291 Cache_wb((Ptr)mem_start_ptr, num_bytes, Cache_Type_ALL, TRUE);
292 }
294 return cacheFlushResult;
295 }
298 /**
299 * Counting Semaphore related functions (OS dependent) should be
300 * called/implemented by the application. A handle to the semaphore
301 * is required while opening the driver/resource manager instance.
302 */
304 /**
305 * \brief EDMA3 OS Semaphore Create
306 *
307 * This function creates a counting semaphore with specified
308 * attributes and initial value. It should be used to create a semaphore
309 * with initial value as '1'. The semaphore is then passed by the user
310 * to the EDMA3 driver/RM for proper sharing of resources.
311 * \param initVal [IN] is initial value for semaphore
312 * \param semParams [IN] is the semaphore attributes.
313 * \param hSem [OUT] is location to recieve the handle to just created
314 * semaphore
315 * \return EDMA3_DRV_SOK if succesful, else a suitable error code.
316 */
317 EDMA3_DRV_Result edma3OsSemCreate(int initVal,
318 const Semaphore_Params *semParams,
319 EDMA3_OS_Sem_Handle *hSem)
320 {
321 EDMA3_DRV_Result semCreateResult = EDMA3_DRV_SOK;
323 if(NULL == hSem)
324 {
325 semCreateResult = EDMA3_DRV_E_INVALID_PARAM;
326 }
327 else
328 {
329 *hSem = (EDMA3_OS_Sem_Handle)Semaphore_create(initVal, semParams, NULL);
330 if ( (*hSem) == NULL )
331 {
332 semCreateResult = EDMA3_DRV_E_SEMAPHORE;
333 }
334 }
336 return semCreateResult;
337 }
340 /**
341 * \brief EDMA3 OS Semaphore Delete
342 *
343 * This function deletes or removes the specified semaphore
344 * from the system. Associated dynamically allocated memory
345 * if any is also freed up.
346 * \param hSem [IN] handle to the semaphore to be deleted
347 * \return EDMA3_DRV_SOK if succesful else a suitable error code
348 */
349 EDMA3_DRV_Result edma3OsSemDelete(EDMA3_OS_Sem_Handle hSem)
350 {
351 EDMA3_DRV_Result semDeleteResult = EDMA3_DRV_SOK;
353 if(NULL == hSem)
354 {
355 semDeleteResult = EDMA3_DRV_E_INVALID_PARAM;
356 }
357 else
358 {
359 Semaphore_delete((Semaphore_Handle *)&hSem);
360 }
362 return semDeleteResult;
363 }
366 /**
367 * \brief EDMA3 OS Semaphore Take
368 *
369 * This function takes a semaphore token if available.
370 * If a semaphore is unavailable, it blocks currently
371 * running thread in wait (for specified duration) for
372 * a free semaphore.
373 * \param hSem [IN] is the handle of the specified semaphore
374 * \param mSecTimeout [IN] is wait time in milliseconds
375 * \return EDMA3_DRV_Result if successful else a suitable error code
376 */
377 EDMA3_DRV_Result edma3OsSemTake(EDMA3_OS_Sem_Handle hSem, int mSecTimeout)
378 {
379 EDMA3_DRV_Result semTakeResult = EDMA3_DRV_SOK;
380 unsigned short semPendResult;
382 if(NULL == hSem)
383 {
384 semTakeResult = EDMA3_DRV_E_INVALID_PARAM;
385 }
386 else
387 {
388 semPendResult = Semaphore_pend(hSem, mSecTimeout);
389 if (semPendResult == FALSE)
390 {
391 semTakeResult = EDMA3_DRV_E_SEMAPHORE;
392 }
393 }
395 return semTakeResult;
396 }
399 /**
400 * \brief EDMA3 OS Semaphore Give
401 *
402 * This function gives or relinquishes an already
403 * acquired semaphore token
404 * \param hSem [IN] is the handle of the specified semaphore
405 * \return EDMA3_DRV_Result if successful else a suitable error code
406 */
407 EDMA3_DRV_Result edma3OsSemGive(EDMA3_OS_Sem_Handle hSem)
408 {
409 EDMA3_DRV_Result semGiveResult = EDMA3_DRV_SOK;
411 if(NULL == hSem)
412 {
413 semGiveResult = EDMA3_DRV_E_INVALID_PARAM;
414 }
415 else
416 {
417 Semaphore_post(hSem);
418 }
420 return semGiveResult;
421 }
423 /* End of File */