mirror of
https://github.com/PX4/PX4-Autopilot.git
synced 2026-05-30 18:06:39 +08:00
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:
@@ -145,7 +145,7 @@ void spix_sync_channel_init(unsigned channel)
|
||||
{
|
||||
/* Only initialize used channels */
|
||||
|
||||
if (spix_sync_channels[channel].timer_channel) {
|
||||
if (spix_sync_channels[channel].gpio_out) {
|
||||
|
||||
unsigned timer = spix_sync_channels[channel].timer_index;
|
||||
|
||||
@@ -156,22 +156,22 @@ void spix_sync_channel_init(unsigned channel)
|
||||
|
||||
/* configure the channel */
|
||||
switch (spix_sync_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;
|
||||
@@ -205,19 +205,19 @@ spix_sync_servo_set(unsigned channel, uint8_t cvalue)
|
||||
|
||||
|
||||
switch (spix_sync_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;
|
||||
|
||||
@@ -239,25 +239,25 @@ unsigned spix_sync_servo_get(unsigned channel)
|
||||
|
||||
/* test timer for validity */
|
||||
if ((spix_sync_timers[timer].base == 0) ||
|
||||
(spix_sync_channels[channel].timer_channel == 0)) {
|
||||
(spix_sync_channels[channel].gpio_out == 0)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* configure the channel */
|
||||
switch (spix_sync_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;
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ void spix_sync_channel_init(unsigned channel)
|
||||
{
|
||||
/* Only initialize used channels */
|
||||
|
||||
if (spix_sync_channels[channel].timer_channel) {
|
||||
if (spix_sync_channels[channel].gpio_out) {
|
||||
|
||||
unsigned timer = spix_sync_channels[channel].timer_index;
|
||||
|
||||
@@ -156,22 +156,22 @@ void spix_sync_channel_init(unsigned channel)
|
||||
|
||||
/* configure the channel */
|
||||
switch (spix_sync_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;
|
||||
@@ -205,19 +205,19 @@ spix_sync_servo_set(unsigned channel, uint8_t cvalue)
|
||||
|
||||
|
||||
switch (spix_sync_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;
|
||||
|
||||
@@ -239,25 +239,25 @@ unsigned spix_sync_servo_get(unsigned channel)
|
||||
|
||||
/* test timer for validity */
|
||||
if ((spix_sync_timers[timer].base == 0) ||
|
||||
(spix_sync_channels[channel].timer_channel == 0)) {
|
||||
(spix_sync_channels[channel].gpio_out == 0)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* configure the channel */
|
||||
switch (spix_sync_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;
|
||||
}
|
||||
|
||||
@@ -87,19 +87,19 @@ const struct timer_io_channels_t led_pwm_channels[MAX_TIMER_LED_CHANNELS] = {
|
||||
.gpio_out = LED_TIM3_CH1OUT, // RGB_R
|
||||
.gpio_in = 0,
|
||||
.timer_index = 0,
|
||||
.timer_channel = 2,
|
||||
.timer_channel = 1,
|
||||
},
|
||||
{
|
||||
.gpio_out = LED_TIM3_CH5OUT, // RGB_G
|
||||
.gpio_in = 0,
|
||||
.timer_index = 0,
|
||||
.timer_channel = 6,
|
||||
.timer_channel = 5,
|
||||
},
|
||||
{
|
||||
.gpio_out = LED_TIM3_CH4OUT, // RGB_B
|
||||
.gpio_in = 0,
|
||||
.timer_index = 0,
|
||||
.timer_channel = 5,
|
||||
.timer_channel = 4,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -85,19 +85,19 @@ const struct timer_io_channels_t led_pwm_channels[MAX_TIMER_LED_CHANNELS] = {
|
||||
.gpio_out = LED_TIM3_CH1OUT, // RGB_R
|
||||
.gpio_in = 0,
|
||||
.timer_index = 0,
|
||||
.timer_channel = 2,
|
||||
.timer_channel = 1,
|
||||
},
|
||||
{
|
||||
.gpio_out = LED_TIM3_CH5OUT, // RGB_G
|
||||
.gpio_in = 0,
|
||||
.timer_index = 0,
|
||||
.timer_channel = 6,
|
||||
.timer_channel = 5,
|
||||
},
|
||||
{
|
||||
.gpio_out = LED_TIM3_CH4OUT, // RGB_B
|
||||
.gpio_in = 0,
|
||||
.timer_index = 0,
|
||||
.timer_channel = 5,
|
||||
.timer_channel = 4,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -105,18 +105,18 @@ const struct timer_io_channels_t led_pwm_channels[MAX_TIMER_LED_CHANNELS] = {
|
||||
.gpio_out = GPIO_LED_R, // RGB_R
|
||||
.gpio_in = 0,
|
||||
.timer_index = 0,
|
||||
.timer_channel = 19,
|
||||
.timer_channel = 18,
|
||||
},
|
||||
{
|
||||
.gpio_out = GPIO_LED_G, // RGB_G
|
||||
.gpio_in = 0,
|
||||
.timer_index = 1,
|
||||
.timer_channel = 10,
|
||||
.timer_channel = 9,
|
||||
},
|
||||
{
|
||||
.gpio_out = GPIO_LED_B, // RGB_B
|
||||
.gpio_in = 0,
|
||||
.timer_index = 1,
|
||||
.timer_channel = 5,
|
||||
.timer_channel = 4,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -131,19 +131,19 @@ const struct timer_io_channels_t led_pwm_channels[MAX_TIMER_LED_CHANNELS] = {
|
||||
.gpio_out = LED_TIM0_CH0OUT, // RGB_R
|
||||
.gpio_in = 0,
|
||||
.timer_index = 0,
|
||||
.timer_channel = 1,
|
||||
.timer_channel = 0,
|
||||
},
|
||||
{
|
||||
.gpio_out = LED_TIM0_CH1OUT, // RGB_G
|
||||
.gpio_in = 0,
|
||||
.timer_index = 0,
|
||||
.timer_channel = 2,
|
||||
.timer_channel = 1,
|
||||
},
|
||||
{
|
||||
.gpio_out = LED_TIM0_CH2OUT, // RGB_B
|
||||
.gpio_in = 0,
|
||||
.timer_index = 0,
|
||||
.timer_channel = 3,
|
||||
.timer_channel = 2,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user