Paparazzi UAS  v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
esc_dshot.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2018 Alexandre Bustico <alexandre.bustico@enac.fr>
3  * Gautier Hattenberger <gautier.hattenberger@enac.fr>
4  *
5  * This file is part of paparazzi
6  *
7  * paparazzi is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2, or (at your option)
10  * any later version.
11  *
12  * paparazzi is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with paparazzi; see the file COPYING. If not, see
19  * <http://www.gnu.org/licenses/>.
20  */
21 
31 #include <stdnoreturn.h>
32 #include <math.h>
33 #include <string.h>
34 #include "mcu_periph/sys_time_arch.h"
35 
36 /*
37 # _ __ _ _ _ _
38 # | | / _| (_) (_) | | (_)
39 # __| | ___ | |_ _ _ __ _ | |_ _ ___ _ __
40 # / _` | / _ \ | _| | | | '_ \ | | | __| | | / _ \ | '_ \
41 # | (_| | | __/ | | | | | | | | | | \ |_ | | | (_) | | | | |
42 # \__,_| \___| |_| |_| |_| |_| |_| \__| |_| \___/ |_| |_|
43 */
44 
48 #ifndef DSHOT_SPEED
49 #define DSHOT_SPEED 300U
50 #endif
51 
55 #ifndef DSHOT_TELEMETRY_BAUD
56 #define DSHOT_TELEMETRY_BAUD 115200U
57 #endif
58 
61 #ifndef DSHOT_TELEMETRY_TIMEOUT_MS
62 #define DSHOT_TELEMETRY_TIMEOUT_MS 3
63 #endif
64 
65 
66 #ifdef STM32H7XX
67 // each H7 timer have the same max clock speed
68 #define PWM_FREQ (STM32_TIMCLK1 / 1000U) // the timer will beat @240Mhz on STM32H7
69 #else
70 // some F4 and F7 timers are limited to / 2
71 // others are limited to STM32_SYSCLK
72 // so we take the max frequency that all timers can run
73 #define PWM_FREQ (STM32_SYSCLK / 2000U) // the timer will beat @84Mhz on STM32F4
74 #endif
75 
76 
83 #define TICKS_PER_PERIOD 1000
84 
85 // ESCs are quite sensitive to the DSHOT duty cycle.
86 // 333 should work most of the time, but some ESC need 373
87 #ifndef DSHOT_BIT0_DUTY_RATIO
88 #define DSHOT_BIT0_DUTY_RATIO 373U
89 #endif
90 
91 // Some extra defines and macros
92 #define DSHOT_FREQ (DSHOT_SPEED*1000) // in Hz
93 #define TICK_FREQ (PWM_FREQ * TICKS_PER_PERIOD)
94 #define DSHOT_PWM_PERIOD (TICK_FREQ/DSHOT_FREQ)
95 #define DSHOT_BIT0_DUTY (DSHOT_PWM_PERIOD * DSHOT_BIT0_DUTY_RATIO / 1000)
96 #define DSHOT_BIT1_DUTY (DSHOT_BIT0_DUTY*2)
97 #define DCR_DBL ((DSHOT_CHANNELS-1) << 8) // DSHOT_CHANNELS transfert(s), first register to get is CCR1
98 #define DCR_DBA(pwmd) (((uint32_t *) (&pwmd->tim->CCR) - ((uint32_t *) pwmd->tim)))
99 
100 #define ARRAY_LEN(a) (sizeof(a)/sizeof(a[0]))
101 #define Min(x,y) (x < y ? x : y)
102 
103 #define DSHOT_MAX_VALUE ((1<<11)-1) // 11 bits used to send command, so maximum value is 2047
104 
105 /*
106 # _ __ _ _ _ _ _ __
107 # | '_ \ | | | | | | | | | '_ \
108 # | |_) | _ __ ___ | |_ ___ | |_ | |_| | | |_) | ___
109 # | .__/ | '__| / _ \ | __| / _ \ | __| \__, | | .__/ / _ \
110 # | | | | | (_) | \ |_ | (_) | \ |_ __/ | | | | __/
111 # |_| |_| \___/ \__| \___/ \__| |___/ |_| \___|
112 */
113 static DshotPacket makeDshotPacket(const uint16_t throttle, const bool tlmRequest);
114 static inline void setDshotPacketThrottle(DshotPacket * const dp, const uint16_t throttle);
115 static inline void setDshotPacketTlm(DshotPacket * const dp, const bool tlmRequest);
116 static void buildDshotDmaBuffer(DshotPackets * const dsp, DshotDmaBuffer * const dma, const size_t timerWidth);
117 static inline uint8_t updateCrc8(uint8_t crc, uint8_t crc_seed);
118 static uint8_t calculateCrc8(const uint8_t *Buf, const uint8_t BufLen);
119 static noreturn void dshotTlmRec(void *arg);
120 static size_t getTimerWidth(const PWMDriver *pwmp);
121 
122 /*
123 # _ __ _
124 # | '_ \ (_)
125 # __ _ | |_) | _
126 # / _` | | .__/ | |
127 # | (_| | | | | |
128 # \__,_| |_| |_|
129 */
130 
139 {
140  memset((void *) config->dma_buf, 0, sizeof(*(config->dma_buf)));
141  const size_t timerWidthInBytes = getTimerWidth(config->pwmp);
142 
143  static const SerialConfig tlmcfg = {
144  .speed = DSHOT_TELEMETRY_BAUD,
145  .cr1 = 0, // pas de parité
146  .cr2 = USART_CR2_STOP1_BITS, // 1 bit de stop
147  .cr3 = 0 // pas de controle de flux hardware (CTS, RTS)
148  };
149 
150  driver->config = config;
151  // use pburst, mburst only if buffer size satisfy aligmnent requirement
152  driver->dma_conf = (DMAConfig) {
153  .stream = config->dma_stream,
154 #if STM32_DMA_SUPPORTS_DMAMUX
155  .dmamux = config->dmamux,
156 #else
157  .channel = config->dma_channel,
158 #endif
159  .dma_priority = 3,
160  .irq_priority = CORTEX_MAX_KERNEL_PRIORITY + 1,
161  .direction = DMA_DIR_M2P,
162  .psize = timerWidthInBytes,
163  .msize = timerWidthInBytes,
164 #if __DCACHE_PRESENT
165  .dcache_memory_in_use = config->dcache_memory_in_use,
166 #endif
167  .inc_peripheral_addr = false,
168  .inc_memory_addr = true,
169  .circular = false,
170  .error_cb = NULL,
171  .end_cb = NULL,
172  .pburst = 0,
173  .mburst = 0,
174  .fifo = 4
175  };
176 
177  driver->pwm_conf = (PWMConfig) {
178  .frequency = TICK_FREQ,
179  .period = TICKS_PER_PERIOD,
180  .callback = NULL,
181  .channels = {
182  {.mode = PWM_OUTPUT_ACTIVE_HIGH,
183  .callback = NULL},
184  {.mode = DSHOT_CHANNELS > 1 ? PWM_OUTPUT_ACTIVE_HIGH : PWM_OUTPUT_DISABLED,
185  .callback = NULL},
186  {.mode = DSHOT_CHANNELS > 2 ? PWM_OUTPUT_ACTIVE_HIGH : PWM_OUTPUT_DISABLED,
187  .callback = NULL},
188  {.mode = DSHOT_CHANNELS > 3 ? PWM_OUTPUT_ACTIVE_HIGH : PWM_OUTPUT_DISABLED,
189  .callback = NULL},
190  },
191  .cr2 = STM32_TIM_CR2_CCDS,
192  .dier = STM32_TIM_DIER_UDE
193  };
194 
195  driver->crc_errors = 0;
196  dmaObjectInit(&driver->dmap);
197  chMBObjectInit(&driver->mb, driver->_mbBuf, ARRAY_LEN(driver->_mbBuf));
198 
199  const bool dmaOk = dmaStart(&driver->dmap, &driver->dma_conf);
200  chDbgAssert(dmaOk == true, "dshot dma start error");
201 
202  if (driver->config->tlm_sd) {
203  sdStart(driver->config->tlm_sd, &tlmcfg);
204  chThdCreateStatic(driver->waDshotTlmRec, sizeof(driver->waDshotTlmRec), NORMALPRIO,
205  dshotTlmRec, driver);
206  }
207 
208  pwmStart(driver->config->pwmp, &driver->pwm_conf);
209  driver->config->pwmp->tim->DCR = DCR_DBL | DCR_DBA(driver->config->pwmp); // enable bloc register DMA transaction
210  pwmChangePeriod(driver->config->pwmp, DSHOT_PWM_PERIOD);
211 
212  for (size_t j = 0; j < DSHOT_CHANNELS; j++) {
213  pwmEnableChannel(driver->config->pwmp, j, 0);
214  driver->dshotMotors.dp[j] = makeDshotPacket(0, 0);
215  }
216  driver->dshotMotors.onGoingQry = false;
217  driver->dshotMotors.currentTlmQry = 0U;
218 }
219 
230 void dshotSetThrottle(DSHOTDriver *driver, const uint8_t index,
231  const uint16_t throttle)
232 {
233  if (throttle > 0 && throttle <= DSHOT_CMD_MAX) {
234  chDbgAssert(false, "dshotSetThrottle throttle error");
235  return; // special commands (except MOTOR_STOP) can't be applied from this function
236  } else {
237  // send normal throttle
238  if (index == DSHOT_ALL_MOTORS) {
239  for (uint8_t _index = 0; _index < DSHOT_CHANNELS; _index++) {
240  setDshotPacketThrottle(&driver->dshotMotors.dp[_index], Min(throttle, DSHOT_MAX_VALUE));
241  }
242  } else if ((index - DSHOT_CHANNEL_FIRST_INDEX) < DSHOT_CHANNELS) {
244  Min(throttle, DSHOT_MAX_VALUE));
245  } else {
246  chDbgAssert(false, "dshotSetThrottle index error");
247  }
248  }
249 }
250 
259 void dshotSendSpecialCommand(DSHOTDriver *driver, const uint8_t index,
260  const dshot_special_commands_t specmd)
261 {
262  if (specmd > DSHOT_CMD_MAX) {
263  return; // Don't apply special commands from this function
264  }
265  if (index < DSHOT_CHANNELS) {
266  setDshotPacketThrottle(&driver->dshotMotors.dp[index], specmd);
267  setDshotPacketTlm(&driver->dshotMotors.dp[index], driver->config->tlm_sd != NULL);
268  } else if (index == DSHOT_ALL_MOTORS) {
269  for (uint8_t _index = 0; _index < DSHOT_CHANNELS; _index++) {
270  setDshotPacketThrottle(&driver->dshotMotors.dp[_index], specmd);
271  setDshotPacketTlm(&driver->dshotMotors.dp[_index], driver->config->tlm_sd != NULL);
272  }
273  }
274 
275  uint8_t repeat;
276  switch (specmd) {
285  repeat = 10;
286  break;
287  default:
288  repeat = 1;
289  }
290 
291  while (repeat--) {
292  dshotSendFrame(driver);
293  chThdSleepMilliseconds(1);
294  }
295 }
296 
306 void dshotSendThrottles(DSHOTDriver *driver, const uint16_t throttles[DSHOT_CHANNELS])
307 {
308  for (uint8_t index = 0; index < DSHOT_CHANNELS; index++) {
309  setDshotPacketThrottle(&driver->dshotMotors.dp[index], throttles[index]);
310  }
311 
312  dshotSendFrame(driver);
313 }
314 
323 {
324  if (driver->dmap.state == DMA_READY) {
325  if ((driver->config->tlm_sd != NULL) &&
326  (driver->dshotMotors.onGoingQry == false)) {
327  driver->dshotMotors.onGoingQry = true;
328  const uint32_t index = (driver->dshotMotors.currentTlmQry + 1) % DSHOT_CHANNELS;
329  driver->dshotMotors.currentTlmQry = index;
330  setDshotPacketTlm(&driver->dshotMotors.dp[index], true);
331  chMBPostTimeout(&driver->mb, driver->dshotMotors.currentTlmQry, TIME_IMMEDIATE);
332  }
333 
334  buildDshotDmaBuffer(&driver->dshotMotors, driver->config->dma_buf, getTimerWidth(driver->config->pwmp));
335  dmaStartTransfert(&driver->dmap,
336  &driver->config->pwmp->tim->DMAR,
338 
339  }
340 }
341 
350 {
351  return driver->crc_errors;
352 }
353 
362 const DshotTelemetry *dshotGetTelemetry(const DSHOTDriver *driver, const uint32_t index)
363 {
364  return &driver->dshotMotors.dt[index - DSHOT_CHANNEL_FIRST_INDEX];
365 }
366 
367 
368 /*
369 # _ __ _ _
370 # | '_ \ (_) | |
371 # | |_) | _ __ _ __ __ __ _ | |_ ___
372 # | .__/ | '__| | | \ \ / / / _` | | __| / _ \
373 # | | | | | | \ V / | (_| | \ |_ | __/
374 # |_| |_| |_| \_/ \__,_| \__| \___|
375 */
376 
377 static DshotPacket makeDshotPacket(const uint16_t _throttle, const bool tlmRequest)
378 {
379  DshotPacket dp = {.throttle = _throttle,
380  .telemetryRequest = (tlmRequest ? 1 : 0),
381  .crc = 0
382  };
383 
384  // compute checksum
385  uint16_t csum = (_throttle << 1) | dp.telemetryRequest;
386  for (int i = 0; i < 3; i++) {
387  dp.crc ^= csum; // xor data by nibbles
388  csum >>= 4;
389  }
390 
391  return dp;
392 }
393 
394 static inline void setDshotPacketThrottle(DshotPacket *const dp, const uint16_t throttle)
395 {
396  dp->throttle = throttle;
397  dp->telemetryRequest = 0;
398 }
399 
400 static inline void setDshotPacketTlm(DshotPacket *const dp, const bool tlmRequest)
401 {
402  dp->telemetryRequest = tlmRequest ? 1 : 0;
403 }
404 
405 static void buildDshotDmaBuffer(DshotPackets *const dsp, DshotDmaBuffer *const dma, const size_t timerWidth)
406 {
407  for (size_t chanIdx = 0; chanIdx < DSHOT_CHANNELS; chanIdx++) {
408  // compute checksum
409  DshotPacket *const dp = &dsp->dp[chanIdx];
410  dp->crc = 0;
411  uint16_t csum = (dp->throttle << 1) | dp->telemetryRequest;
412  for (int i = 0; i < 3; i++) {
413  dp->crc ^= csum; // xor data by nibbles
414  csum >>= 4;
415  }
416  // generate pwm frame
417  for (size_t bitIdx = 0; bitIdx < DSHOT_BIT_WIDTHS; bitIdx++) {
418  const uint16_t value = dp->rawFrame &
419  (1 << ((DSHOT_BIT_WIDTHS - 1) - bitIdx)) ?
421  if (timerWidth == 2) {
422  dma->widths16[bitIdx+DSHOT_PRE_FRAME_SILENT_SYNC_BITS][chanIdx] = value;
423  } else {
424 #if DSHOT_AT_LEAST_ONE_32B_TIMER
425  dma->widths32[bitIdx+DSHOT_PRE_FRAME_SILENT_SYNC_BITS][chanIdx] = value;
426 #else
427  chSysHalt("use of 32 bit timer implies to define DSHOT_AT_LEAST_ONE_32B_TIMER to TRUE");
428 #endif
429  }
430  }
431  // the bits for silence sync (pre and post) in case of continous sending are zeroed once at init
432  }
433 }
434 
435 static inline uint8_t updateCrc8(uint8_t crc, uint8_t crc_seed)
436 {
437  uint8_t crc_u = crc;
438  crc_u ^= crc_seed;
439 
440  for (int i = 0; i < 8; i++) {
441  crc_u = (crc_u & 0x80) ? 0x7 ^ (crc_u << 1) : (crc_u << 1);
442  }
443 
444  return (crc_u);
445 }
446 
447 static uint8_t calculateCrc8(const uint8_t *Buf, const uint8_t BufLen)
448 {
449  uint8_t crc = 0;
450  for (int i = 0; i < BufLen; i++) {
451  crc = updateCrc8(Buf[i], crc);
452  }
453 
454  return crc;
455 }
456 
457 __attribute__((const))
458 static size_t getTimerWidth(const PWMDriver *pwmp)
459 {
460  (void) pwmp;
461 
462  return (0
464  || (pwmp == &PWMD2)
465 #endif
466 #if STM32_PWM_USE_TIM5
467  || (pwmp == &PWMD5)
468 #endif
469  ) ? 4 : 2;
470 }
471 
472 
473 /*
474 # _ _ _
475 # | | | | | |
476 # | |_ | |__ _ __ ___ __ _ __| | ___
477 # | __| | '_ \ | '__| / _ \ / _` | / _` | / __|
478 # \ |_ | | | | | | | __/ | (_| | | (_| | \__ \
479 # \__| |_| |_| |_| \___| \__,_| \__,_| |___/
480 */
481 
482 static noreturn void dshotTlmRec(void *arg)
483 {
484  DSHOTDriver *driver = (DSHOTDriver *) arg;
485 
486  uint32_t escIdx = 0;
487 
488  chRegSetThreadName("dshotTlmRec");
489  while (true) {
490  chMBFetchTimeout(&driver->mb, (msg_t *) &escIdx, TIME_INFINITE);
491  const uint32_t idx = escIdx;
492  const bool success =
493  (sdReadTimeout(driver->config->tlm_sd, driver->dshotMotors.dt[idx].rawData, sizeof(DshotTelemetry),
494  TIME_MS2I(DSHOT_TELEMETRY_TIMEOUT_MS)) == sizeof(DshotTelemetry));
495  if (!success ||
496  (calculateCrc8(driver->dshotMotors.dt[idx].rawData,
497  sizeof(driver->dshotMotors.dt[idx].rawData)) != driver->dshotMotors.dt[idx].crc8)) {
498  // empty buffer to resync
499  while (sdGetTimeout(driver->config->tlm_sd, TIME_IMMEDIATE) >= 0) {};
500  memset(driver->dshotMotors.dt[idx].rawData, 0U, sizeof(DshotTelemetry));
501  // count errors
502  driver->crc_errors++;
503  }
504  driver->dshotMotors.onGoingQry = false;
505  }
506 }
507 
#define STM32_PWM_USE_TIM2
Definition: mcuconf.h:272
void dshotStart(DSHOTDriver *driver, const DSHOTConfig *config)
Configures and activates the DSHOT peripheral.
Definition: esc_dshot.c:138
void dshotSetThrottle(DSHOTDriver *driver, const uint8_t index, const uint16_t throttle)
prepare throttle order for specified ESC
Definition: esc_dshot.c:230
static size_t getTimerWidth(const PWMDriver *pwmp)
Definition: esc_dshot.c:458
#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...
Definition: esc_dshot.c:83
uint32_t dshotGetCrcErrorsCount(DSHOTDriver *driver)
return number of telemetry crc error since dshotStart
Definition: esc_dshot.c:349
#define Min(x, y)
Definition: esc_dshot.c:101
#define TICK_FREQ
Definition: esc_dshot.c:93
static uint8_t calculateCrc8(const uint8_t *Buf, const uint8_t BufLen)
Definition: esc_dshot.c:447
#define DSHOT_MAX_VALUE
Definition: esc_dshot.c:103
static void setDshotPacketThrottle(DshotPacket *const dp, const uint16_t throttle)
Definition: esc_dshot.c:394
void dshotSendThrottles(DSHOTDriver *driver, const uint16_t throttles[DSHOT_CHANNELS])
send throttle packed order to all of the ESCs
Definition: esc_dshot.c:306
#define DSHOT_BIT0_DUTY
Definition: esc_dshot.c:95
#define DCR_DBA(pwmd)
Definition: esc_dshot.c:98
static void buildDshotDmaBuffer(DshotPackets *const dsp, DshotDmaBuffer *const dma, const size_t timerWidth)
Definition: esc_dshot.c:405
#define DSHOT_TELEMETRY_TIMEOUT_MS
Telemetry timeout in ms.
Definition: esc_dshot.c:62
void dshotSendFrame(DSHOTDriver *driver)
send throttle order
Definition: esc_dshot.c:322
static noreturn void dshotTlmRec(void *arg)
Definition: esc_dshot.c:482
#define ARRAY_LEN(a)
Definition: esc_dshot.c:100
static void setDshotPacketTlm(DshotPacket *const dp, const bool tlmRequest)
Definition: esc_dshot.c:400
#define DSHOT_TELEMETRY_BAUD
Baudrate of the serial link used for telemetry data Can depend on the ESC, but only 115k have been us...
Definition: esc_dshot.c:56
#define DSHOT_PWM_PERIOD
Definition: esc_dshot.c:94
#define DSHOT_BIT1_DUTY
Definition: esc_dshot.c:96
static DshotPacket makeDshotPacket(const uint16_t throttle, const bool tlmRequest)
Definition: esc_dshot.c:377
#define DCR_DBL
Definition: esc_dshot.c:97
void dshotSendSpecialCommand(DSHOTDriver *driver, const uint8_t index, const dshot_special_commands_t specmd)
send special order to one of the ESC (BHELIX, KISS, ...)
Definition: esc_dshot.c:259
static uint8_t updateCrc8(uint8_t crc, uint8_t crc_seed)
Definition: esc_dshot.c:435
const DshotTelemetry * dshotGetTelemetry(const DSHOTDriver *driver, const uint32_t index)
return last received telemetry data
Definition: esc_dshot.c:362
DSHOT driver based on ChibiOS.
#define DSHOT_PRE_FRAME_SILENT_SYNC_BITS
Definition: esc_dshot.h:50
#define DSHOT_CHANNELS
Definition: esc_dshot.h:56
SerialDriver * tlm_sd
if non null : dshot telemetry serial driver
Definition: esc_dshot.h:178
#define DSHOT_BIT_WIDTHS
DMA buffer size and number of channels.
Definition: esc_dshot.h:49
volatile bool onGoingQry
Definition: esc_dshot.h:232
PWMDriver * pwmp
PWM driver that feed up to 4 dshot lines.
Definition: esc_dshot.h:173
#define DSHOT_DMA_BUFFER_SIZE
Definition: esc_dshot.h:52
uint16_t widths16[DSHOT_DMA_BUFFER_SIZE][DSHOT_CHANNELS]
Definition: esc_dshot.h:143
#define DSHOT_CHANNEL_FIRST_INDEX
Definition: esc_dshot.h:44
DshotTelemetry dt[DSHOT_CHANNELS]
Definition: esc_dshot.h:230
uint16_t rawFrame
Definition: esc_dshot.h:225
#define DSHOT_ALL_MOTORS
special value for index : send order to all channels
Definition: esc_dshot.h:63
uint8_t crc8
Definition: esc_dshot.h:136
DshotDmaBuffer * dma_buf
dshot dma buffer, sgould be defined in a non Dcached region
Definition: esc_dshot.h:183
dshot_special_commands_t
DSHOT special commands (0-47) for KISS and BLHELI ESC.
Definition: esc_dshot.h:91
@ DSHOT_CMD_SILENT_MODE_ON_OFF
Definition: esc_dshot.h:116
@ DSHOT_CMD_SAVE_SETTINGS
Definition: esc_dshot.h:104
@ DSHOT_CMD_AUDIO_STREAM_MODE_ON_OFF
Definition: esc_dshot.h:115
@ DSHOT_CMD_SETTINGS_REQUEST
Definition: esc_dshot.h:103
@ DSHOT_CMD_SPIN_DIRECTION_1
Definition: esc_dshot.h:99
@ DSHOT_CMD_SPIN_DIRECTION_2
Definition: esc_dshot.h:100
@ DSHOT_CMD_3D_MODE_OFF
Definition: esc_dshot.h:101
@ DSHOT_CMD_MAX
Definition: esc_dshot.h:117
@ DSHOT_CMD_3D_MODE_ON
Definition: esc_dshot.h:102
DshotPacket dp[DSHOT_CHANNELS]
Definition: esc_dshot.h:229
volatile uint8_t currentTlmQry
Definition: esc_dshot.h:231
DSHOT Driver configuration structure.
Definition: esc_dshot.h:155
telemetry packed as sent by some KISS ESC
Definition: esc_dshot.h:125
void dmaObjectInit(DMADriver *dmap)
Definition: hal_stm32_dma.c:56
bool dmaStartTransfert(DMADriver *dmap, volatile void *periphp, void *mem0p, const size_t size)
Starts a DMA transaction.
bool dmaStart(DMADriver *dmap, const DMAConfig *cfg)
Configures and activates the DMA peripheral.
Definition: hal_stm32_dma.c:92
@ DMA_DIR_M2P
MEMORY to PERIPHERAL
Definition: hal_stm32_dma.h:89
uint32_t stream
stream associated with transaction
@ DMA_READY
Ready.
Definition: hal_stm32_dma.h:65
volatile dmastate_t state
Driver state.
DMA stream configuration structure.
static uint32_t idx
static const struct usb_config_descriptor config
Definition: usb_ser_hw.c:200
DSHOT driver structure.
Definition: esc_dshot.h:239
uint32_t crc_errors
number of crc errors
Definition: esc_dshot.h:273
DshotPackets dshotMotors
Definition: esc_dshot.h:280
mailbox_t mb
mailbox for dshot telemetry thread
Definition: esc_dshot.h:268
DMADriver dmap
DMA driver associated with pwm timer.
Definition: esc_dshot.h:258
PWMConfig pwm_conf
PWM config associated with pwm timer.
Definition: esc_dshot.h:253
const DSHOTConfig * config
DMA config associated with pwm timer.
Definition: esc_dshot.h:243
msg_t _mbBuf[1]
mailbox buffer for dshot telemetry thread
Definition: esc_dshot.h:263
DMAConfig dma_conf
DMA config associated with pwm timer.
Definition: esc_dshot.h:248
unsigned short uint16_t
Typedef defining 16 bit unsigned short type.
Definition: vl53l1_types.h:88
unsigned int uint32_t
Typedef defining 32 bit unsigned int type.
Definition: vl53l1_types.h:78
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.
Definition: vl53l1_types.h:98