16
16
*/
17
17
18
18
#include "cmsis.h"
19
+ #include "platform/mbed_toolchain.h"
19
20
#include "platform/mbed_wait_api.h"
20
21
21
22
// This implementation of the wait functions will be compiled only
@@ -47,11 +48,11 @@ void wait_us(int us)
47
48
48
49
#ifdef __CORTEX_M
49
50
#if (__CORTEX_M == 0 && !defined __CM0PLUS_REV ) || __CORTEX_M == 1
50
- // Cortex-M0 and Cortex-M1 take 7 cycles per iteration - SUBS = 1, 2xNOP = 2, BCS = 3
51
+ // Cortex-M0 and Cortex-M1 take 6 cycles per iteration - SUBS = 1, 2xNOP = 2, BCS = 3
51
52
#define LOOP_SCALER 6000
52
53
#elif (__CORTEX_M == 0 && defined __CM0PLUS_REV ) || __CORTEX_M == 3 || __CORTEX_M == 4 || \
53
54
__CORTEX_M == 23 || __CORTEX_M == 33
54
- // Cortex-M0+, M3, M4, M23 and M33 take 6 cycles per iteration - SUBS = 1, 3xNOP = 2, BCS = 2
55
+ // Cortex-M0+, M3, M4, M23 and M33 take 5 cycles per iteration - SUBS = 1, 2xNOP = 2, BCS = 2
55
56
// TODO - check M33
56
57
#define LOOP_SCALER 5000
57
58
#elif __CORTEX_M == 7
@@ -76,52 +77,22 @@ void wait_us(int us)
76
77
*/
77
78
#ifdef LOOP_SCALER
78
79
79
- // *INDENT-OFF*
80
- #ifdef __CC_ARM /* ARMC5 */
81
- __asm static void delay_loop (uint32_t count )
82
- {
83
- 1
84
- SUBS a1 , a1 , #1
85
- NOP
86
- NOP
87
- BCS %BT1
88
- BX lr
89
- }
90
- #elif defined (__ICCARM__ )
91
- static void delay_loop (uint32_t count )
92
- {
93
- __asm volatile (
94
- "loop: \n"
95
- " SUBS %0, %0, #1 \n"
96
- " NOP\n"
97
- " NOP\n"
98
- " BCS.n loop\n"
99
- : "+r" (count )
100
- :
101
- : "cc"
102
- );
103
- }
104
- #else // GCC or ARMC6
105
- static void delay_loop (uint32_t count )
106
- {
107
- __asm__ volatile (
108
- "%=:\n\t"
109
- /* Only GCC insists on non-UAL assembly for Thumb v1 */
110
- #if !defined(__ARMCC_VERSION ) && defined(__thumb__ ) && !defined(__thumb2__ )
111
- "SUB %0, #1\n\t"
112
- #else
113
- "SUBS %0, %0, #1\n\t"
114
- #endif
115
- "NOP\n\t"
116
- "NOP\n\t"
117
- "BCS %=b\n\t"
118
- : "+ l " (count)
119
- :
120
- : " cc "
121
- );
122
- }
123
- #endif
124
- // *INDENT-ON*
80
+ /* Timing seems to depend on alignment, and toolchains do not support aligning
81
+ * functions well. So sidestep that by hand-assembling the code. Also avoids
82
+ * the hassle of handling multiple toolchains with different assembler
83
+ * syntax.
84
+ */
85
+ MBED_ALIGN (8 )
86
+ static const uint16_t delay_loop_code [] = {
87
+ 0x1E40 , // SUBS R0,R0,#1
88
+ 0xBF00 , // NOP
89
+ 0xBF00 , // NOP
90
+ 0xD2FB , // BCS .-3 (0x00 would be .+2, so 0xFB = -5 = .-3)
91
+ 0x4770 // BX LR
92
+ };
93
+
94
+ /* Take the address of the code, set LSB to indicate Thumb, and cast to void() function pointer */
95
+ #define delay_loop ((void(*)()) ((uintptr_t) delay_loop_code | 1))
125
96
126
97
void wait_ns (unsigned int ns )
127
98
{
0 commit comments