2 * This file is part of Cleanflight.
4 * Cleanflight is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * Cleanflight is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
23 #include "drivers/io_types.h"
24 #include "drivers/dma.h"
25 #include "drivers/rcc_types.h"
26 #include "drivers/timer_def.h"
30 #define CC_CHANNELS_PER_TIMER 4 // TIM_Channel_1..4
32 typedef uint16_t captureCompare_t
; // 16 bit on both 103 and 303, just register access must be 32bit sometimes (use timCCR_t)
34 #if defined(STM32F4) || defined(STM32F7) || defined(STM32H7)|| defined(AT32F43x)
35 typedef uint32_t timCCR_t
;
36 typedef uint32_t timCCER_t
;
37 typedef uint32_t timSR_t
;
38 typedef uint32_t timCNT_t
;
39 #elif defined(UNIT_TEST)
40 typedef uint32_t timCCR_t
;
41 typedef uint32_t timCCER_t
;
42 typedef uint32_t timSR_t
;
43 typedef uint32_t timCNT_t
;
44 #elif defined(SITL_BUILD)
45 typedef uint32_t timCCR_t
;
46 typedef uint32_t timCCER_t
;
47 typedef uint32_t timSR_t
;
48 typedef uint32_t timCNT_t
;
50 #error "Unknown CPU defined"
54 #define HARDWARE_TIMER_DEFINITION_COUNT 14
55 #elif defined(STM32F7)
56 #define HARDWARE_TIMER_DEFINITION_COUNT 14
57 #elif defined(STM32H7)
58 #define HARDWARE_TIMER_DEFINITION_COUNT 14
59 #elif defined(AT32F43x)
60 #define HARDWARE_TIMER_DEFINITION_COUNT 15
61 #elif defined(SITL_BUILD)
62 #define HARDWARE_TIMER_DEFINITION_COUNT 0
64 #error "Unknown CPU defined"
66 // tmr_type instead in AT32
68 typedef tmr_type HAL_Timer_t
;
69 typedef struct timerDef_s
{
75 // TCH hardware definition (listed in target.c)
76 typedef struct timerHardware_s
{
82 uint8_t alternateFunction
;
85 uint32_t dmaMuxid
; //DMAMUX ID
88 typedef TIM_TypeDef HAL_Timer_t
;
89 typedef struct timerDef_s
{
96 // TCH hardware definition (listed in target.c)
97 typedef struct timerHardware_s
{
100 uint8_t channelIndex
;
103 uint8_t alternateFunction
;
111 TIM_USE_PPM
= (1 << 0),
112 TIM_USE_PWM
= (1 << 1),
113 TIM_USE_MOTOR
= (1 << 2), // Motor output
114 TIM_USE_SERVO
= (1 << 3), // Servo output
115 TIM_USE_MC_CHNFW
= (1 << 4), // Deprecated and not used after removal of CHANNEL_FORWARDING feature
116 //TIM_USE_FW_MOTOR = (1 << 5), // We no longer differentiate mc from fw on pwm allocation
117 //TIM_USE_FW_SERVO = (1 << 6),
118 TIM_USE_LED
= (1 << 24), // Remapping needs to be in the lower 8 bits.
119 TIM_USE_BEEPER
= (1 << 25),
122 #define TIM_USE_OUTPUT_AUTO (TIM_USE_MOTOR | TIM_USE_SERVO)
124 #define TIM_IS_MOTOR(flags) ((flags) & TIM_USE_MOTOR)
125 #define TIM_IS_SERVO(flags) ((flags) & TIM_USE_SERVO)
126 #define TIM_IS_LED(flags) ((flags) & TIM_USE_LED)
128 #define TIM_IS_MOTOR_ONLY(flags) (TIM_IS_MOTOR(flags) && !TIM_IS_SERVO(flags))
129 #define TIM_IS_SERVO_ONLY(flags) (!TIM_IS_MOTOR(flags) && TIM_IS_SERVO(flags))
132 TIMER_OUTPUT_NONE
= 0x00,
133 TIMER_OUTPUT_INVERTED
= 0x02,
134 TIMER_OUTPUT_N_CHANNEL
= 0x04
143 // Some forward declarations for types
145 struct timHardwareContext_s
;
147 // Timer generic callback
148 typedef void timerCallbackFn(struct TCH_s
* tch
, uint32_t value
);
150 typedef struct timerCallbacks_s
{
151 void * callbackParam
;
152 timerCallbackFn
* callbackEdge
;
153 timerCallbackFn
* callbackOvr
;
156 // Run-time TCH (Timer CHannel) context
157 typedef struct TCH_s
{
158 struct timHardwareContext_s
* timCtx
; // Run-time initialized to parent timer
159 const timerHardware_t
* timHw
; // Link to timerHardware_t definition (target-specific)
160 const timerCallbacks_t
* cb
;
161 DMA_t dma
; // Timer channel DMA handle
162 volatile tchDmaState_e dmaState
;
166 // Run-time timer context (dynamically allocated), includes 4x TCH
167 typedef struct timHardwareContext_s
{
168 const timerDef_t
* timDef
;
169 #ifdef USE_HAL_DRIVER
170 TIM_HandleTypeDef
* timHandle
;
172 TCH_t ch
[CC_CHANNELS_PER_TIMER
];
173 #ifdef USE_DSHOT_DMAR
177 } timHardwareContext_t
;
179 // Per MCU timer definitions
180 extern timHardwareContext_t
* timerCtx
[HARDWARE_TIMER_DEFINITION_COUNT
];
181 extern const timerDef_t timerDefinitions
[HARDWARE_TIMER_DEFINITION_COUNT
];
183 // Per target timer output definitions
184 extern timerHardware_t timerHardware
[];
185 extern const int timerHardwareCount
;
187 #ifdef USE_DSHOT_DMAR
190 #ifdef USE_HAL_DRIVER
194 DMA_Stream_TypeDef
*dmaBurstStream
;
196 timerDMASafeType_t
*dmaBurstBuffer
;
197 uint16_t burstRequestSource
;
205 TYPE_PWMOUTPUT_MOTOR
,
207 TYPE_PWMOUTPUT_SERVO
,
210 TYPE_SOFTSERIAL_RXTX
, // bidirectional pin for softserial
211 TYPE_SOFTSERIAL_AUXTIMER
, // timer channel is used for softserial. No IO function on pin
219 #if defined(AT32F43x)
220 uint32_t timerClock(tmr_type
*tim
);
221 uint16_t timerGetPrescalerByDesiredMhz(tmr_type
*tim
, uint16_t mhz
);
223 uint32_t timerClock(TIM_TypeDef
*tim
);
224 uint16_t timerGetPrescalerByDesiredMhz(TIM_TypeDef
*tim
, uint16_t mhz
);
227 uint32_t timerGetBaseClockHW(const timerHardware_t
* timHw
);
229 const timerHardware_t
* timerGetByUsageFlag(timerUsageFlag_e flag
);
230 const timerHardware_t
* timerGetByTag(ioTag_t tag
, timerUsageFlag_e flag
);
231 TCH_t
* timerGetTCH(const timerHardware_t
* timHw
);
233 uint32_t timerGetBaseClock(TCH_t
* tch
);
234 void timerConfigure(TCH_t
* tch
, uint16_t period
, uint32_t hz
); // This interface should be replaced.
236 void timerChInitCallbacks(timerCallbacks_t
* cb
, void * callbackParam
, timerCallbackFn
* edgeCallback
, timerCallbackFn
* overflowCallback
);
237 void timerChConfigIC(TCH_t
* tch
, bool polarityRising
, unsigned inputFilterSamples
);
238 void timerChConfigCallbacks(TCH_t
* tch
, timerCallbacks_t
* cb
);
239 void timerChCaptureEnable(TCH_t
* tch
);
240 void timerChCaptureDisable(TCH_t
* tch
);
242 void timerInit(void);
243 void timerStart(void);
245 void timerConfigBase(TCH_t
* tch
, uint16_t period
, uint32_t hz
); // TODO - just for migration
246 uint16_t timerGetPeriod(TCH_t
* tch
);
248 void timerEnable(TCH_t
* tch
);
249 void timerPWMConfigChannel(TCH_t
* tch
, uint16_t value
);
250 void timerPWMStart(TCH_t
* tch
);
252 // dmaBufferElementSize is the size in bytes of each element in the memory
253 // buffer. 1, 2 or 4 are the only valid values.
254 // dmaBufferElementCount is the number of elements in the buffer
255 bool timerPWMConfigChannelDMA(TCH_t
* tch
, void * dmaBuffer
, uint8_t dmaBufferElementSize
, uint32_t dmaBufferElementCount
);
256 void timerPWMPrepareDMA(TCH_t
* tch
, uint32_t dmaBufferElementCount
);
257 void timerPWMStartDMA(TCH_t
* tch
);
258 void timerPWMStopDMA(TCH_t
* tch
);
259 bool timerPWMDMAInProgress(TCH_t
* tch
);
261 volatile timCCR_t
*timerCCR(TCH_t
* tch
);
263 uint8_t timer2id(const HAL_Timer_t
*tim
);
265 #ifdef USE_DSHOT_DMAR
266 bool timerPWMConfigDMABurst(burstDmaTimer_t
*burstDmaTimer
, TCH_t
* tch
, void * dmaBuffer
, uint8_t dmaBufferElementSize
, uint32_t dmaBufferElementCount
);
267 void pwmBurstDMAStart(burstDmaTimer_t
* burstDmaTimer
, uint32_t BurstLength
);