blob: 7cd9de724f768bfee6d5e11e0685e7167c74997c (
plain)
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
|
/*
* StepTimer.h
*
* Created on: 9 Sep 2018
* Author: David
*/
#ifndef SRC_MOVEMENT_STEPTIMER_H_
#define SRC_MOVEMENT_STEPTIMER_H_
#include "RepRapFirmware.h"
// Class to implement a software timer with a few microseconds resolution
class StepTimer
{
public:
// The callback function returns true if it wants another callback, after setting the requested time via the second parameter
typedef uint32_t Ticks;
typedef bool (*TimerCallbackFunction)(CallbackParameter, Ticks&);
StepTimer() noexcept;
// Set up the callback function and parameter
void SetCallback(TimerCallbackFunction cb, CallbackParameter param) noexcept;
// Schedule a callback at a particular tick count, returning true if it was not scheduled because it is already due or imminent
bool ScheduleCallback(Ticks when) noexcept;
// As ScheduleCallback but base priority >= NvicPriorityStep when called
bool ScheduleCallbackFromIsr(Ticks when) noexcept;
// Cancel any scheduled callbacks
void CancelCallback() noexcept;
// As CancelCallback but base priority >= NvicPriorityStep when called
void CancelCallbackFromIsr() noexcept;
// Initialise the timer system
static void Init() noexcept;
// Disable the timer interrupt. Called when we shut down the system.
static void DisableTimerInterrupt() noexcept;
// Get the current tick count
static Ticks GetTimerTicks() noexcept __attribute__ ((hot));
// Get the current tick count when we only need a 16-bit value. Faster than GetTimerTicks() on the SAM4S and SAME70.
static uint16_t GetTimerTicks16() noexcept;
// Get the tick rate (can also access it directly as StepClockRate)
static uint32_t GetTickRate() noexcept { return StepClockRate; }
// ISR called from StepTimer. May sometimes get called prematurely.
static void Interrupt() noexcept;
#if SAME70
static constexpr uint32_t StepClockRate = 48000000/64; // 750kHz
#elif defined(__LPC17xx__)
static constexpr uint32_t StepClockRate = 1000000; // 1MHz
#else
static constexpr uint32_t StepClockRate = VARIANT_MCK/128; // just under 1MHz
#endif
static constexpr uint64_t StepClockRateSquared = (uint64_t)StepClockRate * StepClockRate;
static constexpr float StepClocksToMillis = 1000.0/(float)StepClockRate;
static constexpr uint32_t MinInterruptInterval = 6; // about 6us
private:
static bool ScheduleTimerInterrupt(uint32_t tim) noexcept; // Schedule an interrupt at the specified clock count, or return true if it has passed already
StepTimer *next;
Ticks whenDue;
TimerCallbackFunction callback;
CallbackParameter cbParam;
volatile bool active;
static StepTimer * volatile pendingList; // list of pending callbacks, soonest first
};
// Function GetTimerTicks() is quite long for SAM4S and SAME70 processors, so it is moved to StepTimer.cpp and no longer inlined
#if !(SAM4S || SAME70)
inline StepTimer::Ticks StepTimer::GetTimerTicks() noexcept
{
# ifdef __LPC17xx__
return STEP_TC->TC;
# else
return STEP_TC->TC_CHANNEL[STEP_TC_CHAN].TC_CV;
# endif
}
#endif
inline uint16_t StepTimer::GetTimerTicks16() noexcept
{
#ifdef __LPC17xx__
return (uint16_t)STEP_TC->TC;
#else
return (uint16_t)STEP_TC->TC_CHANNEL[STEP_TC_CHAN].TC_CV;
#endif
}
#endif /* SRC_MOVEMENT_STEPTIMER_H_ */
|