31#include <stdnoreturn.h>
34#include "mcu_periph/sys_time_arch.h"
49#ifndef DSHOT_TELEMETRY_BAUD
50#define DSHOT_TELEMETRY_BAUD 115200U
53#ifndef DSHOT_BIDIR_EXTENTED_TELEMETRY
54#define DSHOT_BIDIR_EXTENTED_TELEMETRY FALSE
59#ifndef DSHOT_TELEMETRY_TIMEOUT_MS
60#define DSHOT_TELEMETRY_TIMEOUT_MS 3
66#define PWM_FREQ (STM32_TIMCLK1 / 1000U)
71#define PWM_FREQ (STM32_SYSCLK / 2000U)
81#define TICKS_PER_PERIOD 1000
85#ifndef DSHOT_BIT0_DUTY_RATIO
86#define DSHOT_BIT0_DUTY_RATIO 373U
90# define DSHOT_FREQ (DSHOT_SPEED*1000)
91# define DSHOT_BIT0_DUTY (DSHOT_PWM_PERIOD * DSHOT_BIT0_DUTY_RATIO / 1000U)
92# define DSHOT_BIT1_DUTY (DSHOT_BIT0_DUTY*2)
94# define DSHOT_FREQ (driver->config->speed_khz * 1000U)
95# define DSHOT_BIT0_DUTY (driver->bit0Duty)
96# define DSHOT_BIT1_DUTY (driver->bit1Duty)
98#define TICK_FREQ (PWM_FREQ * TICKS_PER_PERIOD)
99#define DSHOT_PWM_PERIOD (TICK_FREQ/DSHOT_FREQ)
102#define DCR_DBL ((DSHOT_CHANNELS-1) << 8)
104#define DCR_DBA(pwmd) (((uint32_t *) (&pwmd->tim->CCR) - ((uint32_t *) pwmd->tim)))
106#define DSHOT_MAX_VALUE ((1U<<11U)-1U)
108#define ARRAY_LEN(a) (sizeof(a)/sizeof(a[0]))
109#define Min(x,y) (x < y ? x : y)
133#if DSHOT_BIDIR_EXTENTED_TELEMETRY
178#if STM32_DMA_SUPPORTS_DMAMUX
181 .channel =
config->dma_channel,
189 .dcache_memory_in_use =
config->dcache_memory_in_use,
191 .inc_peripheral_addr =
false,
192 .inc_memory_addr =
true,
305 chDbgAssert(
false,
"dshotSetThrottle throttle error");
317 chDbgAssert(
false,
"dshotSetThrottle index error");
368 chDbgAssert(
false,
"dshotSetThrottle index error");
489#if DSHOT_BIDIR && DSHOT_BIDIR_EXTENTED_TELEMETRY
530#if DSHOT_BIDIR_EXTENTED_TELEMETRY
560#if DSHOT_BIDIR_EXTENTED_TELEMETRY
591 uint16_t csum = (dp->throttle << 1) | dp->telemetryRequest;
592 for (
int i = 0; i < 3; i++) {
597 dp->crc = ~(dp->crc);
614 dp->throttle = throttle;
615 dp->telemetryRequest = 0;
641#if DSHOT_AT_LEAST_ONE_32B_TIMER
644 chSysHalt(
"use of 32 bit timer implies to define DSHOT_AT_LEAST_ONE_32B_TIMER to TRUE");
658 for (
int i = 0; i < 8; i++) {
668 for (
int i = 0; i <
BufLen; i++) {
695#if STM32_PWM_USE_TIM5
uint32_t DshotErpsGetRpm(const DshotErps *derpsp)
calculate and return rpm
uint32_t DshotErpsGetEperiod(const DshotErps *derpsp)
return eperiod from mantisse and exponent
const DshotErps * DshotErpsSetFromFrame(DshotErps *derpsp, uint32_t frame)
initialise from GCR encoded frame
bool DshotErpsCheckCrc4(const DshotErps *derpsp)
check packed validity
static uint16_t DshotErpsEdtStatus(const DshotErps *derpsp)
return status value
static uint8_t DshotErpsEdtTempCentigrade(const DshotErps *derpsp)
return temperature for a temperature telemetry frame
static uint16_t DshotErpsEdtStress(const DshotErps *derpsp)
return stress value
static EdtType DshotErpsEdtType(const DshotErps *derpsp)
return type of a telemetry frame
static uint16_t DshotErpsEdtCentiVolts(const DshotErps *derpsp)
return voltage for a voltage telemetry frame
static uint16_t DshotErpsEdtCurrentAmp(const DshotErps *derpsp)
return current intensity for a current telemetry frame
static bool DshotErpsIsEdt(const DshotErps *derpsp)
return true if current frame is a telemetry frame
ERPS complete frame, raw and decoded.
void dshotRpmCaptureStart(DshotRpmCapture *drcp, const DshotRpmCaptureConfig *cfg, stm32_tim_t *timer)
Configures and activates the DSHOT ERPS CAPTURE driver.
void dshotRpmCatchErps(DshotRpmCapture *drcp)
capture the DSHOT ERPS frame(s) : one frame for each DSHOT_CHANNELS
static uint32_t dshotRpmGetFrame(const DshotRpmCapture *drcp, uint8_t index)
return last collected erps frame
static void buildDshotDmaBuffer(DSHOTDriver *driver)
void dshotStart(DSHOTDriver *driver, const DSHOTConfig *config)
Configures and activates the DSHOT peripheral.
void dshotSetThrottle(DSHOTDriver *driver, const uint8_t index, const uint16_t throttle)
prepare throttle order for specified ESC
static size_t getTimerWidth(const PWMDriver *pwmp)
#define TICKS_PER_PERIOD
Ticks per period that let use any timer: does not care if linked to PCLK1 or PCLK2 tick_per_period wi...
uint32_t dshotGetTelemetryFrameCount(const DSHOTDriver *driver)
return number of telemetry succesfull frame since dshotStart
static uint8_t calculateCrc8(const uint8_t *Buf, const uint8_t BufLen)
DshotTelemetry dshotGetTelemetry(DSHOTDriver *driver, uint32_t index)
return last received telemetry data
static void setDshotPacketThrottle(DshotPacket *const dp, const uint16_t throttle)
void dshotSendThrottles(DSHOTDriver *driver, const uint16_t throttles[DSHOT_CHANNELS])
send throttle packed order to all of the ESCs
static void setCrc4(DshotPacket *dp)
uint32_t dshotGetCrcErrorCount(const DSHOTDriver *driver)
return number of telemetry crc error since dshotStart
void dshotStop(DSHOTDriver *driver)
stop the DSHOT driver and free the related resources : pwm driver and dma driver.
#define DSHOT_TELEMETRY_TIMEOUT_MS
Telemetry timeout in ms.
#define DSHOT_BIT0_DUTY_RATIO
void dshotSendFrame(DSHOTDriver *driver)
send throttle order
static noreturn void dshotTlmRec(void *arg)
static void setDshotPacketTlm(DshotPacket *const dp, const bool tlmRequest)
#define DSHOT_TELEMETRY_BAUD
Baudrate of the serial link used for telemetry data Can depend on the ESC, but only 115k have been us...
static DshotPacket makeDshotPacket(const uint16_t throttle, const bool tlmRequest)
void dshotSendSpecialCommand(DSHOTDriver *driver, const uint8_t index, const dshot_special_commands_t specmd)
send special order to one of the ESC (BHELIX, KISS, ...)
static uint8_t updateCrc8(uint8_t crc, uint8_t crc_seed)
DSHOT driver based on ChibiOS.
mutex_t tlmMtx[DSHOT_CHANNELS]
#define DSHOT_PRE_FRAME_SILENT_SYNC_BITS
SerialDriver * tlm_sd
if non null : dshot telemetry serial driver
#define DSHOT_BIT_WIDTHS
DMA buffer size and number of channels.
PWMDriver * pwmp
PWM driver that feed up to 4 dshot lines.
#define DSHOT_DMA_BUFFER_SIZE
uint16_t widths16[DSHOT_DMA_BUFFER_SIZE][DSHOT_CHANNELS]
#define DSHOT_CHANNEL_FIRST_INDEX
DshotTelemetry dt[DSHOT_CHANNELS]
#define DSHOT_ALL_MOTORS
special value for index : send order to all channels
#define DSHOT_BIDIR_TLM_EDT
DshotDmaBuffer * dma_buf
dshot dma buffer, should be defined in a non Dcached region
dshot_special_commands_t
DSHOT special commands (0-47) for KISS and BLHELI ESC.
@ DSHOT_CMD_SILENT_MODE_ON_OFF
@ DSHOT_CMD_SAVE_SETTINGS
@ DSHOT_CMD_AUDIO_STREAM_MODE_ON_OFF
@ DSHOT_CMD_SETTINGS_REQUEST
@ DSHOT_CMD_BIDIR_EDT_MODE_OFF
@ DSHOT_CMD_SPIN_DIRECTION_1
@ DSHOT_CMD_SPIN_DIRECTION_2
@ DSHOT_CMD_BIDIR_EDT_MODE_ON
#define DSHOT_BIDIR_ERR_CRC
special values returned by dshotGetRpm function
DshotPacket dp[DSHOT_CHANNELS]
DSHOT Driver configuration structure.
telemetry packed as sent by some KISS ESC
void dmaObjectInit(DMADriver *dmap)
void dmaStop(DMADriver *dmap)
Deactivates the DMA peripheral.
void dmaStopTransfert(DMADriver *dmap)
Stops an ongoing transaction.
bool dmaStart(DMADriver *dmap, const DMAConfig *cfg)
Configures and activates the DMA peripheral.
@ DMA_ONESHOT
One transert then stop
@ DMA_DIR_M2P
MEMORY to PERIPHERAL
uint32_t stream
stream associated with transaction
static msg_t dmaTransfert(DMADriver *dmap, volatile void *periphp, void *mem0p, const size_t size)
volatile dmastate_t state
Driver state.
DMA stream configuration structure.
#define STM32_PWM_USE_TIM2
static const struct usb_config_descriptor config
uint32_t crc_errors
number of crc errors
DshotPackets dshotMotors
object managing dma control frame for outgoing command
mailbox_t mb
mailbox for dshot telemetry thread
DMADriver dmap
DMA driver associated with pwm timer.
PWMConfig pwm_conf
PWM config associated with pwm timer.
const DSHOTConfig * config
DMA config associated with pwm timer.
msg_t _mbBuf[1]
mailbox buffer for dshot telemetry thread
uint32_t tlm_frame_nb
number of sucessful telemetry frame received
DMAConfig dma_conf
DMA config associated with pwm timer.
unsigned short uint16_t
Typedef defining 16 bit unsigned short type.
unsigned int uint32_t
Typedef defining 32 bit unsigned int type.
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.