From a7cfe65cb19a9e503860f86ae1a7b14a56e9eece Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Sun, 22 Sep 2024 22:43:25 +0200 Subject: [PATCH] [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 3fa4ccd646..4a8cba7d42 100644 --- a/README.md +++ b/README.md @@ -658,59 +658,60 @@ We have out-of-box support for many development boards including documentation. FEATHER-RP2040 MEGA-2560-PRO +NUCLEO-C031C6 NUCLEO-F031K6 -NUCLEO-F042K6 +NUCLEO-F042K6 NUCLEO-F072RB NUCLEO-F091RC NUCLEO-F103RB -NUCLEO-F303K8 +NUCLEO-F303K8 NUCLEO-F303RE NUCLEO-F334R8 NUCLEO-F401RE -NUCLEO-F411RE +NUCLEO-F411RE NUCLEO-F429ZI NUCLEO-F439ZI NUCLEO-F446RE -NUCLEO-F446ZE +NUCLEO-F446ZE NUCLEO-F746ZG NUCLEO-F767ZI NUCLEO-G070RB -NUCLEO-G071RB +NUCLEO-G071RB NUCLEO-G431KB NUCLEO-G431RB NUCLEO-G474RE -NUCLEO-H723ZG +NUCLEO-H723ZG NUCLEO-H743ZI NUCLEO-L031K6 NUCLEO-L053R8 -NUCLEO-L152RE +NUCLEO-L152RE NUCLEO-L432KC NUCLEO-L452RE NUCLEO-L476RG -NUCLEO-L496ZG-P +NUCLEO-L496ZG-P NUCLEO-L552ZE-Q NUCLEO-U575ZI-Q OLIMEXINO-STM32 -Raspberry Pi Pico +Raspberry Pi Pico SAMD21-MINI SAMD21-XPLAINED-PRO SAME54-XPLAINED-PRO -SAME70-XPLAINED +SAME70-XPLAINED SAMG55-XPLAINED-PRO SAMV71-XPLAINED-ULTRA Smart Response XE -STM32-F4VE +STM32-F4VE STM32F030-DEMO THINGPLUS-RP2040 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