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