Repository navigation
Expand file tree
/
Copy pathdelay.c
More file actions
135 lines (115 loc) · 3.55 KB
/
Copy pathdelay.c
File metadata and controls
135 lines (115 loc) · 3.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*
Copyright (c) 2015 Arduino LLC. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "Arduino.h"
#ifdef __cplusplus
extern "C" {
#endif
/** Tick Counter united by ms */
static volatile uint32_t _ulTickCount=0 ;
unsigned long millis( void )
{
// todo: ensure no interrupts
return _ulTickCount ;
}
// Interrupt-compatible version of micros
// Theory: repeatedly take readings of SysTick counter, millis counter and SysTick interrupt pending flag.
// When it appears that millis counter and pending is stable and SysTick hasn't rolled over, use these
// values to calculate micros. If there is a pending SysTick, add one to the millis counter in the calculation.
unsigned long micros( void )
{
uint32_t ticks, ticks2;
uint32_t pend, pend2;
uint32_t count, count2;
ticks2 = SysTick->VAL;
pend2 = !!(SCB->ICSR & SCB_ICSR_PENDSTSET_Msk) ;
count2 = _ulTickCount ;
do
{
ticks=ticks2;
pend=pend2;
count=count2;
ticks2 = SysTick->VAL;
pend2 = !!(SCB->ICSR & SCB_ICSR_PENDSTSET_Msk) ;
count2 = _ulTickCount ;
} while ((pend != pend2) || (count != count2) || (ticks < ticks2));
return ((count+pend) * 1000) + (((SysTick->LOAD - ticks)*(1048576/(VARIANT_MCK/1000000)))>>20) ;
// this is an optimization to turn a runtime division into two compile-time divisions and
// a runtime multiplication and shift, saving a few cycles
}
void delay( unsigned long ms )
{
if (ms == 0)
{
return;
}
uint32_t start = micros();
while (ms > 0)
{
yield();
while (ms > 0 && (micros() - start) >= 1000)
{
ms--;
start += 1000;
}
}
}
#include "Reset.h" // for tickReset()
void SysTick_DefaultHandler(void)
{
// Increment tick count each ms
_ulTickCount++;
tickReset();
}
/**
* \brief Pauses the program for the amount of time (in microseconds) specified as parameter.
*
* \param dwUs the number of microseconds to pause (uint32_t)
*/
void delayMicroseconds( unsigned int usec )
{
if ( usec == 0 )
{
return ;
}
/*
* The following loop:
*
* for (; ul; ul--) {
* __asm__ volatile("");
* }
*
* produce the following assembly code:
*
* loop:
* subs r3, #1 // 1 Core cycle
* bne.n loop // 1 Core cycle + 1 if branch is taken
*/
// VARIANT_MCK / 1000000 == cycles needed to delay 1uS
// 3 == cycles used in a loop
uint32_t n = usec * (VARIANT_MCK / 1000000) / 3;
__asm__ __volatile__(
"1: \n"
" sub %0, #1 \n" // substract 1 from %0 (n)
" bne 1b \n" // if result is not 0 jump to 1
: "+r" (n) // '%0' is n variable with RW constraints
: // no input
: // no clobber
);
// https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html
// https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Volatile
}
#ifdef __cplusplus
}
#endif