From 7722eb9cc94d8538758ced9153f2fac5b75bdce1 Mon Sep 17 00:00:00 2001
From: Thibaut VIARD <thibaut.viard@atmel.com>
Date: Wed, 17 Sep 2014 17:17:22 +0200
Subject: [PATCH]  Fixing delayMicroseconds()

---
 cores/arduino/delay.h | 59 +++++++++++++++++++++++--------------------
 1 file changed, 31 insertions(+), 28 deletions(-)

diff --git a/cores/arduino/delay.h b/cores/arduino/delay.h
index 9809fc37..527bf464 100644
--- a/cores/arduino/delay.h
+++ b/cores/arduino/delay.h
@@ -60,40 +60,43 @@ extern void delay( uint32_t dwMs ) ;
  *
  * \param dwUs the number of microseconds to pause (uint32_t)
  */
-static inline void delayMicroseconds(uint32_t) __attribute__((always_inline, unused));
-static inline void delayMicroseconds(uint32_t usec){
-    if (usec == 0) return;
-    uint32_t n = usec * (VARIANT_MCK / 3000000);
-#if 0
-    __asm__ volatile(
-        "L_%=_delayMicroseconds:"       "\n\t"
-        "subs   %0, %0, #1"                 "\n\t"
-        "bne    L_%=_delayMicroseconds" "\n"
-        : "+r" (n) :
-    );
-#else
-  for ( ; n != 0 ; n-- )
+static __inline__ void delayMicroseconds( uint32_t ) __attribute__((always_inline, unused)) ;
+static __inline__ void delayMicroseconds( uint32_t ul_usec )
+{
+  if ( ul_usec == 0 )
   {
+    return ;
   }
-#endif
-}
 
-/*
-__attribute__((naked)) static void delay_loop(unsigned n)
-{
-	__asm volatile ("1: subs r0, r0, #1");
-	__asm volatile (" bne 1b");
-	__asm volatile (" bx lr");
-}
+  uint32_t ul = ul_usec * (VARIANT_MCK / 3000000); // = ul_usec * 16 with VARIANT_MCK @ 48MHz
 
-void delay_microseconds(unsigned n)
-{
-	// Bogus assumption:
-	// Assume 8 cycles/iteration and running at 80MHz
-	delay_loop(n * 10);
-}
+/* following 'for' loop will generate this:
+ * loop:
+ * subs r3, #1 // 1 Core cycle
+ * bne.n loop // 1 or 2 Core cycles, depends on pipeline break (50/50?)
+
+  for ( ; ul != 0 ; ul-- )
+  {
+    __asm__ volatile("");
+  }
 */
 
+/*
+ * __asm__ [__volatile__] ( AssemblerTemplate : [OutputOperands] [ : [InputOperands] [ : [Clobbers] ] ] )
+ *
+ * __asm__ documentation for GCC: https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html
+ * __volatile__ documentation for GCC: https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Volatile
+ *
+ */
+  __asm__ __volatile__( "1:      \n"
+                        "sub %0, #1              \n" /* substract 1 from %0 (ul) */
+                        "bne 1b   \n"
+                        : /* no outputs */
+                        : "r" (ul) /* 'ul' variable is '%0', '+' means R/W constraint on this variable/register, 'r' means 'register' (versus 'm' for 'memory' */
+                        : /* no clobber, ie nothing should be damaged by this asm code */
+                      ) ;
+}
+
 #ifdef __cplusplus
 }
 #endif
-- 
GitLab