detect clock with TIM11 instead of TIM5 (#2989)

* detect clock with TIM11 instead of TIM5

* s

* h7 has a different register name

* s

* rename
This commit is contained in:
Matthew Kennedy 2021-07-19 15:04:59 -07:00 committed by GitHub
parent af73cd4b66
commit a0a5d42eed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 38 additions and 54 deletions

View File

@ -44,8 +44,8 @@ static void sayHello(void) {
#ifdef ENABLE_AUTO_DETECT_HSE
extern float hseFrequencyMhz;
extern uint8_t autoDetectedPllMValue;
efiPrintf(PROTOCOL_HELLO_PREFIX " detected HSE clock %.2f MHz, PLLM = %d", hseFrequencyMhz, autoDetectedPllMValue);
extern uint8_t autoDetectedRoundedMhz;
efiPrintf(PROTOCOL_HELLO_PREFIX " detected HSE clock %.2f MHz PLLM = %d", hseFrequencyMhz, autoDetectedRoundedMhz);
#endif /* ENABLE_AUTO_DETECT_HSE */
#if defined(STM32F4) || defined(STM32F7)

View File

@ -20,41 +20,24 @@
#ifdef ENABLE_AUTO_DETECT_HSE
float hseFrequencyMhz;
uint8_t autoDetectedPllMValue;
static void useHsi() {
// clear SW to use HSI
RCC->CFGR &= ~RCC_CFGR_SW;
}
static void useHse() {
// Switch to HSE clock
RCC->CFGR &= ~RCC_CFGR_SW;
RCC->CFGR |= RCC_CFGR_SW_HSE;
}
static void usePll() {
RCC->CFGR &= ~RCC_CFGR_SW;
RCC->CFGR |= RCC_CFGR_SW_PLL;
while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2));
}
uint8_t autoDetectedRoundedMhz;
static uint32_t getOneCapture() {
// wait for input capture
while ((TIM5->SR & TIM_SR_CC4IF) == 0);
while ((TIM11->SR & TIM_SR_CC1IF) == 0);
// Return captured count
return TIM5->CCR4;
return TIM11->CCR1;
}
static uint32_t getAverageLsiCounts() {
static uint32_t getTimerCounts(size_t count) {
// Burn one count
getOneCapture();
uint32_t firstCapture = getOneCapture();
uint32_t lastCapture;
for (size_t i = 0; i < 20; i++)
for (size_t i = 0; i < count; i++)
{
lastCapture = getOneCapture();
}
@ -67,12 +50,12 @@ static_assert(STM32_SW == RCC_CFGR_SW_PLL);
// These clocks must all be enabled for this to work
static_assert(STM32_HSI_ENABLED);
static_assert(STM32_LSI_ENABLED);
static_assert(STM32_HSE_ENABLED);
static void reprogramPll(uint8_t pllM) {
static void reprogramPll(uint8_t roundedMhz) {
// Switch back to HSI to configure PLL
useHsi();
// clear SW to use HSI
RCC->CFGR &= ~RCC_CFGR_SW;
// Stop the PLL
RCC->CR &= ~RCC_CR_PLLON;
@ -81,7 +64,7 @@ static void reprogramPll(uint8_t pllM) {
RCC->PLLCFGR &= ~(RCC_PLLCFGR_PLLM_Msk | RCC_PLLCFGR_PLLSRC_Msk);
// Stick in the new PLLM value
RCC->PLLCFGR |= (pllM << RCC_PLLCFGR_PLLM_Pos) & RCC_PLLCFGR_PLLM_Msk;
RCC->PLLCFGR |= (roundedMhz << RCC_PLLCFGR_PLLM_Pos) & RCC_PLLCFGR_PLLM_Msk;
// Set PLLSRC to HSE
RCC->PLLCFGR |= RCC_PLLCFGR_PLLSRC_HSE;
@ -90,45 +73,46 @@ static void reprogramPll(uint8_t pllM) {
while (!(RCC->CR & RCC_CR_PLLRDY));
// Switch clock source back to PLL
usePll();
RCC->CFGR &= ~RCC_CFGR_SW;
RCC->CFGR |= RCC_CFGR_SW_PLL;
while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2));
}
// __late_init runs after bss/zero initialziation, but before static constructors and main
extern "C" void __late_init() {
// Turn on timer 5
RCC->APB1ENR |= RCC_APB1ENR_TIM5EN;
// Set RTCPRE to /31 - just set all the bits
RCC->CFGR |= RCC_CFGR_RTCPRE_Msk;
// Remap to connect LSI to input capture channel 4
TIM5->OR = TIM_OR_TI4_RMP_0;
// Turn on timer 11
RCC->APB2ENR |= RCC_APB2ENR_TIM11EN;
// Enable capture on channel 4
TIM5->CCMR2 = TIM_CCMR2_CC4S_0;
TIM5->CCER = TIM_CCER_CC4E;
// Remap to connect HSERTC to TIM11 CH1
#ifdef STM32F4XX
TIM11->OR = TIM_OR_TI1_RMP_1;
#else
// the definition has a different name on F7 for whatever reason
TIM11->OR = TIM11_OR_TI1_RMP_1;
#endif
// Start TIM5
TIM5->CR1 |= TIM_CR1_CEN;
// Enable capture on channel 1
TIM11->CCMR1 = TIM_CCMR1_CC1S_0;
TIM11->CCER = TIM_CCER_CC1E;
// Use HSI
useHsi();
// Start TIM11
TIM11->CR1 |= TIM_CR1_CEN;
// Measure LSI against HSI
auto hsiCounts = getAverageLsiCounts();
// Measure HSE against SYSCLK
auto hseCounts = getTimerCounts(10);
useHse();
// Turn off timer 11 now that we're done with it
RCC->APB2ENR &= ~RCC_APB2ENR_TIM11EN;
// Measure LSI against HSE
auto hseCounts = getAverageLsiCounts();
float hseFrequencyHz = 10 * 31.0f * STM32_SYSCLK / hseCounts;
// Turn off timer 5 now that we're done with it
RCC->APB1ENR &= ~RCC_APB1ENR_TIM5EN;
hseFrequencyMhz = hseFrequencyHz / 1e6;
autoDetectedRoundedMhz = efiRound(hseFrequencyMhz, 1);
// The external clocks's frequency is the ratio of the measured LSI speed, times HSI's speed (16MHz)
constexpr float hsiMhz = STM32_HSICLK * 1e-6;
hseFrequencyMhz = hsiMhz * hseCounts / hsiCounts;
autoDetectedPllMValue = efiRound(hseFrequencyMhz, 1);
reprogramPll(autoDetectedPllMValue);
reprogramPll(autoDetectedRoundedMhz);
}
#endif // defined ENABLE_AUTO_DETECT_HSE