diff --git a/targets/TARGET_NUVOTON/nu_timer.c b/targets/TARGET_NUVOTON/nu_timer.c index ef3d3489ca..a58e7b2f5c 100644 --- a/targets/TARGET_NUVOTON/nu_timer.c +++ b/targets/TARGET_NUVOTON/nu_timer.c @@ -65,3 +65,65 @@ void nu_busy_wait_us(uint32_t us) prev = cur; } } + +/* Delay 4 cycles per round by hand-counting instruction cycles + * + * The delay function here is implemented by just hand-counting instruction cycles rather than preferred + * H/W timer since it is to use in cases where H/W timer is not available. Usually, it can delay at least + * 4-cycles per round. + * + * In modern pipeline core, plus flash performance and other factors, we cannot rely accurately on hand- + * counting instruction cycles for expected delay cycles. + */ +#if defined(__CC_ARM) +MBED_NOINLINE +__asm void nu_delay_cycle_x4(uint32_t rounds) +{ +// AStyle should not format inline assembly +// *INDENT-OFF* +1 +#if !defined(__CORTEX_M0) + NOP // 1 cycle +#endif + SUBS a1, a1, #1 // 1 cycle + BCS %BT1 // 3 cycles(M0)/2 cycles(non-M0) + BX lr +// *INDENT-ON* +} +#elif defined (__ICCARM__) +MBED_NOINLINE +void nu_delay_cycle_x4(uint32_t rounds) +{ + __asm volatile( + "loop: \n" +#if !defined(__CORTEX_M0) + " NOP \n" // 1 cycle +#endif + " SUBS %0, %0, #1 \n" // 1 cycle + " BCS.n loop\n" // 3 cycles(M0)/2 cycles(non-M0) + : "+r"(rounds) + : + : "cc" + ); +} +#elif defined ( __GNUC__ ) || (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)) +MBED_NOINLINE +void nu_delay_cycle_x4(uint32_t rounds) +{ + __asm__ volatile( + "%=:\n\t" +#if !defined(__CORTEX_M0) + "NOP\n\t" // 1 cycle +#endif +#if defined(__thumb__) && !defined(__thumb2__) && !defined(__ARMCC_VERSION) + "SUB %0, #1\n\t" // 1 cycle +#else + "SUBS %0, %0, #1\n\t" // 1 cycle +#endif + "BCS %=b\n\t" // 3 cycles(M0)/2 cycles(non-M0) + : "+l"(rounds) + : + : "cc" + ); +} +#endif diff --git a/targets/TARGET_NUVOTON/nu_timer.h b/targets/TARGET_NUVOTON/nu_timer.h index 4b9f359e2e..f3d4d867bb 100644 --- a/targets/TARGET_NUVOTON/nu_timer.h +++ b/targets/TARGET_NUVOTON/nu_timer.h @@ -74,6 +74,9 @@ void nu_countdown_free(struct nu_countdown_ctx_s *ctx); */ void nu_busy_wait_us(uint32_t us); +/* Delay 4 cycles per round by hand-counting instruction cycles */ +void nu_delay_cycle_x4(uint32_t rounds); + #ifdef __cplusplus } #endif