From c36d8848992ef1eda659ec23918e49e5e36ec595 Mon Sep 17 00:00:00 2001 From: Dominic Clifton Date: Thu, 3 Apr 2014 12:40:17 +0100 Subject: [PATCH] Change softserial timer calculation code to support baud rates in the range 600 to 19200 (tested) --- src/cli.c | 2 +- src/drv_softserial.c | 26 +++++++++++++++++++++----- src/drv_timer.c | 11 ++++++++--- src/drv_timer.h | 4 ++-- 4 files changed, 32 insertions(+), 11 deletions(-) diff --git a/src/cli.c b/src/cli.c index 94bda8a425..7b70d90280 100644 --- a/src/cli.c +++ b/src/cli.c @@ -126,7 +126,7 @@ const clivalue_t valueTable[] = { { "flaps_speed", VAR_UINT8, &mcfg.flaps_speed, 0, 100 }, { "fixedwing_althold_dir", VAR_INT8, &mcfg.fixedwing_althold_dir, -1, 1 }, { "serial_baudrate", VAR_UINT32, &mcfg.serial_baudrate, 1200, 115200 }, - { "softserial_baudrate", VAR_UINT32, &mcfg.softserial_baudrate, 9600, 19200 }, + { "softserial_baudrate", VAR_UINT32, &mcfg.softserial_baudrate, 600, 19200 }, { "softserial_inverted", VAR_UINT8, &mcfg.softserial_inverted, 0, 1 }, { "gps_type", VAR_UINT8, &mcfg.gps_type, 0, 3 }, { "gps_baudrate", VAR_INT8, &mcfg.gps_baudrate, -1, 4 }, diff --git a/src/drv_softserial.c b/src/drv_softserial.c index 2cae1f2817..cec19ee6e2 100644 --- a/src/drv_softserial.c +++ b/src/drv_softserial.c @@ -1,8 +1,5 @@ #include "board.h" -// There needs to be a table of timerMhz per baud rate so the system can set the timer correctly. -// See http://www.wormfood.net/avrbaudcalc.php?postbitrate=19200&postclock=72 -// Currently defaulting to 3Mhz to support 19200. #define SOFT_SERIAL_TIMER_MHZ 3 #define SOFT_SERIAL_1_TIMER_RX_HARDWARE 4 #define SOFT_SERIAL_1_TIMER_TX_HARDWARE 5 @@ -74,10 +71,29 @@ void serialInputPortConfig(const timerHardware_t *timerHardwarePtr) #define TICKS_PER_BIT 3 +bool isTimerPeriodTooLarge(uint32_t timerPeriod) +{ + return timerPeriod > 0xFFFF; +} + void serialTimerConfig(const timerHardware_t *timerHardwarePtr, uint32_t baud, uint8_t reference, timerCCCallbackPtr callback) { - uint16_t timerPeriod = (SOFT_SERIAL_TIMER_MHZ * 1000000) / (baud * TICKS_PER_BIT); - timerInConfig(timerHardwarePtr, timerPeriod, SOFT_SERIAL_TIMER_MHZ); + uint32_t clock = SystemCoreClock; + uint32_t timerPeriod; + do { + timerPeriod = clock / (baud * TICKS_PER_BIT); + if (isTimerPeriodTooLarge(timerPeriod)) { + if (clock > 1) { + clock = clock / 2; + } else { + // TODO unable to continue, unable to determine clock and timerPeriods for the given baud + } + + } + } while (isTimerPeriodTooLarge(timerPeriod)); + + uint8_t mhz = SystemCoreClock / 1000000; + timerInConfig(timerHardwarePtr, timerPeriod, mhz); configureTimerCaptureCompareInterrupt(timerHardwarePtr, reference, callback); } diff --git a/src/drv_timer.c b/src/drv_timer.c index 0619b0baaf..2c2a884880 100644 --- a/src/drv_timer.c +++ b/src/drv_timer.c @@ -145,19 +145,24 @@ void timerNVICConfig(uint8_t irq) NVIC_Init(&NVIC_InitStructure); } -void configTimeBase(TIM_TypeDef *tim, uint32_t period, uint8_t mhz) +void configTimeBase(TIM_TypeDef *tim, uint16_t period, uint8_t mhz) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); - TIM_TimeBaseStructure.TIM_Period = period - 1; + TIM_TimeBaseStructure.TIM_Period = period - 1; // AKA TIMx_ARR + + // "The counter clock frequency (CK_CNT) is equal to f CK_PSC / (PSC[15:0] + 1)." - STM32F10x Reference Manual 14.4.11 + // Thus for 1Mhz: 72000000 / 1000000 = 72, 72 - 1 = 71 = TIM_Prescaler TIM_TimeBaseStructure.TIM_Prescaler = (SystemCoreClock / ((uint32_t)mhz * 1000000)) - 1; + + TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(tim, &TIM_TimeBaseStructure); } -void timerInConfig(const timerHardware_t *timerHardwarePtr, uint32_t period, uint8_t mhz) +void timerInConfig(const timerHardware_t *timerHardwarePtr, uint16_t period, uint8_t mhz) { configTimeBase(timerHardwarePtr->tim, period, mhz); TIM_Cmd(timerHardwarePtr->tim, ENABLE); diff --git a/src/drv_timer.h b/src/drv_timer.h index ab99059aa3..cae2e20a02 100644 --- a/src/drv_timer.h +++ b/src/drv_timer.h @@ -13,8 +13,8 @@ typedef struct { extern const timerHardware_t timerHardware[]; -void configTimeBase(TIM_TypeDef *tim, uint32_t period, uint8_t mhz); -void timerInConfig(const timerHardware_t *timerHardwarePtr, uint32_t period, uint8_t mhz); +void configTimeBase(TIM_TypeDef *tim, uint16_t period, uint8_t mhz); +void timerInConfig(const timerHardware_t *timerHardwarePtr, uint16_t period, uint8_t mhz); void timerNVICConfig(uint8_t irq); void configureTimerInputCaptureCompareChannel(TIM_TypeDef *tim, const uint8_t channel);