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