3a6c2bd64f30812c403ee2707acea14392bb607f
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 - 2019 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>
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 uint32_t ccXferCompInt[EDMA3_MAX_EDMA3_INSTANCES][EDMA3_MAX_REGIONS];
51 extern uint32_t ccErrorInt[EDMA3_MAX_EDMA3_INSTANCES];
52 extern uint32_t tcErrorInt[EDMA3_MAX_EDMA3_INSTANCES][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 uint32_t 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 (uint32_t edma3InstanceId,
80 int32_t level, uint32_t *intState)
81 {
82 if (((level == EDMA3_OS_PROTECT_INTERRUPT)
83 || (level == EDMA3_OS_PROTECT_INTERRUPT_TC_ERROR))
84 && (intState == NULL))
85 {
86 /* Nothing to be done here */
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 Hwi_disableInterrupt(ccXferCompInt[edma3InstanceId][region_id]);
105 break;
107 /* Disable EDMA3 CC error interrupt only */
108 case EDMA3_OS_PROTECT_INTERRUPT_CC_ERROR :
109 Hwi_disableInterrupt(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 Hwi_disableInterrupt(tcErrorInt[edma3InstanceId][*intState]);
127 break;
129 default:
130 break;
131 }
133 break;
135 default:
136 break;
137 }
138 }
139 return;
140 }
143 /**
144 * \brief EDMA3 OS Protect Exit
145 *
146 * This function undoes the protection enforced to original state
147 * as is specified by the variable 'intState' passed, if the protection
148 * level is EDMA3_OS_PROTECT_INTERRUPT.
149 * For EDMA3_OS_PROTECT_INTERRUPT_XFER_COMPLETION and
150 * EDMA3_OS_PROTECT_INTERRUPT_CC_ERROR, variable 'intState' is ignored,
151 * and the requested interrupt is enabled.
152 * For EDMA3_OS_PROTECT_INTERRUPT_TC_ERROR, 'intState' specifies the
153 * Transfer Controller number whose interrupt needs to be enabled.
154 * \param level is numeric identifier of the desired degree of protection.
155 * \param intState is original state of protection at time when the
156 * corresponding edma3OsProtectEntry() was called (Only
157 * for EDMA3_OS_PROTECT_INTERRUPT protection level).
158 * \return None
159 */
160 void edma3OsProtectExit (uint32_t edma3InstanceId,
161 int32_t level, uint32_t intState)
162 {
163 switch (level)
164 {
165 /* Enable all (global) interrupts */
166 case EDMA3_OS_PROTECT_INTERRUPT :
167 Hwi_restore(intState);
168 break;
170 /* Enable scheduler */
171 case EDMA3_OS_PROTECT_SCHEDULER :
172 Task_enable();
173 break;
175 /* Enable EDMA3 transfer completion interrupt only */
176 case EDMA3_OS_PROTECT_INTERRUPT_XFER_COMPLETION :
177 Hwi_enableInterrupt(ccXferCompInt[edma3InstanceId][region_id]);
178 break;
180 /* Enable EDMA3 CC error interrupt only */
181 case EDMA3_OS_PROTECT_INTERRUPT_CC_ERROR :
182 Hwi_enableInterrupt(ccErrorInt[edma3InstanceId]);
183 break;
185 /* Enable EDMA3 TC error interrupt only */
186 case EDMA3_OS_PROTECT_INTERRUPT_TC_ERROR :
187 switch ((int32_t)intState)
188 {
189 case 0:
190 case 1:
191 case 2:
192 case 3:
193 case 4:
194 case 5:
195 case 6:
196 case 7:
197 /* Fall through... */
198 /* Enable the corresponding interrupt */
199 Hwi_enableInterrupt(tcErrorInt[edma3InstanceId][intState]);
200 break;
202 default:
203 break;
204 }
206 break;
208 default:
209 break;
210 }
211 }
214 /**
215 * \brief EDMA3 Cache Invalidate
216 *
217 * This function invalidates the D cache.
218 *
219 * \param mem_start_ptr [IN] Starting address of memory.
220 * Please note that this should be
221 * aligned according to the cache line size.
222 * \param num_bytes [IN] length of buffer
223 * \return EDMA3_DRV_SOK if success, else error code in case of error
224 * or non-alignment of buffers.
225 *
226 * Note: This function is required if the buffer is in DDR.
227 * For other cases, where buffer is NOT in DDR, user
228 * may or may not require the below implementation and
229 * should modify it according to her need.
230 */
231 EDMA3_DRV_Result Edma3_CacheInvalidate(uint32_t mem_start_ptr,
232 uint32_t num_bytes)
233 {
234 EDMA3_DRV_Result cacheInvResult = EDMA3_DRV_SOK;
236 /* Verify whether the start address is cache aligned or not */
237 if((mem_start_ptr & (EDMA3_CACHE_LINE_SIZE_IN_BYTES-1U)) != 0)
238 {
239 #ifdef EDMA3_DRV_DEBUG
240 EDMA3_DRV_PRINTF("\r\n Cache : Memory is not %d bytes alinged\r\n",
241 EDMA3_CACHE_LINE_SIZE_IN_BYTES);
242 #endif
243 cacheInvResult = EDMA3_NON_ALIGNED_BUFFERS_ERROR;
244 }
245 else
246 {
247 Cache_inv((Ptr)mem_start_ptr, num_bytes, Cache_Type_ALL, (Bool)TRUE);
248 }
250 return cacheInvResult;
251 }
255 /**
256 * \brief EDMA3 Cache Flush
257 *
258 * This function flushes (cleans) the Cache
259 *
260 * \param mem_start_ptr [IN] Starting address of memory.
261 * Please note that this should be
262 * aligned according to the cache line size.
263 * \param num_bytes [IN] length of buffer
264 * \return EDMA3_DRV_SOK if success, else error code in case of error
265 * or non-alignment of buffers.
266 *
267 * Note: This function is required if the buffer is in DDR.
268 * For other cases, where buffer is NOT in DDR, user
269 * may or may not require the below implementation and
270 * should modify it according to her need.
271 */
272 EDMA3_DRV_Result Edma3_CacheFlush(uint32_t mem_start_ptr,
273 uint32_t num_bytes)
274 {
275 EDMA3_DRV_Result cacheFlushResult = EDMA3_DRV_SOK;
277 /* Verify whether the start address is cache aligned or not */
278 if((mem_start_ptr & (EDMA3_CACHE_LINE_SIZE_IN_BYTES-1U)) != 0)
279 {
280 #ifdef EDMA3_DRV_DEBUG
281 EDMA3_DRV_PRINTF("\r\n Cache : Memory is not %d bytes alinged\r\n",
282 EDMA3_CACHE_LINE_SIZE_IN_BYTES);
283 #endif
284 cacheFlushResult = EDMA3_NON_ALIGNED_BUFFERS_ERROR;
285 }
286 else
287 {
288 Cache_wb((Ptr)mem_start_ptr, num_bytes, Cache_Type_ALL, (Bool)TRUE);
289 }
291 return cacheFlushResult;
292 }
295 /**
296 * Counting Semaphore related functions (OS dependent) should be
297 * called/implemented by the application. A handle to the semaphore
298 * is required while opening the driver/resource manager instance.
299 */
301 /**
302 * \brief EDMA3 OS Semaphore Create
303 *
304 * This function creates a counting semaphore with specified
305 * attributes and initial value. It should be used to create a semaphore
306 * with initial value as '1'. The semaphore is then passed by the user
307 * to the EDMA3 driver/RM for proper sharing of resources.
308 * \param initVal [IN] is initial value for semaphore
309 * \param semParams [IN] is the semaphore attributes.
310 * \param hSem [OUT] is location to recieve the handle to just created
311 * semaphore
312 * \return EDMA3_DRV_SOK if succesful, else a suitable error code.
313 */
314 EDMA3_DRV_Result edma3OsSemCreate(int32_t initVal,
315 const Semaphore_Params *semParams,
316 EDMA3_OS_Sem_Handle *hSem)
317 {
318 EDMA3_DRV_Result semCreateResult = EDMA3_DRV_SOK;
320 if(NULL == hSem)
321 {
322 semCreateResult = EDMA3_DRV_E_INVALID_PARAM;
323 }
324 else
325 {
326 *hSem = (EDMA3_OS_Sem_Handle)Semaphore_create(initVal, semParams, NULL);
327 if ( (*hSem) == NULL )
328 {
329 semCreateResult = EDMA3_DRV_E_SEMAPHORE;
330 }
331 }
333 return semCreateResult;
334 }
337 /**
338 * \brief EDMA3 OS Semaphore Delete
339 *
340 * This function deletes or removes the specified semaphore
341 * from the system. Associated dynamically allocated memory
342 * if any is also freed up.
343 * \param hSem [IN] handle to the semaphore to be deleted
344 * \return EDMA3_DRV_SOK if succesful else a suitable error code
345 */
346 EDMA3_DRV_Result edma3OsSemDelete(EDMA3_OS_Sem_Handle hSem)
347 {
348 EDMA3_DRV_Result semDeleteResult = EDMA3_DRV_SOK;
350 if(NULL == hSem)
351 {
352 semDeleteResult = EDMA3_DRV_E_INVALID_PARAM;
353 }
354 else
355 {
356 Semaphore_delete((Semaphore_Handle *)&hSem);
357 }
359 return semDeleteResult;
360 }
363 /**
364 * \brief EDMA3 OS Semaphore Take
365 *
366 * This function takes a semaphore token if available.
367 * If a semaphore is unavailable, it blocks currently
368 * running thread in wait (for specified duration) for
369 * a free semaphore.
370 * \param hSem [IN] is the handle of the specified semaphore
371 * \param mSecTimeout [IN] is wait time in milliseconds
372 * \return EDMA3_Result if successful else a suitable error code
373 */
374 EDMA3_Result edma3OsSemTake(EDMA3_OS_Sem_Handle hSem, int32_t mSecTimeout)
375 {
376 EDMA3_Result semTakeResult = EDMA3_DRV_SOK;
378 if(NULL == hSem)
379 {
380 semTakeResult = EDMA3_DRV_E_INVALID_PARAM;
381 }
382 else
383 {
384 if((Semaphore_pend((Semaphore_Handle)hSem, (uint32_t)mSecTimeout)) == 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_Result if successful else a suitable error code
401 */
402 EDMA3_Result edma3OsSemGive(EDMA3_OS_Sem_Handle hSem)
403 {
404 EDMA3_Result semGiveResult = EDMA3_DRV_SOK;
406 if(NULL == hSem)
407 {
408 semGiveResult = EDMA3_DRV_E_INVALID_PARAM;
409 }
410 else
411 {
412 Semaphore_post((Semaphore_Handle)hSem);
413 }
415 return semGiveResult;
416 }
418 /* End of File */