refactor(io_timer): make timer_io_channels[].timer_channel 0-indexed (#26845)

* refactor: make timer_io_channels[].timer_channel 0-indexed

timer_channel was 1-indexed (1-4) to mirror STM32 hardware naming
(TIM_CH1-CH4), but this was purely cosmetic — the ccr_offset field
already handles register mapping. Every consumer did timer_channel - 1
to get a 0-based index, creating underflow bugs when the guard was
missing (e.g. dshot.c capture_complete_callback,
output_channel_from_timer_channel, up_bdshot_get_erpm).

Changes:
- STM32: Timer::Channel enum starts at 0, initIOTimerChannel assigns
  directly, removed all timer_channel - 1 in dshot.c and io_timer.c
- NXP (kinetis, s32k1xx, s32k3xx): removed the + 1 in
  initIOTimerChannel, removed timer_channel - 1 in io_timer.c,
  led_pwm.cpp, and input_capture.c
- RPI: Channel enum starts at 0, removed timer_channel - 1 in
  io_timer.c
- Validity checks updated from timer_channel <= 0 || >= 5 to
  timer_channel >= 4

Closes #26747

Signed-off-by: Pavel Guzenfeld <pavelgu@gmail.com>

* fix: complete 0-indexed timer_channel migration across all platforms

Address review feedback for incomplete migration:

1. STM32H7 io_timer_hw_description.h: update standalone
   initIOTimerChannel() to assign timer_channel from enum
   (0-based) instead of hardcoded 1/2/3/4

2. Switch case labels: update all switch(timer_channel) blocks
   from 1/2/3/4 to 0/1/2/3 in:
   - stm32_common: input_capture.c (4 blocks), led_pwm.cpp (3),
     io_timer.c DMA base register switch
   - kinetis: input_capture.c (2 filter blocks)
   - s32k1xx: input_capture.c (2 filter blocks)
   - spix_sync.c (ark/fpv + ark/pi6x, 3 blocks each)

3. Sentinel checks: replace timer_channel != 0 / == 0 (which
   now conflicts with valid channel 0) with gpio_out-based
   checks in:
   - io_timer_validate_channel_index() across all 5 platforms
   - led_pwm_channel_init() and led_pwm_servo_get() in all
     led_pwm.cpp variants (STM32 + 4 NXP)
   - spix_sync_channel_init() and spix_sync_servo_get()

Tested: px4_fmu-v6x_default (H7) build OK, px4_sitl_default
build OK, 154/154 unit tests pass, ASan build clean.

* fix: update NXP board led_pwm_channels to 0-indexed timer_channel

These 4 board files manually specify led_pwm_channels[] with
1-indexed timer_channel values. Since the platform code no longer
subtracts 1, decrement all values to match the new 0-indexed
convention.

* fix: correct FTM CH3 filter mask in kinetis and s32k1xx input capture

Case 3 in up_input_capture_set_filter() was using CH2FVAL_MASK/SHIFT
instead of CH3FVAL_MASK/SHIFT due to a copy-paste error, causing
channel 3 filter writes to modify channel 2's filter register instead.

---------

Signed-off-by: Pavel Guzenfeld <pavelgu@gmail.com>
Co-authored-by: Jacob Dahl <dahl.jakejacob@gmail.com>
This commit is contained in:
Pavel Guzenfeld
2026-04-13 04:16:47 +03:00
committed by GitHub
parent 92439467ee
commit 02d9884979
29 changed files with 181 additions and 190 deletions
@@ -93,7 +93,7 @@ static void input_capture_chan_handler(void *context, const io_timers_t *timer,
channel_stats[chan_index].edges++;
channel_stats[chan_index].last_time = isrs_time - (isrs_rcnt - capture);
uint32_t overflow = 0;//_REG32(timer, KINETIS_FTM_CSC_OFFSET(chan->timer_channel - 1)) & FTM_CSC_CHF;
uint32_t overflow = 0;//_REG32(timer, KINETIS_FTM_CSC_OFFSET(chan->timer_channel)) & FTM_CSC_CHF;
if (overflow) {
@@ -238,7 +238,7 @@ led_pwm_channel_init(unsigned channel)
{
/* Only initialize used channels */
if (led_pwm_channels[channel].timer_channel) {
if (led_pwm_channels[channel].gpio_out) {
unsigned timer = led_pwm_channels[channel].timer_index;
irqstate_t flags = px4_enter_critical_section();
@@ -249,7 +249,7 @@ led_pwm_channel_init(unsigned channel)
/* configure the channel */
uint32_t chan = led_pwm_channels[channel].timer_channel - 1;
uint32_t chan = led_pwm_channels[channel].timer_channel;
uint16_t rvalue = REG(timer, KINETIS_FTM_CSC_OFFSET(chan));
rvalue &= ~CnSC_RESET;
@@ -284,7 +284,7 @@ led_pwm_servo_set(unsigned channel, uint8_t cvalue)
value--;
}
REG(timer, KINETIS_FTM_CV_OFFSET(led_pwm_channels[channel].timer_channel - 1)) = value;
REG(timer, KINETIS_FTM_CV_OFFSET(led_pwm_channels[channel].timer_channel)) = value;
return 0;
}
@@ -300,11 +300,11 @@ unsigned led_pwm_servo_get(unsigned channel)
/* test timer for validity */
if ((led_pwm_timers[timer].base == 0) ||
(led_pwm_channels[channel].timer_channel == 0)) {
(led_pwm_channels[channel].gpio_out == 0)) {
return value;
}
value = REG(timer, KINETIS_FTM_CV_OFFSET(led_pwm_channels[channel].timer_channel - 1));
value = REG(timer, KINETIS_FTM_CV_OFFSET(led_pwm_channels[channel].timer_channel));
unsigned period = led_pwm_timer_get_period(timer);
return ((value + 1) * 255 / period);
}
@@ -93,7 +93,7 @@ static inline constexpr timer_io_channels_t initIOTimerChannel(const io_timers_t
ret.gpio_in = gpio_af | gpio_pin_port;
ret.gpio_out = gpio_af | gpio_pin_port;
ret.timer_channel = (int)timer.channel + 1;
ret.timer_channel = (uint8_t)timer.channel;
// find timer index
ret.timer_index = 0xff;
@@ -110,7 +110,7 @@ static void input_capture_chan_handler(void *context, const io_timers_t *timer,
channel_stats[chan_index].edges++;
channel_stats[chan_index].last_time = isrs_time - (isrs_rcnt - capture);
uint32_t overflow = _REG32(timer, KINETIS_FTM_CSC_OFFSET(chan->timer_channel - 1)) & FTM_CSC_CHF;
uint32_t overflow = _REG32(timer, KINETIS_FTM_CSC_OFFSET(chan->timer_channel)) & FTM_CSC_CHF;
if (overflow) {
@@ -157,7 +157,7 @@ int up_input_capture_set(unsigned channel, input_capture_edge edge, capture_filt
/* This register selects the filter value for the inputs of channels.
Channels 4, 5, 6 and 7 do not have an input filter.
*/
if (filter && timer_io_channels[channel].timer_channel - 1 > 3) {
if (filter && timer_io_channels[channel].timer_channel > 3) {
return -EINVAL;
}
@@ -200,7 +200,7 @@ int up_input_capture_get_filter(unsigned channel, capture_filter_t *filter)
rv = -EINVAL;
if (timer_io_channels[channel].timer_channel - 1 <= 3) {
if (timer_io_channels[channel].timer_channel <= 3) {
rv = -ENXIO;
/* Any pins in capture mode */
@@ -213,22 +213,22 @@ int up_input_capture_get_filter(unsigned channel, capture_filter_t *filter)
switch (timer_io_channels[channel].timer_channel) {
case 1:
case 0:
rvalue = rFILTER(timer) & FTM_FILTER_CH0FVAL_MASK;
*filter = (rvalue >> FTM_FILTER_CH0FVAL_SHIFT);
break;
case 2:
case 1:
rvalue = rFILTER(timer) & FTM_FILTER_CH1FVAL_MASK;
*filter = (rvalue >> FTM_FILTER_CH1FVAL_SHIFT);
break;
case 3:
case 2:
rvalue = rFILTER(timer) & FTM_FILTER_CH2FVAL_MASK;
*filter = (rvalue >> FTM_FILTER_CH2FVAL_SHIFT);
break;
case 4:
case 3:
rvalue = rFILTER(timer) & FTM_FILTER_CH3FVAL_MASK;
*filter = (rvalue >> FTM_FILTER_CH3FVAL_SHIFT);
break;
@@ -266,27 +266,27 @@ int up_input_capture_set_filter(unsigned channel, capture_filter_t filter)
switch (timer_io_channels[channel].timer_channel) {
case 1:
case 0:
rvalue = rFILTER(timer) & ~FTM_FILTER_CH0FVAL_MASK;
rvalue |= (filter << FTM_FILTER_CH0FVAL_SHIFT);
rFILTER(timer) = rvalue;
break;
case 2:
case 1:
rvalue = rFILTER(timer) & ~FTM_FILTER_CH1FVAL_MASK;
rvalue |= (filter << FTM_FILTER_CH1FVAL_SHIFT);
rFILTER(timer) = rvalue;
break;
case 3:
case 2:
rvalue = rFILTER(timer) & ~FTM_FILTER_CH2FVAL_MASK;
rvalue |= (filter << FTM_FILTER_CH2FVAL_SHIFT);
rFILTER(timer) = rvalue;
break;
case 4:
rvalue = rFILTER(timer) & ~FTM_FILTER_CH2FVAL_MASK;
rvalue |= (filter << FTM_FILTER_CH2FVAL_SHIFT);
case 3:
rvalue = rFILTER(timer) & ~FTM_FILTER_CH3FVAL_MASK;
rvalue |= (filter << FTM_FILTER_CH3FVAL_SHIFT);
rFILTER(timer) = rvalue;
break;
@@ -316,7 +316,7 @@ int up_input_capture_get_trigger(unsigned channel, input_capture_edge *edge)
rv = OK;
uint32_t timer = timer_io_channels[channel].timer_index;
uint16_t rvalue = _REG32(timer, KINETIS_FTM_CSC_OFFSET(timer_io_channels[channel].timer_channel - 1));
uint16_t rvalue = _REG32(timer, KINETIS_FTM_CSC_OFFSET(timer_io_channels[channel].timer_channel));
rvalue &= (FTM_CSC_MSB | FTM_CSC_MSA);
switch (rvalue) {
@@ -377,10 +377,10 @@ int up_input_capture_set_trigger(unsigned channel, input_capture_edge edge)
uint32_t timer = timer_io_channels[channel].timer_index;
irqstate_t flags = px4_enter_critical_section();
uint32_t rvalue = _REG32(timer, KINETIS_FTM_CSC_OFFSET(timer_io_channels[channel].timer_channel - 1));
uint32_t rvalue = _REG32(timer, KINETIS_FTM_CSC_OFFSET(timer_io_channels[channel].timer_channel));
rvalue &= (FTM_CSC_MSB | FTM_CSC_MSA);
rvalue |= edge_bits;
_REG32(timer, KINETIS_FTM_CSC_OFFSET(timer_io_channels[channel].timer_channel - 1)) = rvalue;
_REG32(timer, KINETIS_FTM_CSC_OFFSET(timer_io_channels[channel].timer_channel)) = rvalue;
px4_leave_critical_section(flags);
rv = OK;
}
@@ -343,7 +343,7 @@ int io_timer_validate_channel_index(unsigned channel)
{
int rv = -EINVAL;
if (channel < MAX_TIMER_IO_CHANNELS && timer_io_channels[channel].timer_channel != 0) {
if (channel < MAX_TIMER_IO_CHANNELS) {
unsigned timer = timer_io_channels[channel].timer_index;
@@ -740,7 +740,7 @@ int io_timer_channel_init(unsigned channel, io_timer_channel_mode_t mode,
/* configure the channel */
uint32_t chan = timer_io_channels[channel].timer_channel - 1;
uint32_t chan = timer_io_channels[channel].timer_channel;
uint16_t rvalue = REG(timer, KINETIS_FTM_CSC_OFFSET(chan));
rvalue &= ~clearbits;
@@ -820,7 +820,7 @@ int io_timer_set_enable(bool state, io_timer_channel_mode_t mode, io_timer_chann
masks &= ~(1 << chan_index);
if (io_timer_validate_channel_index(chan_index) == 0) {
uint32_t chan = timer_io_channels[chan_index].timer_channel - 1;
uint32_t chan = timer_io_channels[chan_index].timer_channel;
uint32_t timer = channels_timer(chan_index);
action_cache[timer].base = io_timers[timer].base;
action_cache[timer].cnsc[action_cache[timer].index].cnsc_offset = io_timers[timer].base + KINETIS_FTM_CSC_OFFSET(chan);
@@ -905,7 +905,7 @@ int io_timer_set_ccr(unsigned channel, uint16_t value)
irqstate_t flags = px4_enter_critical_section();
uint32_t save = rSC(timer);
rSC(timer) = save & ~(FTM_SC_CLKS_MASK);
REG(timer, KINETIS_FTM_CV_OFFSET(timer_io_channels[channel].timer_channel - 1)) = value;
REG(timer, KINETIS_FTM_CV_OFFSET(timer_io_channels[channel].timer_channel)) = value;
rSC(timer) = save;
px4_leave_critical_section(flags);
}
@@ -924,7 +924,7 @@ uint16_t io_channel_get_ccr(unsigned channel)
if ((mode == IOTimerChanMode_PWMOut) ||
(mode == IOTimerChanMode_OneShot) ||
(mode == IOTimerChanMode_Trigger)) {
value = REG(channels_timer(channel), KINETIS_FTM_CV_OFFSET(timer_io_channels[channel].timer_channel - 1));
value = REG(channels_timer(channel), KINETIS_FTM_CV_OFFSET(timer_io_channels[channel].timer_channel));
}
}
@@ -228,7 +228,7 @@ led_pwm_channel_init(unsigned channel)
{
/* Only initialize used channels */
if (led_pwm_channels[channel].timer_channel) {
if (led_pwm_channels[channel].gpio_out) {
unsigned timer = led_pwm_channels[channel].timer_index;
irqstate_t flags = px4_enter_critical_section();
@@ -239,7 +239,7 @@ led_pwm_channel_init(unsigned channel)
/* configure the channel */
uint32_t chan = led_pwm_channels[channel].timer_channel - 1;
uint32_t chan = led_pwm_channels[channel].timer_channel;
uint16_t rvalue = REG(timer, KINETIS_FTM_CSC_OFFSET(chan));
rvalue &= ~CnSC_RESET;
@@ -274,7 +274,7 @@ led_pwm_servo_set(unsigned channel, uint8_t cvalue)
value--;
}
REG(timer, KINETIS_FTM_CV_OFFSET(led_pwm_channels[channel].timer_channel - 1)) = value;
REG(timer, KINETIS_FTM_CV_OFFSET(led_pwm_channels[channel].timer_channel)) = value;
return 0;
}
@@ -290,11 +290,11 @@ unsigned led_pwm_servo_get(unsigned channel)
/* test timer for validity */
if ((led_pwm_timers[timer].base == 0) ||
(led_pwm_channels[channel].timer_channel == 0)) {
(led_pwm_channels[channel].gpio_out == 0)) {
return value;
}
value = REG(timer, KINETIS_FTM_CV_OFFSET(led_pwm_channels[channel].timer_channel - 1));
value = REG(timer, KINETIS_FTM_CV_OFFSET(led_pwm_channels[channel].timer_channel));
unsigned period = led_pwm_timer_get_period(timer);
return ((value + 1) * 255 / period);
}
@@ -151,7 +151,7 @@ static inline constexpr timer_io_channels_t initIOTimerChannel(const io_timers_t
ret.gpio_in = gpio_af | gpio_pin_port;
ret.gpio_out = gpio_af | gpio_pin_port;
ret.timer_channel = (int)timer.channel + 1;
ret.timer_channel = (uint8_t)timer.channel;
// find timer index
ret.timer_index = 0xff;
@@ -110,7 +110,7 @@ static void input_capture_chan_handler(void *context, const io_timers_t *timer,
channel_stats[chan_index].edges++;
channel_stats[chan_index].last_time = isrs_time - (isrs_rcnt - capture);
uint32_t overflow = _REG32(timer, S32K1XX_FTM_CNSC_OFFSET(chan->timer_channel - 1)) & FTM_CNSC_CHF;
uint32_t overflow = _REG32(timer, S32K1XX_FTM_CNSC_OFFSET(chan->timer_channel)) & FTM_CNSC_CHF;
if (overflow) {
@@ -157,7 +157,7 @@ int up_input_capture_set(unsigned channel, input_capture_edge edge, capture_filt
/* This register selects the filter value for the inputs of channels.
Channels 4, 5, 6 and 7 do not have an input filter.
*/
if (filter && timer_io_channels[channel].timer_channel - 1 > 3) {
if (filter && timer_io_channels[channel].timer_channel > 3) {
return -EINVAL;
}
@@ -200,7 +200,7 @@ int up_input_capture_get_filter(unsigned channel, capture_filter_t *filter)
rv = -EINVAL;
if (timer_io_channels[channel].timer_channel - 1 <= 3) {
if (timer_io_channels[channel].timer_channel <= 3) {
rv = -ENXIO;
/* Any pins in capture mode */
@@ -213,22 +213,22 @@ int up_input_capture_get_filter(unsigned channel, capture_filter_t *filter)
switch (timer_io_channels[channel].timer_channel) {
case 1:
case 0:
rvalue = rFILTER(timer) & FTM_FILTER_CH0FVAL_MASK;
*filter = (rvalue >> FTM_FILTER_CH0FVAL_SHIFT);
break;
case 2:
case 1:
rvalue = rFILTER(timer) & FTM_FILTER_CH1FVAL_MASK;
*filter = (rvalue >> FTM_FILTER_CH1FVAL_SHIFT);
break;
case 3:
case 2:
rvalue = rFILTER(timer) & FTM_FILTER_CH2FVAL_MASK;
*filter = (rvalue >> FTM_FILTER_CH2FVAL_SHIFT);
break;
case 4:
case 3:
rvalue = rFILTER(timer) & FTM_FILTER_CH3FVAL_MASK;
*filter = (rvalue >> FTM_FILTER_CH3FVAL_SHIFT);
break;
@@ -266,27 +266,27 @@ int up_input_capture_set_filter(unsigned channel, capture_filter_t filter)
switch (timer_io_channels[channel].timer_channel) {
case 1:
case 0:
rvalue = rFILTER(timer) & ~FTM_FILTER_CH0FVAL_MASK;
rvalue |= (filter << FTM_FILTER_CH0FVAL_SHIFT);
rFILTER(timer) = rvalue;
break;
case 2:
case 1:
rvalue = rFILTER(timer) & ~FTM_FILTER_CH1FVAL_MASK;
rvalue |= (filter << FTM_FILTER_CH1FVAL_SHIFT);
rFILTER(timer) = rvalue;
break;
case 3:
case 2:
rvalue = rFILTER(timer) & ~FTM_FILTER_CH2FVAL_MASK;
rvalue |= (filter << FTM_FILTER_CH2FVAL_SHIFT);
rFILTER(timer) = rvalue;
break;
case 4:
rvalue = rFILTER(timer) & ~FTM_FILTER_CH2FVAL_MASK;
rvalue |= (filter << FTM_FILTER_CH2FVAL_SHIFT);
case 3:
rvalue = rFILTER(timer) & ~FTM_FILTER_CH3FVAL_MASK;
rvalue |= (filter << FTM_FILTER_CH3FVAL_SHIFT);
rFILTER(timer) = rvalue;
break;
@@ -316,7 +316,7 @@ int up_input_capture_get_trigger(unsigned channel, input_capture_edge *edge)
rv = OK;
uint32_t timer = timer_io_channels[channel].timer_index;
uint16_t rvalue = _REG32(timer, S32K1XX_FTM_CNSC_OFFSET(timer_io_channels[channel].timer_channel - 1));
uint16_t rvalue = _REG32(timer, S32K1XX_FTM_CNSC_OFFSET(timer_io_channels[channel].timer_channel));
rvalue &= (FTM_CNSC_MSB | FTM_CNSC_MSA);
switch (rvalue) {
@@ -377,10 +377,10 @@ int up_input_capture_set_trigger(unsigned channel, input_capture_edge edge)
uint32_t timer = timer_io_channels[channel].timer_index;
irqstate_t flags = px4_enter_critical_section();
uint32_t rvalue = _REG32(timer, S32K1XX_FTM_CNSC_OFFSET(timer_io_channels[channel].timer_channel - 1));
uint32_t rvalue = _REG32(timer, S32K1XX_FTM_CNSC_OFFSET(timer_io_channels[channel].timer_channel));
rvalue &= (FTM_CNSC_MSB | FTM_CNSC_MSA);
rvalue |= edge_bits;
_REG32(timer, S32K1XX_FTM_CNSC_OFFSET(timer_io_channels[channel].timer_channel - 1)) = rvalue;
_REG32(timer, S32K1XX_FTM_CNSC_OFFSET(timer_io_channels[channel].timer_channel)) = rvalue;
px4_leave_critical_section(flags);
rv = OK;
}
@@ -339,7 +339,7 @@ int io_timer_validate_channel_index(unsigned channel)
{
int rv = -EINVAL;
if (channel < MAX_TIMER_IO_CHANNELS && timer_io_channels[channel].timer_channel != 0) {
if (channel < MAX_TIMER_IO_CHANNELS) {
unsigned timer = timer_io_channels[channel].timer_index;
@@ -742,7 +742,7 @@ int io_timer_channel_init(unsigned channel, io_timer_channel_mode_t mode,
/* configure the channel */
uint32_t chan = timer_io_channels[channel].timer_channel - 1;
uint32_t chan = timer_io_channels[channel].timer_channel;
uint16_t rvalue = REG(timer, S32K1XX_FTM_CNSC_OFFSET(chan));
rvalue &= ~clearbits;
@@ -823,7 +823,7 @@ int io_timer_set_enable(bool state, io_timer_channel_mode_t mode, io_timer_chann
masks &= ~(1 << chan_index);
if (io_timer_validate_channel_index(chan_index) == 0) {
uint32_t chan = timer_io_channels[chan_index].timer_channel - 1;
uint32_t chan = timer_io_channels[chan_index].timer_channel;
uint32_t timer = channels_timer(chan_index);
action_cache[timer].base = io_timers[timer].base;
action_cache[timer].cnsc[action_cache[timer].index].cnsc_offset = io_timers[timer].base + S32K1XX_FTM_CNSC_OFFSET(chan);
@@ -912,7 +912,7 @@ int io_timer_set_ccr(unsigned channel, uint16_t value)
irqstate_t flags = px4_enter_critical_section();
uint32_t save = rSC(timer);
rSC(timer) = save & ~(FTM_SC_CLKS_MASK);
REG(timer, S32K1XX_FTM_CNV_OFFSET(timer_io_channels[channel].timer_channel - 1)) = value;
REG(timer, S32K1XX_FTM_CNV_OFFSET(timer_io_channels[channel].timer_channel)) = value;
rSC(timer) = save;
px4_leave_critical_section(flags);
}
@@ -931,7 +931,7 @@ uint16_t io_channel_get_ccr(unsigned channel)
if ((mode == IOTimerChanMode_PWMOut) ||
(mode == IOTimerChanMode_OneShot) ||
(mode == IOTimerChanMode_Trigger)) {
value = REG(channels_timer(channel), S32K1XX_FTM_CNV_OFFSET(timer_io_channels[channel].timer_channel - 1));
value = REG(channels_timer(channel), S32K1XX_FTM_CNV_OFFSET(timer_io_channels[channel].timer_channel));
}
}
@@ -228,7 +228,7 @@ led_pwm_channel_init(unsigned channel)
{
/* Only initialize used channels */
if (led_pwm_channels[channel].timer_channel) {
if (led_pwm_channels[channel].gpio_out) {
unsigned timer = led_pwm_channels[channel].timer_index;
irqstate_t flags = px4_enter_critical_section();
@@ -239,7 +239,7 @@ led_pwm_channel_init(unsigned channel)
/* configure the channel */
uint32_t chan = led_pwm_channels[channel].timer_channel - 1;
uint32_t chan = led_pwm_channels[channel].timer_channel;
uint16_t rvalue = REG(timer, S32K1XX_FTM_CNSC_OFFSET(chan));
rvalue &= ~CnSC_RESET;
@@ -275,7 +275,7 @@ led_pwm_servo_set(unsigned channel, uint8_t cvalue)
value--;
}
REG(timer, S32K1XX_FTM_CNV_OFFSET(led_pwm_channels[channel].timer_channel - 1)) = value;
REG(timer, S32K1XX_FTM_CNV_OFFSET(led_pwm_channels[channel].timer_channel)) = value;
return 0;
}
@@ -291,11 +291,11 @@ unsigned led_pwm_servo_get(unsigned channel)
/* test timer for validity */
if ((led_pwm_timers[timer].base == 0) ||
(led_pwm_channels[channel].timer_channel == 0)) {
(led_pwm_channels[channel].gpio_out == 0)) {
return value;
}
value = REG(timer, S32K1XX_FTM_CNV_OFFSET(led_pwm_channels[channel].timer_channel - 1));
value = REG(timer, S32K1XX_FTM_CNV_OFFSET(led_pwm_channels[channel].timer_channel));
unsigned period = led_pwm_timer_get_period(timer);
return ((value + 1) * 255 / period);
}
@@ -52,7 +52,7 @@ static inline constexpr timer_io_channels_t initIOTimerChannel(const io_timers_t
ret.gpio_in = pinmux;
ret.gpio_out = pinmux;
ret.timer_channel = (int)timer.channel + 1;
ret.timer_channel = (uint8_t)timer.channel;
// find timer index
ret.timer_index = timer.channel;
@@ -108,7 +108,7 @@ static void input_capture_chan_handler(void *context, const io_timers_t *timer,
channel_stats[chan_index].edges++;
channel_stats[chan_index].last_time = isrs_time - (isrs_rcnt - capture);
uint32_t overflow = 0;//_REG32(timer, S32K1XX_FTM_CNSC_OFFSET(chan->timer_channel - 1)) & FTM_CNSC_CHF;
uint32_t overflow = 0;//_REG32(timer, S32K1XX_FTM_CNSC_OFFSET(chan->timer_channel)) & FTM_CNSC_CHF;
if (overflow) {
@@ -155,7 +155,7 @@ int up_input_capture_set(unsigned channel, input_capture_edge edge, capture_filt
/* This register selects the filter value for the inputs of channels.
Channels 4, 5, 6 and 7 do not have an input filter.
*/
if (filter && timer_io_channels[channel].timer_channel - 1 > 3) {
if (filter && timer_io_channels[channel].timer_channel > 3) {
return -EINVAL;
}
@@ -198,7 +198,7 @@ int up_input_capture_get_filter(unsigned channel, capture_filter_t *filter)
rv = -EINVAL;
if (timer_io_channels[channel].timer_channel - 1 <= 3) {
if (timer_io_channels[channel].timer_channel <= 3) {
rv = -ENXIO;
/* Any pins in capture mode */
@@ -274,7 +274,7 @@ int up_input_capture_get_trigger(unsigned channel, input_capture_edge *edge)
rv = OK;
//uint32_t timer = timer_io_channels[channel].timer_index;
/*uint16_t rvalue = _REG32(timer, S32K1XX_FTM_CNSC_OFFSET(timer_io_channels[channel].timer_channel - 1));
/*uint16_t rvalue = _REG32(timer, S32K1XX_FTM_CNSC_OFFSET(timer_io_channels[channel].timer_channel));
rvalue &= (FTM_CNSC_MSB | FTM_CNSC_MSA);
switch (rvalue) {
@@ -335,10 +335,10 @@ int up_input_capture_set_trigger(unsigned channel, input_capture_edge edge)
//uint32_t timer = timer_io_channels[channel].timer_index;
irqstate_t flags = px4_enter_critical_section();
/*uint32_t rvalue = _REG32(timer, S32K1XX_FTM_CNSC_OFFSET(timer_io_channels[channel].timer_channel - 1));
/*uint32_t rvalue = _REG32(timer, S32K1XX_FTM_CNSC_OFFSET(timer_io_channels[channel].timer_channel));
rvalue &= (FTM_CNSC_MSB | FTM_CNSC_MSA);
rvalue |= edge_bits;
_REG32(timer, S32K1XX_FTM_CNSC_OFFSET(timer_io_channels[channel].timer_channel - 1)) = rvalue;*/
_REG32(timer, S32K1XX_FTM_CNSC_OFFSET(timer_io_channels[channel].timer_channel)) = rvalue;*/
px4_leave_critical_section(flags);
rv = OK;
}
@@ -301,7 +301,7 @@ int io_timer_validate_channel_index(unsigned channel)
{
int rv = -EINVAL;
if (channel < MAX_TIMER_IO_CHANNELS && timer_io_channels[channel].timer_channel != 0) {
if (channel < MAX_TIMER_IO_CHANNELS) {
unsigned timer = timer_io_channels[channel].timer_index;
@@ -731,7 +731,7 @@ int io_timer_channel_init(unsigned channel, io_timer_channel_mode_t mode,
/* configure the channel */
uint32_t chan = timer_io_channels[channel].timer_channel - 1;
uint32_t chan = timer_io_channels[channel].timer_channel;
//FIXME use setbits/clearbits for different modes
@@ -830,7 +830,7 @@ int io_timer_set_enable(bool state, io_timer_channel_mode_t mode, io_timer_chann
masks &= ~(1 << chan_index);
if (io_timer_validate_channel_index(chan_index) == 0) {
uint32_t chan = timer_io_channels[chan_index].timer_channel - 1;
uint32_t chan = timer_io_channels[chan_index].timer_channel;
uint32_t timer = channels_timer(chan_index);
if ((state &&
@@ -875,7 +875,7 @@ int io_timer_set_ccr(unsigned channel, uint16_t value)
/* configure the channel */
irqstate_t flags = px4_enter_critical_section();
rA(channels_timer(channel), timer_io_channels[channel].timer_channel - 1) = EMIOS_A(value * 2);
rA(channels_timer(channel), timer_io_channels[channel].timer_channel) = EMIOS_A(value * 2);
px4_leave_critical_section(flags);
}
}
@@ -895,7 +895,7 @@ uint16_t io_channel_get_ccr(unsigned channel)
(mode == IOTimerChanMode_OneShot) ||
(mode == IOTimerChanMode_Trigger)) {
/* Read rALTA to fetch AS2 shadow register */
value = (rALTA(channels_timer(channel), timer_io_channels[channel].timer_channel - 1) & EMIOS_A_MASK) / 2;
value = (rALTA(channels_timer(channel), timer_io_channels[channel].timer_channel) & EMIOS_A_MASK) / 2;
}
}
@@ -228,7 +228,7 @@ led_pwm_channel_init(unsigned channel)
{
/* Only initialize used channels */
if (led_pwm_channels[channel].timer_channel) {
if (led_pwm_channels[channel].gpio_out) {
unsigned timer = led_pwm_channels[channel].timer_index;
irqstate_t flags = px4_enter_critical_section();
@@ -239,7 +239,7 @@ led_pwm_channel_init(unsigned channel)
/* configure the channel */
uint32_t chan = led_pwm_channels[channel].timer_channel - 1;
uint32_t chan = led_pwm_channels[channel].timer_channel;
uint16_t rvalue = REG(timer, S32K1XX_FTM_CNSC_OFFSET(chan));
rvalue &= ~CnSC_RESET;
@@ -275,7 +275,7 @@ led_pwm_servo_set(unsigned channel, uint8_t cvalue)
value--;
}
REG(timer, S32K1XX_FTM_CNV_OFFSET(led_pwm_channels[channel].timer_channel - 1)) = value;
REG(timer, S32K1XX_FTM_CNV_OFFSET(led_pwm_channels[channel].timer_channel)) = value;
return 0;
}
@@ -291,11 +291,11 @@ led_pwm_servo_get(unsigned channel)
/* test timer for validity */
if ((led_pwm_timers[timer].base == 0) ||
(led_pwm_channels[channel].timer_channel == 0)) {
(led_pwm_channels[channel].gpio_out == 0)) {
return value;
}
value = REG(timer, S32K1XX_FTM_CNV_OFFSET(led_pwm_channels[channel].timer_channel - 1));
value = REG(timer, S32K1XX_FTM_CNV_OFFSET(led_pwm_channels[channel].timer_channel));
unsigned period = led_pwm_timer_get_period(timer);
return ((value + 1) * 255 / period);
}
@@ -57,7 +57,7 @@ enum Timer {
Timer7,
};
enum Channel {
ChannelA = 1,
ChannelA = 0,
ChannelB,
};
struct TimerChannel {
@@ -266,7 +266,7 @@ int io_timer_validate_channel_index(unsigned channel)
{
int rv = -EINVAL;
if (channel < MAX_TIMER_IO_CHANNELS && timer_io_channels[channel].timer_channel != 0) {
if (channel < MAX_TIMER_IO_CHANNELS) {
unsigned timer = timer_io_channels[channel].timer_index;
@@ -602,7 +602,7 @@ int io_timer_channel_init(unsigned channel, io_timer_channel_mode_t mode,
/* configure the channel */ // Nothing to configure here really.
// uint32_t chan = timer_io_channels[channel].timer_channel - 1;
// uint32_t chan = timer_io_channels[channel].timer_channel;
channel_handlers[channel].callback = channel_handler;
channel_handlers[channel].context = context;
@@ -664,7 +664,7 @@ int io_timer_set_enable(bool state, io_timer_channel_mode_t mode, io_timer_chann
masks &= ~(1 << chan_index);
if (io_timer_validate_channel_index(chan_index) == 0) {
// uint32_t chan = timer_io_channels[chan_index].timer_channel - 1;
// uint32_t chan = timer_io_channels[chan_index].timer_channel;
uint32_t timer = channels_timer(chan_index);
action_cache[timer].base = io_timers[timer].base;
// action_cache[timer].cnsc[action_cache[timer].index].cnsc_offset = io_timers[timer].base + KINETIS_FTM_CSC_OFFSET(chan);
@@ -739,8 +739,8 @@ int io_timer_set_ccr(unsigned channel, uint16_t value)
/* configure the channel */
int regVal = rCCR(channels_timer(channel));
regVal &= ~(0xffff << (timer_io_channels[channel].timer_channel - 1) * 16);
regVal |= value << (timer_io_channels[channel].timer_channel - 1) * 16;
regVal &= ~(0xffff << (timer_io_channels[channel].timer_channel) * 16);
regVal |= value << (timer_io_channels[channel].timer_channel) * 16;
rCCR(channels_timer(channel)) = regVal;
}
}
@@ -758,7 +758,7 @@ uint16_t io_channel_get_ccr(unsigned channel)
if ((mode == IOTimerChanMode_PWMOut) ||
(mode == IOTimerChanMode_OneShot) ||
(mode == IOTimerChanMode_Trigger)) {
value = rCCR(channels_timer(channel)) >> (timer_io_channels[channel].timer_channel - 1) * 16;
value = rCCR(channels_timer(channel)) >> (timer_io_channels[channel].timer_channel) * 16;
}
}
@@ -191,13 +191,11 @@ static void init_timer_config(uint32_t channel_mask)
uint8_t timer_channel = timer_io_channels[output_channel].timer_channel;
if ((timer_channel <= 0) || (timer_channel >= 5)) {
// invalid channel, only 1 - 4
if (timer_channel >= 4) {
// invalid channel, only 0 - 3
continue;
}
uint8_t timer_channel_index = timer_channel - 1;
if (io_timers[timer_index].dshot.dma_base == 0) {
// board does not configure dshot on this timer
continue;
@@ -205,7 +203,7 @@ static void init_timer_config(uint32_t channel_mask)
timer_configs[timer_index].timer_index = timer_index;
timer_configs[timer_index].enabled = true;
timer_configs[timer_index].enabled_channels[timer_channel_index] = true;
timer_configs[timer_index].enabled_channels[timer_channel] = true;
// TODO: bdshot per timer not on all timers
// Mark timer as bidirectional
@@ -275,14 +273,13 @@ static int32_t init_timer_channels(uint8_t timer_index)
uint8_t timer_channel = timer_io_channels[output_channel].timer_channel;
if ((timer_channel <= 0) || (timer_channel >= 5)) {
// invalid channel, only 1 - 4
if (timer_channel >= 4) {
// invalid channel, only 0 - 3
continue;
}
uint8_t timer_channel_index = timer_channel - 1;
bool this_timer = timer_index == timer_io_channels[output_channel].timer_index;
bool channel_enabled = timer_configs[timer_index].enabled_channels[timer_channel_index];
bool channel_enabled = timer_configs[timer_index].enabled_channels[timer_channel];
if (this_timer && channel_enabled) {
int ret = io_timer_channel_init(output_channel, mode, NULL, NULL);
@@ -292,7 +289,7 @@ static int32_t init_timer_channels(uint8_t timer_index)
continue;
}
timer_configs[timer_index].initialized_channels[timer_channel_index] = true;
timer_configs[timer_index].initialized_channels[timer_channel] = true;
channels_init_mask |= (1 << output_channel);
PX4_DEBUG("%sDShot initialized OutputChannel %u", timer_configs[timer_index].bidirectional ? "B" : "", output_channel);
@@ -366,10 +363,8 @@ int up_dshot_init(uint32_t channel_mask, uint32_t bdshot_channel_mask, unsigned
uint8_t timer_index = timer_io_channels[output_channel].timer_index;
uint8_t timer_channel = timer_io_channels[output_channel].timer_channel;
if (timer_channel >= 1 && timer_channel <= 4) {
uint8_t timer_channel_index = timer_channel - 1;
if (io_timers[timer_index].dshot.dma_map_ch[timer_channel_index] != 0) {
if (timer_channel < 4) {
if (io_timers[timer_index].dshot.dma_map_ch[timer_channel] != 0) {
_bdshot_capture_supported[output_channel] = true;
} else {
@@ -509,7 +504,7 @@ static uint8_t output_channel_from_timer_channel(uint8_t timer_index, uint8_t ti
for (uint8_t output_channel = 0; output_channel < MAX_TIMER_IO_CHANNELS; output_channel++) {
bool is_this_timer = timer_index == timer_io_channels[output_channel].timer_index;
uint8_t channel_index = timer_io_channels[output_channel].timer_channel - 1;
uint8_t channel_index = timer_io_channels[output_channel].timer_channel;
if (is_this_timer && (channel_index == timer_channel_index)) {
// We found the output channel associated with this timer channel
@@ -632,7 +627,7 @@ static void capture_complete_callback(void *arg)
for (uint8_t output_channel = 0; output_channel < MAX_TIMER_IO_CHANNELS; output_channel++) {
bool is_this_timer = timer_index == timer_io_channels[output_channel].timer_index;
uint8_t timer_channel_index = timer_io_channels[output_channel].timer_channel - 1;
uint8_t timer_channel_index = timer_io_channels[output_channel].timer_channel;
bool channel_initialized = timer_configs[timer_index].initialized_channels[timer_channel_index];
if (is_this_timer && channel_initialized) {
@@ -923,7 +918,7 @@ void dshot_motor_data_set(uint8_t channel, uint16_t data, bool telemetry)
}
uint8_t timer_index = timer_io_channels[channel].timer_index;
uint8_t timer_channel_index = timer_io_channels[channel].timer_channel - 1;
uint8_t timer_channel_index = timer_io_channels[channel].timer_channel;
bool channel_initialized = timer_configs[timer_index].initialized_channels[timer_channel_index];
if (!channel_initialized) {
@@ -999,7 +994,7 @@ int up_bdshot_get_erpm(uint8_t channel, int *erpm)
}
uint8_t timer_index = timer_io_channels[channel].timer_index;
uint8_t timer_channel_index = timer_io_channels[channel].timer_channel - 1;
uint8_t timer_channel_index = timer_io_channels[channel].timer_channel;
bool channel_initialized = timer_configs[timer_index].initialized_channels[timer_channel_index];
if (channel_initialized && _erpms[channel].ready) {
@@ -102,7 +102,7 @@ enum Timer {
#endif
};
enum Channel {
Channel1 = 1,
Channel1 = 0,
Channel2,
Channel3,
Channel4,
@@ -52,29 +52,27 @@ static inline constexpr timer_io_channels_t initIOTimerChannel(const io_timers_t
// TODO: here we could validate that pin actually maps to the given timer channel
ret.timer_channel = (uint8_t)timer.channel;
switch (timer.channel) {
case Timer::Channel1:
ret.ccr_offset = STM32_GTIM_CCR1_OFFSET;
ret.masks = GTIM_SR_CC1IF | GTIM_SR_CC1OF;
ret.timer_channel = 1;
break;
case Timer::Channel2:
ret.ccr_offset = STM32_GTIM_CCR2_OFFSET;
ret.masks = GTIM_SR_CC2IF | GTIM_SR_CC2OF;
ret.timer_channel = 2;
break;
case Timer::Channel3:
ret.ccr_offset = STM32_GTIM_CCR3_OFFSET;
ret.masks = GTIM_SR_CC3IF | GTIM_SR_CC3OF;
ret.timer_channel = 3;
break;
case Timer::Channel4:
ret.ccr_offset = STM32_GTIM_CCR4_OFFSET;
ret.masks = GTIM_SR_CC4IF | GTIM_SR_CC4OF;
ret.timer_channel = 4;
break;
}
@@ -203,22 +203,22 @@ int up_input_capture_get_filter(unsigned channel, capture_filter_t *filter)
switch (timer_io_channels[channel].timer_channel) {
case 1:
case 0:
rvalue = rCCMR1(timer) & GTIM_CCMR1_IC1F_MASK;
*filter = (rvalue >> GTIM_CCMR1_IC1F_SHIFT);
break;
case 2:
case 1:
rvalue = rCCMR1(timer) & GTIM_CCMR1_IC2F_MASK;
*filter = (rvalue >> GTIM_CCMR1_IC2F_SHIFT);
break;
case 3:
case 2:
rvalue = rCCMR2(timer) & GTIM_CCMR2_IC3F_MASK;
*filter = (rvalue >> GTIM_CCMR2_IC3F_SHIFT);
break;
case 4:
case 3:
rvalue = rCCMR2(timer) & GTIM_CCMR2_IC4F_MASK;
*filter = (rvalue >> GTIM_CCMR2_IC4F_SHIFT);
break;
@@ -255,25 +255,25 @@ int up_input_capture_set_filter(unsigned channel, capture_filter_t filter)
switch (timer_io_channels[channel].timer_channel) {
case 1:
case 0:
rvalue = rCCMR1(timer) & ~GTIM_CCMR1_IC1F_MASK;
rvalue |= (filter << GTIM_CCMR1_IC1F_SHIFT);
rCCMR1(timer) = rvalue;
break;
case 2:
case 1:
rvalue = rCCMR1(timer) & ~GTIM_CCMR1_IC2F_MASK;
rvalue |= (filter << GTIM_CCMR1_IC2F_SHIFT);
rCCMR1(timer) = rvalue;
break;
case 3:
case 2:
rvalue = rCCMR2(timer) & ~GTIM_CCMR2_IC3F_MASK;
rvalue |= (filter << GTIM_CCMR2_IC3F_SHIFT);
rCCMR2(timer) = rvalue;
break;
case 4:
case 3:
rvalue = rCCMR2(timer) & ~GTIM_CCMR2_IC4F_MASK;
rvalue |= (filter << GTIM_CCMR2_IC4F_SHIFT);
rCCMR2(timer) = rvalue;
@@ -309,21 +309,21 @@ int up_input_capture_get_trigger(unsigned channel, input_capture_edge *edge)
switch (timer_io_channels[channel].timer_channel) {
case 1:
case 0:
rvalue = rCCER(timer) & (GTIM_CCER_CC1P | GTIM_CCER_CC1NP);
break;
case 2:
case 1:
rvalue = rCCER(timer) & (GTIM_CCER_CC2P | GTIM_CCER_CC2NP);
rvalue >>= 4;
break;
case 3:
case 2:
rvalue = rCCER(timer) & (GTIM_CCER_CC3P | GTIM_CCER_CC3NP);
rvalue >>= 8;
break;
case 4:
case 3:
rvalue = rCCER(timer) & (GTIM_CCER_CC4P | GTIM_CCER_CC4NP);
rvalue >>= 12;
break;
@@ -400,28 +400,28 @@ int up_input_capture_set_trigger(unsigned channel, input_capture_edge edge)
switch (timer_io_channels[channel].timer_channel) {
case 1:
case 0:
rvalue = rCCER(timer);
rvalue &= ~(GTIM_CCER_CC1P | GTIM_CCER_CC1NP);
rvalue |= edge_bits;
rCCER(timer) = rvalue;
break;
case 2:
case 1:
rvalue = rCCER(timer);
rvalue &= ~(GTIM_CCER_CC2P | GTIM_CCER_CC2NP);
rvalue |= (edge_bits << 4);
rCCER(timer) = rvalue;
break;
case 3:
case 2:
rvalue = rCCER(timer);
rvalue &= ~(GTIM_CCER_CC3P | GTIM_CCER_CC3NP);
rvalue |= edge_bits << 8;
rCCER(timer) = rvalue;
break;
case 4:
case 3:
rvalue = rCCER(timer);
rvalue &= ~(GTIM_CCER_CC4P | GTIM_CCER_CC4NP);
rvalue |= edge_bits << 12;
@@ -357,7 +357,7 @@ int io_timer_validate_channel_index(unsigned channel)
{
int rv = -EINVAL;
if (channel < MAX_TIMER_IO_CHANNELS && timer_io_channels[channel].timer_channel != 0) {
if (channel < MAX_TIMER_IO_CHANNELS) {
unsigned timer = timer_io_channels[channel].timer_index;
@@ -606,7 +606,7 @@ int io_timer_set_dshot_burst_mode(uint8_t timer, unsigned dshot_pwm_freq, uint8_
rEGR(timer) = ATIM_EGR_UG;
// find the lowest channel index for the timer (they are not necessarily in ascending order)
unsigned lowest_timer_channel = 4;
unsigned lowest_timer_channel = 3;
uint32_t first_channel_index = io_timers_channel_mapping.element[timer].first_channel_index;
uint32_t last_channel_index = first_channel_index + io_timers_channel_mapping.element[timer].channel_count;
@@ -619,13 +619,13 @@ int io_timer_set_dshot_burst_mode(uint8_t timer, unsigned dshot_pwm_freq, uint8_
uint32_t start_ccr_register = 0;
switch (lowest_timer_channel) {
case 1: start_ccr_register = TIM_DMABASE_CCR1; break;
case 0: start_ccr_register = TIM_DMABASE_CCR1; break;
case 2: start_ccr_register = TIM_DMABASE_CCR2; break;
case 1: start_ccr_register = TIM_DMABASE_CCR2; break;
case 3: start_ccr_register = TIM_DMABASE_CCR3; break;
case 2: start_ccr_register = TIM_DMABASE_CCR3; break;
case 4: start_ccr_register = TIM_DMABASE_CCR4; break;
case 3: start_ccr_register = TIM_DMABASE_CCR4; break;
}
rDCR(timer) = start_ccr_register | tim_dma_burst_length;
@@ -934,9 +934,9 @@ int io_timer_channel_init(unsigned channel, io_timer_channel_mode_t mode,
/* configure the channel */
uint32_t shifts = timer_io_channels[channel].timer_channel - 1;
uint32_t shifts = timer_io_channels[channel].timer_channel;
/* Map shifts timer channel 1-4 to 0-3 */
/* Map shifts timer channel 0-3 */
uint32_t ccmr_offset = STM32_GTIM_CCMR1_OFFSET + ((shifts >> 1) * sizeof(uint32_t));
uint32_t ccr_offset = STM32_GTIM_CCR1_OFFSET + (shifts * sizeof(uint32_t));
@@ -1047,7 +1047,7 @@ int io_timer_set_enable(bool state, io_timer_channel_mode_t mode, io_timer_chann
for (int chan_index = 0; masks != 0 && chan_index < MAX_TIMER_IO_CHANNELS; chan_index++) {
if (masks & (1 << chan_index)) {
masks &= ~(1 << chan_index);
uint32_t shifts = timer_io_channels[chan_index].timer_channel - 1;
uint32_t shifts = timer_io_channels[chan_index].timer_channel;
uint32_t timer = channels_timer(chan_index);
action_cache[timer].base = io_timers[timer].base;
action_cache[timer].ccer_clearbits |= CCER_C1_INIT << (shifts * CCER_C1_NUM_BITS);
@@ -166,7 +166,7 @@ led_pwm_channel_init(unsigned channel)
{
/* Only initialize used channels */
if (led_pwm_channels[channel].timer_channel) {
if (led_pwm_channels[channel].gpio_out) {
unsigned timer = led_pwm_channels[channel].timer_index;
@@ -177,22 +177,22 @@ led_pwm_channel_init(unsigned channel)
/* configure the channel */
switch (led_pwm_channels[channel].timer_channel) {
case 1:
case 0:
rCCMR1(timer) |= (GTIM_CCMR_MODE_PWM1 << GTIM_CCMR1_OC1M_SHIFT) | GTIM_CCMR1_OC1PE;
rCCER(timer) |= polarity | GTIM_CCER_CC1E;
break;
case 2:
case 1:
rCCMR1(timer) |= (GTIM_CCMR_MODE_PWM1 << GTIM_CCMR1_OC2M_SHIFT) | GTIM_CCMR1_OC2PE;
rCCER(timer) |= polarity | GTIM_CCER_CC2E;
break;
case 3:
case 2:
rCCMR2(timer) |= (GTIM_CCMR_MODE_PWM1 << GTIM_CCMR2_OC3M_SHIFT) | GTIM_CCMR2_OC3PE;
rCCER(timer) |= polarity | GTIM_CCER_CC3E;
break;
case 4:
case 3:
rCCMR2(timer) |= (GTIM_CCMR_MODE_PWM1 << GTIM_CCMR2_OC4M_SHIFT) | GTIM_CCMR2_OC4PE;
rCCER(timer) |= polarity | GTIM_CCER_CC4E;
break;
@@ -226,19 +226,19 @@ led_pwm_servo_set(unsigned channel, uint8_t cvalue)
switch (led_pwm_channels[channel].timer_channel) {
case 1:
case 0:
rCCR1(timer) = value;
break;
case 2:
case 1:
rCCR2(timer) = value;
break;
case 3:
case 2:
rCCR3(timer) = value;
break;
case 4:
case 3:
rCCR4(timer) = value;
break;
@@ -260,25 +260,25 @@ unsigned led_pwm_servo_get(unsigned channel)
/* test timer for validity */
if ((led_pwm_timers[timer].base == 0) ||
(led_pwm_channels[channel].timer_channel == 0)) {
(led_pwm_channels[channel].gpio_out == 0)) {
return 0;
}
/* configure the channel */
switch (led_pwm_channels[channel].timer_channel) {
case 1:
case 0:
value = rCCR1(timer);
break;
case 2:
case 1:
value = rCCR2(timer);
break;
case 3:
case 2:
value = rCCR3(timer);
break;
case 4:
case 3:
value = rCCR4(timer);
break;
}
@@ -93,29 +93,27 @@ static inline constexpr timer_io_channels_t initIOTimerChannel(const io_timers_t
{
timer_io_channels_t ret = initIOTimerGPIOInOut(timer, pin);
ret.timer_channel = (uint8_t)timer.channel;
switch (timer.channel) {
case Timer::Channel1:
ret.ccr_offset = STM32_GTIM_CCR1_OFFSET;
ret.masks = GTIM_SR_CC1IF | GTIM_SR_CC1OF;
ret.timer_channel = 1;
break;
case Timer::Channel2:
ret.ccr_offset = STM32_GTIM_CCR2_OFFSET;
ret.masks = GTIM_SR_CC2IF | GTIM_SR_CC2OF;
ret.timer_channel = 2;
break;
case Timer::Channel3:
ret.ccr_offset = STM32_GTIM_CCR3_OFFSET;
ret.masks = GTIM_SR_CC3IF | GTIM_SR_CC3OF;
ret.timer_channel = 3;
break;
case Timer::Channel4:
ret.ccr_offset = STM32_GTIM_CCR4_OFFSET;
ret.masks = GTIM_SR_CC4IF | GTIM_SR_CC4OF;
ret.timer_channel = 4;
break;
}