1 /******************************************************************************
2 * Filename: cpu.c
3 * Revised: 2019-05-27 15:23:10 +0200 (Mon, 27 May 2019)
4 * Revision: 55701
5 *
6 * Description: Instruction wrappers for special CPU instructions needed by
7 * the drivers.
8 *
9 * Copyright (c) 2015 - 2017, 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 "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(DOXYGEN)
67 uint32_t
CPUcpsid(void)68 CPUcpsid(void)
69 {
70 // This function is written in assembly. See cpu.c for compiler specific implementation.
71 }
72 #elif defined(__IAR_SYSTEMS_ICC__)
73 uint32_t
CPUcpsid(void)74 CPUcpsid(void)
75 {
76 // Read PRIMASK and disable interrupts.
77 __asm(" mrs r0, PRIMASK\n"
78 " cpsid i\n");
79
80 // "Warning[Pe940]: missing return statement at end of non-void function"
81 // is suppressed here to avoid putting a "bx lr" in the inline assembly
82 // above and a superfluous return statement here.
83 #pragma diag_suppress=Pe940
84 }
85 #pragma diag_default=Pe940
86 #elif defined(__CC_ARM) || defined(__ARMCC_VERSION)
87 __asm uint32_t
CPUcpsid(void)88 CPUcpsid(void)
89 {
90 // Read PRIMASK and disable interrupts.
91 mrs r0, PRIMASK;
92 cpsid i;
93 bx lr
94 }
95 #elif (defined(__TI_COMPILER_VERSION__) || defined(__clang__))
96 uint32_t
CPUcpsid(void)97 CPUcpsid(void)
98 {
99 // Read PRIMASK and disable interrupts.
100 __asm(" mrs r0, PRIMASK\n"
101 " cpsid i\n"
102 " bx lr\n");
103
104 // The following keeps the compiler happy, because it wants to see a
105 // return value from this function. It will generate code to return
106 // a zero. However, the real return is the "bx lr" above, so the
107 // return(0) is never executed and the function returns with the value
108 // you expect in R0.
109 return(0);
110 }
111 #else
112 uint32_t __attribute__((naked))
CPUcpsid(void)113 CPUcpsid(void)
114 {
115 uint32_t ui32Ret;
116
117 // Read PRIMASK and disable interrupts
118 __asm volatile (" mrs %0, PRIMASK\n"
119 " cpsid i\n"
120 " bx lr\n"
121 : "=r"(ui32Ret)
122 );
123
124 // The return is handled in the inline assembly, but the compiler will
125 // still complain if there is not an explicit return here (despite the fact
126 // that this does not result in any code being produced because of the
127 // naked attribute).
128 return(ui32Ret);
129 }
130 #endif
131
132 //*****************************************************************************
133 //
134 // Get the current interrupt state
135 //
136 //*****************************************************************************
137 #if defined(DOXYGEN)
138 uint32_t
CPUprimask(void)139 CPUprimask(void)
140 {
141 // This function is written in assembly. See cpu.c for compiler specific implementation.
142 }
143 #elif defined(__IAR_SYSTEMS_ICC__)
144 uint32_t
CPUprimask(void)145 CPUprimask(void)
146 {
147 // Read PRIMASK.
148 __asm(" mrs r0, PRIMASK\n");
149
150 // "Warning[Pe940]: missing return statement at end of non-void function"
151 // is suppressed here to avoid putting a "bx lr" in the inline assembly
152 // above and a superfluous return statement here.
153 #pragma diag_suppress=Pe940
154 }
155 #pragma diag_default=Pe940
156 #elif defined(__CC_ARM) || defined(__ARMCC_VERSION)
157 __asm uint32_t
CPUprimask(void)158 CPUprimask(void)
159 {
160 // Read PRIMASK.
161 mrs r0, PRIMASK;
162 bx lr
163 }
164 #elif (defined(__TI_COMPILER_VERSION__) || defined(__clang__))
165 uint32_t
CPUprimask(void)166 CPUprimask(void)
167 {
168 // Read PRIMASK.
169 __asm(" mrs r0, PRIMASK\n"
170 " bx lr\n");
171
172 // The following keeps the compiler happy, because it wants to see a
173 // return value from this function. It will generate code to return
174 // a zero. However, the real return is the "bx lr" above, so the
175 // return(0) is never executed and the function returns with the value
176 // you expect in R0.
177 return(0);
178 }
179 #else
180 uint32_t __attribute__((naked))
CPUprimask(void)181 CPUprimask(void)
182 {
183 uint32_t ui32Ret;
184
185 // Read PRIMASK
186 __asm volatile (" mrs %0, PRIMASK\n"
187 " bx lr\n"
188 : "=r"(ui32Ret)
189 );
190
191 // The return is handled in the inline assembly, but the compiler will
192 // still complain if there is not an explicit return here (despite the fact
193 // that this does not result in any code being produced because of the
194 // naked attribute).
195 return(ui32Ret);
196 }
197 #endif
198
199 //*****************************************************************************
200 //
201 // Enable all external interrupts
202 //
203 //*****************************************************************************
204 #if defined(DOXYGEN)
205 uint32_t
CPUcpsie(void)206 CPUcpsie(void)
207 {
208 // This function is written in assembly. See cpu.c for compiler specific implementation.
209 }
210 #elif defined(__IAR_SYSTEMS_ICC__)
211 uint32_t
CPUcpsie(void)212 CPUcpsie(void)
213 {
214 // Read PRIMASK and enable interrupts.
215 __asm(" mrs r0, PRIMASK\n"
216 " cpsie i\n");
217
218 // "Warning[Pe940]: missing return statement at end of non-void function"
219 // is suppressed here to avoid putting a "bx lr" in the inline assembly
220 // above and a superfluous return statement here.
221 #pragma diag_suppress=Pe940
222 }
223 #pragma diag_default=Pe940
224 #elif defined(__CC_ARM) || defined(__ARMCC_VERSION)
225 __asm uint32_t
CPUcpsie(void)226 CPUcpsie(void)
227 {
228 // Read PRIMASK and enable interrupts.
229 mrs r0, PRIMASK;
230 cpsie i;
231 bx lr
232 }
233 #elif (defined(__TI_COMPILER_VERSION__) || defined(__clang__))
234 uint32_t
CPUcpsie(void)235 CPUcpsie(void)
236 {
237 // Read PRIMASK and enable interrupts.
238 __asm(" mrs r0, PRIMASK\n"
239 " cpsie i\n"
240 " bx lr\n");
241
242 // The following keeps the compiler happy, because it wants to see a
243 // return value from this function. It will generate code to return
244 // a zero. However, the real return is the "bx lr" above, so the
245 // return(0) is never executed and the function returns with the value
246 // you expect in R0.
247 return(0);
248 }
249 #else
250 uint32_t __attribute__((naked))
CPUcpsie(void)251 CPUcpsie(void)
252 {
253 uint32_t ui32Ret;
254
255 // Read PRIMASK and enable interrupts.
256 __asm volatile (" mrs %0, PRIMASK\n"
257 " cpsie i\n"
258 " bx lr\n"
259 : "=r"(ui32Ret)
260 );
261
262 // The return is handled in the inline assembly, but the compiler will
263 // still complain if there is not an explicit return here (despite the fact
264 // that this does not result in any code being produced because of the
265 // naked attribute).
266 return(ui32Ret);
267 }
268 #endif
269
270 //*****************************************************************************
271 //
272 // Get the interrupt priority disable level
273 //
274 //*****************************************************************************
275 #if defined(DOXYGEN)
276 uint32_t
CPUbasepriGet(void)277 CPUbasepriGet(void)
278 {
279 // This function is written in assembly. See cpu.c for compiler specific implementation.
280 }
281 #elif defined(__IAR_SYSTEMS_ICC__)
282 uint32_t
CPUbasepriGet(void)283 CPUbasepriGet(void)
284 {
285 // Read BASEPRI.
286 __asm(" mrs r0, BASEPRI\n");
287
288 // "Warning[Pe940]: missing return statement at end of non-void function"
289 // is suppressed here to avoid putting a "bx lr" in the inline assembly
290 // above and a superfluous return statement here.
291 #pragma diag_suppress=Pe940
292 }
293 #pragma diag_default=Pe940
294 #elif defined(__CC_ARM) || defined(__ARMCC_VERSION)
295 __asm uint32_t
CPUbasepriGet(void)296 CPUbasepriGet(void)
297 {
298 // Read BASEPRI.
299 mrs r0, BASEPRI;
300 bx lr
301 }
302 #elif (defined(__TI_COMPILER_VERSION__) || defined(__clang__))
303 uint32_t
CPUbasepriGet(void)304 CPUbasepriGet(void)
305 {
306 // Read BASEPRI.
307 __asm(" mrs r0, BASEPRI\n"
308 " bx lr\n");
309
310 // The following keeps the compiler happy, because it wants to see a
311 // return value from this function. It will generate code to return
312 // a zero. However, the real return is the "bx lr" above, so the
313 // return(0) is never executed and the function returns with the value
314 // you expect in R0.
315 return(0);
316 }
317 #else
318 uint32_t __attribute__((naked))
CPUbasepriGet(void)319 CPUbasepriGet(void)
320 {
321 uint32_t ui32Ret;
322
323 // Read BASEPRI.
324 __asm volatile (" mrs %0, BASEPRI\n"
325 " bx lr\n"
326 : "=r"(ui32Ret)
327 );
328
329 // The return is handled in the inline assembly, but the compiler will
330 // still complain if there is not an explicit return here (despite the fact
331 // that this does not result in any code being produced because of the
332 // naked attribute).
333 return(ui32Ret);
334 }
335 #endif
336 //*****************************************************************************
337 //
338 // Provide a small delay
339 //
340 //*****************************************************************************
341 #if defined(DOXYGEN)
342 void
CPUdelay(uint32_t ui32Count)343 CPUdelay(uint32_t ui32Count)
344 {
345 // This function is written in assembly. See cpu.c for compiler specific implementation.
346 }
347 #elif defined(__IAR_SYSTEMS_ICC__)
348 void
CPUdelay(uint32_t ui32Count)349 CPUdelay(uint32_t ui32Count)
350 {
351 // Loop the specified number of times
352 __asm("CPUdelay:\n"
353 " subs r0, #1\n"
354 " bne.n CPUdelay\n"
355 " bx lr");
356 #pragma diag_suppress=Pe940
357 }
358 #pragma diag_default=Pe940
359 #elif defined(__CC_ARM) || defined(__ARMCC_VERSION)
360 __asm void
CPUdelay(uint32_t ui32Count)361 CPUdelay(uint32_t ui32Count)
362 {
363 // Delay the specified number of times (3 cycles pr. loop)
364 CPUdel
365 subs r0, #1;
366 bne CPUdel;
367 bx lr;
368 }
369 #elif defined(__TI_COMPILER_VERSION__)
370 // For CCS implement this function in pure assembly. This prevents the TI
371 // compiler from doing funny things with the optimizer.
372
373 // Loop the specified number of times
374 __asm(" .sect \".text:NOROM_CPUdelay\"\n"
375 " .clink\n"
376 " .thumbfunc NOROM_CPUdelay\n"
377 " .thumb\n"
378 " .global NOROM_CPUdelay\n"
379 "NOROM_CPUdelay:\n"
380 " subs r0, #1\n"
381 " bne.n NOROM_CPUdelay\n"
382 " bx lr\n");
383 #elif defined(__clang__)
384 void
CPUdelay(uint32_t ui32Count)385 CPUdelay(uint32_t ui32Count)
386 {
387 // Loop the specified number of times
388 __asm("CPUdelay:\n"
389 " subs r0, #1\n"
390 " bne.n CPUdelay\n"
391 " bx lr");
392 }
393 #else
394 // GCC
395 void __attribute__((naked))
CPUdelay(uint32_t ui32Count)396 CPUdelay(uint32_t ui32Count)
397 {
398 // Loop the specified number of times
399 __asm volatile ("%=: subs %0, #1\n"
400 " bne %=b\n"
401 " bx lr\n"
402 : /* No output */
403 : "r" (ui32Count)
404 );
405 }
406 #endif
407