1 /*
2 * Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com/
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the
14 * distribution.
15 *
16 * Neither the name of Texas Instruments Incorporated nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33 //*****************************************************************************
34 //
35 // cpu.c
36 //
37 // Instruction wrappers for special CPU instructions needed by the
38 //
39 //
40 //*****************************************************************************
41 #include "cpu.h"
42
43 //*****************************************************************************
44 //
45 // Wrapper function for the CPSID instruction. Returns the state of PRIMASK
46 // on entry.
47 //
48 //*****************************************************************************
49 #if defined(gcc)
50 unsigned long __attribute__((naked))
CPUcpsid(void)51 CPUcpsid(void)
52 {
53 unsigned long ulRet;
54
55 //
56 // Read PRIMASK and disable interrupts.
57 //
58 __asm(" mrs r0, PRIMASK\n"
59 " cpsid i\n"
60 " dsb \n"
61 " isb \n"
62 " bx lr\n"
63 : "=r" (ulRet));
64
65 //
66 // The return is handled in the inline assembly, but the compiler will
67 // still complain if there is not an explicit return here (despite the fact
68 // that this does not result in any code being produced because of the
69 // naked attribute).
70 //
71 return(ulRet);
72 }
73 #endif
74 #if defined(ewarm)
75 unsigned long
CPUcpsid(void)76 CPUcpsid(void)
77 {
78 //
79 // Read PRIMASK and disable interrupts.
80 //
81 __asm(" mrs r0, PRIMASK\n"
82 " cpsid i\n"
83 " dsb \n"
84 " isb \n");
85
86 //
87 // "Warning[Pe940]: missing return statement at end of non-void function"
88 // is suppressed here to avoid putting a "bx lr" in the inline assembly
89 // above and a superfluous return statement here.
90 //
91 #pragma diag_suppress=Pe940
92 }
93 #pragma diag_default=Pe940
94 #endif
95 #if defined(ccs)
96 unsigned long
CPUcpsid(void)97 CPUcpsid(void)
98 {
99 //
100 // Read PRIMASK and disable interrupts.
101 //
102 __asm(" mrs r0, PRIMASK\n"
103 " cpsid i\n"
104 " dsb \n"
105 " isb \n"
106 " bx lr\n");
107
108 //
109 // The following keeps the compiler happy, because it wants to see a
110 // return value from this function. It will generate code to return
111 // a zero. However, the real return is the "bx lr" above, so the
112 // return(0) is never executed and the function returns with the value
113 // you expect in R0.
114 //
115 return(0);
116 }
117 #endif
118 #if defined(ticlang)
119 unsigned long
CPUcpsid(void)120 CPUcpsid(void)
121 {
122 //
123 // Read PRIMASK and disable interrupts.
124 //
125 __asm(" mrs r0, PRIMASK\n"
126 " cpsid i\n"
127 " dsb \n"
128 " isb \n"
129 " bx lr\n");
130
131 //
132 // The following keeps the compiler happy, because it wants to see a
133 // return value from this function. It will generate code to return
134 // a zero. However, the real return is the "bx lr" above, so the
135 // return(0) is never executed and the function returns with the value
136 // you expect in R0.
137 //
138 return(0);
139 }
140 #endif
141
142 //*****************************************************************************
143 //
144 // Wrapper function returning the state of PRIMASK (indicating whether
145 // interrupts are enabled or disabled).
146 //
147 //*****************************************************************************
148 #if defined(gcc)
149 unsigned long __attribute__((naked))
CPUprimask(void)150 CPUprimask(void)
151 {
152 unsigned long ulRet;
153
154 //
155 // Read PRIMASK and disable interrupts.
156 //
157 __asm(" mrs r0, PRIMASK\n"
158 " bx lr\n"
159 : "=r" (ulRet));
160
161 //
162 // The return is handled in the inline assembly, but the compiler will
163 // still complain if there is not an explicit return here (despite the fact
164 // that this does not result in any code being produced because of the
165 // naked attribute).
166 //
167 return(ulRet);
168 }
169 #endif
170 #if defined(ewarm)
171 unsigned long
CPUprimask(void)172 CPUprimask(void)
173 {
174 //
175 // Read PRIMASK and disable interrupts.
176 //
177 __asm(" mrs r0, PRIMASK\n");
178
179 //
180 // "Warning[Pe940]: missing return statement at end of non-void function"
181 // is suppressed here to avoid putting a "bx lr" in the inline assembly
182 // above and a superfluous return statement here.
183 //
184 #pragma diag_suppress=Pe940
185 }
186 #pragma diag_default=Pe940
187 #endif
188 #if defined(ccs)
189 unsigned long
CPUprimask(void)190 CPUprimask(void)
191 {
192 //
193 // Read PRIMASK and disable interrupts.
194 //
195 __asm(" mrs r0, PRIMASK\n"
196 " bx lr\n");
197
198 //
199 // The following keeps the compiler happy, because it wants to see a
200 // return value from this function. It will generate code to return
201 // a zero. However, the real return is the "bx lr" above, so the
202 // return(0) is never executed and the function returns with the value
203 // you expect in R0.
204 //
205 return(0);
206 }
207 #endif
208 #if defined(ticlang)
209 unsigned long
CPUprimask(void)210 CPUprimask(void)
211 {
212 //
213 // Read PRIMASK and disable interrupts.
214 //
215 __asm(" mrs r0, PRIMASK\n"
216 " bx lr\n");
217
218 //
219 // The following keeps the compiler happy, because it wants to see a
220 // return value from this function. It will generate code to return
221 // a zero. However, the real return is the "bx lr" above, so the
222 // return(0) is never executed and the function returns with the value
223 // you expect in R0.
224 //
225 return(0);
226 }
227 #endif
228
229 //*****************************************************************************
230 //
231 // Wrapper function for the CPSIE instruction. Returns the state of PRIMASK
232 // on entry.
233 //
234 //*****************************************************************************
235 #if defined(gcc)
236 unsigned long __attribute__((naked))
CPUcpsie(void)237 CPUcpsie(void)
238 {
239 unsigned long ulRet;
240
241 //
242 // Read PRIMASK and enable interrupts.
243 //
244 __asm(" mrs r0, PRIMASK\n"
245 " cpsie i\n"
246 " dsb \n"
247 " isb \n"
248 " bx lr\n"
249 : "=r" (ulRet));
250
251 //
252 // The return is handled in the inline assembly, but the compiler will
253 // still complain if there is not an explicit return here (despite the fact
254 // that this does not result in any code being produced because of the
255 // naked attribute).
256 //
257 return(ulRet);
258 }
259 #endif
260 #if defined(ewarm)
261 unsigned long
CPUcpsie(void)262 CPUcpsie(void)
263 {
264 //
265 // Read PRIMASK and enable interrupts.
266 //
267 __asm(" mrs r0, PRIMASK\n"
268 " cpsie i\n"
269 " dsb \n"
270 " isb \n");
271
272 //
273 // "Warning[Pe940]: missing return statement at end of non-void function"
274 // is suppressed here to avoid putting a "bx lr" in the inline assembly
275 // above and a superfluous return statement here.
276 //
277 #pragma diag_suppress=Pe940
278 }
279 #pragma diag_default=Pe940
280 #endif
281 #if defined(ccs)
282 unsigned long
CPUcpsie(void)283 CPUcpsie(void)
284 {
285 //
286 // Read PRIMASK and enable interrupts.
287 //
288 __asm(" mrs r0, PRIMASK\n"
289 " cpsie i\n"
290 " dsb \n"
291 " isb \n"
292 " bx lr\n");
293
294 //
295 // The following keeps the compiler happy, because it wants to see a
296 // return value from this function. It will generate code to return
297 // a zero. However, the real return is the "bx lr" above, so the
298 // return(0) is never executed and the function returns with the value
299 // you expect in R0.
300 //
301 return(0);
302 }
303 #endif
304 #if defined(ticlang)
305 unsigned long
CPUcpsie(void)306 CPUcpsie(void)
307 {
308 //
309 // Read PRIMASK and enable interrupts.
310 //
311 __asm(" mrs r0, PRIMASK\n"
312 " cpsie i\n"
313 " dsb \n"
314 " isb \n"
315 " bx lr\n");
316
317 //
318 // The following keeps the compiler happy, because it wants to see a
319 // return value from this function. It will generate code to return
320 // a zero. However, the real return is the "bx lr" above, so the
321 // return(0) is never executed and the function returns with the value
322 // you expect in R0.
323 //
324 return(0);
325 }
326 #endif
327
328 //*****************************************************************************
329 //
330 // Wrapper function for the WFI instruction.
331 //
332 //*****************************************************************************
333 #if defined(gcc)
334 void __attribute__((naked))
CPUwfi(void)335 CPUwfi(void)
336 {
337 //
338 // Wait for the next interrupt.
339 //
340 __asm(" dsb \n"
341 " isb \n"
342 " wfi \n"
343 " bx lr\n");
344 }
345 #endif
346 #if defined(ewarm)
347 void
CPUwfi(void)348 CPUwfi(void)
349 {
350 //
351 // Wait for the next interrupt.
352 //
353 __asm(" dsb \n"
354 " isb \n"
355 " wfi \n");
356 }
357 #endif
358 #if defined(ccs)
359 void
CPUwfi(void)360 CPUwfi(void)
361 {
362 //
363 // Wait for the next interrupt.
364 //
365 __asm(" dsb \n"
366 " isb \n"
367 " wfi \n");
368 }
369 #endif
370 #if defined(ticlang)
371 void
CPUwfi(void)372 CPUwfi(void)
373 {
374 //
375 // Wait for the next interrupt.
376 //
377 __asm(" dsb \n"
378 " isb \n"
379 " wfi \n");
380 }
381 #endif
382
383 //*****************************************************************************
384 //
385 // Wrapper function for writing the BASEPRI register.
386 //
387 //*****************************************************************************
388 #if defined(gcc)
389 void __attribute__((naked))
CPUbasepriSet(unsigned long ulNewBasepri)390 CPUbasepriSet(unsigned long ulNewBasepri)
391 {
392
393 //
394 // Set the BASEPRI register
395 //
396 __asm(" msr BASEPRI, r0\n"
397 " dsb \n"
398 " isb \n"
399 " bx lr\n");
400 }
401 #endif
402 #if defined(ewarm)
403 void
CPUbasepriSet(unsigned long ulNewBasepri)404 CPUbasepriSet(unsigned long ulNewBasepri)
405 {
406 //
407 // Set the BASEPRI register
408 //
409 __asm(" msr BASEPRI, r0\n"
410 " dsb \n"
411 " isb \n");
412 }
413 #endif
414 #if defined(ccs)
415 void
CPUbasepriSet(unsigned long ulNewBasepri)416 CPUbasepriSet(unsigned long ulNewBasepri)
417 {
418 //
419 // Set the BASEPRI register
420 //
421 __asm(" msr BASEPRI, r0\n"
422 " dsb \n"
423 " isb \n");
424 }
425 #endif
426 #if defined(ticlang)
427 void
CPUbasepriSet(unsigned long ulNewBasepri)428 CPUbasepriSet(unsigned long ulNewBasepri)
429 {
430 //
431 // Set the BASEPRI register
432 //
433 __asm(" msr BASEPRI, r0\n"
434 " dsb \n"
435 " isb \n");
436 }
437 #endif
438
439 //*****************************************************************************
440 //
441 // Wrapper function for reading the BASEPRI register.
442 //
443 //*****************************************************************************
444 #if defined(gcc)
445 unsigned long __attribute__((naked))
CPUbasepriGet(void)446 CPUbasepriGet(void)
447 {
448 unsigned long ulRet;
449
450 //
451 // Read BASEPRI
452 //
453 __asm(" mrs r0, BASEPRI\n"
454 " bx lr\n"
455 : "=r" (ulRet));
456
457 //
458 // The return is handled in the inline assembly, but the compiler will
459 // still complain if there is not an explicit return here (despite the fact
460 // that this does not result in any code being produced because of the
461 // naked attribute).
462 //
463 return(ulRet);
464 }
465 #endif
466 #if defined(ewarm)
467 unsigned long
CPUbasepriGet(void)468 CPUbasepriGet(void)
469 {
470 //
471 // Read BASEPRI
472 //
473 __asm(" mrs r0, BASEPRI\n");
474
475 //
476 // "Warning[Pe940]: missing return statement at end of non-void function"
477 // is suppressed here to avoid putting a "bx lr" in the inline assembly
478 // above and a superfluous return statement here.
479 //
480 #pragma diag_suppress=Pe940
481 }
482 #pragma diag_default=Pe940
483 #endif
484 #if defined(ccs)
485 unsigned long
CPUbasepriGet(void)486 CPUbasepriGet(void)
487 {
488 //
489 // Read BASEPRI
490 //
491 __asm(" mrs r0, BASEPRI\n"
492 " bx lr\n");
493
494 //
495 // The following keeps the compiler happy, because it wants to see a
496 // return value from this function. It will generate code to return
497 // a zero. However, the real return is the "bx lr" above, so the
498 // return(0) is never executed and the function returns with the value
499 // you expect in R0.
500 //
501 return(0);
502 }
503 #endif
504 #if defined(ticlang)
505 unsigned long
CPUbasepriGet(void)506 CPUbasepriGet(void)
507 {
508 //
509 // Read BASEPRI
510 //
511 __asm(" mrs r0, BASEPRI\n"
512 " bx lr\n");
513
514 //
515 // The following keeps the compiler happy, because it wants to see a
516 // return value from this function. It will generate code to return
517 // a zero. However, the real return is the "bx lr" above, so the
518 // return(0) is never executed and the function returns with the value
519 // you expect in R0.
520 //
521 return(0);
522 }
523 #endif
524