dRonin  adbada4
dRonin firmware
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pios_servo.c
Go to the documentation of this file.
1 
17 /*
18  * This program is free software; you can redistribute it and/or modify
19  * it under the terms of the GNU General Public License as published by
20  * the Free Software Foundation; either version 3 of the License, or
21  * (at your option) any later version.
22  *
23  * This program is distributed in the hope that it will be useful, but
24  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
25  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
26  * for more details.
27  *
28  * You should have received a copy of the GNU General Public License along
29  * with this program; if not, see <http://www.gnu.org/licenses/>
30  *
31  * Additional note on redistribution: The copyright and license notices above
32  * must be maintained in each individual source file that is a derivative work
33  * of this source file; otherwise redistribution is prohibited.
34  */
35 
36 /* Project Includes */
37 #include "pios.h"
38 #include "pios_servo_priv.h"
39 #include "pios_tim_priv.h"
40 
41 #include <pios_dio.h>
42 
43 #ifndef STM32F0XX // No high-res delay on F0 yet
44 #include "pios_inlinedelay.h"
45 #include "pios_irq.h"
46 #endif
47 
48 #if defined(PIOS_INCLUDE_DMASHOT)
49 #include "pios_dmashot.h"
50 #endif
51 
52 #include "misc_math.h"
53 
54 /* Private variables */
55 static const struct pios_servo_cfg *servo_cfg;
56 
57 static uint32_t channel_mask = 0;
58 
60 
61 enum dshot_gpio {
62  DS_GPIOA = 0,
63  DS_GPIOB,
64  DS_GPIOC,
66 } __attribute__((packed));
67 
69  UNCONFIGURED = 0,
72  SYNC_PWM,
77 } __attribute__((packed));
78 
79 struct dshot_info {
80  uint16_t value;
81  uint16_t pin;
83 };
84 
87 
88  union {
89  uint32_t pwm_res;
90  struct dshot_info dshot;
91  } i;
92 } __attribute__((packed));
93 
95 
96 static uintptr_t servo_tim_id;
97 
98 static bool resetting;
99 
100 static bool dshot_in_use;
101 
102 /* Private function prototypes */
103 static uint32_t timer_apb_clock(TIM_TypeDef *timer);
104 static uint32_t max_timer_clock(TIM_TypeDef *timer);
105 
109 int32_t PIOS_Servo_Init(const struct pios_servo_cfg *cfg)
110 {
111  PIOS_Assert(!servo_tim_id); // Make sure not inited already
112 
113  if (PIOS_TIM_InitChannels(&servo_tim_id, cfg->channels, cfg->num_channels, NULL, 0)) {
114  return -1;
115  }
116 
117  /* Store away the requested configuration */
118  servo_cfg = cfg;
119 
120  /* Configure the channels to be in output compare mode */
121  for (uint8_t i = 0; i < cfg->num_channels; i++) {
122  const struct pios_tim_channel *chan = &cfg->channels[i];
123 
124  /* Set up for output compare function */
125  switch(chan->timer_chan) {
126  case TIM_Channel_1:
127  TIM_OC1Init(chan->timer, (TIM_OCInitTypeDef *)&cfg->tim_oc_init);
128  TIM_OC1PreloadConfig(chan->timer, TIM_OCPreload_Enable);
129  break;
130  case TIM_Channel_2:
131  TIM_OC2Init(chan->timer, (TIM_OCInitTypeDef *)&cfg->tim_oc_init);
132  TIM_OC2PreloadConfig(chan->timer, TIM_OCPreload_Enable);
133  break;
134  case TIM_Channel_3:
135  TIM_OC3Init(chan->timer, (TIM_OCInitTypeDef *)&cfg->tim_oc_init);
136  TIM_OC3PreloadConfig(chan->timer, TIM_OCPreload_Enable);
137  break;
138  case TIM_Channel_4:
139  TIM_OC4Init(chan->timer, (TIM_OCInitTypeDef *)&cfg->tim_oc_init);
140  TIM_OC4PreloadConfig(chan->timer, TIM_OCPreload_Enable);
141  break;
142  }
143 
144  TIM_ARRPreloadConfig(chan->timer, ENABLE);
145  TIM_CtrlPWMOutputs(chan->timer, ENABLE);
146  TIM_Cmd(chan->timer, ENABLE);
147  }
148 
149  output_channels = PIOS_malloc(servo_cfg->num_channels * sizeof(*output_channels));
150  if (output_channels == NULL) {
151  return -1;
152  }
153  memset(output_channels, 0, servo_cfg->num_channels * sizeof(*output_channels));
154 
155  return 0;
156 }
157 
158 void PIOS_Servo_DisableChannel(int channel)
159 {
160  channel_mask |= 1 << channel;
161 }
162 
163 int PIOS_Servo_GetPins(dio_tag_t *dios, int max_dio)
164 {
165  int i;
166 
167  for (i = 0; (i < servo_cfg->num_channels) && (i < max_dio); i++) {
168  if (channel_mask & (1 << i)) {
169  dios[i] = DIO_NULL;
170  continue;
171  }
172 
173  dios[i] = DIO_MAKE_TAG(servo_cfg->channels[i].pin.gpio,
174  servo_cfg->channels[i].pin.init.GPIO_Pin);
175  }
176 
177  return i;
178 }
179 
180 struct timer_bank {
181  TIM_TypeDef *timer;
182  uint32_t clk_rate;
183  uint16_t max_pulse;
184  uint16_t prescaler;
185  uint16_t period;
186 };
187 
188 static void ChannelSetup_DShot(int j, uint16_t rate)
189 {
190  switch (rate) {
191  case SHOT_DSHOT300:
192  output_channels[j].mode = SYNC_DSHOT_300;
193  break;
194  case SHOT_DSHOT600:
195  output_channels[j].mode = SYNC_DSHOT_600;
196  break;
197  case SHOT_DSHOT1200:
198  output_channels[j].mode = SYNC_DSHOT_1200;
199  break;
200  default:
201  PIOS_Assert(false);
202  };
203 
204  struct dshot_info *ds_info = &output_channels[j].i.dshot;
205 
206  ds_info->value = 0;
207 
208  switch ((uintptr_t) servo_cfg->channels[j].pin.gpio) {
209  case (uintptr_t) GPIOA:
210  ds_info->gpio = DS_GPIOA;
211  break;
212  case (uintptr_t) GPIOB:
213  ds_info->gpio = DS_GPIOB;
214  break;
215  case (uintptr_t) GPIOC:
216  ds_info->gpio = DS_GPIOC;
217  break;
218  default:
219  PIOS_Assert(false);
220  }
221 
222  ds_info->pin = servo_cfg->channels[j].pin.init.GPIO_Pin;
223 }
224 
225 static int BankSetup_DShot(struct timer_bank *bank)
226 {
227  /*
228  * Relatively simple configuration here. Just seize it!
229  */
230  PIOS_TIM_SetBankToGPOut(servo_tim_id, bank->timer);
231 
232  return 0;
233 }
234 
235 static int BankSetup_OneShot(struct timer_bank *bank, int32_t max_tim_clock)
236 {
237  /*
238  * Ensure a dead time of 2% + 10 us, e.g. 15us for 250us
239  * long pulses, 50 us for 2000us long pulses
240  */
241  float period = 1.02f * bank->max_pulse + 10.0f;
242  float num_ticks = period / 1e6f * max_tim_clock;
243  // assume 16-bit timer
244  bank->prescaler = num_ticks / 0xffff + 0.5f;
245  bank->clk_rate = max_tim_clock / (bank->prescaler + 1);
246  bank->period = period / 1e6f * bank->clk_rate;
247 
248  // select one pulse mode for SyncPWM
249  TIM_SelectOnePulseMode(bank->timer, TIM_OPMode_Single);
250  // Need to invert output polarity for one-pulse mode
251  uint16_t inverted_polarity = (servo_cfg->tim_oc_init.TIM_OCPolarity == TIM_OCPolarity_Low) ?
252  TIM_OCPolarity_High : TIM_OCPolarity_Low;
253  TIM_OC1PolarityConfig(bank->timer, inverted_polarity);
254  TIM_OC2PolarityConfig(bank->timer, inverted_polarity);
255  TIM_OC3PolarityConfig(bank->timer, inverted_polarity);
256  TIM_OC4PolarityConfig(bank->timer, inverted_polarity);
257 
258  return 0;
259 }
260 
261 static int BankSetup_PWM(struct timer_bank *bank, int32_t max_tim_clock,
262  uint16_t rate)
263 {
264  // assume 16-bit timer
265  if (servo_cfg->force_1MHz) {
266  bank->prescaler = max_tim_clock / 1000000 - 1;
267  } else {
268  float num_ticks = (float)max_tim_clock / (float)rate;
269 
270  bank->prescaler = num_ticks / 0xffff + 0.5f;
271  }
272 
273  bank->clk_rate = max_tim_clock / (bank->prescaler + 1);
274  bank->period = (float)bank->clk_rate / (float)rate;
275 
276  // de-select one pulse mode in case SyncPWM was previously used
277  TIM_SelectOnePulseMode(bank->timer, TIM_OPMode_Repetitive);
278 
279  // and make sure the output is enabled
280  TIM_Cmd(bank->timer, ENABLE);
281 
282  // restore polarity in case one-pulse was used
283  TIM_OC1PolarityConfig(bank->timer, servo_cfg->tim_oc_init.TIM_OCPolarity);
284  TIM_OC2PolarityConfig(bank->timer, servo_cfg->tim_oc_init.TIM_OCPolarity);
285  TIM_OC3PolarityConfig(bank->timer, servo_cfg->tim_oc_init.TIM_OCPolarity);
286  TIM_OC4PolarityConfig(bank->timer, servo_cfg->tim_oc_init.TIM_OCPolarity);
287 
288  return 0;
289 }
290 
304 int PIOS_Servo_SetMode(const uint16_t *out_rate, const int banks, const uint16_t *channel_max, const uint16_t *channel_min)
305 {
306  if (!servo_cfg || banks > PIOS_SERVO_MAX_BANKS) {
307  return -10;
308  }
309 
310 #if defined(PIOS_INCLUDE_DMASHOT)
313  }
314 #endif
315 
316  dshot_in_use = false;
317 
318  struct timer_bank timer_banks[PIOS_SERVO_MAX_BANKS];
319 
320  memset(&timer_banks, 0, sizeof(timer_banks));
321  int banks_found = 0;
322 
323  // find max pulse length for each bank
324  for (int i = 0; i < servo_cfg->num_channels; i++) {
325  if (channel_mask & (1 << i)) {
326  continue;
327  }
328 
329  PIOS_TIM_InitTimerPin(servo_tim_id, i);
330 
331  int bank = -1;
332  const struct pios_tim_channel *chan = &servo_cfg->channels[i];
333 
334  for (int j = 0; j < banks_found; j++) {
335  if (timer_banks[j].timer == chan->timer)
336  bank = j;
337  }
338 
339  if ((bank < 0) && (banks_found < PIOS_SERVO_MAX_BANKS)) {
340  bank = banks_found++;
341  }
342 
343  if (bank >= 0) {
344  timer_banks[bank].timer = chan->timer;
345  timer_banks[bank].max_pulse = MAX(timer_banks[bank].max_pulse, channel_max[i]);
346  timer_banks[bank].max_pulse = MAX(timer_banks[bank].max_pulse, channel_min[i]);
347  }
348  }
349 
350  // configure timers/banks
351  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure = servo_cfg->tim_base_init;
352  TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
353  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
354  for (int i = 0; i < banks_found; i++) {
355  // Skip the bank if no outputs are configured
356  if (timer_banks[i].max_pulse == 0)
357  continue;
358 
359  /* Calculate the maximum clock frequency for the timer */
360  uint32_t max_tim_clock = max_timer_clock(timer_banks[i].timer);
361  // check if valid timer
362  if (!max_tim_clock) {
363  return -20;
364  }
365 
366  uint16_t rate = out_rate[i];
367 
368  if (servo_cfg->force_1MHz && (rate == SHOT_ONESHOT)) {
369  /* We've been asked for syncPWM but are in a config
370  * where we can't do it. This means CC3D + 333Hz.
371  * Getting fast output is functionally identical
372  * to oneshot on a target like this. Pick a period
373  * that has a lot of deadtime and call it good.
374  */
375 
376  /* Works out to 2500Hz at normal 250us max pulse,
377  * 400Hz at 2000us.
378  *
379  * Put one more way, with "oneshot", 400us of variable
380  * delay on 3300us control period.
381  */
382 
383  rate = 1000000 / (timer_banks[i].max_pulse +
384  timer_banks[i].max_pulse / 5 +
385  100);
386  }
387 
388  int ret;
389 
390  // output rate of 0 means SyncPWM
391  switch (rate) {
392  case SHOT_ONESHOT:
393  ret = BankSetup_OneShot(&timer_banks[i], max_tim_clock);
394 
395  if (ret) {
396  return ret;
397  }
398 
399  TIM_TimeBaseStructure.TIM_Prescaler = timer_banks[i].prescaler;
400  TIM_TimeBaseStructure.TIM_Period = timer_banks[i].period;
401 
402  // Configure this timer appropriately.
403  TIM_TimeBaseInit(timer_banks[i].timer, &TIM_TimeBaseStructure);
404  break;
405 
406  default:
407  ret = BankSetup_PWM(&timer_banks[i], max_tim_clock, rate);
408 
409  if (ret) {
410  return ret;
411  }
412 
413  TIM_TimeBaseStructure.TIM_Prescaler = timer_banks[i].prescaler;
414  TIM_TimeBaseStructure.TIM_Period = timer_banks[i].period;
415 
416  // Configure this timer appropriately.
417  TIM_TimeBaseInit(timer_banks[i].timer, &TIM_TimeBaseStructure);
418  break;
419 
420  case SHOT_DSHOT300:
421  case SHOT_DSHOT600:
422  case SHOT_DSHOT1200:
423  ret = 1;
424 #if defined(PIOS_INCLUDE_DMASHOT)
426  uint32_t freq;
427  switch(rate) {
428  default:
429  // If for whatever reason new frequencies show up in the GPIO version,
430  // we oughta know about it. So fail if that happens.
431  PIOS_Assert(0);
432  case SHOT_DSHOT300:
433  freq = DMASHOT_300;
434  break;
435  case SHOT_DSHOT600:
436  freq = DMASHOT_600;
437  break;
438  case SHOT_DSHOT1200:
439  freq = DMASHOT_1200;
440  break;
441  }
442  ret = PIOS_DMAShot_RegisterTimer(timer_banks[i].timer, max_tim_clock, freq) ? 0 : 1;
443  }
444 #endif
445  if (ret) {
446  /* TODO: attempts to just fall back to
447  * bitbanging, which seems not ideal-- no
448  * benefit to doing DMA if we are bitbanging
449  * at the same time.
450  */
451  ret = BankSetup_DShot(&timer_banks[i]);
452  }
453 
454  if (ret) {
455  return ret;
456  }
457 
458  dshot_in_use = true;
459 
460  break;
461  }
462 
463 
464  /* Configure frequency scaler for all channels that use the same timer */
465  for (uint8_t j = 0; j < servo_cfg->num_channels; j++) {
466  if (channel_mask & (1 << j)) {
467  continue;
468  }
469 
470  const struct pios_tim_channel *chan = &servo_cfg->channels[j];
471  if (timer_banks[i].timer == chan->timer) {
472  /* save the frequency for these channels */
473  switch (rate) {
474  case SHOT_DSHOT300:
475  case SHOT_DSHOT600:
476  case SHOT_DSHOT1200:
477 #if defined(PIOS_INCLUDE_DMASHOT)
479  output_channels[j].mode = SYNC_DSHOT_DMA;
480  } else {
481  // If RegisterServo fails, the relevant timer wasn't registered, or DMAShot
482  // isn't configured, so we expect the bank to be set up already higher up in this
483  // section.
484  ChannelSetup_DShot(j, rate);
485  }
486 #else
487  ChannelSetup_DShot(j, rate);
488 #endif
489  break;
490  case SHOT_ONESHOT:
491  output_channels[j].i.pwm_res = timer_banks[i].clk_rate;
492  output_channels[j].mode = SYNC_PWM;
493  break;
494  default:
495  output_channels[j].i.pwm_res = timer_banks[i].clk_rate;
496  if (channel_max[j] >= channel_min[j]) {
497  output_channels[j].mode = REGULAR_PWM;
498  } else {
499  output_channels[j].mode = REGULAR_INVERTED_PWM;
500  }
501  break;
502  }
503  }
504  }
505  }
506 
507 #if defined (PIOS_INCLUDE_DMASHOT)
510  PIOS_DMAShot_InitializeTimers((TIM_OCInitTypeDef *)&servo_cfg->tim_oc_init);
513  }
514 #endif
515 
516  return 0;
517 }
518 
519 static void PIOS_Servo_SetRaw(uint8_t servo, uint32_t raw_position) {
520  const struct pios_tim_channel *chan = &servo_cfg->channels[servo];
521 
522  // in one-pulse mode, the pulse length is ARR - CCR
523  if (output_channels[servo].mode == SYNC_PWM) {
524  raw_position = chan->timer->ARR - raw_position;
525  }
526 
527  /* Update the raw_position */
528  switch(chan->timer_chan) {
529  case TIM_Channel_1:
530  TIM_SetCompare1(chan->timer, raw_position);
531  break;
532  case TIM_Channel_2:
533  TIM_SetCompare2(chan->timer, raw_position);
534  break;
535  case TIM_Channel_3:
536  TIM_SetCompare3(chan->timer, raw_position);
537  break;
538  case TIM_Channel_4:
539  TIM_SetCompare4(chan->timer, raw_position);
540  break;
541  }
542 }
543 
544 // Fraction: 0.16
545 // max_val, min_val: microseconds (seconds * 1000000)
546 void PIOS_Servo_SetFraction(uint8_t servo, uint16_t fraction,
547  uint16_t max_val, uint16_t min_val)
548 {
549  PIOS_Assert(max_val >= min_val);
550 
551  /* Make sure servo exists */
552  if (!servo_cfg || servo >= servo_cfg->num_channels ||
553  output_channels[servo].mode == UNCONFIGURED) {
554  return;
555  }
556 
557  if (channel_mask & (1 << servo)) {
558  return;
559  }
560 
561  switch (output_channels[servo].mode) {
562  case SYNC_DSHOT_300:
563  case SYNC_DSHOT_600:
564  case SYNC_DSHOT_1200:
565  case SYNC_DSHOT_DMA:
566  /* Expect a 0 to 2047 range!
567  * Don't bother with min/max tomfoolery here.
568  */
569  output_channels[servo].i.dshot.value = fraction >> 5;
570  return;
571  default:
572  break;
573  };
574 
575  // Seconds * 1000000 : 16.0
576  uint16_t spread = max_val - min_val;
577 
578  uint64_t val = min_val;
579  val = val << 16;
580  // Seconds * 1000000 : 16.16
581 
582  val += spread * fraction;
583 
584  // Multiply by ticks/second to get: Ticks * 1000000: 36.16
585  val *= output_channels[servo].i.pwm_res;
586 
587  // Ticks: 16.16
588  val /= 1000000;
589 
590  // Round to nearest, 16.0
591  val += 32767;
592  val = val >> 16;
593 
594  if (resetting && (fraction < 0xff00)) {
595  /* If we're resetting and the value isn't driven to the maximum
596  * value, drive low with no pulses. If it's at the max value,
597  * it could be driving brushed motors and forced low is bad.
598  */
599  val = 0;
600  }
601 
602  PIOS_Servo_SetRaw(servo, val);
603 }
604 
605 bool PIOS_Servo_IsDshot(uint8_t servo) {
606  switch (output_channels[servo].mode) {
607  case SYNC_DSHOT_300:
608  case SYNC_DSHOT_600:
609  case SYNC_DSHOT_1200:
610  case SYNC_DSHOT_DMA:
611  return true;
612  default:
613  break;
614  };
615 
616  return false;
617 }
618 
624 void PIOS_Servo_Set(uint8_t servo, float position)
625 {
626  /* Make sure servo exists */
627  if (!servo_cfg || servo >= servo_cfg->num_channels ||
628  output_channels[servo].mode == UNCONFIGURED) {
629  return;
630  }
631 
632  if (channel_mask & (1 << servo)) {
633  return;
634  }
635 
636  switch (output_channels[servo].mode) {
637  case SYNC_DSHOT_300:
638  case SYNC_DSHOT_600:
639  case SYNC_DSHOT_1200:
640  case SYNC_DSHOT_DMA:
641  if (position > 2047)
642  position = 2047;
643  else if (position < 0)
644  position = 0;
645 
646  output_channels[servo].i.dshot.value = position;
647  return;
648  default:
649  break;
650  };
651 
652 
653  /* recalculate the position value based on timer clock rate */
654  /* position is in us. */
655  float us_to_count = output_channels[servo].i.pwm_res / 1000000.0f;
656  position = position * us_to_count;
657 
658  if (resetting && (output_channels[servo].mode != REGULAR_INVERTED_PWM)) {
659  /* Don't nail inverted channels low during reset, because they
660  * could be driving brushed motors.
661  */
662  position = 0;
663  }
664 
665  PIOS_Servo_SetRaw(servo, position);
666 }
667 
668 #ifdef STM32F0XX // No high-res delay on F0 yet
669 static int DSHOT_Update()
670 {
671  return -1;
672 }
673 #else
674 static int DSHOT_Update()
675 {
676  bool triggered = false;
677 
678  uint16_t dshot_bits[DS_GPIO_NUMVALS] = { 0 };
679  uint16_t dshot_msg_zeroes[16][DS_GPIO_NUMVALS] = { { 0 } };
680 
681  enum channel_mode dshot_mode = UNCONFIGURED;
682 
683  for (int i = 0; i < servo_cfg->num_channels; i++) {
684  struct output_channel *chan = &output_channels[i];
685  struct dshot_info *info = &chan->i.dshot;
686 
687  if (channel_mask & (1 << i)) {
688  continue;
689  }
690 
691  switch (chan->mode) {
692  case SYNC_DSHOT_300:
693  case SYNC_DSHOT_600:
694  case SYNC_DSHOT_1200:
695  break;
696  case SYNC_DSHOT_DMA:
697 #if defined(PIOS_INCLUDE_DMASHOT)
698  PIOS_DMAShot_WriteValue(&servo_cfg->channels[i],
699  info->value);
700  continue;
701 #endif
702  default:
703  continue; // Continue enclosing loop if not ds
704  }
705 
706  if (dshot_mode == UNCONFIGURED) {
707  dshot_mode = chan->mode;
708  } else if (dshot_mode != chan->mode) {
709  /* Multiple dshot rates not supported */
710  return -1;
711  }
712 
713  PIOS_Assert(info->gpio >= 0);
715 
716  dshot_bits[info->gpio] |= info->pin;
717 
718  PIOS_Assert(info->value < 2048);
719 
720  uint16_t message = info->value << 5;
721 
722  /* Set telem bit on commands */
723  if ((info->value > 0) && (info->value < 48)) {
724  message |= 16;
725  }
726 
727  message |=
728  ((message >> 4 ) & 0xf) ^
729  ((message >> 8 ) & 0xf) ^
730  ((message >> 12) & 0xf);
731 
732  for (int j = 0; j < 16; j++) {
733  if (! (message & 0x8000)) {
734  dshot_msg_zeroes[j][info->gpio] |= info->pin;
735  }
736 
737  message <<= 1;
738  }
739 
740  info->value = 0; /* turn off motor if not updated */
741  }
742 
743 #if defined(PIOS_INCLUDE_DMASHOT)
744  // Do it before bitbanging, so the updates line up +/-.
745  // XXX: what's the use case for doing both at once?
746  if (PIOS_DMAShot_IsReady()) {
748  triggered = true;
749  }
750 #endif
751  uint16_t time_0, time_1, time_tot;
752 
753  /* As specified by original document:
754  * DShot 300 - 1250ns 0, 2500ns 1, 3333ns total
755  * DShot 600 - 625ns 0, 1250ns 1, 1667ns total
756  * DShot 1200- 312ns 0, 625ns 1, 833ns total
757  *
758  * Below timings are as used by Betaflight, which blheli_s seems to
759  * demand. Meh.
760  * DShot 300 - 1000ns 0, 2166ns 1, 3333ns total
761  * DShot 600 - 500ns 0, 1083ns 1, 1667ns total
762  * DShot 1200- 250ns 0, 541ns 1, 833ns total
763  */
764 
765  switch (dshot_mode) {
766  case UNCONFIGURED:
767  return !triggered;
768  case SYNC_DSHOT_300:
769  time_0 = PIOS_INLINEDELAY_NsToCycles(1000);
770  time_1 = PIOS_INLINEDELAY_NsToCycles(2166);
771  time_tot = PIOS_INLINEDELAY_NsToCycles(3333);
772  break;
773  case SYNC_DSHOT_600:
774  time_0 = PIOS_INLINEDELAY_NsToCycles(500);
775  time_1 = PIOS_INLINEDELAY_NsToCycles(1083);
776  time_tot = PIOS_INLINEDELAY_NsToCycles(1667);
777  break;
778  case SYNC_DSHOT_1200:
779  time_0 = PIOS_INLINEDELAY_NsToCycles(250);
780  time_1 = PIOS_INLINEDELAY_NsToCycles(541);
781  time_tot = PIOS_INLINEDELAY_NsToCycles(833);
782  break;
783  default:
784  PIOS_Assert(0);
785  break;
786  }
787 
788  if (dshot_mode == UNCONFIGURED) {
789  return -1;
790  }
791 
792  PIOS_IRQ_Disable(); // Necessary for critical timing below
793 
794  register uint16_t a = dshot_bits[DS_GPIOA];
795  register uint16_t b = dshot_bits[DS_GPIOB];
796  register uint16_t c = dshot_bits[DS_GPIOC];
797 
798  uint32_t start_cycle = PIOS_INLINEDELAY_GetCycleCnt() + 30;
799 
800  /* Time to get down to business of bitbanging this out. */
801  for (int i = 0; i < 16; i++) {
802  // Always delay at the beginning for consistent timing
803  PIOS_INLINEDELAY_TillCycleCnt(start_cycle);
804 
805 #if defined(STM32F40_41xxx) || defined(STM32F446xx)
806 #define CLEAR_BITS(gpio, bits) do { (gpio)->BSRRH = bits; } while (0)
807 #define SET_BITS(gpio, bits) do { (gpio)->BSRRL = bits; } while (0)
808 #else
809  // Many STM32F* do not allow halfword writes to BSRR (or have
810  // BSRRL/H definitions), so do it this way:
811 
812 #define CLEAR_BITS(gpio, bits) do { (gpio)->BSRR = ((uint32_t) bits) << 16; } while (0)
813 #define SET_BITS(gpio, bits) do { (gpio)->BSRR = bits; } while (0)
814 #endif
815 
816  // Start pulse by writing to BSRRL's
817  SET_BITS(GPIOA, a);
818  SET_BITS(GPIOB, b);
819  SET_BITS(GPIOC, c);
820 
821  // Calculate falling edge time for 0's
822  uint32_t next_tick = start_cycle + time_0;
823 
824  // And preload next values before waiting
825  a = dshot_msg_zeroes[i][DS_GPIOA];
826  b = dshot_msg_zeroes[i][DS_GPIOB];
827  c = dshot_msg_zeroes[i][DS_GPIOC];
828 
830 
831  // Generate falling edges for zeroes (shorter pulses)
832  CLEAR_BITS(GPIOA, a);
833  CLEAR_BITS(GPIOB, b);
834  CLEAR_BITS(GPIOC, c);
835 
836  // Calculate falling edge time for 1's
837  next_tick = start_cycle + time_1;
838 
839  // Adjust next cycle time for when next bit should begin
840  start_cycle += time_tot;
841 
842  // And next time, all bits will fall (no harm in doing twice for
843  // the 0 bits)
844  a = dshot_bits[DS_GPIOA];
845  b = dshot_bits[DS_GPIOB];
846  c = dshot_bits[DS_GPIOC];
847 
849 
850  // Falling edges for all remaining bits.
851  CLEAR_BITS(GPIOA, a);
852  CLEAR_BITS(GPIOB, b);
853  CLEAR_BITS(GPIOC, c);
854  }
855 
856  PIOS_IRQ_Enable();
857 
858  return 0;
859 }
860 #endif /* !STM32F0xx */
861 
866 {
867  if (!servo_cfg) {
868  return;
869  }
870 
871  // If some banks are oneshot and some are dshot (why would you do this?)
872  // get the oneshots firing first.
873  for (uint8_t i = 0; i < servo_cfg->num_channels; i++) {
874  if (channel_mask & (1 << i)) {
875  continue;
876  }
877 
878  if (output_channels[i].mode != SYNC_PWM) {
879  continue;
880  }
881 
882  const struct pios_tim_channel * chan = &servo_cfg->channels[i];
883 
884  /* Look for a disabled timer using synchronous output */
885  if (!(chan->timer->CR1 & TIM_CR1_CEN)) {
886  /* enable it again and reinitialize it */
887  TIM_GenerateEvent(chan->timer, TIM_EventSource_Update);
888  TIM_Cmd(chan->timer, ENABLE);
889  }
890  }
891 
892  if (dshot_in_use) {
893  if (DSHOT_Update()) {
894  dshot_in_use = false;
895  }
896  }
897 }
898 
905 #if defined(STM32F0XX) /* F0 */
906 static uint32_t timer_apb_clock(TIM_TypeDef *timer)
907 {
909 }
910 
911 #elif defined(STM32F10X_MD) /* F1 */
912 
913 static uint32_t timer_apb_clock(TIM_TypeDef *timer)
914 {
915  if (timer == TIM1 || timer == TIM8)
917  else
919 }
920 
921 #elif defined(STM32F30X) /* F3 */
922 
923 static uint32_t timer_apb_clock(TIM_TypeDef *timer)
924 {
925  if (timer == TIM2 || timer == TIM3 || timer == TIM4)
927  else
929 }
930 
931 #elif defined(STM32F40_41xxx) || defined(STM32F446xx) /* F4 */
932 
933 static uint32_t timer_apb_clock(TIM_TypeDef *timer)
934 {
935  if (timer == TIM1 || timer == TIM8 || timer == TIM9 || timer == TIM10 || timer == TIM11)
937  else
939 }
940 
941 #else
942 #error Unsupported microcontroller
943 #endif
944 
949  resetting = true;
950 }
951 
957 static uint32_t max_timer_clock(TIM_TypeDef *timer)
958 {
959  if (timer == TIM6 || timer == TIM7) {
960  // TIM6 and TIM7 cannot be used
961  PIOS_Assert(0);
962  return 0;
963  }
964 
965  // "The timer clock frequencies are automatically fixed by hardware. There are two cases:
966  // 1. if the APB prescaler is 1, the timer clock frequencies are set to the same frequency as
967  // that of the APB domain to which the timers are connected.
968  // 2. otherwise, they are set to twice (*2) the frequency of the APB domain to which the
969  // timers are connected."
970  uint32_t apb_clock = timer_apb_clock(timer);
971  if (apb_clock == PIOS_SYSCLK)
972  return apb_clock;
973  else
974  return apb_clock * 2;
975 }
976 
977 /*
978  * @}
979  * @}
980  */
int32_t PIOS_IRQ_Enable(void)
Definition: pios_irq.c:53
SYNC_DSHOT_DMA
Definition: pios_servo.c:58
DS_GPIOA
Definition: pios_servo.c:58
Main PiOS header to include all the compiled in PiOS options.
void PIOS_DMAShot_Prepare()
Makes sure the DMAShot driver has allocated all internal structs.
Definition: pios_dmashot.c:104
SYNC_DSHOT_600
Definition: pios_servo.c:58
channel_mode
Definition: pios_servo.c:68
bool PIOS_Servo_IsDshot(uint8_t servo)
Definition: pios_servo.c:605
GPIO_InitTypeDef init
Definition: pios_stm32.h:61
DS_GPIO_NUMVALS
Definition: pios_servo.c:58
uint32_t pwm_res
Definition: pios_servo.c:89
static uint32_t channel_mask
Definition: pios_servo.c:57
void PIOS_DMAShot_InitializeTimers(TIM_OCInitTypeDef *ocinit)
Initializes and configures the registered timers for DMAShot operation.
Definition: pios_dmashot.c:367
uint16_t max_pulse
Definition: pios_servo.c:183
GPIO_TypeDef * gpio
Definition: pios_stm32.h:60
void PIOS_TIM_InitTimerPin(uintptr_t tim_id, int idx)
Definition: pios_tim.c:111
static uint32_t PIOS_INLINEDELAY_NsToCycles(uint32_t ns)
#define DIO_MAKE_TAG(port, pin)
Definition: pios_dio.h:171
volatile int j
Definition: loadabletest.c:12
void PIOS_DMAShot_Validate()
Validates any timer and servo registrations.
Definition: pios_dmashot.c:279
static int DSHOT_Update()
Definition: pios_servo.c:674
void * PIOS_malloc(size_t size)
Definition: pios_heap.c:125
bool PIOS_DMAShot_RegisterTimer(TIM_TypeDef *timer, uint32_t clockrate, uint32_t dshot_freq)
Tells the DMAShot driver about a timer that needs to be set up.
Definition: pios_dmashot.c:190
bool PIOS_DMAShot_RegisterServo(const struct pios_tim_channel *servo_channel)
Tells the DMAShot driver about a servo that needs to be set up.
Definition: pios_dmashot.c:250
UNCONFIGURED
Definition: pios_servo.c:58
const struct pios_tim_channel * channels
struct stm32_gpio pin
Definition: pios_tim_priv.h:17
uint16_t prescaler
Definition: pios_servo.c:184
void PIOS_Servo_Set(uint8_t servo, float position)
Definition: pios_servo.c:624
REGULAR_PWM
Definition: pios_servo.c:58
void PIOS_Servo_SetFraction(uint8_t servo, uint16_t fraction, uint16_t max_val, uint16_t min_val)
Definition: pios_servo.c:546
static struct flyingpicmd_cfg_fa cfg
Definition: main.c:49
int PIOS_Servo_GetPins(dio_tag_t *dios, int max_dio)
Definition: pios_servo.c:163
bool PIOS_DMAShot_IsConfigured()
Checks whether DMAShot has been configured.
Definition: pios_dmashot.c:565
static uint32_t timer_apb_clock(TIM_TypeDef *timer)
void PIOS_Servo_DisableChannel(int channel)
Definition: pios_servo.c:158
static void ChannelSetup_DShot(int j, uint16_t rate)
Definition: pios_servo.c:188
static bool dshot_in_use
Definition: pios_servo.c:100
void PIOS_Servo_PrepareForReset()
Determines the APB clock used by a given timer.
Definition: pios_servo.c:948
void PIOS_DMAShot_InitializeGPIOs()
Initializes the GPIO on the registered servos for DMAShot operation.
Definition: pios_dmashot.c:297
SYNC_PWM
Definition: pios_servo.c:58
union @20 i
uint16_t value
Definition: pios_servo.c:80
enum dshot_gpio gpio
Definition: pios_servo.c:82
#define MAX(a, b)
Definition: misc_math.h:40
#define PIOS_PERIPHERAL_APB1_CLOCK
Definition: pios_board.h:154
void PIOS_DMAShot_InitializeDMAs()
Initializes and configures the known DMA channels for DMAShot operation.
Definition: pios_dmashot.c:467
REGULAR_INVERTED_PWM
Definition: pios_servo.c:58
union output_channel::@19 i
uint16_t period
Definition: pios_servo.c:185
enum channel_mode mode
Definition: pios_servo.c:58
TIM_OCInitTypeDef tim_oc_init
#define DMASHOT_300
Definition: pios_dmashot.h:42
enum channel_mode mode
Definition: pios_servo.c:86
SYNC_DSHOT_300
Definition: pios_servo.c:58
static struct output_channel * output_channels
Definition: pios_servo.c:94
int PIOS_Servo_SetMode(const uint16_t *out_rate, const int banks, const uint16_t *channel_max, const uint16_t *channel_min)
PIOS_Servo_SetMode Sets the PWM output frequency and resolution. An output rate of 0 indicates Synchr...
Definition: pios_servo.c:304
Servo private structures.
int32_t PIOS_Servo_Init(const struct pios_servo_cfg *cfg)
Definition: pios_servo.c:109
DS_GPIOC
Definition: pios_servo.c:58
#define CLEAR_BITS(gpio, bits)
static void PIOS_INLINEDELAY_TillCycleCnt(uint32_t whence)
int32_t PIOS_IRQ_Disable(void)
Definition: pios_irq.c:40
static int BankSetup_OneShot(struct timer_bank *bank, int32_t max_tim_clock)
Definition: pios_servo.c:235
int32_t PIOS_TIM_InitChannels(uintptr_t *tim_id, const struct pios_tim_channel *channels, uint8_t num_channels, const struct pios_tim_callbacks *callbacks, uintptr_t context)
Definition: pios_tim.c:172
#define SET_BITS(gpio, bits)
static int BankSetup_DShot(struct timer_bank *bank)
Definition: pios_servo.c:225
uint8_t rate
Definition: msp_messages.h:99
static uintptr_t servo_tim_id
Definition: pios_servo.c:96
static uint32_t PIOS_INLINEDELAY_GetCycleCnt()
static bool resetting
Definition: pios_servo.c:98
void PIOS_DMAShot_WriteValue(const struct pios_tim_channel *servo_channel, uint16_t throttle)
Sets the throttle value of a specific servo.
Definition: pios_dmashot.c:143
void PIOS_TIM_SetBankToGPOut(uintptr_t tim_id, TIM_TypeDef *timer)
Definition: pios_tim.c:151
void * dio_tag_t
Definition: pios_dio.h:12
#define PIOS_PERIPHERAL_APB2_CLOCK
Definition: pios_board.h:164
DS_GPIOB
Definition: pios_servo.c:58
TIM_TimeBaseInitTypeDef tim_base_init
uint16_t servo[8]
Definition: msp_messages.h:96
#define PIOS_SERVO_MAX_BANKS
Definition: pios_servo.h:35
dshot_gpio
The counter rate for the channel, used to calculate compare values.
Definition: pios_servo.c:61
uint8_t num_channels
void PIOS_Servo_Update(void)
Definition: pios_servo.c:865
#define PIOS_SYSCLK
Definition: pios_board.h:143
bool PIOS_DMAShot_IsReady()
Checks whether DMAShot is ready for use (i.e. at least one DMA configured timer). ...
Definition: pios_dmashot.c:552
#define DMASHOT_600
Definition: pios_dmashot.h:43
struct dshot_info dshot
Definition: pios_servo.c:90
struct dshot_info __attribute__
static int BankSetup_PWM(struct timer_bank *bank, int32_t max_tim_clock, uint16_t rate)
Definition: pios_servo.c:261
TIM_TypeDef * timer
Definition: pios_servo.c:181
TIM_TypeDef * timer
Definition: pios_tim_priv.h:14
static uint32_t max_timer_clock(TIM_TypeDef *timer)
Determines the maximum clock rate for a given timer (i.e. no prescale)
Definition: pios_servo.c:957
#define PIOS_Assert(test)
Definition: pios_debug.h:52
#define DMASHOT_1200
Definition: pios_dmashot.h:44
uint32_t clk_rate
Definition: pios_servo.c:182
uint16_t pin
Definition: pios_servo.c:81
SYNC_DSHOT_1200
Definition: pios_servo.c:58
void PIOS_DMAShot_TriggerUpdate()
Triggers the configured DMA channels to fire and send throttle values to the timer DMAR and optional ...
Definition: pios_dmashot.c:489
static void PIOS_Servo_SetRaw(uint8_t servo, uint32_t raw_position)
Definition: pios_servo.c:519
static const struct pios_servo_cfg * servo_cfg
Definition: pios_servo.c:55
#define DIO_NULL
Definition: pios_dio.h:86