From 92e4a1faf74aae7f50f5fe785371842d468183a2 Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 29 Jun 2017 09:51:44 +0100 Subject: [PATCH 1/5] Fix timing issues found in "Flash - clock and cache test" ARMCC seemed to be inlining time_cpu_cycles() but with a different number of clock cycles in the loop, GCC worked fine. --- TESTS/mbed_hal/flash/functional_tests/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TESTS/mbed_hal/flash/functional_tests/main.cpp b/TESTS/mbed_hal/flash/functional_tests/main.cpp index d2bf288467..1c933ecdd1 100644 --- a/TESTS/mbed_hal/flash/functional_tests/main.cpp +++ b/TESTS/mbed_hal/flash/functional_tests/main.cpp @@ -53,7 +53,7 @@ static void erase_range(flash_t *flash, uint32_t addr, uint32_t size) } } -static int time_cpu_cycles(uint32_t cycles) +__attribute__((noinline)) static int time_cpu_cycles(uint32_t cycles) { Timer timer; timer.start(); From 3df42bcfb4a080d5d9866a47259484eb5dd9b3fc Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 30 Jun 2017 20:32:17 +0100 Subject: [PATCH 2/5] Toolchain independent noinline --- platform/mbed_toolchain.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/platform/mbed_toolchain.h b/platform/mbed_toolchain.h index a2dae81645..b9579e5f5a 100644 --- a/platform/mbed_toolchain.h +++ b/platform/mbed_toolchain.h @@ -137,6 +137,27 @@ #endif #endif +/** MBED_NOINLINE + * Declare a function that must not be inlined. + * + * @code + * #include "mbed_toolchain.h" + * + * MBED_NOINLINE void foo() { + * + * } + * @endcode + */ +#ifndef MBED_NOINLINE +#if defined(__GNUC__) || defined(__clang__) || defined(__CC_ARM) +#define MBED_NOINLINE __attribute__((noinline)) +#elif defined(__ICCARM__) +#define MBED_NOINLINE _Pragma("inline=never") +#else +#define MBED_NOINLINE +#endif +#endif + /** MBED_FORCEINLINE * Declare a function that must always be inlined. Failure to inline * such a function will result in an error. From 562a5480532bb98f71bcf5b2666ec46d506626a0 Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 30 Jun 2017 20:33:58 +0100 Subject: [PATCH 3/5] Assembly based loop for timing test --- .../mbed_hal/flash/functional_tests/main.cpp | 46 +++++++++++++++++-- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/TESTS/mbed_hal/flash/functional_tests/main.cpp b/TESTS/mbed_hal/flash/functional_tests/main.cpp index 1c933ecdd1..579995ed8c 100644 --- a/TESTS/mbed_hal/flash/functional_tests/main.cpp +++ b/TESTS/mbed_hal/flash/functional_tests/main.cpp @@ -52,8 +52,49 @@ static void erase_range(flash_t *flash, uint32_t addr, uint32_t size) size = size > sector_size ? size - sector_size : 0; } } +#ifdef __CC_ARM +MBED_NOINLINE +__asm static void delay_loop(uint32_t count) +{ +1 + SUBS a1, a1, #1 + BCS %BT1 + BX lr +} +#elif defined (__ICCARM__) +MBED_NOINLINE +static void delay_loop(uint32_t count) +{ + __asm volatile( + "loop: \n" + " SUBS %0, %0, #1 \n" + " BCS.n loop\n" + : "+r" (count) + : + : "cc" + ); +} +#else // GCC +MBED_NOINLINE +static void delay_loop(uint32_t count) +{ + __asm__ volatile ( + "%=:\n\t" +#if defined(__thumb__) && !defined(__thumb2__) + "SUB %0, #1\n\t" +#else + "SUBS %0, %0, #1\n\t" +#endif + "BCS %=b\n\t" + : "+l" (count) + : + : "cc" + ); +} +#endif -__attribute__((noinline)) static int time_cpu_cycles(uint32_t cycles) +MBED_NOINLINE +static int time_cpu_cycles(uint32_t cycles) { Timer timer; timer.start(); @@ -61,8 +102,7 @@ __attribute__((noinline)) static int time_cpu_cycles(uint32_t cycles) int timer_start = timer.read_us(); volatile uint32_t delay = (volatile uint32_t)cycles; - while (delay--); - + delay_loop(delay); int timer_end = timer.read_us(); timer.stop(); From ed8b378c6edacfdd7187fce7b49af963373c2cda Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 30 Jun 2017 22:09:47 +0100 Subject: [PATCH 4/5] Code tidy --- TESTS/mbed_hal/flash/functional_tests/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TESTS/mbed_hal/flash/functional_tests/main.cpp b/TESTS/mbed_hal/flash/functional_tests/main.cpp index 579995ed8c..644b693f58 100644 --- a/TESTS/mbed_hal/flash/functional_tests/main.cpp +++ b/TESTS/mbed_hal/flash/functional_tests/main.cpp @@ -102,7 +102,7 @@ static int time_cpu_cycles(uint32_t cycles) int timer_start = timer.read_us(); volatile uint32_t delay = (volatile uint32_t)cycles; - delay_loop(delay); + delay_loop(delay); int timer_end = timer.read_us(); timer.stop(); From 8365d9d00ddd9ce73b67d6e9926075a1d20a8674 Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 30 Jun 2017 22:44:05 +0100 Subject: [PATCH 5/5] Remove volatile --- TESTS/mbed_hal/flash/functional_tests/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TESTS/mbed_hal/flash/functional_tests/main.cpp b/TESTS/mbed_hal/flash/functional_tests/main.cpp index 644b693f58..cabe49ec4e 100644 --- a/TESTS/mbed_hal/flash/functional_tests/main.cpp +++ b/TESTS/mbed_hal/flash/functional_tests/main.cpp @@ -101,7 +101,7 @@ static int time_cpu_cycles(uint32_t cycles) int timer_start = timer.read_us(); - volatile uint32_t delay = (volatile uint32_t)cycles; + uint32_t delay = cycles; delay_loop(delay); int timer_end = timer.read_us();