From c4e96272e270bfbec0ff91bcd4ffc1e638c165b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Ebeling?= Date: Sun, 22 Sep 2024 14:06:14 +0200 Subject: [PATCH 1/2] [stm32] Enable and port HAL for STM32C0 family --- .github/workflows/compile-all.yml | 26 +++++++++ README.md | 28 +++++++-- ext/modm-devices | 2 +- ext/st/module.lb | 2 +- ext/st/stm32 | 2 +- repo.lb | 3 +- src/modm/platform/adc/stm32f0/adc.hpp.in | 21 ++++--- src/modm/platform/adc/stm32f0/adc_impl.hpp.in | 31 +++++----- src/modm/platform/adc/stm32f0/module.lb | 8 ++- src/modm/platform/clock/stm32/module.lb | 12 ++-- src/modm/platform/clock/stm32/rcc.cpp.in | 4 +- src/modm/platform/clock/stm32/rcc.hpp.in | 57 ++++++++++++++++--- src/modm/platform/clock/stm32/rcc_impl.hpp.in | 2 +- src/modm/platform/core/stm32/module.lb | 1 + .../platform/core/stm32/startup_platform.c.in | 2 +- src/modm/platform/dma/stm32/dma.hpp.in | 2 +- src/modm/platform/dma/stm32/module.lb | 6 +- src/modm/platform/extint/stm32/module.lb | 4 +- src/modm/platform/gpio/stm32/enable.cpp.in | 2 +- src/modm/platform/gpio/stm32/module.lb | 4 ++ tools/build_script_generator/module.lb | 2 +- 21 files changed, 164 insertions(+), 57 deletions(-) diff --git a/.github/workflows/compile-all.yml b/.github/workflows/compile-all.yml index e4e78ec4b6..b0538e2d97 100644 --- a/.github/workflows/compile-all.yml +++ b/.github/workflows/compile-all.yml @@ -109,6 +109,32 @@ jobs: name: samx7-compile-all path: test/all/log + stm32c0-compile-all: + if: github.event.label.name == 'ci:hal' + runs-on: ubuntu-22.04 + container: + image: ghcr.io/modm-ext/modm-build-cortex-m:2023-03-12 + steps: + - name: Check out repository + uses: actions/checkout@v4 + with: + submodules: 'recursive' + - name: Fix Git permission/ownership problem + run: | + git config --global --add safe.directory /__w/modm/modm + - name: Update lbuild + run: | + pip3 install --upgrade --upgrade-strategy=eager modm + - name: Compile HAL for all STM32C0 + run: | + (cd test/all && python3 run_all.py stm32c0 --quick-remaining) + - name: Upload log artifacts + if: always() + uses: actions/upload-artifact@v4 + with: + name: stm32c0-compile-all + path: test/all/log + stm32f0-compile-all: if: github.event.label.name == 'ci:hal' runs-on: ubuntu-22.04 diff --git a/README.md b/README.md index b3371bed15..e3de674f1f 100644 --- a/README.md +++ b/README.md @@ -82,9 +82,9 @@ git clone --recurse-submodules --jobs 8 https://github.com/modm-io/modm.git ## Microcontrollers -modm can create a HAL for 3779 devices of these vendors: +modm can create a HAL for 3839 devices of these vendors: -- STMicroelectronics STM32: 2974 devices. +- STMicroelectronics STM32: 3034 devices. - Microchip SAM: 416 devices. - Microchip AVR: 388 devices. - Raspberry Pi: 1 device. @@ -104,12 +104,13 @@ Please [discover modm's peripheral drivers for your specific device][discover]. - + + @@ -143,6 +144,7 @@ Please [discover modm's peripheral drivers for your specific device][discover]. + @@ -158,6 +160,7 @@ Please [discover modm's peripheral drivers for your specific device][discover]. + @@ -182,6 +185,7 @@ Please [discover modm's peripheral drivers for your specific device][discover]. + @@ -206,6 +210,7 @@ Please [discover modm's peripheral drivers for your specific device][discover]. + @@ -243,6 +248,7 @@ Please [discover modm's peripheral drivers for your specific device][discover]. + @@ -255,6 +261,7 @@ Please [discover modm's peripheral drivers for your specific device][discover]. + @@ -293,6 +300,7 @@ Please [discover modm's peripheral drivers for your specific device][discover]. + @@ -303,6 +311,7 @@ Please [discover modm's peripheral drivers for your specific device][discover]. + @@ -320,7 +329,7 @@ Please [discover modm's peripheral drivers for your specific device][discover]. - + @@ -348,6 +357,7 @@ Please [discover modm's peripheral drivers for your specific device][discover]. + @@ -364,6 +374,7 @@ Please [discover modm's peripheral drivers for your specific device][discover]. + @@ -375,6 +386,7 @@ Please [discover modm's peripheral drivers for your specific device][discover]. + @@ -412,6 +424,7 @@ Please [discover modm's peripheral drivers for your specific device][discover]. + @@ -424,6 +437,7 @@ Please [discover modm's peripheral drivers for your specific device][discover]. + @@ -459,6 +473,7 @@ Please [discover modm's peripheral drivers for your specific device][discover]. + @@ -489,6 +504,7 @@ Please [discover modm's peripheral drivers for your specific device][discover]. + @@ -508,6 +524,7 @@ Please [discover modm's peripheral drivers for your specific device][discover]. + @@ -539,6 +556,7 @@ Please [discover modm's peripheral drivers for your specific device][discover]. + @@ -556,6 +574,7 @@ Please [discover modm's peripheral drivers for your specific device][discover]. + @@ -572,6 +591,7 @@ Please [discover modm's peripheral drivers for your specific device][discover]. + diff --git a/ext/modm-devices b/ext/modm-devices index 7d5855812d..202131e0a3 160000 --- a/ext/modm-devices +++ b/ext/modm-devices @@ -1 +1 @@ -Subproject commit 7d5855812d5657f1e65335d2f85be3f6820201df +Subproject commit 202131e0a30fdd4a05988c7e9c333e5526b663fc diff --git a/ext/st/module.lb b/ext/st/module.lb index 051355c7df..53cd92b173 100644 --- a/ext/st/module.lb +++ b/ext/st/module.lb @@ -127,7 +127,7 @@ def common_header_file(env): define = None content = Path(localpath(folder, family_header)).read_text(encoding="utf-8", errors="replace") - match = re.findall(r"if defined\((?PSTM32[FGHLU][\w\d]+)\)", content) + match = re.findall(r"if defined\((?PSTM32[CFGHLU][\w\d]+)\)", content) define = getDefineForDevice(device.identifier, match) if define is None or match is None: raise ValidateException("No device define found for '{}'!".format(device.partname)) diff --git a/ext/st/stm32 b/ext/st/stm32 index 27fbc105fe..ec0df54b45 160000 --- a/ext/st/stm32 +++ b/ext/st/stm32 @@ -1 +1 @@ -Subproject commit 27fbc105fe83f5f488b327766393dc6e7cce4abb +Subproject commit ec0df54b45ed2ff28ca84bc50c45e52b3f01daea diff --git a/repo.lb b/repo.lb index ace0a02dcc..95caae6990 100644 --- a/repo.lb +++ b/repo.lb @@ -83,7 +83,8 @@ class DevicesCache(dict): device_file_names += glob.glob(repopath("tools/devices/**/*.xml")) # roughly filter to supported devices - supported = ["stm32f0", "stm32f1", "stm32f2", "stm32f3", "stm32f4", "stm32f7", + supported = ["stm32c0", + "stm32f0", "stm32f1", "stm32f2", "stm32f3", "stm32f4", "stm32f7", "stm32g0", "stm32g4", "stm32h7", "stm32l0", "stm32l1", "stm32l4", "stm32l5", diff --git a/src/modm/platform/adc/stm32f0/adc.hpp.in b/src/modm/platform/adc/stm32f0/adc.hpp.in index c40e837589..dddac75b7f 100644 --- a/src/modm/platform/adc/stm32f0/adc.hpp.in +++ b/src/modm/platform/adc/stm32f0/adc.hpp.in @@ -89,7 +89,7 @@ public: %% endif }; -%% if target.family in ["g0"] +%% if target.family in ["c0", "g0"] enum class SampleTimeGroup { Group1, @@ -229,7 +229,7 @@ public: static inline void setWaitMode(bool enable); -%% if target.family in ["g0"] +%% if target.family in ["c0", "g0"] static inline void enableOversampling(OversampleRatio ratio, OversampleShift shift = OversampleShift::Div1); @@ -299,7 +299,7 @@ public: * initialize() */ static inline bool -%% if target.family in ["g0"] +%% if target.family in ["c0", "g0"] setChannel(Channel channel, SampleTimeGroup group = SampleTimeGroup::Group1); %% else setChannel(Channel channel); @@ -318,7 +318,7 @@ public: static consteval ChannelMask_t channelMaskFromPins(); -%% if target.family in ["g0"] +%% if target.family in ["c0", "g0"] /** * Set channel scan sequence to convert up to 8 channels in arbitrary order. * @@ -342,7 +342,7 @@ public: /// Setting the channel for a Pin template< class Gpio > static inline bool -%% if target.family in ["g0"] +%% if target.family in ["c0", "g0"] setPinChannel(SampleTimeGroup group = SampleTimeGroup::Group1) { return setChannel(getPinChannel(), group); @@ -369,7 +369,7 @@ public: return readChannel(getPinChannel()); } -%% if target.family in ["g0"] +%% if target.family in ["c0", "g0"] static inline void setSampleTime(SampleTime sampleTime, SampleTimeGroup group = SampleTimeGroup::Group1); @@ -429,7 +429,7 @@ public: enableInternalChannel(Channel channel); private: -%% if target.family in ["g0"] +%% if target.family in ["c0", "g0"] static inline void waitChannelConfigReady(); @@ -445,7 +445,12 @@ private: public: static constexpr uint8_t TS_CAL1_TEMP{30}; -%% if target.family in ["f0"] +%% if target.family in ["c0"] + static constexpr uint16_t VDDA_CAL{3000}; + static inline volatile uint16_t *const VREFINT_CAL{(volatile uint16_t *)0x1FFF756A}; + static inline volatile uint16_t *const TS_CAL1{(volatile uint16_t *)0x1FFF7568}; + static constexpr uint16_t TS_AVG_SLOPE{3454}; // Typ. 2.53mV/°C => 2530uV * 4096 / 3000 +%% elif target.family in ["f0"] static constexpr uint16_t VDDA_CAL{3300}; static inline volatile uint16_t *const VREFINT_CAL{(volatile uint16_t *)0x1FFF'F7BA}; static inline volatile uint16_t *const TS_CAL1{(volatile uint16_t *)0x1FFF'F7B8}; diff --git a/src/modm/platform/adc/stm32f0/adc_impl.hpp.in b/src/modm/platform/adc/stm32f0/adc_impl.hpp.in index 80e0d722a3..9b2c6f18c5 100644 --- a/src/modm/platform/adc/stm32f0/adc_impl.hpp.in +++ b/src/modm/platform/adc/stm32f0/adc_impl.hpp.in @@ -31,8 +31,8 @@ modm::platform::Adc{{ id }}::initialize() { Rcc::enable(); -%% if target.family in ["g0"] - ADC1->CR |= ADC_CR_ADVREGEN; +%% if target.family in ["c0", "g0"] + ADC1->CR |= ADC_CR_ADVREGEN; // Enable internal ADC VREG modm::delay_us(20); %% endif @@ -48,7 +48,7 @@ modm::platform::Adc{{ id }}::initialize() ADC1->CFGR2 = (ADC1->CFGR2 & ~ADC_CFGR2_CKMODE) | prescaler; } else { - ADC1->CFGR2 &= ~ADC_CFGR2_CKMODE; + ADC1->CFGR2 &= ~ADC_CFGR2_CKMODE; // Switch to async clock mode %% if target.family in ["f0"] Rcc::enableInternalClockMHz14(); // There are no prescalers for the asynchronous clock @@ -138,13 +138,13 @@ modm::platform::Adc{{ id }}::setChannel(const Channel channel, const SampleTimeG if(uint32_t(channel) > {{channels | max}}) return false; -%% if target.family in ["g0"] +%% if target.family in ["c0", "g0"] disableOrderedSequenceMode(); resetChannelConfigReady(); %% endif enableInternalChannel(channel); -%% if target.family in ["g0"] +%% if target.family in ["c0", "g0"] setSampleTimeGroup(channel, group); // clear Channel Configuration Ready flag resetChannelConfigReady(); @@ -160,12 +160,12 @@ modm::platform::Adc{{ id }}::setChannel(const Channel channel, const SampleTimeG void modm::platform::Adc{{ id }}::setChannels(ChannelMask_t channels) { -%% if target.family in ["g0"] +%% if target.family in ["c0", "g0"] disableOrderedSequenceMode(); resetChannelConfigReady(); %% endif ADC1->CHSELR = channels.value; -%% if target.family in ["g0"] +%% if target.family in ["c0", "g0"] waitChannelConfigReady(); %% endif } @@ -177,7 +177,7 @@ modm::platform::Adc{{ id }}::channelMaskFromPins() -> ChannelMask_t return (static_cast(1u << std::to_underlying(getPinChannel())) | ...); } -%% if target.family in ["g0"] +%% if target.family in ["c0", "g0"] bool modm::platform::Adc{{ id }}::setChannels(std::span channels) { @@ -226,7 +226,7 @@ modm::platform::Adc{{ id }}::enableInternalChannel(Channel channel) if (channel == Channel::InternalReference and not (ADC1_COMMON->CCR & ADC_CCR_VREFEN)) { -%% if target.family in ["g0"] +%% if target.family in ["c0", "g0"] ADC1->CR |= ADC_CR_ADVREGEN; modm::delay_us(30); %% endif @@ -245,7 +245,7 @@ modm::platform::Adc{{ id }}::enableInternalChannel(Channel channel) } } -%% if target.family in ["g0"] +%% if target.family in ["c0", "g0"] void modm::platform::Adc{{ id }}::setSampleTimeGroup(Channel channel, SampleTimeGroup group) { @@ -274,7 +274,7 @@ modm::platform::Adc{{ id }}::disableOversampling() void -%% if target.family in ["g0"] +%% if target.family in ["c0", "g0"] modm::platform::Adc{{ id }}::setSampleTime(const SampleTime sampleTime, const SampleTimeGroup group) { if (group == SampleTimeGroup::Group1) { @@ -295,7 +295,7 @@ modm::platform::Adc{{ id }}::clearChannel(const Channel channel) if(uint32_t(channel) > {{channels | max}}) return; -%% if target.family in ["g0"] +%% if target.family in ["c0", "g0"] ADC1->ISR = ADC_ISR_CCRDY; ADC1->CHSELR = 0; while(not (ADC1->ISR & ADC_ISR_CCRDY)) ; @@ -304,7 +304,7 @@ modm::platform::Adc{{ id }}::clearChannel(const Channel channel) %% endif if (channel == Channel::InternalReference) { -%% if target.family in ["g0"] +%% if target.family in ["c0", "g0"] ADC1->CR &= ~ADC_CR_ADVREGEN; %% endif ADC1_COMMON->CCR &= ~ADC_CCR_VREFEN; @@ -334,6 +334,9 @@ modm::platform::Adc{{ id }}::readTemperature(uint16_t Vref) %% if target.family == "f0" and target.name in ["30", "70"] const int32_t value = (int32_t(*TS_CAL1) - (TS_DATA * Vref / VDDA_CAL)) * 1000; return value / TS_AVG_SLOPE + TS_CAL1_TEMP; +%% elif target.family == "c0" + const int32_t value = ((TS_DATA * Vref / VDDA_CAL) - int32_t(*TS_CAL1)) * 1000; + return (value / TS_AVG_SLOPE) + TS_CAL1_TEMP; %% else const int32_t value = int32_t(TS_CAL2_TEMP - TS_CAL1_TEMP) * (TS_DATA * Vref / VDDA_CAL - *TS_CAL1); return value / (*TS_CAL2 - *TS_CAL1) + TS_CAL1_TEMP; @@ -483,7 +486,7 @@ modm::platform::Adc{{ id }}::getAdcEnabled() return (ADC1->CR & ADC_CR_ADEN); } -%% if target.family in ["g0"] +%% if target.family in ["c0", "g0"] void modm::platform::Adc{{ id }}::waitChannelConfigReady() { diff --git a/src/modm/platform/adc/stm32f0/module.lb b/src/modm/platform/adc/stm32f0/module.lb index 64e089a779..8348ef97c2 100644 --- a/src/modm/platform/adc/stm32f0/module.lb +++ b/src/modm/platform/adc/stm32f0/module.lb @@ -18,7 +18,8 @@ def init(module): def prepare(module, options): device = options[":target"] - if not (device.has_driver("adc:stm32-f0") or + if not (device.has_driver("adc:stm32-c0") or + device.has_driver("adc:stm32-f0") or device.has_driver("adc:stm32-g0")): return False module.depends( @@ -40,7 +41,10 @@ def build(env): properties["id"] = driver.get("instance", [""])[0] channels = {i:"In{}".format(i) for i in reversed(range(0,19))} - if target.family in ["g0"]: + if target.family in ["c0"]: + channels[9] = "Temperature" + channels[10] = "InternalReference" + elif target.family in ["g0"]: channels[12] = "Temperature" channels[13] = "InternalReference" channels[14] = "Battery" diff --git a/src/modm/platform/clock/stm32/module.lb b/src/modm/platform/clock/stm32/module.lb index ceda4c17db..7534615703 100644 --- a/src/modm/platform/clock/stm32/module.lb +++ b/src/modm/platform/clock/stm32/module.lb @@ -35,7 +35,11 @@ def build(env): properties["partname"] = device.partname properties["core"] = core = device.get_driver("core")["type"] - if target["family"] in ["f1", "f3"]: + if target["family"] in ["c0"]: + properties["hsi_frequency"] = 48_000_000 + properties["lsi_frequency"] = 32_000 + properties["boot_frequency"] = 12_000_000 + elif target["family"] in ["f1", "f3"]: properties["hsi_frequency"] = 8_000_000 properties["lsi_frequency"] = 40_000 properties["boot_frequency"] = properties["hsi_frequency"] @@ -71,7 +75,7 @@ def build(env): (target["family"] == "u5") if target["family"] in ["l4", "l5"]: properties["hsi48_cr"] = "CRRCR" - elif target["family"] in ["u5"]: + elif target["family"] in ["c0", "u5"]: properties["hsi48_cr"] = "CR" else: properties["hsi48_cr"] = "CR2" @@ -111,8 +115,8 @@ def build(env): if target.family == "h7" else "" properties["cfgr3"] = ("SRDCFGR" if target.name in ["a0", "a3", "b0", "b3"] else "D3CFGR") properties["d3"] = ("SRD" if target.name in ["a0", "a3", "b0", "b3"] else "D3") - properties["bdcr"] = "CSR" if target.family in ["l0", "l1"] else "BDCR" - properties["pll_ids"] = ["1", "2", "3"] if target.family in ["h7", "u5"] else [""] + properties["bdcr"] = "CSR1" if target.family in ["c0"] else "CSR" if target.family in ["l0", "l1"] else "BDCR" + properties["pll_ids"] = ["1", "2", "3"] if target.family in ["h7", "u5"] else [] if target.family in ["c0"] else [""] properties["has_smps"] = target["family"] == "h7" and (target["name"] in ["25", "35", "45", "47", "55", "57"] or \ (target["name"] in ["30", "a3", "b0", "b3"] and target["variant"] == "q")) properties["ccipr1"] = "CCIPR1" if target.family in ["l5", "u5"] else "CCIPR" diff --git a/src/modm/platform/clock/stm32/rcc.cpp.in b/src/modm/platform/clock/stm32/rcc.cpp.in index 62d6dd9f8a..e3c471f357 100644 --- a/src/modm/platform/clock/stm32/rcc.cpp.in +++ b/src/modm/platform/clock/stm32/rcc.cpp.in @@ -125,7 +125,7 @@ Rcc::enableExternalCrystal(uint32_t waitCycles) } -%% set lsi_cr="BDCR" if target.family in ["u5"] else "CSR" +%% set lsi_cr="CSR2" if target.family in ["c0"] else "BDCR" if target.family in ["u5"] else "CSR" bool Rcc::enableLowSpeedInternalClock(uint32_t waitCycles) { @@ -576,7 +576,6 @@ Rcc::setHsiPredivider4Enabled(bool divideBy4, uint32_t waitCycles) } %% endif - %% set sysclksrcf_cfgr="CFGR1" if target.family in ["u5"] else "CFGR" bool Rcc::enableSystemClock(SystemClockSource src, uint32_t waitCycles) @@ -591,7 +590,6 @@ Rcc::enableSystemClock(SystemClockSource src, uint32_t waitCycles) return true; } - %% if target.family in ["g4", "l5"] bool Rcc::setCanPrescaler(CanPrescaler prescaler) diff --git a/src/modm/platform/clock/stm32/rcc.hpp.in b/src/modm/platform/clock/stm32/rcc.hpp.in index 72a379e84a..9f0c408422 100644 --- a/src/modm/platform/clock/stm32/rcc.hpp.in +++ b/src/modm/platform/clock/stm32/rcc.hpp.in @@ -43,6 +43,20 @@ public: static constexpr uint32_t HsiFrequency = {{ hsi_frequency | modm.digsep }}; static constexpr uint32_t BootFrequency = {{ boot_frequency | modm.digsep }}; +%% if target.family == "c0" + enum class + HsiSysDivider : uint32_t + { + Div1 = 0, + Div2 = RCC_CR_HSIDIV_0, + Div4 = RCC_CR_HSIDIV_1, + Div8 = RCC_CR_HSIDIV_1 | RCC_CR_HSIDIV_0, + Div16 = RCC_CR_HSIDIV_2, + Div64 = RCC_CR_HSIDIV_2 | RCC_CR_HSIDIV_1, + Div128 = RCC_CR_HSIDIV_2 | RCC_CR_HSIDIV_1 | RCC_CR_HSIDIV_0, + }; + +%% else enum class PllSource : uint32_t { @@ -104,7 +118,7 @@ public: %% endif %% if hsi48 and target.family not in ["l4", "l5", "u5"] /// High speed internal clock (48 MHz) - Hsi48 = RCC_CFGR_PLLSRC_HSI48_PREDIV, + Hsi48 = RCC_CFGR_PLLSRC_HSI48_PREDIV, InternalClockMHz48 = Hsi48, %% endif %% if target.family in ["l4"] @@ -114,6 +128,7 @@ public: ExternalClock = Hse, ExternalCrystal = Hse, }; +%% endif %% if target.family in ["l0", "l1"] enum class @@ -134,7 +149,12 @@ public: enum class SystemClockSource : uint32_t { -%% if target.family == "l5" +%% if target.family == "c0" + Hsi = RCC_CFGR_SWS_HSI, + Hse = RCC_CFGR_SWS_HSE, + Lsi = RCC_CFGR_SWS_LSI, + Lse = RCC_CFGR_SWS_LSE, +%% elif target.family == "l5" Msi = 0, Hsi = RCC_CFGR_SW_0, Hsi16 = Hsi, @@ -194,7 +214,7 @@ public: enum class AhbPrescaler : uint32_t { -%% if target.family in ["l5", "u5"] +%% if target.family in ["c0", "l5", "u5"] Div1 = 0b0000 << RCC_{{cfgr_prescaler}}_HPRE_Pos, Div2 = 0b1000 << RCC_{{cfgr_prescaler}}_HPRE_Pos, Div4 = 0b1001 << RCC_{{cfgr_prescaler}}_HPRE_Pos, @@ -217,7 +237,17 @@ public: %% endif }; -%% if target.family in ["f0", "g0"] +%% if target.family in ["c0"] + enum class + ApbPrescaler : uint32_t + { + Div1 = RCC_CFGR_PPRE_0, + Div2 = RCC_CFGR_PPRE_2, + Div4 = RCC_CFGR_PPRE_2 | RCC_CFGR_PPRE_0, + Div8 = RCC_CFGR_PPRE_2 | RCC_CFGR_PPRE_1, + Div16 = RCC_CFGR_PPRE_2 | RCC_CFGR_PPRE_1 | RCC_CFGR_PPRE_0 + }; +%% elif target.family in ["f0", "g0"] enum class ApbPrescaler : uint32_t { @@ -396,7 +426,7 @@ public: Csi = RCC_CFGR_MCO2_2, Lsi = RCC_CFGR_MCO2_2 | RCC_CFGR_MCO2_0 }; -%% elif target.family in ["l0", "l1", "l4", "l5", "g0", "g4", "u5"] +%% elif target.family in ["l0", "l1", "l4", "l5", "g0", "g4", "u5", "c0"] %% set cfgr_mco="CFGR1" if target.family in ["u5"] else "CFGR" enum class ClockOutputSource : uint32_t @@ -615,6 +645,7 @@ public: }; %% endif +%% if target.family != "c0" struct PllFactors { %% if target.family in ["h7"] @@ -667,6 +698,7 @@ public: %% endif %% endif }; +%% endif %% if pllsai_p_usb struct PllSaiFactors @@ -835,7 +867,7 @@ public: RCC->CFGR = tmp | uint32_t(src); return true; } -%% elif target.family in ["l0", "l1", "l4", "l5", "g0", "g4", "u5"] +%% elif target.family in ["l0", "l1", "l4", "l5", "g0", "g4", "u5", "c0"] enum class ClockOutputPrescaler : uint32_t { @@ -844,7 +876,7 @@ public: Div4 = (2 << RCC_{{cfgr_mco}}_MCOPRE_Pos), Div8 = (3 << RCC_{{cfgr_mco}}_MCOPRE_Pos), Div16 = (4 << RCC_{{cfgr_mco}}_MCOPRE_Pos), -%% if target.family in ["g0"] +%% if target.family in ["c0", "g0"] Div32 = (5 << RCC_{{cfgr_mco}}_MCOPRE_Pos), Div64 = (6 << RCC_{{cfgr_mco}}_MCOPRE_Pos), Div128 = (7 << RCC_{{cfgr_mco}}_MCOPRE_Pos), @@ -867,6 +899,15 @@ public: %% endif public: +%% if target.family in ["c0"] + static inline bool + setHsiSysDivider(HsiSysDivider hsisysdivider) + { + RCC->CR = (RCC->CR & ~RCC_CR_HSIDIV_Msk) | uint32_t(hsisysdivider); + return true; + } + +%% endif static inline bool setAhbPrescaler(AhbPrescaler prescaler) { @@ -874,7 +915,7 @@ public: return true; } -%% if target.family in ["f0", "g0"] +%% if target.family in ["c0", "f0", "g0"] static inline bool setApbPrescaler(ApbPrescaler prescaler) { diff --git a/src/modm/platform/clock/stm32/rcc_impl.hpp.in b/src/modm/platform/clock/stm32/rcc_impl.hpp.in index f71428ec39..e1ce1aff37 100644 --- a/src/modm/platform/clock/stm32/rcc_impl.hpp.in +++ b/src/modm/platform/clock/stm32/rcc_impl.hpp.in @@ -63,7 +63,7 @@ Rcc::setFlashLatency() %% if target["family"] in ["f2", "f4", "l4", "g4"] // enable flash prefetch and data and instruction cache acr |= FLASH_ACR_PRFTEN | FLASH_ACR_DCEN | FLASH_ACR_ICEN; -%% elif target["family"] in ["g0"] +%% elif target["family"] in ["c0", "g0"] // enable flash prefetch and instruction cache acr |= FLASH_ACR_PRFTEN | FLASH_ACR_ICEN; %% elif target["family"] == "f7" diff --git a/src/modm/platform/core/stm32/module.lb b/src/modm/platform/core/stm32/module.lb index 8e0141b5c4..de7c732d45 100644 --- a/src/modm/platform/core/stm32/module.lb +++ b/src/modm/platform/core/stm32/module.lb @@ -57,6 +57,7 @@ def build(env): # (cycles per loop, setup cost in loops) tuning = { "g4": (3, 4), # CM4 tested on G476 in RAM + "c0": (3, 4), # CM0+ tested on C031 in RAM "l0": (3, 4), # CM0+ tested on L031 in RAM "g0": (3, 4), # CM0+ tested on G072 in RAM "f7": (4, 4), # CM7 tested on F767 in ITCM diff --git a/src/modm/platform/core/stm32/startup_platform.c.in b/src/modm/platform/core/stm32/startup_platform.c.in index 5764524b36..338a68ce8c 100644 --- a/src/modm/platform/core/stm32/startup_platform.c.in +++ b/src/modm/platform/core/stm32/startup_platform.c.in @@ -29,7 +29,7 @@ void __modm_initialize_platform(void) { // Enable SYSCFG -%% if target.family == "g0" +%% if target.family in ["c0", "g0"] RCC->APBENR2 |= RCC_APBENR2_SYSCFGEN; %% elif target.family == "f1" RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; diff --git a/src/modm/platform/dma/stm32/dma.hpp.in b/src/modm/platform/dma/stm32/dma.hpp.in index 4a8e895a58..71306c4086 100644 --- a/src/modm/platform/dma/stm32/dma.hpp.in +++ b/src/modm/platform/dma/stm32/dma.hpp.in @@ -73,7 +73,7 @@ public: %% endif } %% endif -%% if dmaType in ["stm32-mux"] and target.family != "g0": +%% if dmaType in ["stm32-mux"] and target.family not in ["c0", "g0"]: Rcc::enable(); %% endif } diff --git a/src/modm/platform/dma/stm32/module.lb b/src/modm/platform/dma/stm32/module.lb index 3f4cc4344b..52fe233c80 100644 --- a/src/modm/platform/dma/stm32/module.lb +++ b/src/modm/platform/dma/stm32/module.lb @@ -41,10 +41,10 @@ def prepare(module, options): def get_irq_list(device): irqs = {v["position"]: v["name"] for v in device.get_driver("core")["vector"]} - irqs = [v for v in irqs.values() if v.startswith("DMA") and v[3].isdigit() and not "DMA2D" in v] + irqs = [v for v in irqs.values() if re.match(r"(?:\w+_)?DMA\d_", v)] - instance_pattern = re.compile(r"(DMA\d_(Ch|Channel|Stream)\d(_\d)*)") - channel_pattern = re.compile(r"DMA(?P\d)_(Ch|Channel|Stream)(?P(\d(_\d)*))") + instance_pattern = re.compile(r"(DMA\d_(Ch|CH|Channel|Stream)\d(_\d)*)") + channel_pattern = re.compile(r"DMA(?P\d)_(Ch|CH|Channel|Stream)(?P(\d(_\d)*))") irq_list = [] for irq in irqs: instances = [] diff --git a/src/modm/platform/extint/stm32/module.lb b/src/modm/platform/extint/stm32/module.lb index b47983ff80..58f8abd410 100644 --- a/src/modm/platform/extint/stm32/module.lb +++ b/src/modm/platform/extint/stm32/module.lb @@ -47,12 +47,12 @@ def validate(env): def build(env): target = env[":target"].identifier - separate_flags = target.family in ["g0", "l5", "u5"] + separate_flags = target.family in ["c0", "g0", "l5", "u5"] extended = target.family in ["l4", "l5", "g4", "h7"] if separate_flags: extended = target.name in ["b1", "c1"] exti_reg = "SYSCFG" - if target.family in ["g0", "l5", "u5"]: exti_reg = "EXTI" + if target.family in ["c0", "g0", "l5", "u5"]: exti_reg = "EXTI" if target.family in ["f1"]: exti_reg = "AFIO" global extimap diff --git a/src/modm/platform/gpio/stm32/enable.cpp.in b/src/modm/platform/gpio/stm32/enable.cpp.in index 701fb88c13..68e20eee54 100644 --- a/src/modm/platform/gpio/stm32/enable.cpp.in +++ b/src/modm/platform/gpio/stm32/enable.cpp.in @@ -28,7 +28,7 @@ modm_gpio_enable(void) %% set prefix = "IOP" %% elif target.family in ["l4", "l5", "g4", "u5"] %% set clock_tree = 'AHB2' -%% elif target.family in ["g0", "l0"] +%% elif target.family in ["c0", "g0", "l0"] %% set clock_tree = 'IOP' %% endif diff --git a/src/modm/platform/gpio/stm32/module.lb b/src/modm/platform/gpio/stm32/module.lb index 7876cef738..fd99bfdcad 100644 --- a/src/modm/platform/gpio/stm32/module.lb +++ b/src/modm/platform/gpio/stm32/module.lb @@ -125,6 +125,10 @@ def validate_alternate_functions(driver, env): def get_remap_command(family, key): reg = 'SYSCFG->CFGR1' mask = { + ('c0', 'a9') : 'SYSCFG_CFGR1_PA11_RMP', + ('c0', 'a10'): 'SYSCFG_CFGR1_PA12_RMP', + ('c0', 'a11'): 'SYSCFG_CFGR1_PA11_RMP', + ('c0', 'a12'): 'SYSCFG_CFGR1_PA12_RMP', ('f0', 'a9') : 'SYSCFG_CFGR1_PA11_PA12_RMP', ('f0', 'a10'): 'SYSCFG_CFGR1_PA11_PA12_RMP', ('f0', 'a11'): 'SYSCFG_CFGR1_PA11_PA12_RMP', diff --git a/tools/build_script_generator/module.lb b/tools/build_script_generator/module.lb index 42d129ed70..8a538dce42 100644 --- a/tools/build_script_generator/module.lb +++ b/tools/build_script_generator/module.lb @@ -248,7 +248,7 @@ def post_build(env): env.substitutions["openocd_sources"] = env.collector_values("openocd.source") linkerscript = env.query(":platform:cortex-m:linkerscript", {}) - all_rams = [m for m in linkerscript.get("memories") if "w" in m["access"]] + all_rams = [m for m in linkerscript.get("memories", []) if "w" in m["access"]] env.substitutions["all_rams"] = all_rams vector_table = env.query(":platform:cortex-m:vector_table", {"vector_table_size": 16*4}) env.substitutions["vector_table_size"] = vector_table["vector_table_size"] From 34207512a6ff3ad68c1b32538ddde1c026105566 Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Sun, 22 Sep 2024 22:43:25 +0200 Subject: [PATCH 2/2] [examples] Add NUCLEO-C031C6 board examples --- .github/workflows/linux.yml | 4 + README.md | 23 ++-- examples/nucleo_c031c6/adc/main.cpp | 48 ++++++++ examples/nucleo_c031c6/adc/project.xml | 10 ++ examples/nucleo_c031c6/adc_sequence/main.cpp | 83 ++++++++++++++ .../nucleo_c031c6/adc_sequence/project.xml | 10 ++ examples/nucleo_c031c6/blink/main.cpp | 40 +++++++ examples/nucleo_c031c6/blink/project.xml | 9 ++ examples/nucleo_c031c6/timer/main.cpp | 55 +++++++++ examples/nucleo_c031c6/timer/project.xml | 11 ++ src/modm/board/nucleo64_arduino_c0.hpp | 42 +++++++ src/modm/board/nucleo_c031c6/board.hpp | 108 ++++++++++++++++++ src/modm/board/nucleo_c031c6/board.xml | 15 +++ src/modm/board/nucleo_c031c6/module.lb | 43 +++++++ tools/openocd/modm/st_nucleo_c0.cfg | 11 ++ 15 files changed, 501 insertions(+), 11 deletions(-) create mode 100644 examples/nucleo_c031c6/adc/main.cpp create mode 100644 examples/nucleo_c031c6/adc/project.xml create mode 100644 examples/nucleo_c031c6/adc_sequence/main.cpp create mode 100644 examples/nucleo_c031c6/adc_sequence/project.xml create mode 100644 examples/nucleo_c031c6/blink/main.cpp create mode 100644 examples/nucleo_c031c6/blink/project.xml create mode 100644 examples/nucleo_c031c6/timer/main.cpp create mode 100644 examples/nucleo_c031c6/timer/project.xml create mode 100644 src/modm/board/nucleo64_arduino_c0.hpp create mode 100644 src/modm/board/nucleo_c031c6/board.hpp create mode 100644 src/modm/board/nucleo_c031c6/board.xml create mode 100644 src/modm/board/nucleo_c031c6/module.lb create mode 100644 tools/openocd/modm/st_nucleo_c0.cfg diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 7036c52bd7..1d0d4cdca6 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -135,6 +135,10 @@ jobs: - name: Update lbuild run: | pip3 install --upgrade --upgrade-strategy=eager modm + - name: Examples STM32C0 Series + if: always() + run: | + (cd examples && ../tools/scripts/examples_compile.py nucleo_c031c6) - name: Examples STM32F0 Series if: always() run: | diff --git a/README.md b/README.md index e3de674f1f..00f21a9b8e 100644 --- a/README.md +++ b/README.md @@ -658,59 +658,60 @@ We have out-of-box support for many development boards including documentation. + - + - + - + - + - + - + - + - + - + - + - + diff --git a/examples/nucleo_c031c6/adc/main.cpp b/examples/nucleo_c031c6/adc/main.cpp new file mode 100644 index 0000000000..25c7a9e607 --- /dev/null +++ b/examples/nucleo_c031c6/adc/main.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2024, Jörg Ebeling + * + * This file is part of the modm project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +using namespace Board; + +/* + * This example demonstrates the usage of the ADC peripheral. + * Connect two potentiometers to A0 and A1 to get reasonable readings or just + * touch the two pins with your fingers to get ... interesting readings. + * Make sure you're not too charged up with static electricity! + */ + +int +main() +{ + Board::initialize(); + Board::LedD13::setOutput(); + + Adc1::connect(); + Adc1::initialize(); // 24MHz/160.5 sample time=6.6us (fulfill Ts_temp of 5us) + + Adc1::setResolution(Adc1::Resolution::Bits12); + Adc1::setSampleTime(Adc1::SampleTime::Cycles160_5); + Adc1::setRightAdjustResult(); + Adc1::enableOversampling(Adc1::OversampleRatio::x16, Adc1::OversampleShift::Div16); + + while (true) + { + Board::LedD13::toggle(); + modm::delay(500ms); + + const uint16_t vref = Adc1::readInternalVoltageReference(); + MODM_LOG_INFO.printf("Vref=%4humV T=%2hu°C A0=%4humV A1=%4humV\n", + vref, Adc1::readTemperature(vref), + (vref * Adc1::readChannel(Adc1::Channel::In0) / 0xFFF), + (vref * Adc1::readChannel(Adc1::Channel::In1) / 0xFFF)); + } +} diff --git a/examples/nucleo_c031c6/adc/project.xml b/examples/nucleo_c031c6/adc/project.xml new file mode 100644 index 0000000000..42012ee55b --- /dev/null +++ b/examples/nucleo_c031c6/adc/project.xml @@ -0,0 +1,10 @@ + + modm:nucleo-c031c6 + + + + + modm:build:scons + modm:platform:adc + + diff --git a/examples/nucleo_c031c6/adc_sequence/main.cpp b/examples/nucleo_c031c6/adc_sequence/main.cpp new file mode 100644 index 0000000000..b397d8bfda --- /dev/null +++ b/examples/nucleo_c031c6/adc_sequence/main.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2024, Jörg Ebeling + * + * This file is part of the modm project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include + +using namespace Board; + +/* + * This example demonstrates the usage of the ADC peripheral. + * Connect two potentiometers to A0 and A1 to get reasonable readings or just + * touch the two pins with your fingers to get ... interesting readings. + * Make sure you're not too charged up with static electricity! + * + * NOTE: the readings are raw ADC values and need to be converted to voltage! + */ + +std::array adc_data_buf; + +static void +adc_handler() +{ + static uint8_t adc_data_idx = 0; + + if (Adc1::getInterruptFlags() & Adc1::InterruptFlag::EndOfConversion) + { + Adc1::acknowledgeInterruptFlags(Adc1::InterruptFlag::EndOfConversion); + adc_data_buf.at(adc_data_idx) = Adc1::getValue(); + adc_data_idx++; + } + if (Adc1::getInterruptFlags() & Adc1::InterruptFlag::EndOfSequence) + { + Adc1::acknowledgeInterruptFlags(Adc1::InterruptFlag::EndOfSequence); + adc_data_idx = 0; + } +} + +// ---------------------------------------------------------------------------- +int +main() +{ + Board::initialize(); + Board::LedD13::setOutput(); + MODM_LOG_INFO << "Board initialized" << modm::endl; + + Adc1::connect(); + Adc1::initialize(); // 24MHz/160.5 sample time=6.6us (fulfill Ts_temp of 5us) + Adc1::setResolution(Adc1::Resolution::Bits12); + Adc1::setRightAdjustResult(); + Adc1::setSampleTime(Adc1::SampleTime::Cycles160_5); + + const Adc1::Channel sequence[4] = {Adc1::Channel::InternalReference, Adc1::Channel::In0, + Adc1::Channel::In1, Adc1::Channel::Temperature}; + Adc1::setChannels(sequence); + + Adc1::enableInterruptVector(15); + Adc1::enableInterrupt(Adc1::Interrupt::EndOfConversion | Adc1::Interrupt::EndOfSequence); + AdcInterrupt1::attachInterruptHandler(adc_handler); + Adc1::enableFreeRunningMode(); + Adc1::startConversion(); + + while (true) + { + Board::LedD13::toggle(); + modm::delay(500ms); + + MODM_LOG_INFO << "ADC: "; + for (size_t i = 0; auto value : adc_data_buf) + { + MODM_LOG_INFO << i++ << "=" << value << " "; + } + MODM_LOG_INFO << modm::endl; + } + return 0; +} diff --git a/examples/nucleo_c031c6/adc_sequence/project.xml b/examples/nucleo_c031c6/adc_sequence/project.xml new file mode 100644 index 0000000000..472b223801 --- /dev/null +++ b/examples/nucleo_c031c6/adc_sequence/project.xml @@ -0,0 +1,10 @@ + + modm:nucleo-c031c6 + + + + + modm:build:scons + modm:platform:adc + + diff --git a/examples/nucleo_c031c6/blink/main.cpp b/examples/nucleo_c031c6/blink/main.cpp new file mode 100644 index 0000000000..27b5693d5a --- /dev/null +++ b/examples/nucleo_c031c6/blink/main.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2016-2017, Niklas Hauser + * Copyright (c) 2017, Nick Sarten + * + * This file is part of the modm project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +using namespace Board; + +int +main() +{ + Board::initialize(); + LedD13::setOutput(); + + // Use the logging streams to print some messages. + // Change MODM_LOG_LEVEL above to enable or disable these messages + MODM_LOG_DEBUG << "debug" << modm::endl; + MODM_LOG_INFO << "info" << modm::endl; + MODM_LOG_WARNING << "warning" << modm::endl; + MODM_LOG_ERROR << "error" << modm::endl; + + uint32_t counter(0); + + while (true) + { + LedD13::toggle(); + modm::delay(Button::read() ? 100ms : 500ms); + + MODM_LOG_INFO << "loop: " << counter++ << modm::endl; + } + + return 0; +} diff --git a/examples/nucleo_c031c6/blink/project.xml b/examples/nucleo_c031c6/blink/project.xml new file mode 100644 index 0000000000..19fc51bc78 --- /dev/null +++ b/examples/nucleo_c031c6/blink/project.xml @@ -0,0 +1,9 @@ + + modm:nucleo-c031c6 + + + + + modm:build:scons + + diff --git a/examples/nucleo_c031c6/timer/main.cpp b/examples/nucleo_c031c6/timer/main.cpp new file mode 100644 index 0000000000..551a18fcfa --- /dev/null +++ b/examples/nucleo_c031c6/timer/main.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2024, Jörg Ebeling + * + * This file is part of the modm project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +using namespace Board; + +MODM_ISR(TIM14) +{ + Timer14::acknowledgeInterruptFlags(Timer14::InterruptFlag::Update); + MODM_LOG_DEBUG << "Set LED" << modm::endl; + Board::LedD13::set(); +} + +MODM_ISR(TIM16) +{ + Timer16::acknowledgeInterruptFlags(Timer16::InterruptFlag::Update); + MODM_LOG_DEBUG << "Reset LED" << modm::endl; + Board::LedD13::reset(); +} + +int +main() +{ + Board::initialize(); + Board::LedD13::setOutput(); + + MODM_LOG_INFO << "Board & Logger initialized" << modm::endl; + + Timer14::enable(); + Timer14::setMode(Timer14::Mode::UpCounter); + Timer14::setPeriod(1000ms); + Timer14::applyAndReset(); + Timer14::enableInterrupt(Timer14::Interrupt::Update); + Timer14::enableInterruptVector(true, 5); + + Timer16::enable(); + Timer16::setMode(Timer16::Mode::UpCounter); + Timer16::setPeriod(909ms); + Timer16::applyAndReset(); + Timer16::enableInterrupt(Timer16::Interrupt::Update); + Timer16::enableInterruptVector(true, 5); + + Timer14::start(); + Timer16::start(); + + while (true) ; +} diff --git a/examples/nucleo_c031c6/timer/project.xml b/examples/nucleo_c031c6/timer/project.xml new file mode 100644 index 0000000000..41da61568a --- /dev/null +++ b/examples/nucleo_c031c6/timer/project.xml @@ -0,0 +1,11 @@ + + modm:nucleo-c031c6 + + + + + modm:build:scons + modm:platform:timer:14 + modm:platform:timer:16 + + diff --git a/src/modm/board/nucleo64_arduino_c0.hpp b/src/modm/board/nucleo64_arduino_c0.hpp new file mode 100644 index 0000000000..647eebabdb --- /dev/null +++ b/src/modm/board/nucleo64_arduino_c0.hpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2017, Sascha Schade + * + * This file is part of the modm project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +// ---------------------------------------------------------------------------- + +// Nucleo64 Arduino Header Footprint for STM32C031C6 +// Schematic: https://www.st.com/resource/en/schematic_pack/mb1549-u575ziq-c03_schematic.pdf + +#ifndef MODM_STM32_NUCLEO64_ARDUINO_HPP +#define MODM_STM32_NUCLEO64_ARDUINO_HPP + +using A0 = GpioA0; +using A1 = GpioA1; +using A2 = GpioA4; +using A3 = GpioB1; +using A4 = GpioA11; +using A5 = GpioA12; + +using D0 = GpioB7; +using D1 = GpioB6; +using D2 = GpioA10; +using D3 = GpioB3; +using D4 = GpioB10; +using D5 = GpioB4; +using D6 = GpioB5; +using D7 = GpioA15; +using D8 = GpioA9; +using D9 = GpioC7; +using D10 = GpioB0; +using D11 = GpioA7; +using D12 = GpioA6; +using D13 = GpioA5; +using D14 = GpioB9; +using D15 = GpioB8; + +#endif // MODM_STM32_NUCLEO64_ARDUINO_HPP diff --git a/src/modm/board/nucleo_c031c6/board.hpp b/src/modm/board/nucleo_c031c6/board.hpp new file mode 100644 index 0000000000..4cac0fa817 --- /dev/null +++ b/src/modm/board/nucleo_c031c6/board.hpp @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2016-2018, 2024, Niklas Hauser + * Copyright (c) 2017, Nick Sarten + * Copyright (c) 2017, Sascha Schade + * + * This file is part of the modm project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef MODM_STM32_NUCLEO_C031C6_HPP +#define MODM_STM32_NUCLEO_C031C6_HPP + +#include +#include +#include +/// @ingroup modm_board_nucleo_c031c6 +#define MODM_BOARD_HAS_LOGGER + +using namespace modm::platform; + +namespace Board +{ +/// @ingroup modm_board_nucleo_c031c6 +/// @{ +using namespace modm::literals; + +/// STM32C031C6 running at 48MHz generated from the internal clock +struct SystemClock +{ + static constexpr uint32_t Frequency = Rcc::HsiFrequency; + static constexpr uint32_t Ahb = Frequency; + static constexpr uint32_t Apb = Frequency; + + static constexpr uint32_t Adc1 = Apb; + + static constexpr uint32_t Spi1 = Apb; + + static constexpr uint32_t Usart1 = Apb; + static constexpr uint32_t Usart2 = Apb; + + static constexpr uint32_t I2c1 = Apb; + + static constexpr uint32_t Timer1 = Apb; + static constexpr uint32_t Timer2 = Apb; + static constexpr uint32_t Timer3 = Apb; + static constexpr uint32_t Timer14 = Apb; + static constexpr uint32_t Timer16 = Apb; + static constexpr uint32_t Timer17 = Apb; + static constexpr uint32_t Iwdg = Rcc::LsiFrequency; + + static bool inline + enable() + { + // 48MHz generated from internal RC + Rcc::enableInternalClock(); + Rcc::setHsiSysDivider(Rcc::HsiSysDivider::Div1); + // set flash latency for 48MHz + Rcc::setFlashLatency(); + // switch system clock to PLL output + Rcc::setAhbPrescaler(Rcc::AhbPrescaler::Div1); + Rcc::setApbPrescaler(Rcc::ApbPrescaler::Div1); + // update frequencies for busy-wait delay functions + Rcc::updateCoreFrequency(); + + return true; + } +}; + +// Arduino Footprint +#include "nucleo64_arduino.hpp" + +using Button = GpioInputC13; +using LedD13 = D13; + +using Leds = SoftwareGpioPort< LedD13 >; +/// @} + +namespace stlink +{ +/// @ingroup modm_board_nucleo_c031c6 +/// @{ +using Rx = GpioInputA3; +using Tx = GpioOutputA2; +using Uart = BufferedUart>; +/// @} +} + +/// @ingroup modm_board_nucleo_c031c6 +/// @{ +using LoggerDevice = modm::IODeviceWrapper< stlink::Uart, modm::IOBuffer::BlockIfFull >; + +inline void +initialize() +{ + SystemClock::enable(); + SysTickTimer::initialize(); + + stlink::Uart::connect(); + stlink::Uart::initialize(); +} +/// @} + +} + +#endif // MODM_STM32_NUCLEO_C031C6_HPP diff --git a/src/modm/board/nucleo_c031c6/board.xml b/src/modm/board/nucleo_c031c6/board.xml new file mode 100644 index 0000000000..5e205b3693 --- /dev/null +++ b/src/modm/board/nucleo_c031c6/board.xml @@ -0,0 +1,15 @@ + + + + ../../../../repo.lb + + + + + + + + + modm:board:nucleo-c031c6 + + diff --git a/src/modm/board/nucleo_c031c6/module.lb b/src/modm/board/nucleo_c031c6/module.lb new file mode 100644 index 0000000000..8d72e77882 --- /dev/null +++ b/src/modm/board/nucleo_c031c6/module.lb @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# Copyright (c) 2016-2018, Niklas Hauser +# Copyright (c) 2017, Fabian Greif +# +# This file is part of the modm project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# ----------------------------------------------------------------------------- + +def init(module): + module.name = ":board:nucleo-c031c6" + module.description = """\ +# NUCLEO-C031C6 + +[Nucleo kit for STM32C031C6](https://www.st.com/en/evaluation-tools/nucleo-c031c6.html) +""" + +def prepare(module, options): + if not options[":target"].partname.startswith("stm32c031c6t"): + return False + + module.depends(":platform:core", ":platform:gpio", ":platform:clock", ":platform:uart:2", + ":debug", ":architecture:clock", ":architecture:clock") + return True + +def build(env): + env.outbasepath = "modm/src/modm/board" + env.substitutions = { + "with_logger": True, + "with_assert": env.has_module(":architecture:assert"), + "has_gpio_c14_c15": False + } + env.template("../board.cpp.in", "board.cpp") + env.copy('.') + env.copy("../nucleo64_arduino_c0.hpp", "nucleo64_arduino.hpp") + + env.outbasepath = "modm/openocd/modm/board/" + env.copy(repopath("tools/openocd/modm/st_nucleo_c0.cfg"), "st_nucleo_c0.cfg") + env.collect(":build:openocd.source", "modm/board/st_nucleo_c0.cfg") diff --git a/tools/openocd/modm/st_nucleo_c0.cfg b/tools/openocd/modm/st_nucleo_c0.cfg new file mode 100644 index 0000000000..6e92b32c43 --- /dev/null +++ b/tools/openocd/modm/st_nucleo_c0.cfg @@ -0,0 +1,11 @@ +# Should work with all STM32C0 Nucleo Dev Boards. +# http://www.st.com/en/evaluation-tools/stm32-mcu-nucleo.html + +source [find interface/stlink.cfg] + +transport select hla_swd + +source [find target/stm32c0x.cfg] + +# use hardware reset +reset_config srst_only srst_nogate
STM32STM32 SAM RP AT
PeripheralC0 F0 F1 F2
CAN
Comparator
DAC
Ethernet
External Memory
I2C
Internal Flash Random Generator
Unique ID
FEATHER-RP2040 MEGA-2560-PRONUCLEO-C031C6 NUCLEO-F031K6NUCLEO-F042K6
NUCLEO-F042K6 NUCLEO-F072RB NUCLEO-F091RC NUCLEO-F103RBNUCLEO-F303K8
NUCLEO-F303K8 NUCLEO-F303RE NUCLEO-F334R8 NUCLEO-F401RENUCLEO-F411RE
NUCLEO-F411RE NUCLEO-F429ZI NUCLEO-F439ZI NUCLEO-F446RENUCLEO-F446ZE
NUCLEO-F446ZE NUCLEO-F746ZG NUCLEO-F767ZI NUCLEO-G070RBNUCLEO-G071RB
NUCLEO-G071RB NUCLEO-G431KB NUCLEO-G431RB NUCLEO-G474RENUCLEO-H723ZG
NUCLEO-H723ZG NUCLEO-H743ZI NUCLEO-L031K6 NUCLEO-L053R8NUCLEO-L152RE
NUCLEO-L152RE NUCLEO-L432KC NUCLEO-L452RE NUCLEO-L476RGNUCLEO-L496ZG-P
NUCLEO-L496ZG-P NUCLEO-L552ZE-Q NUCLEO-U575ZI-Q OLIMEXINO-STM32Raspberry Pi Pico
Raspberry Pi Pico SAMD21-MINI SAMD21-XPLAINED-PRO SAME54-XPLAINED-PROSAME70-XPLAINED
SAME70-XPLAINED SAMG55-XPLAINED-PRO SAMV71-XPLAINED-ULTRA Smart Response XESTM32-F4VE
STM32-F4VE STM32F030-DEMO THINGPLUS-RP2040