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