Skip to content

Commit 91b22f8

Browse files
committed
Hand assemble to get alignment
1 parent 66dea08 commit 91b22f8

File tree

1 file changed

+19
-48
lines changed

1 file changed

+19
-48
lines changed

platform/mbed_wait_api_no_rtos.c

Lines changed: 19 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
*/
1717

1818
#include "cmsis.h"
19+
#include "platform/mbed_toolchain.h"
1920
#include "platform/mbed_wait_api.h"
2021

2122
// This implementation of the wait functions will be compiled only
@@ -47,11 +48,11 @@ void wait_us(int us)
4748

4849
#ifdef __CORTEX_M
4950
#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
5152
#define LOOP_SCALER 6000
5253
#elif (__CORTEX_M == 0 && defined __CM0PLUS_REV) || __CORTEX_M == 3 || __CORTEX_M == 4 || \
5354
__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
5556
// TODO - check M33
5657
#define LOOP_SCALER 5000
5758
#elif __CORTEX_M == 7
@@ -76,52 +77,22 @@ void wait_us(int us)
7677
*/
7778
#ifdef LOOP_SCALER
7879

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))
12596

12697
void wait_ns(unsigned int ns)
12798
{

0 commit comments

Comments
 (0)