[ion] LED: start fixing the blinking frequency

This commit is contained in:
Émilie Feral
2019-04-10 10:24:59 +02:00
parent 198b5c486d
commit fefa5beac4
5 changed files with 36 additions and 23 deletions

View File

@@ -27,18 +27,23 @@ constexpr static int PLL_N = 192;
constexpr static Regs::RCC::PLLCFGR::PLLP PLL_P_Reg = Regs::RCC::PLLCFGR::PLLP::PLLP2;
constexpr static int PLL_P = ((int)PLL_P_Reg | 1) << 1;
constexpr static int SYSCLKFrequency = ((HSE/PLL_M)*PLL_N)/PLL_P;
constexpr static int AHB_prescaler = 1;
constexpr static int HCLKFrequency = SYSCLKFrequency/AHB_prescaler;
constexpr static int AHBFrequency = HCLKFrequency;
constexpr static Regs::RCC::CFGR::APBPrescaler APB1PrescalerRegs = Regs::RCC::CFGR::APBPrescaler::AHBDividedBy2;
constexpr static int APB1Prescaler = 2;
constexpr static int APB1Frequency = HCLKFrequency/APB1Prescaler;
constexpr static int APB1TimerFrequency = 2*APB1Frequency;
constexpr static int AHBPrescaler = 1;
/* To slow down the whole system, we prescale the AHB clock.
* We could divide the system clock by 512. However, the HCLK clock
* frequency must be >= 14.2MHz and <=216 MHz which forces the
* AHBPrescaler to be below 96MHz/14.2MHz~6.7. */
constexpr static Regs::RCC::CFGR::AHBPrescaler AHBLowFrequencyPrescaler = Regs::RCC::CFGR::AHBPrescaler::SysClkDividedBy4;
constexpr static Regs::RCC::CFGR::AHBPrescaler AHBLowFrequencyPrescalerReg = Regs::RCC::CFGR::AHBPrescaler::SysClkDividedBy4;
constexpr static int AHBLowFrequencyPrescaler = 4;
constexpr static int HCLKFrequency = SYSCLKFrequency/AHBPrescaler;
constexpr static int HCLKLowFrequency = SYSCLKFrequency/AHBLowFrequencyPrescaler;
constexpr static int AHBFrequency = HCLKFrequency;
//constexpr static int AHBLowFrequency = HCLKLowFrequency;
constexpr static Regs::RCC::CFGR::APBPrescaler APB1PrescalerRegs = Regs::RCC::CFGR::APBPrescaler::AHBDividedBy2;
constexpr static int APB1Prescaler = 2;
//constexpr static int APB1Frequency = HCLKFrequency/APB1Prescaler;
constexpr static int APB1LowFrequency = HCLKLowFrequency/APB1Prescaler;
//constexpr static int APB1TimerFrequency = 2*APB1Frequency;
constexpr static int APB1TimerLowFrequency = 2*APB1LowFrequency;
}
}

View File

@@ -176,9 +176,9 @@ void initClocks() {
FLASH.ACR()->setARTEN(true);
// 192 MHz is too fast for APB1. Divide it by four to reach 48 MHz
RCC.CFGR()->setPPRE1(RCC::CFGR::APBPrescaler::AHBDividedBy4);
RCC.CFGR()->setPPRE1(Clocks::Config::APB1PrescalerReg);
// 192 MHz is too fast for APB2. Divide it by two to reach 96 MHz
RCC.CFGR()->setPPRE2(RCC::CFGR::APBPrescaler::AHBDividedBy2);
RCC.CFGR()->setPPRE2(Clocks::Config::APB2PrescalerReg);
while(!RCC.CR()->getPLLRDY()) {
}

View File

@@ -28,18 +28,24 @@ constexpr static int PLL_P = ((int)PLL_P_Reg | 1) << 1;
constexpr static int PLL_Q = 8;
constexpr static int SYSCLKFrequency = ((HSE/PLL_M)*PLL_N)/PLL_P;
constexpr static int AHBPrescaler = 1;
constexpr static int HCLKFrequency = SYSCLKFrequency/AHBPrescaler;
constexpr static int AHBFrequency = HCLKFrequency;
constexpr static int APB1Prescaler = 4;
constexpr static int APB1Frequency = HCLKFrequency/APB1Prescaler;
constexpr static int APB1TimerFrequency = 2*APB1Frequency;
/* To slow down the whole system, we prescale the AHB clock.
* We could divide the system clock by 512. However, the HCLK clock
* frequency must be >= 14.2MHz and <=216 MHz which forces the
* AHBPrescaler to be below 192MHz/14.2MHz~13.5. */
constexpr static Regs::RCC::CFGR::AHBPrescaler AHBLowFrequencyPrescaler = Regs::RCC::CFGR::AHBPrescaler::SysClkDividedBy8;
constexpr static Regs::RCC::CFGR::AHBPrescaler AHBLowFrequencyPrescalerReg = Regs::RCC::CFGR::AHBPrescaler::SysClkDividedBy8;
constexpr static int AHBLowFrequencyPrescaler = 8;
constexpr static int HCLKFrequency = SYSCLKFrequency/AHBPrescaler;
constexpr static int HCLKLowFrequency = SYSCLKFrequency/AHBLowFrequencyPrescaler;
constexpr static int AHBFrequency = HCLKFrequency;
//constexpr static int AHBLowFrequency = HCLKLowFrequency;
constexpr static Regs::RCC::CFGR::APBPrescaler APB1PrescalerReg = Regs::RCC::CFGR::APBPrescaler::AHBDividedBy4;
constexpr static int APB1Prescaler = 4;
//constexpr static int APB1Frequency = HCLKFrequency/APB1Prescaler;
constexpr static int APB1LowFrequency = HCLKLowFrequency/APB1Prescaler;
//constexpr static int APB1TimerFrequency = 2*APB1Frequency;
constexpr static int APB1TimerLowFrequency = 2*APB1LowFrequency;
constexpr static Regs::RCC::CFGR::APBPrescaler APB2PrescalerReg = Regs::RCC::CFGR::APBPrescaler::AHBDividedBy2;
}
}
}

View File

@@ -61,13 +61,14 @@ void shutdownPeripherals(bool keepLEDAwake) {
}
void setClockFrequency(Frequency f) {
// TODO: Update TIM3 prescaler or ARR to avoid irregular LED blinking
switch (f) {
case Frequency::High:
RCC.CFGR()->setHPRE(RCC::CFGR::AHBPrescaler::SysClk);
return;
default:
assert(f == Frequency::Low);
RCC.CFGR()->setHPRE(Clocks::Config::AHBLowFrequencyPrescaler);
RCC.CFGR()->setHPRE(Clocks::Config::AHBLowFrequencyPrescalerReg);
return;
}
}

View File

@@ -1,6 +1,7 @@
#include "led.h"
#include <ion/led.h>
#include <drivers/config/led.h>
#include <drivers/config/clocks.h>
static KDColor sLedColor = KDColorBlack;
@@ -113,15 +114,15 @@ void setPeriodAndDutyCycles(Mode mode, float dutyCycleRed, float dutyCycleGreen,
period = PWMPeriod;
break;
case Mode::Blink:
int systemClockFreq = 96;
/* We still want to do PWM, but at a rate slow enough to blink. Ideally,
* we want to pre-scale the period to be able to set it in milliseconds;
* however, as the prescaler is cap by 2^16-1, we divide it by a factor
* and correct the period consequently. */
int factor = 2;
// TODO: explain the 2 ?
TIM3.PSC()->set(systemClockFreq*1000/factor);
period *= factor;
int prescalerFactor = 4;
/* Most of the time AP1TimerFrequency is the 'low' one as most of the time
* is spent in Timing::msleep. */
TIM3.PSC()->set(Clocks::Config::APB1TimerLowFrequency*1000/prescalerFactor-1);
period *= prescalerFactor;
TIM3.ARR()->set(period);
break;
}