@@ -65,3 +65,65 @@ void nu_busy_wait_us(uint32_t us)
65
65
prev = cur ;
66
66
}
67
67
}
68
+
69
+ /* Delay 4 cycles per round by hand-counting instruction cycles
70
+ *
71
+ * The delay function here is implemented by just hand-counting instruction cycles rather than preferred
72
+ * H/W timer since it is to use in cases where H/W timer is not available. Usually, it can delay at least
73
+ * 4-cycles per round.
74
+ *
75
+ * In modern pipeline core, plus flash performance and other factors, we cannot rely accurately on hand-
76
+ * counting instruction cycles for expected delay cycles.
77
+ */
78
+ #if defined(__CC_ARM )
79
+ MBED_NOINLINE
80
+ __asm void nu_delay_cycle_x4 (uint32_t rounds )
81
+ {
82
+ // AStyle should not format inline assembly
83
+ // *INDENT-OFF*
84
+ 1
85
+ #if !defined(__CORTEX_M0 )
86
+ NOP // 1 cycle
87
+ #endif
88
+ SUBS a1 , a1 , #1 // 1 cycle
89
+ BCS %BT1 // 3 cycles(M0)/2 cycles(non-M0)
90
+ BX lr
91
+ // *INDENT-ON*
92
+ }
93
+ #elif defined (__ICCARM__ )
94
+ MBED_NOINLINE
95
+ void nu_delay_cycle_x4 (uint32_t rounds )
96
+ {
97
+ __asm volatile (
98
+ "loop: \n"
99
+ #if !defined(__CORTEX_M0 )
100
+ " NOP \n" // 1 cycle
101
+ #endif
102
+ " SUBS %0, %0, #1 \n" // 1 cycle
103
+ " BCS.n loop\n" // 3 cycles(M0)/2 cycles(non-M0)
104
+ : "+ r "(rounds)
105
+ :
106
+ : " cc "
107
+ );
108
+ }
109
+ #elif defined ( __GNUC__ ) || (defined(__ARMCC_VERSION ) && (__ARMCC_VERSION >= 6010050 ))
110
+ MBED_NOINLINE
111
+ void nu_delay_cycle_x4 (uint32_t rounds )
112
+ {
113
+ __asm__ volatile (
114
+ "%=:\n\t"
115
+ #if !defined(__CORTEX_M0 )
116
+ "NOP\n\t" // 1 cycle
117
+ #endif
118
+ #if defined(__thumb__ ) && !defined(__thumb2__ ) && !defined(__ARMCC_VERSION )
119
+ "SUB %0, #1\n\t" // 1 cycle
120
+ #else
121
+ "SUBS %0, %0, #1\n\t" // 1 cycle
122
+ #endif
123
+ "BCS %=b\n\t" // 3 cycles(M0)/2 cycles(non-M0)
124
+ : "+ l "(rounds)
125
+ :
126
+ : " cc "
127
+ );
128
+ }
129
+ #endif
0 commit comments