|
Paparazzi UAS
v5.18.0_stable
Paparazzi is a free software Unmanned Aircraft System.
|
Go to the documentation of this file.
31 #include <stdnoreturn.h>
48 #define DSHOT_SPEED 300
54 #ifndef DSHOT_TELEMETRY_BAUD
55 #define DSHOT_TELEMETRY_BAUD 115200
60 #ifndef DSHOT_TELEMETRY_TIMEOUT_MS
61 #define DSHOT_TELEMETRY_TIMEOUT_MS 3
65 #define PWM_FREQ (STM32_SYSCLK/2000)
73 #define TICKS_PER_PERIOD 1000
76 #define DSHOT_FREQ (DSHOT_SPEED*1000) // in Hz
77 #define TICK_FREQ (PWM_FREQ * TICKS_PER_PERIOD)
78 #define DSHOT_PWM_PERIOD (TICK_FREQ/DSHOT_FREQ)
79 #define DSHOT_BIT0_DUTY (DSHOT_PWM_PERIOD * 373 / 1000)
80 #define DSHOT_BIT1_DUTY (DSHOT_BIT0_DUTY*2)
81 #define DCR_DBL ((DSHOT_CHANNELS-1) << 8) // DSHOT_CHANNELS transfert(s), first register to get is CCR1
82 #define DCR_DBA(pwmd) (((uint32_t *) (&pwmd->tim->CCR) - ((uint32_t *) pwmd->tim)))
84 #define ARRAY_LEN(a) (sizeof(a)/sizeof(a[0]))
85 #define Min(x,y) (x < y ? x : y)
87 #define DSHOT_MAX_VALUE ((1<<11)-1) // 11 bits used to send command, so maximum value is 2047
124 memset((
void *)
config->dma_buf, 0,
sizeof(*(
config->dma_buf)));
127 static const SerialConfig tlmcfg = {
130 .cr2 = USART_CR2_STOP1_BITS,
138 .channel =
config->dma_channel,
142 .psize = timerWidthInBytes,
143 .msize = timerWidthInBytes,
145 .dcache_memory_in_use =
config->dcache_memory_in_use,
147 .inc_peripheral_addr =
false,
148 .inc_memory_addr =
true,
162 {.mode = PWM_OUTPUT_ACTIVE_HIGH,
164 {.mode =
DSHOT_CHANNELS > 1 ? PWM_OUTPUT_ACTIVE_HIGH : PWM_OUTPUT_DISABLED,
166 {.mode =
DSHOT_CHANNELS > 2 ? PWM_OUTPUT_ACTIVE_HIGH : PWM_OUTPUT_DISABLED,
168 {.mode =
DSHOT_CHANNELS > 3 ? PWM_OUTPUT_ACTIVE_HIGH : PWM_OUTPUT_DISABLED,
171 .cr2 = STM32_TIM_CR2_CCDS,
172 .dier = STM32_TIM_DIER_UDE
180 chDbgAssert(dmaOk ==
true,
"dshot dma start error");
184 chThdCreateStatic(driver->waDshotTlmRec,
sizeof(driver->waDshotTlmRec), NORMALPRIO,
214 chDbgAssert(
false,
"dshotSetThrottle throttle error");
226 chDbgAssert(
false,
"dshotSetThrottle index error");
273 chThdSleepMilliseconds(1);
360 .telemetryRequest = (tlmRequest ? 1 : 0),
365 uint16_t csum = (_throttle << 1) | dp.telemetryRequest;
366 for (
int i = 0; i < 3; i++) {
376 dp->throttle = throttle;
377 dp->telemetryRequest = 0;
382 dp->telemetryRequest = tlmRequest ? 1 : 0;
391 uint16_t csum = (dp->throttle << 1) | dp->telemetryRequest;
392 for (
int i = 0; i < 3; i++) {
401 if (timerWidth == 2) {
404 #if DSHOT_AT_LEAST_ONE_32B_TIMER
407 chSysHalt(
"use of 32 bit timer implies to define DSHOT_AT_LEAST_ONE_32B_TIMER to TRUE");
420 for (
int i = 0; i < 8; i++) {
421 crc_u = (crc_u & 0x80) ? 0x7 ^ (crc_u << 1) : (crc_u << 1);
430 for (
int i = 0; i < BufLen; i++) {
437 __attribute__((
const))
446 #if STM32_PWM_USE_TIM5
468 chRegSetThreadName(
"dshotTlmRec");
470 chMBFetchTimeout(&driver->
mb, (msg_t *) &escIdx, TIME_INFINITE);
479 while (sdGetTimeout(driver->
config->
tlm_sd, TIME_IMMEDIATE) >= 0) {};
bool dmaStartTransfert(DMADriver *dmap, volatile void *periphp, void *mem0p, const size_t size)
Starts a DMA transaction.
@ DSHOT_CMD_SAVE_SETTINGS
@ DMA_DIR_M2P
MEMORY to PERIPHERAL
void dshotSendThrottles(DSHOTDriver *driver, const uint16_t throttles[DSHOT_CHANNELS])
send throttle packed order to all of the ESCs
@ DSHOT_CMD_SPIN_DIRECTION_2
DshotTelemetry dt[DSHOT_CHANNELS]
@ DSHOT_CMD_AUDIO_STREAM_MODE_ON_OFF
PWMConfig pwm_conf
PWM config associated with pwm timer.
PWMDriver * pwmp
PWM driver that feed up to 4 dshot lines.
#define DSHOT_CHANNEL_FIRST_INDEX
DshotPacket dp[DSHOT_CHANNELS]
void dshotSetThrottle(DSHOTDriver *driver, const uint8_t index, const uint16_t throttle)
prepare throttle order for specified ESC
#define DSHOT_TELEMETRY_TIMEOUT_MS
Telemetry timeout in ms.
const DSHOTConfig * config
DMA config associated with pwm timer.
volatile uint8_t currentTlmQry
@ DSHOT_CMD_SPIN_DIRECTION_1
uint32_t crc_errors
number of crc errors
#define DSHOT_PRE_FRAME_SILENT_SYNC_BITS
#define DSHOT_ALL_MOTORS
special value for index : send order to all channels
#define STM32_PWM_USE_TIM2
void dshotSendSpecialCommand(DSHOTDriver *driver, const uint8_t index, const dshot_special_commands_t specmd)
send special order to one of the ESC (BHELIX, KISS, ...)
void dmaObjectInit(DMADriver *dmap)
uint32_t dshotGetCrcErrorsCount(DSHOTDriver *driver)
return number of telemetry crc error since dshotStart
DMADriver dmap
DMA driver associated with pwm timer.
static const struct usb_config_descriptor config
DSHOT driver based on ChibiOS.
@ DSHOT_CMD_SETTINGS_REQUEST
DshotDmaBuffer * dma_buf
dshot dma buffer, sgould be defined in a non Dcached region
static void setDshotPacketThrottle(DshotPacket *const dp, const uint16_t throttle)
mailbox_t mb
mailbox for dshot telemetry thread
volatile dmastate_t state
Driver state.
static void buildDshotDmaBuffer(DshotPackets *const dsp, DshotDmaBuffer *const dma, const size_t timerWidth)
static uint8_t calculateCrc8(const uint8_t *Buf, const uint8_t BufLen)
static noreturn void dshotTlmRec(void *arg)
static uint8_t updateCrc8(uint8_t crc, uint8_t crc_seed)
msg_t _mbBuf[1]
mailbox buffer for dshot telemetry thread
SerialDriver * tlm_sd
if non null : dshot telemetry serial driver
DMAConfig dma_conf
DMA config associated with pwm timer.
void dshotSendFrame(DSHOTDriver *driver)
send throttle order
@ DSHOT_CMD_SILENT_MODE_ON_OFF
static DshotPacket makeDshotPacket(const uint16_t throttle, 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...
telemetry packed as sent by some KISS ESC
dshot_special_commands_t
DSHOT special commands (0-47) for KISS and BLHELI ESC.
#define DSHOT_BIT_WIDTHS
DMA buffer size and number of channels.
uint32_t stream
stream associated with transaction
void dshotStart(DSHOTDriver *driver, const DSHOTConfig *config)
Configures and activates the DSHOT peripheral.
bool dmaStart(DMADriver *dmap, const DMAConfig *cfg)
Configures and activates the DMA peripheral.
static void setDshotPacketTlm(DshotPacket *const dp, const bool tlmRequest)
#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...
DMA stream configuration structure.
static size_t getTimerWidth(const PWMDriver *pwmp)
uint16_t widths16[DSHOT_DMA_BUFFER_SIZE][DSHOT_CHANNELS]
#define DSHOT_DMA_BUFFER_SIZE
DSHOT Driver configuration structure.
const DshotTelemetry * dshotGetTelemetry(const DSHOTDriver *driver, const uint32_t index)
return last received telemetry data