1
0
Fork 0
mirror of https://github.com/iNavFlight/inav.git synced 2025-07-26 17:55:28 +03:00
inav/src/main/drivers/timer.h

267 lines
8.3 KiB
C

/*
* This file is part of Cleanflight.
*
* Cleanflight is free software: you can redistribute it and/or modify
* it 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 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include "drivers/io_types.h"
#include "drivers/dma.h"
#include "drivers/rcc_types.h"
#include "drivers/timer_def.h"
#include "platform.h"
#define CC_CHANNELS_PER_TIMER 4 // TIM_Channel_1..4
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) || defined(STM32F7) || defined(STM32H7)|| defined(AT32F43x)
typedef uint32_t timCCR_t;
typedef uint32_t timCCER_t;
typedef uint32_t timSR_t;
typedef uint32_t timCNT_t;
#elif defined(UNIT_TEST)
typedef uint32_t timCCR_t;
typedef uint32_t timCCER_t;
typedef uint32_t timSR_t;
typedef uint32_t timCNT_t;
#elif defined(SITL_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
#if 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
#elif defined(AT32F43x)
#define HARDWARE_TIMER_DEFINITION_COUNT 15
#elif defined(SITL_BUILD)
#define HARDWARE_TIMER_DEFINITION_COUNT 0
#else
#error "Unknown CPU defined"
#endif
// tmr_type instead in AT32
#if defined(AT32F43x)
typedef tmr_type HAL_Timer_t;
typedef struct timerDef_s {
HAL_Timer_t * tim;
rccPeriphTag_t rcc;
uint8_t irq;
uint8_t secondIrq;
} timerDef_t;
// TCH hardware definition (listed in target.c)
typedef struct timerHardware_s {
tmr_type *tim;
ioTag_t tag;
uint8_t channelIndex;
uint8_t output;
ioConfig_t ioMode;
uint8_t alternateFunction;
uint32_t usageFlags;
dmaTag_t dmaTag;
uint32_t dmaMuxid; //DMAMUX ID
} timerHardware_t;
#else
typedef TIM_TypeDef HAL_Timer_t;
typedef struct timerDef_s {
HAL_Timer_t * tim;
rccPeriphTag_t rcc;
uint8_t irq;
uint8_t secondIrq;
} timerDef_t;
// TCH hardware definition (listed in target.c)
typedef struct timerHardware_s {
TIM_TypeDef *tim;
ioTag_t tag;
uint8_t channelIndex;
uint8_t output;
ioConfig_t ioMode;
uint8_t alternateFunction;
uint32_t usageFlags;
dmaTag_t dmaTag;
} timerHardware_t;
#endif
typedef enum {
TIM_USE_ANY = 0,
TIM_USE_PPM = (1 << 0),
TIM_USE_PWM = (1 << 1),
TIM_USE_MOTOR = (1 << 2), // Motor output
TIM_USE_SERVO = (1 << 3), // Servo output
TIM_USE_MC_CHNFW = (1 << 4), // Deprecated and not used after removal of CHANNEL_FORWARDING feature
//TIM_USE_FW_MOTOR = (1 << 5), // We no longer differentiate mc from fw on pwm allocation
//TIM_USE_FW_SERVO = (1 << 6),
TIM_USE_LED = (1 << 24),
TIM_USE_BEEPER = (1 << 25),
} timerUsageFlag_e;
#define TIM_USE_OUTPUT_AUTO (TIM_USE_MOTOR | TIM_USE_SERVO)
#define TIM_IS_MOTOR(flags) ((flags) & TIM_USE_MOTOR)
#define TIM_IS_SERVO(flags) ((flags) & TIM_USE_SERVO)
#define TIM_IS_MOTOR_ONLY(flags) (TIM_IS_MOTOR(flags) && !TIM_IS_SERVO(flags))
#define TIM_IS_SERVO_ONLY(flags) (!TIM_IS_MOTOR(flags) && TIM_IS_SERVO(flags))
enum {
TIMER_OUTPUT_NONE = 0x00,
TIMER_OUTPUT_INVERTED = 0x02,
TIMER_OUTPUT_N_CHANNEL= 0x04
};
typedef enum {
TCH_DMA_IDLE = 0,
TCH_DMA_READY,
TCH_DMA_ACTIVE,
} tchDmaState_e;
// Some forward declarations for types
struct TCH_s;
struct timHardwareContext_s;
// Timer generic callback
typedef void timerCallbackFn(struct TCH_s * tch, uint32_t value);
typedef struct timerCallbacks_s {
void * callbackParam;
timerCallbackFn * callbackEdge;
timerCallbackFn * callbackOvr;
} timerCallbacks_t;
// Run-time TCH (Timer CHannel) context
typedef struct TCH_s {
struct timHardwareContext_s * timCtx; // Run-time initialized to parent timer
const timerHardware_t * timHw; // Link to timerHardware_t definition (target-specific)
const timerCallbacks_t * cb;
DMA_t dma; // Timer channel DMA handle
volatile tchDmaState_e dmaState;
void * dmaBuffer;
} TCH_t;
// Run-time timer context (dynamically allocated), includes 4x TCH
typedef struct timHardwareContext_s {
const timerDef_t * timDef;
#ifdef USE_HAL_DRIVER
TIM_HandleTypeDef * timHandle;
#endif
TCH_t ch[CC_CHANNELS_PER_TIMER];
#ifdef USE_DSHOT_DMAR
DMA_t dmaBurstRef;
uint16_t DMASource;
#endif
} timHardwareContext_t;
// Per MCU timer definitions
extern timHardwareContext_t * timerCtx[HARDWARE_TIMER_DEFINITION_COUNT];
extern const timerDef_t timerDefinitions[HARDWARE_TIMER_DEFINITION_COUNT];
// Per target timer output definitions
extern timerHardware_t timerHardware[];
extern const int timerHardwareCount;
#ifdef USE_DSHOT_DMAR
typedef struct {
TIM_TypeDef *timer;
#ifdef USE_HAL_DRIVER
DMA_TypeDef *dma;
uint32_t streamLL;
#else
DMA_Stream_TypeDef *dmaBurstStream;
#endif
timerDMASafeType_t *dmaBurstBuffer;
uint16_t burstRequestSource;
} burstDmaTimer_t;
#endif
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;
#if defined(AT32F43x)
uint32_t timerClock(tmr_type *tim);
uint16_t timerGetPrescalerByDesiredMhz(tmr_type *tim, uint16_t mhz);
#else
uint32_t timerClock(TIM_TypeDef *tim);
uint16_t timerGetPrescalerByDesiredMhz(TIM_TypeDef *tim, uint16_t mhz);
#endif
uint32_t timerGetBaseClockHW(const timerHardware_t * timHw);
const timerHardware_t * timerGetByUsageFlag(timerUsageFlag_e flag);
const timerHardware_t * timerGetByTag(ioTag_t tag, timerUsageFlag_e flag);
TCH_t * timerGetTCH(const timerHardware_t * timHw);
uint32_t timerGetBaseClock(TCH_t * tch);
void timerConfigure(TCH_t * tch, uint16_t period, uint32_t hz); // This interface should be replaced.
void timerChInitCallbacks(timerCallbacks_t * cb, void * callbackParam, timerCallbackFn * edgeCallback, timerCallbackFn * overflowCallback);
void timerChConfigIC(TCH_t * tch, bool polarityRising, unsigned inputFilterSamples);
void timerChConfigCallbacks(TCH_t * tch, timerCallbacks_t * cb);
void timerChCaptureEnable(TCH_t * tch);
void timerChCaptureDisable(TCH_t * tch);
void timerInit(void);
void timerStart(void);
void timerConfigBase(TCH_t * tch, uint16_t period, uint32_t hz); // TODO - just for migration
uint16_t timerGetPeriod(TCH_t * tch);
void timerEnable(TCH_t * tch);
void timerPWMConfigChannel(TCH_t * tch, uint16_t value);
void timerPWMStart(TCH_t * tch);
// dmaBufferElementSize is the size in bytes of each element in the memory
// buffer. 1, 2 or 4 are the only valid values.
// dmaBufferElementCount is the number of elements in the buffer
bool timerPWMConfigChannelDMA(TCH_t * tch, void * dmaBuffer, uint8_t dmaBufferElementSize, uint32_t dmaBufferElementCount);
void timerPWMPrepareDMA(TCH_t * tch, uint32_t dmaBufferElementCount);
void timerPWMStartDMA(TCH_t * tch);
void timerPWMStopDMA(TCH_t * tch);
bool timerPWMDMAInProgress(TCH_t * tch);
volatile timCCR_t *timerCCR(TCH_t * tch);
uint8_t timer2id(const HAL_Timer_t *tim);
#ifdef USE_DSHOT_DMAR
bool timerPWMConfigDMABurst(burstDmaTimer_t *burstDmaTimer, TCH_t * tch, void * dmaBuffer, uint8_t dmaBufferElementSize, uint32_t dmaBufferElementCount);
void pwmBurstDMAStart(burstDmaTimer_t * burstDmaTimer, uint32_t BurstLength);
#endif