1
0
Fork 0
mirror of https://github.com/betaflight/betaflight.git synced 2025-07-15 20:35:33 +03:00

STM32F30x - Working parallel PWM. Timer IRQ handle was not defined for

TIM8 correctly. Software serial conficted with parallel PWM input. Fixed
crash due to incorrect timerConfig index calculation code.

The crash occurred when capture compare interrupt handlers attempted to
call an invalid callback.

Note: the crash does not affect existing baseflight code since the
formula is OK when using a 2 dimensional array with equal dimensions.

Formula details here:
https://docs.google.com/spreadsheets/d/1UuxnC0VKiprvt1wt3KXffefEWJUb_-ILFLQuP377Anw
This commit is contained in:
Dominic Clifton 2014-05-02 17:09:41 +01:00
parent fbe2f82c05
commit 92bed4a33d
10 changed files with 82 additions and 82 deletions

View file

@ -449,3 +449,10 @@ uint32_t featureMask(void)
return masterConfig.enabledFeatures;
}
bool canSoftwareSerialBeUsed(void)
{
// FIXME this is not ideal because it means you can't disable parallel PWM input even when using spektrum/sbus etc.
// really we want to say 'return !feature(FEATURE_PARALLEL_PWM);'
return feature(FEATURE_SOFTSERIAL) && feature(FEATURE_PPM); // Software serial can only be used in PPM mode because parallel PWM uses the same hardware pins/timers
}

View file

@ -32,3 +32,5 @@ void readEEPROMAndNotify(void);
void writeEEPROM();
void ensureEEPROMContainsValidData(void);
void saveAndReloadCurrentProfileToCurrentProfileSlot(void);
bool canSoftwareSerialBeUsed(void);

View file

@ -48,7 +48,9 @@ typedef enum
Mode_Out_OD = (GPIO_OType_OD << 4) | GPIO_Mode_OUT,
Mode_Out_PP = (GPIO_OType_PP << 4) | GPIO_Mode_OUT,
Mode_AF_OD = (GPIO_OType_OD << 4) | GPIO_Mode_AF,
Mode_AF_PP = (GPIO_OType_PP << 4) | GPIO_Mode_AF
Mode_AF_PP = (GPIO_OType_PP << 4) | GPIO_Mode_AF,
Mode_AF_PP_PD = (GPIO_OType_PP << 4) | (GPIO_PuPd_DOWN << 2) | GPIO_Mode_AF,
Mode_AF_PP_PU = (GPIO_OType_PP << 4) | (GPIO_PuPd_UP << 2) | GPIO_Mode_AF
} GPIO_Mode;
#endif

View file

@ -13,20 +13,6 @@
#define MODE_MASK ((1|2) << MODE_OFFSET)
#define PUPD_MASK ((1|2) << PUPD_OFFSET)
#define OUTPUT_MASK ((1|2) << OUTPUT_OFFSET)
/*
typedef enum
{
Mode_AIN = (GPIO_PuPd_NOPULL << 2) | GPIO_Mode_AN,
Mode_IN_FLOATING = (GPIO_PuPd_NOPULL << 2) | GPIO_Mode_IN,
Mode_IPD = (GPIO_PuPd_DOWN << 2) | GPIO_Mode_IN,
Mode_IPU = (GPIO_PuPd_UP << 2) | GPIO_Mode_IN,
Mode_Out_OD = (GPIO_OType_OD << 4) | GPIO_Mode_OUT,
Mode_Out_PP = (GPIO_OType_PP << 4) | GPIO_Mode_OUT,
Mode_AF_OD = (GPIO_OType_OD << 4) | GPIO_Mode_AF,
Mode_AF_PP = (GPIO_OType_PP << 4) | GPIO_Mode_AF
} GPIO_Mode;
*/
//#define GPIO_Speed_10MHz GPIO_Speed_Level_1 Fast Speed:10MHz
//#define GPIO_Speed_2MHz GPIO_Speed_Level_2 Medium Speed:2MHz

View file

@ -59,9 +59,9 @@ typedef struct {
// for input only
uint8_t channel;
uint8_t state;
uint16_t rise;
uint16_t fall;
uint16_t capture;
captureCompare_t rise;
captureCompare_t fall;
captureCompare_t capture;
} pwmPortData_t;
enum {
@ -261,11 +261,12 @@ static pwmPortData_t *pwmInConfig(uint8_t port, timerCCCallbackPtr callback, uin
return p;
}
static void ppmCallback(uint8_t port, uint16_t capture)
static void ppmCallback(uint8_t port, captureCompare_t capture)
{
uint16_t diff;
static uint16_t now;
static uint16_t last = 0;
captureCompare_t diff;
static captureCompare_t now;
static captureCompare_t last = 0;
static uint8_t chan = 0;
static uint8_t GoodPulses;
@ -290,7 +291,7 @@ static void ppmCallback(uint8_t port, uint16_t capture)
}
}
static void pwmCallback(uint8_t port, uint16_t capture)
static void pwmCallback(uint8_t port, captureCompare_t capture)
{
if (pwmPorts[port].state == 0) {
pwmPorts[port].rise = capture;
@ -380,11 +381,16 @@ void pwmInit(drv_pwm_config_t *init, failsafe_t *initialFailsafe)
mask = TYPE_S;
#endif
#ifdef STM32F303xC
// remap PWM5+6 as servos
if (port == PWM5 || port == PWM6)
mask = TYPE_S;
#endif
// remap PWM 5+6 or 9+10 as servos - softserial pin pairs timer ports that use the same timer
if (init->useSoftSerial) {
if (port == PWM5 || port == PWM6)
mask = TYPE_S;
} else {
if (port == PWM9 || port == PWM10)
mask = TYPE_S;
}
#endif
}
if (init->extraServos && !init->airplane) {
// remap PWM5..8 as servos when used in extended servo mode

View file

@ -32,8 +32,8 @@
softSerial_t softSerialPorts[MAX_SOFTSERIAL_PORTS];
void onSerialTimer(uint8_t portIndex, uint16_t capture);
void onSerialRxPinChange(uint8_t portIndex, uint16_t capture);
void onSerialTimer(uint8_t portIndex, captureCompare_t capture);
void onSerialRxPinChange(uint8_t portIndex, captureCompare_t capture);
void setTxSignal(softSerial_t *softSerial, uint8_t state)
{
@ -335,7 +335,7 @@ void processRxState(softSerial_t *softSerial)
}
}
void onSerialTimer(uint8_t portIndex, uint16_t capture)
void onSerialTimer(uint8_t portIndex, captureCompare_t capture)
{
softSerial_t *softSerial = &(softSerialPorts[portIndex]);
@ -343,7 +343,7 @@ void onSerialTimer(uint8_t portIndex, uint16_t capture)
processRxState(softSerial);
}
void onSerialRxPinChange(uint8_t portIndex, uint16_t capture)
void onSerialRxPinChange(uint8_t portIndex, captureCompare_t capture)
{
softSerial_t *softSerial = &(softSerialPorts[portIndex]);

View file

@ -1,6 +1,8 @@
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "platform.h"
@ -75,48 +77,25 @@ static const TIM_TypeDef *timers[MAX_TIMERS] = {
#endif
// Parallel PWM Inputs
// RX1 TIM1_CH1 PA8
// RX2 TIM16_CH1 PB8
// RX3 TIM17_CH1 PB9
// RX4 TIM8_CH1 PC6
// RX5 TIM8_CH2 PC7
// RX6 TIM8_CH3 PC8
// RX7 TIM15_CH1 PF9
// RX8 TIM15_CH2 PF10
// Servo PWM1 TIM3_CH3 PB0
// Servo PWM2 TIM3_CH4 PB1
// Servo PWM3 TIM3_CH2 PA4
// ESC PWM1 TIM4_CH1 PD12
// ESC PWM2 TIM4_CH2 PD13
// ESC PWM3 TIM4_CH3 PD14
// ESC PWM4 TIM4_CH4 PD15
// ESC PWM5 TIM2_CH2 PA1
// ESC PWM6 TIM2_CH3 PA2
#if defined(STM32F303xC) || defined(STM32F3DISCOVERY)
const timerHardware_t timerHardware[USABLE_TIMER_CHANNEL_COUNT] = {
{ TIM1, GPIOA, Pin_8, TIM_Channel_1, TIM1_CC_IRQn, 1, Mode_AF_PP}, // PWM1
{ TIM16, GPIOB, Pin_8, TIM_Channel_1, TIM1_UP_TIM16_IRQn, 0, Mode_AF_PP}, // PWM2
{ TIM17, GPIOB, Pin_9, TIM_Channel_1, TIM1_TRG_COM_TIM17_IRQn, 0, Mode_AF_PP}, // PWM3
{ TIM8, GPIOC, Pin_6, TIM_Channel_1, TIM8_CC_IRQn, 1, Mode_AF_PP}, // PWM4
{ TIM8, GPIOC, Pin_7, TIM_Channel_2, TIM8_CC_IRQn, 1, Mode_AF_PP}, // PWM5
{ TIM8, GPIOC, Pin_8, TIM_Channel_3, TIM8_CC_IRQn, 1, Mode_AF_PP}, // PWM6
//{ TIM15, GPIOF, Pin_9, TIM_Channel_1, TIM1_BRK_TIM15_IRQn, 0, }, // PWM1 - Potential alternate, untested
//{ TIM15, GPIOF, Pin_10, TIM_Channel_2, TIM1_BRK_TIM15_IRQn, 0, }, // PWM1 - Potential alternate, untested
{ TIM3, GPIOB, Pin_1, TIM_Channel_4, TIM3_IRQn, 0, Mode_AF_PP}, // PWM7
{ TIM3, GPIOA, Pin_4, TIM_Channel_2, TIM3_IRQn, 0, Mode_AF_PP}, // PWM8
{ TIM4, GPIOD, Pin_12, TIM_Channel_1, TIM4_IRQn, 0, Mode_AF_PP}, // PWM9
{ TIM4, GPIOD, Pin_13, TIM_Channel_2, TIM4_IRQn, 0, Mode_AF_PP}, // PWM10
{ TIM4, GPIOD, Pin_14, TIM_Channel_3, TIM4_IRQn, 0, Mode_AF_PP}, // PWM11
{ TIM4, GPIOD, Pin_15, TIM_Channel_4, TIM4_IRQn, 0, Mode_AF_PP}, // PWM12
{ TIM2, GPIOA, Pin_1, TIM_Channel_2, TIM2_IRQn, 0, Mode_AF_PP}, // PWM13
{ TIM2, GPIOA, Pin_2, TIM_Channel_3, TIM2_IRQn, 0, Mode_AF_PP}, // PWM14
{ TIM1, GPIOA, Pin_8, TIM_Channel_1, TIM1_CC_IRQn, 1, Mode_AF_PP_PD}, // PWM1 - PA8
{ TIM16, GPIOB, Pin_8, TIM_Channel_1, TIM1_UP_TIM16_IRQn, 0, Mode_AF_PP_PD}, // PWM2 - PB8
{ TIM17, GPIOB, Pin_9, TIM_Channel_1, TIM1_TRG_COM_TIM17_IRQn, 0, Mode_AF_PP_PD}, // PWM3 - PB9
{ TIM8, GPIOC, Pin_6, TIM_Channel_1, TIM8_CC_IRQn, 1, Mode_AF_PP_PD}, // PWM4 - PC6
{ TIM8, GPIOC, Pin_7, TIM_Channel_2, TIM8_CC_IRQn, 1, Mode_AF_PP_PD}, // PWM5 - PC7
{ TIM8, GPIOC, Pin_8, TIM_Channel_3, TIM8_CC_IRQn, 1, Mode_AF_PP_PD}, // PWM6 - PC8
{ TIM3, GPIOB, Pin_1, TIM_Channel_4, TIM3_IRQn, 0, Mode_AF_PP_PD}, // PWM7 - PB1
{ TIM3, GPIOA, Pin_4, TIM_Channel_2, TIM3_IRQn, 0, Mode_AF_PP_PD}, // PWM8 - PA2
//{ TIM15, GPIOF, Pin_9, TIM_Channel_1, TIM1_BRK_TIM15_IRQn, 0, }, // PWMx - PF9 Potential alternate, untested
//{ TIM15, GPIOF, Pin_10, TIM_Channel_2, TIM1_BRK_TIM15_IRQn, 0, }, // PWMx - PF10 Potential alternate, untested
{ TIM4, GPIOD, Pin_12, TIM_Channel_1, TIM4_IRQn, 0, Mode_AF_PP}, // PWM9 - PD12
{ TIM4, GPIOD, Pin_13, TIM_Channel_2, TIM4_IRQn, 0, Mode_AF_PP}, // PWM10 - PD13
{ TIM4, GPIOD, Pin_14, TIM_Channel_3, TIM4_IRQn, 0, Mode_AF_PP}, // PWM11 - PD14
{ TIM4, GPIOD, Pin_15, TIM_Channel_4, TIM4_IRQn, 0, Mode_AF_PP}, // PWM12 - PD15
{ TIM2, GPIOA, Pin_1, TIM_Channel_2, TIM2_IRQn, 0, Mode_AF_PP}, // PWM13 - PA1
{ TIM2, GPIOA, Pin_2, TIM_Channel_3, TIM2_IRQn, 0, Mode_AF_PP}, // PWM14 - PA2
};
#define MAX_TIMERS 7
@ -127,7 +106,7 @@ static const TIM_TypeDef *timers[MAX_TIMERS] = {
#endif
#define CC_CHANNELS_PER_TIMER 4 // TIM_Channel_1..4
static const uint8_t channels[CC_CHANNELS_PER_TIMER] = {
static const uint16_t channels[CC_CHANNELS_PER_TIMER] = {
TIM_Channel_1, TIM_Channel_2, TIM_Channel_3, TIM_Channel_4
};
@ -149,7 +128,7 @@ static uint8_t lookupTimerIndex(const TIM_TypeDef *tim)
return timerIndex;
}
static uint8_t lookupChannelIndex(const uint8_t channel)
static uint8_t lookupChannelIndex(const uint16_t channel)
{
uint8_t channelIndex = 0;
while (channels[channelIndex] != channel) {
@ -158,11 +137,16 @@ static uint8_t lookupChannelIndex(const uint8_t channel)
return channelIndex;
}
static uint8_t lookupTimerConfigIndex(TIM_TypeDef *tim, const uint16_t channel)
{
return lookupTimerIndex(tim) + (MAX_TIMERS * lookupChannelIndex(channel));
}
void configureTimerChannelCallback(TIM_TypeDef *tim, uint8_t channel, uint8_t reference, timerCCCallbackPtr *callback)
{
assert_param(IS_TIM_CHANNEL(channel));
uint8_t timerConfigIndex = (lookupTimerIndex(tim) * MAX_TIMERS) + lookupChannelIndex(channel);
uint8_t timerConfigIndex = lookupTimerConfigIndex(tim, channel);
if (timerConfigIndex >= MAX_TIMERS * CC_CHANNELS_PER_TIMER) {
return;
@ -232,16 +216,15 @@ void timerConfigure(const timerHardware_t *timerHardwarePtr, uint16_t period, ui
timerNVICConfigure(timerHardwarePtr->irq);
}
timerConfig_t *findTimerConfig(TIM_TypeDef *tim, uint8_t channel)
timerConfig_t *findTimerConfig(TIM_TypeDef *tim, uint16_t channel)
{
uint8_t timerConfigIndex = (lookupTimerIndex(tim) * MAX_TIMERS) + lookupChannelIndex(channel);
uint8_t timerConfigIndex = lookupTimerConfigIndex(tim, channel);
return &(timerConfig[timerConfigIndex]);
}
static void timCCxHandler(TIM_TypeDef *tim)
{
uint16_t capture;
captureCompare_t capture;
timerConfig_t *timerConfig;
uint8_t channelIndex = 0;
@ -300,7 +283,7 @@ void TIM4_IRQHandler(void)
}
#if defined(STM32F303xC) || defined(STM32F3DISCOVERY)
void TIM8_IRQHandler(void)
void TIM8_CC_IRQHandler(void)
{
timCCxHandler(TIM8);
}
@ -322,3 +305,8 @@ void TIM1_TRG_COM_TIM17_IRQHandler(void)
timCCxHandler(TIM17);
}
#endif
void timerInit(void)
{
memset(timerConfig, 0, sizeof (timerConfig));
}

View file

@ -2,7 +2,14 @@
#define USABLE_TIMER_CHANNEL_COUNT 14
typedef void timerCCCallbackPtr(uint8_t port, uint16_t capture);
#ifdef STM32F303xC
typedef uint32_t captureCompare_t;
#endif
#ifdef STM32F10X_MD
typedef uint32_t captureCompare_t;
#endif
typedef void timerCCCallbackPtr(uint8_t port, captureCompare_t capture);
typedef struct {
TIM_TypeDef *tim;

View file

@ -49,6 +49,7 @@ extern uint32_t previousTime;
failsafe_t *failsafe;
void timerInit(void);
void initTelemetry(serialPorts_t *serialPorts);
void serialInit(serialConfig_t *initialSerialConfig);
failsafe_t* failsafeInit(rxConfig_t *intialRxConfig);
@ -97,7 +98,7 @@ int main(void)
else
pwm_params.airplane = false;
pwm_params.useUART = feature(FEATURE_GPS) || feature(FEATURE_SERIALRX); // serial rx support uses UART too
pwm_params.useSoftSerial = feature(FEATURE_SOFTSERIAL);
pwm_params.useSoftSerial = canSoftwareSerialBeUsed();
pwm_params.usePPM = feature(FEATURE_PPM);
pwm_params.enableInput = !feature(FEATURE_SERIALRX); // disable inputs if using spektrum
pwm_params.useServos = isMixerUsingServos();
@ -126,6 +127,7 @@ int main(void)
failsafe = failsafeInit(&masterConfig.rxConfig);
buzzerInit(failsafe);
timerInit();
pwmInit(&pwm_params, failsafe);
rxInit(&masterConfig.rxConfig, failsafe);
@ -171,7 +173,7 @@ int main(void)
serialInit(&masterConfig.serialConfig);
#ifndef FY90Q
if (feature(FEATURE_SOFTSERIAL)) {
if (canSoftwareSerialBeUsed()) {
//mcfg.softserial_baudrate = 19200; // Uncomment to override config value
setupSoftSerialPrimary(masterConfig.serialConfig.softserial_baudrate, masterConfig.serialConfig.softserial_1_inverted);

View file

@ -62,7 +62,7 @@ bool canUseTelemetryWithCurrentConfiguration(void)
void initTelemetry(serialPorts_t *serialPorts)
{
// Force telemetry to uart when softserial disabled
if (!feature(FEATURE_SOFTSERIAL))
if (canSoftwareSerialBeUsed())
telemetryConfig->telemetry_port = TELEMETRY_PORT_UART;
#ifdef FY90Q