forked from emuflight/EmuFlight
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtimer.h
More file actions
211 lines (181 loc) · 7.54 KB
/
Copy pathtimer.h
File metadata and controls
211 lines (181 loc) · 7.54 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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
/*
* This file is part of Cleanflight and Betaflight.
*
* Cleanflight and Betaflight are free software. You can redistribute
* this software and/or modify this software under the terms of the
* GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option)
* any later version.
*
* Cleanflight and Betaflight are distributed in the hope that they
* will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software.
*
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include "drivers/io_types.h"
#include "drivers/resource.h"
#include "rcc_types.h"
#include "drivers/timer_def.h"
#define CC_CHANNELS_PER_TIMER 4 // TIM_Channel_1..4
#define CC_INDEX_FROM_CHANNEL(x) ((uint8_t)((x) >> 2))
#define CC_CHANNEL_FROM_INDEX(x) ((uint16_t)(x) << 2)
typedef uint16_t captureCompare_t; // 16 bit on both 103 and 303, just register access must be 32bit sometimes (use timCCR_t)
#if defined(STM32F4)
typedef uint32_t timCCR_t;
typedef uint32_t timCCER_t;
typedef uint32_t timSR_t;
typedef uint32_t timCNT_t;
#elif defined(STM32F7) || defined(STM32H7)
typedef uint32_t timCCR_t;
typedef uint32_t timCCER_t;
typedef uint32_t timSR_t;
typedef uint32_t timCNT_t;
#elif defined(UNIT_TEST) || defined(SIMULATOR_BUILD)
typedef uint32_t timCCR_t;
typedef uint32_t timCCER_t;
typedef uint32_t timSR_t;
typedef uint32_t timCNT_t;
#else
#error "Unknown CPU defined"
#endif
typedef enum {
TIM_USE_ANY = 0x0,
TIM_USE_NONE = 0x0,
TIM_USE_PPM = 0x1,
TIM_USE_PWM = 0x2,
TIM_USE_MOTOR = 0x4,
TIM_USE_SERVO = 0x8,
TIM_USE_LED = 0x10,
TIM_USE_TRANSPONDER = 0x20,
TIM_USE_BEEPER = 0x40
} timerUsageFlag_e;
// use different types from capture and overflow - multiple overflow handlers are implemented as linked list
struct timerCCHandlerRec_s;
struct timerOvrHandlerRec_s;
typedef void timerCCHandlerCallback(struct timerCCHandlerRec_s* self, uint16_t capture);
typedef void timerOvrHandlerCallback(struct timerOvrHandlerRec_s* self, uint16_t capture);
typedef struct timerCCHandlerRec_s {
timerCCHandlerCallback* fn;
} timerCCHandlerRec_t;
typedef struct timerOvrHandlerRec_s {
timerOvrHandlerCallback* fn;
struct timerOvrHandlerRec_s* next;
} timerOvrHandlerRec_t;
typedef struct timerDef_s {
TIM_TypeDef *TIMx;
rccPeriphTag_t rcc;
uint8_t inputIrq;
} timerDef_t;
typedef struct timerHardware_s {
TIM_TypeDef *tim;
ioTag_t tag;
uint8_t channel;
timerUsageFlag_e usageFlags;
uint8_t output;
#if defined(STM32F4) || defined(STM32F7) || defined(STM32H7)
uint8_t alternateFunction;
#endif
#if defined(USE_DSHOT) || defined(USE_LED_STRIP) || defined(USE_TRANSPONDER)
#if defined(STM32F4) || defined(STM32F7) || defined(STM32H7)
DMA_Stream_TypeDef *dmaRef;
uint32_t dmaChannel;
#else
DMA_Channel_TypeDef *dmaRef;
#endif
uint8_t dmaIrqHandler;
#if defined(STM32F4) || defined(STM32F7) || defined(STM32H7)
// TIMUP
DMA_Stream_TypeDef *dmaTimUPRef;
uint32_t dmaTimUPChannel;
uint8_t dmaTimUPIrqHandler;
#endif
#endif
} timerHardware_t;
typedef enum {
TIMER_OUTPUT_NONE = 0,
TIMER_OUTPUT_INVERTED = (1 << 0),
TIMER_OUTPUT_N_CHANNEL = (1 << 1),
} timerFlag_e;
#if defined(STM32F411xE)
#define HARDWARE_TIMER_DEFINITION_COUNT 10
#elif defined(STM32F4)
#define HARDWARE_TIMER_DEFINITION_COUNT 14
#elif defined(STM32F7)
#define HARDWARE_TIMER_DEFINITION_COUNT 14
#elif defined(STM32H7)
#define HARDWARE_TIMER_DEFINITION_COUNT 14
#endif
#define MHZ_TO_HZ(x) ((x) * 1000000)
extern const timerHardware_t timerHardware[];
extern const timerDef_t timerDefinitions[];
typedef enum {
TYPE_FREE,
TYPE_PWMINPUT,
TYPE_PPMINPUT,
TYPE_PWMOUTPUT_MOTOR,
TYPE_PWMOUTPUT_FAST,
TYPE_PWMOUTPUT_SERVO,
TYPE_SOFTSERIAL_RX,
TYPE_SOFTSERIAL_TX,
TYPE_SOFTSERIAL_RXTX, // bidirectional pin for softserial
TYPE_SOFTSERIAL_AUXTIMER, // timer channel is used for softserial. No IO function on pin
TYPE_ADC,
TYPE_SERIAL_RX,
TYPE_SERIAL_TX,
TYPE_SERIAL_RXTX,
TYPE_TIMER
} channelType_t;
void timerConfigure(const timerHardware_t *timHw, uint16_t period, uint32_t hz); // This interface should be replaced.
void timerReconfigureTimeBase(TIM_TypeDef *tim, uint16_t period, uint32_t hz);
void timerChConfigIC(const timerHardware_t *timHw, bool polarityRising, unsigned inputFilterSamples);
void timerChConfigICDual(const timerHardware_t* timHw, bool polarityRising, unsigned inputFilterSamples);
void timerChICPolarity(const timerHardware_t *timHw, bool polarityRising);
volatile timCCR_t* timerChCCR(const timerHardware_t* timHw);
volatile timCCR_t* timerChCCRLo(const timerHardware_t* timHw);
volatile timCCR_t* timerChCCRHi(const timerHardware_t* timHw);
void timerChConfigOC(const timerHardware_t* timHw, bool outEnable, bool stateHigh);
void timerChConfigGPIO(const timerHardware_t* timHw, ioConfig_t mode);
void timerChCCHandlerInit(timerCCHandlerRec_t *self, timerCCHandlerCallback *fn);
void timerChOvrHandlerInit(timerOvrHandlerRec_t *self, timerOvrHandlerCallback *fn);
void timerChConfigCallbacks(const timerHardware_t *channel, timerCCHandlerRec_t *edgeCallback, timerOvrHandlerRec_t *overflowCallback);
void timerChConfigCallbacksDual(const timerHardware_t *channel, timerCCHandlerRec_t *edgeCallbackLo, timerCCHandlerRec_t *edgeCallbackHi, timerOvrHandlerRec_t *overflowCallback);
void timerChITConfigDualLo(const timerHardware_t* timHw, FunctionalState newState);
void timerChITConfig(const timerHardware_t* timHw, FunctionalState newState);
void timerChClearCCFlag(const timerHardware_t* timHw);
void timerChInit(const timerHardware_t *timHw, channelType_t type, int irqPriority, uint8_t irq);
void timerInit(void);
void timerStart(void);
void timerForceOverflow(TIM_TypeDef *tim);
uint32_t timerClock(TIM_TypeDef *tim);
void configTimeBase(TIM_TypeDef *tim, uint16_t period, uint32_t hz); // TODO - just for migration
rccPeriphTag_t timerRCC(TIM_TypeDef *tim);
uint8_t timerInputIrq(TIM_TypeDef *tim);
const timerHardware_t *timerGetByTag(ioTag_t ioTag);
const timerHardware_t *timerAllocate(ioTag_t ioTag, resourceOwner_e owner, uint8_t resourceIndex);
resourceOwner_e timerGetOwner(ioTag_t ioTag);
uint8_t timerGetOwnerResourceIndex(ioTag_t ioTag);
ioTag_t timerioTagGetByUsage(timerUsageFlag_e usageFlag, uint8_t index);
#if defined(USE_HAL_DRIVER)
TIM_HandleTypeDef* timerFindTimerHandle(TIM_TypeDef *tim);
HAL_StatusTypeDef TIM_DMACmd(TIM_HandleTypeDef *htim, uint32_t Channel, FunctionalState NewState);
HAL_StatusTypeDef DMA_SetCurrDataCounter(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length);
uint16_t timerDmaIndex(uint8_t channel);
#else
void timerOCInit(TIM_TypeDef *tim, uint8_t channel, TIM_OCInitTypeDef *init);
void timerOCPreloadConfig(TIM_TypeDef *tim, uint8_t channel, uint16_t preload);
#endif
volatile timCCR_t *timerCCR(TIM_TypeDef *tim, uint8_t channel);
uint16_t timerDmaSource(uint8_t channel);
uint16_t timerGetPrescalerByDesiredHertz(TIM_TypeDef *tim, uint32_t hz);
uint16_t timerGetPrescalerByDesiredMhz(TIM_TypeDef *tim, uint16_t mhz);
uint16_t timerGetPeriodByPrescaler(TIM_TypeDef *tim, uint16_t prescaler, uint32_t hz);
int8_t timerGetTIMNumber(const TIM_TypeDef *tim);
uint8_t timerLookupChannelIndex(const uint16_t channel);