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