From 564e20975b670d4bee1de525e9a25c33730fd7c2 Mon Sep 17 00:00:00 2001 From: Clyne Sullivan Date: Sat, 23 Jan 2021 09:59:11 -0500 Subject: [PATCH] untested port cleanup; add sclock; up cpu to 480M --- .../os/hal/ports/STM32/STM32H7xx/hal_lld.h | 4 +- cfg/mcuconf.h | 22 ++--- source/adc.cpp | 90 +++++++------------ source/adc.hpp | 23 +---- source/dac.cpp | 31 ++----- source/dac.hpp | 3 - source/main.cpp | 7 +- source/sclock.cpp | 54 +++++++++++ source/sclock.hpp | 36 ++++++++ 9 files changed, 151 insertions(+), 119 deletions(-) create mode 100644 source/sclock.cpp create mode 100644 source/sclock.hpp diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/STM32H7xx/hal_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32H7xx/hal_lld.h index b1b9a42..af36372 100644 --- a/ChibiOS_20.3.2/os/hal/ports/STM32/STM32H7xx/hal_lld.h +++ b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32H7xx/hal_lld.h @@ -1821,8 +1821,8 @@ /** * @brief PLL1 DIVP field. */ -#if ((STM32_PLL1_DIVP_VALUE >= 2) && (STM32_PLL1_DIVP_VALUE <= 128) && \ - ((STM32_PLL1_DIVP_VALUE & 1U) == 0U)) || \ +#if ((STM32_PLL1_DIVP_VALUE >= 1) && (STM32_PLL1_DIVP_VALUE <= 128) && \ + ((STM32_PLL1_DIVP_VALUE & 1U) == 0U || STM32_PLL1_DIVP_VALUE == 1)) || \ defined(__DOXYGEN__) #define STM32_PLL1_DIVP ((STM32_PLL1_DIVP_VALUE - 1U) << 9U) #else diff --git a/cfg/mcuconf.h b/cfg/mcuconf.h index 98da3a7..af176ad 100644 --- a/cfg/mcuconf.h +++ b/cfg/mcuconf.h @@ -71,7 +71,7 @@ #define STM32_HSI48_ENABLED TRUE #define STM32_HSE_ENABLED FALSE #define STM32_LSE_ENABLED FALSE -#define STM32_HSIDIV STM32_HSIDIV_DIV8 // 8 +#define STM32_HSIDIV STM32_HSIDIV_DIV8 // HSI = 8MHz /* * PLLs static settings. @@ -83,20 +83,20 @@ #define STM32_PLL1_P_ENABLED TRUE #define STM32_PLL1_Q_ENABLED FALSE #define STM32_PLL1_R_ENABLED FALSE -#define STM32_PLL1_DIVM_VALUE 4 // 2 -#define STM32_PLL1_DIVN_VALUE 384 // 2(384) +#define STM32_PLL1_DIVM_VALUE 4 // 8 / 4 = 2MHz +#define STM32_PLL1_DIVN_VALUE 240 // = 2 * 240 #define STM32_PLL1_FRACN_VALUE 0 -#define STM32_PLL1_DIVP_VALUE 2 // 384 +#define STM32_PLL1_DIVP_VALUE 1 // = 480MHz #define STM32_PLL1_DIVQ_VALUE 16 #define STM32_PLL1_DIVR_VALUE 8 -#define STM32_PLL2_ENABLED TRUE +#define STM32_PLL2_ENABLED TRUE // PLL2 adjusted by adc.cpp #define STM32_PLL2_P_ENABLED TRUE #define STM32_PLL2_Q_ENABLED FALSE #define STM32_PLL2_R_ENABLED FALSE #define STM32_PLL2_DIVM_VALUE 4 -#define STM32_PLL2_DIVN_VALUE 384 +#define STM32_PLL2_DIVN_VALUE 80 #define STM32_PLL2_FRACN_VALUE 0 -#define STM32_PLL2_DIVP_VALUE 32 +#define STM32_PLL2_DIVP_VALUE 20 #define STM32_PLL2_DIVQ_VALUE 8 #define STM32_PLL2_DIVR_VALUE 8 #define STM32_PLL3_ENABLED FALSE @@ -117,9 +117,9 @@ #define STM32_SW STM32_SW_PLL1_P_CK #define STM32_RTCSEL STM32_RTCSEL_LSI_CK #define STM32_D1CPRE STM32_D1CPRE_DIV1 -#define STM32_D1HPRE STM32_D1HPRE_DIV2 +#define STM32_D1HPRE STM32_D1HPRE_DIV2 // /2 = 240MHz #define STM32_D1PPRE3 STM32_D1PPRE3_DIV2 -#define STM32_D2PPRE1 STM32_D2PPRE1_DIV2 // 192 +#define STM32_D2PPRE1 STM32_D2PPRE1_DIV2 #define STM32_D2PPRE2 STM32_D2PPRE2_DIV2 #define STM32_D3PPRE4 STM32_D3PPRE4_DIV2 @@ -231,7 +231,7 @@ #define STM32_ADC_ADC3_IRQ_PRIORITY 5 #define STM32_ADC_ADC12_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV4 #define STM32_ADC_ADC3_CLOCK_MODE ADC_CCR_CKMODE_ADCCK -#define STM32_ADC_ADC3_PRESC (5 << ADC_CCR_PRESC_Pos) // div10 +#define STM32_ADC_ADC3_PRESC (5 << ADC_CCR_PRESC_Pos) // /10 /* * CAN driver system settings. @@ -244,7 +244,7 @@ */ #define STM32_DAC_DUAL_MODE FALSE #define STM32_DAC_USE_DAC1_CH1 TRUE -#define STM32_DAC_USE_DAC1_CH2 FALSE +#define STM32_DAC_USE_DAC1_CH2 TRUE #define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 #define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 #define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 diff --git a/source/adc.cpp b/source/adc.cpp index a830017..ab06410 100644 --- a/source/adc.cpp +++ b/source/adc.cpp @@ -12,20 +12,19 @@ #include "adc.hpp" ADCDriver *ADC::m_driver = &ADCD3; -GPTDriver *ADC::m_timer = &GPTD6; const ADCConfig ADC::m_config = { .difsel = 0, .calibration = 0, }; -ADCConversionGroup ADC::m_group_config = { +const ADCConversionGroup ADC::m_group_config = { .circular = true, .num_channels = 1, .end_cb = ADC::conversionCallback, .error_cb = nullptr, .cfgr = ADC_CFGR_EXTEN_RISING | ADC_CFGR_EXTSEL_SRC(13), /* TIM6_TRGO */ - .cfgr2 = 0,//ADC_CFGR2_ROVSE | ADC_CFGR2_OVSR_0 | ADC_CFGR2_OVSS_1, // Oversampling 2x + .cfgr2 = ADC_CFGR2_ROVSE | ADC_CFGR2_OVSR_0 | ADC_CFGR2_OVSS_1, // Oversampling 2x .ccr = 0, .pcsel = 0, .ltr1 = 0, .htr1 = 0x0FFF, @@ -40,38 +39,28 @@ ADCConversionGroup ADC::m_group_config = { }, }; -const GPTConfig ADC::m_timer_config = { - .frequency = 4800000, - .callback = nullptr, - .cr2 = TIM_CR2_MMS_1, /* TRGO */ - .dier = 0 -}; - -std::array, 6> ADC::m_rate_presets = {{ - // Rate PLLSAI2N R OVERSAMPLE 2x? GPT_DIV - {/* 8k */ 16, 3, 1, 4500}, - {/* 16k */ 32, 3, 1, 2250}, - {/* 20k */ 40, 3, 1, 1800}, - {/* 32k */ 64, 3, 1, 1125}, - {/* 48k */ 24, 3, 0, 750}, - {/* 96k */ 48, 3, 0, 375} +std::array, 6> ADC::m_rate_presets = {{ + // Rate PLL N PLL P + {/* 8k */ 80, 20}, + {/* 16k */ 80, 10}, + {/* 20k */ 80, 8}, + {/* 32k */ 80, 5}, + {/* 48k */ 96, 4}, + {/* 96k */ 96, 2} }}; adcsample_t *ADC::m_current_buffer = nullptr; size_t ADC::m_current_buffer_size = 0; ADC::Operation ADC::m_operation = nullptr; -unsigned int ADC::m_timer_divisor = 50; - void ADC::begin() { palSetPadMode(GPIOF, 3, PAL_MODE_INPUT_ANALOG); adcStart(m_driver, &m_config); adcSTM32EnableVREF(m_driver); - gptStart(m_timer, &m_timer_config); - //setRate(Rate::R32K); + setRate(SClock::Rate::R32K); } void ADC::start(adcsample_t *buffer, size_t count, Operation operation) @@ -81,12 +70,12 @@ void ADC::start(adcsample_t *buffer, size_t count, Operation operation) m_operation = operation; adcStartConversion(m_driver, &m_group_config, buffer, count); - gptStartContinuous(m_timer, m_timer_divisor); + SClock::start(); } void ADC::stop() { - gptStopTimer(m_timer); + SClock::stop(); adcStopConversion(m_driver); m_current_buffer = nullptr; @@ -94,27 +83,25 @@ void ADC::stop() m_operation = nullptr; } -void ADC::setRate(ADC::Rate rate) +void ADC::setRate(SClock::Rate rate) { -// auto& preset = m_rate_presets[static_cast(rate)]; -// auto pllnr = (preset[0] << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) | -// (preset[1] << RCC_PLLSAI2CFGR_PLLSAI2R_Pos); -// bool oversample = preset[2] != 0; -// m_timer_divisor = preset[3]; - -// adcStop(m_driver); -// -// // Adjust PLLSAI2 -// RCC->CR &= ~(RCC_CR_PLLSAI2ON); -// while ((RCC->CR & RCC_CR_PLLSAI2RDY) == RCC_CR_PLLSAI2RDY); -// RCC->PLLSAI2CFGR = (RCC->PLLSAI2CFGR & ~(RCC_PLLSAI2CFGR_PLLSAI2N_Msk | RCC_PLLSAI2CFGR_PLLSAI2R_Msk)) | pllnr; -// RCC->CR |= RCC_CR_PLLSAI2ON; -// while ((RCC->CR & RCC_CR_PLLSAI2RDY) != RCC_CR_PLLSAI2RDY); -// -// // Set 2x oversampling -// m_group_config.cfgr2 = oversample ? ADC_CFGR2_ROVSE | ADC_CFGR2_OVSR_0 | ADC_CFGR2_OVSS_1 : 0; -// -// adcStart(m_driver, &m_config); + auto& preset = m_rate_presets[static_cast(rate)]; + auto pllbits = (preset[0] << RCC_PLL2DIVR_N2_Pos) | + (preset[1] << RCC_PLL2DIVR_P2_Pos); + + adcStop(m_driver); + + // Adjust PLL2 + RCC->CR &= ~(RCC_CR_PLL2ON); + while ((RCC->CR & RCC_CR_PLL2RDY) == RCC_CR_PLL2RDY); + auto pll2divr = RCC->PLL2DIVR & + ~(RCC_PLL2DIVR_N2_Msk | RCC_PLL2DIVR_P2_Msk); + pll2divr |= pllbits; + RCC->PLL2DIVR = pll2divr; + RCC->CR |= RCC_CR_PLL2ON; + while ((RCC->CR & RCC_CR_PLL2RDY) != RCC_CR_PLL2RDY); + + adcStart(m_driver, &m_config); } void ADC::setOperation(ADC::Operation operation) @@ -122,21 +109,6 @@ void ADC::setOperation(ADC::Operation operation) m_operation = operation; } -int ADC::getRate() -{ - for (unsigned int i = 0; i < m_rate_presets.size(); i++) { - if (m_timer_divisor == m_rate_presets[i][3]) - return i; - } - - return -1; -} - -unsigned int ADC::getTimerDivisor() -{ - return m_timer_divisor; -} - void ADC::conversionCallback(ADCDriver *driver) { if (m_operation != nullptr) { diff --git a/source/adc.hpp b/source/adc.hpp index 5f9dc23..96fe506 100644 --- a/source/adc.hpp +++ b/source/adc.hpp @@ -13,6 +13,7 @@ #define STMDSP_ADC_HPP_ #include "hal.h" +#include "sclock.hpp" #include @@ -21,42 +22,26 @@ class ADC public: using Operation = void (*)(adcsample_t *buffer, size_t count); - enum class Rate : int { - R8K = 0, - R16K, - R20K, - R32K, - R48K, - R96K - }; - static void begin(); static void start(adcsample_t *buffer, size_t count, Operation operation); static void stop(); - static void setRate(Rate rate); + static void setRate(SClock::Rate rate); static void setOperation(Operation operation); - static int getRate(); - static unsigned int getTimerDivisor(); - private: static ADCDriver *m_driver; - static GPTDriver *m_timer; static const ADCConfig m_config; - static /*const*/ ADCConversionGroup m_group_config; - static const GPTConfig m_timer_config; + static const ADCConversionGroup m_group_config; - static std::array, 6> m_rate_presets; + static std::array, 6> m_rate_presets; static adcsample_t *m_current_buffer; static size_t m_current_buffer_size; static Operation m_operation; - static unsigned int m_timer_divisor; - static void conversionCallback(ADCDriver *); }; diff --git a/source/dac.cpp b/source/dac.cpp index 283d8a9..2116dcb 100644 --- a/source/dac.cpp +++ b/source/dac.cpp @@ -9,14 +9,12 @@ * If not, see . */ -#include "adc.hpp" // ADC::getTimerDivisor #include "dac.hpp" +#include "sclock.hpp" DACDriver *DAC::m_driver[2] = { - &DACD1, nullptr/*&DACD2*/ + &DACD1, &DACD2 }; -GPTDriver *DAC::m_timer = nullptr;//&GPTD7; -int DAC::m_timer_user_count = 0; const DACConfig DAC::m_config = { .init = 0, @@ -28,14 +26,7 @@ const DACConversionGroup DAC::m_group_config = { .num_channels = 1, .end_cb = nullptr, .error_cb = nullptr, - .trigger = 5 -}; - -const GPTConfig DAC::m_timer_config = { - .frequency = 4800000, - .callback = nullptr, - .cr2 = TIM_CR2_MMS_1, /* TRGO */ - .dier = 0 + .trigger = 5 // TIM6_TRGO }; void DAC::begin() @@ -44,28 +35,22 @@ void DAC::begin() palSetPadMode(GPIOA, 5, PAL_MODE_INPUT_ANALOG); dacStart(m_driver[0], &m_config); - //dacStart(m_driver[1], &m_config); - //gptStart(m_timer, &m_timer_config); + dacStart(m_driver[1], &m_config); } void DAC::start(int channel, dacsample_t *buffer, size_t count) { - if (channel >= 0 && channel < 1) { + if (channel >= 0 && channel < 2) { dacStartConversion(m_driver[channel], &m_group_config, buffer, count); - - //if (m_timer_user_count == 0) - // gptStartContinuous(m_timer, ADC::getTimerDivisor()); - //m_timer_user_count++; + SClock::start(); } } void DAC::stop(int channel) { - if (channel >= 0 && channel < 1) { + if (channel >= 0 && channel < 2) { dacStopConversion(m_driver[channel]); - - //if (--m_timer_user_count == 0) - // gptStopTimer(m_timer); + SClock::stop(); } } diff --git a/source/dac.hpp b/source/dac.hpp index 542b4a1..e305c4b 100644 --- a/source/dac.hpp +++ b/source/dac.hpp @@ -25,12 +25,9 @@ public: private: static DACDriver *m_driver[2]; - static GPTDriver *m_timer; - static int m_timer_user_count; static const DACConfig m_config; static const DACConversionGroup m_group_config; - static const GPTConfig m_timer_config; }; #endif // STMDSP_DAC_HPP_ diff --git a/source/main.cpp b/source/main.cpp index 639f455..bb980d0 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -21,6 +21,7 @@ static_assert(sizeof(dacsample_t) == sizeof(uint16_t)); #include "adc.hpp" #include "dac.hpp" #include "elf_load.hpp" +#include "sclock.hpp" #include "usbserial.hpp" #include @@ -206,10 +207,12 @@ void main_loop() case 'r': if (EM.assert(USBSerial::read(&cmd[1], 1) == 1, Error::BadParamSize)) { if (cmd[1] == 0xFF) { - unsigned char r = static_cast(ADC::getRate()); + unsigned char r = SClock::getRate(); USBSerial::write(&r, 1); } else { - ADC::setRate(static_cast(cmd[1])); + auto r = static_cast(cmd[1]); + SClock::setRate(r); + ADC::setRate(r); } } break; diff --git a/source/sclock.cpp b/source/sclock.cpp new file mode 100644 index 0000000..795274d --- /dev/null +++ b/source/sclock.cpp @@ -0,0 +1,54 @@ +#include "sclock.hpp" + +GPTDriver *SClock::m_timer = &GPTD6; +unsigned int SClock::m_div = 1; +unsigned int SClock::m_runcount = 0; + +const GPTConfig SClock::m_timer_config = { + .frequency = 4800000, + .callback = nullptr, + .cr2 = TIM_CR2_MMS_1, /* TRGO */ + .dier = 0 +}; + +const std::array SClock::m_rate_divs = {{ + /* 8k */ 600, + /* 16k */ 300, + /* 20k */ 240, + /* 32k */ 150, + /* 48k */ 100, + /* 96k */ 50 +}}; + +void SClock::begin() +{ + gptStart(m_timer, &m_timer_config); +} + +void SClock::start() +{ + if (m_runcount++ == 0) + gptStartContinuous(m_timer, m_div); +} + +void SClock::stop() +{ + if (--m_runcount == 0) + gptStopTimer(m_timer); +} + +void SClock::setRate(SClock::Rate rate) +{ + m_div = m_rate_divs[static_cast(rate)]; +} + +unsigned int SClock::getRate() +{ + for (unsigned int i = 0; i < m_rate_divs.size(); ++i) { + if (m_rate_divs[i] == m_div) + return i; + } + + return static_cast(-1); +} + diff --git a/source/sclock.hpp b/source/sclock.hpp new file mode 100644 index 0000000..960d9e3 --- /dev/null +++ b/source/sclock.hpp @@ -0,0 +1,36 @@ +#ifndef SCLOCK_HPP_ +#define SCLOCK_HPP_ + +#include "hal.h" + +#include + +class SClock +{ +public: + enum class Rate : unsigned int { + R8K = 0, + R16K, + R20K, + R32K, + R48K, + R96K + }; + + static void begin(); + static void start(); + static void stop(); + + static void setRate(Rate rate); + static unsigned int getRate(); + +private: + static GPTDriver *m_timer; + static unsigned int m_div; + static unsigned int m_runcount; + static const GPTConfig m_timer_config; + static const std::array m_rate_divs; +}; + +#endif // SCLOCK_HPP_ +