Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Nucleo446ZE + various fixes #533

Merged
merged 6 commits into from
Jan 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,23 +150,24 @@ documentation.
<td align="center">NUCLEO-F411RE</td>
<td align="center">NUCLEO-F429ZI</td>
<td align="center">NUCLEO-F446RE</td>
<td align="center">NUCLEO-F746ZG</td>
<td align="center">NUCLEO-F446ZE</td>
</tr><tr>
<td align="center">NUCLEO-F746ZG</td>
<td align="center">NUCLEO-G071RB</td>
<td align="center">NUCLEO-G431KB</td>
<td align="center">NUCLEO-G431RB</td>
<td align="center">NUCLEO-G474RE</td>
</tr><tr>
<td align="center">NUCLEO-G474RE</td>
<td align="center">NUCLEO-L152RE</td>
<td align="center">NUCLEO-L432KC</td>
<td align="center">NUCLEO-L476RG</td>
<td align="center">OLIMEXINO-STM32</td>
</tr><tr>
<td align="center">OLIMEXINO-STM32</td>
<td align="center">RASPBERRYPI</td>
<td align="center">SAMD21-MINI</td>
<td align="center">STM32-F4VE</td>
<td align="center">STM32F030F4P6-DEMO</td>
</tr><tr>
<td align="center">STM32F030F4P6-DEMO</td>
</tr>
</table>
<!--/bsptable-->
Expand Down
40 changes: 40 additions & 0 deletions examples/nucleo_f446ze/blink/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright (c) 2016-2017, Niklas Hauser
*
* 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 <modm/board.hpp>

using namespace Board;

int
main()
{
Board::initialize();
Leds::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)
{
Leds::write(1 << (counter % (Leds::width+1) ));
modm::delay(Button::read() ? 100ms : 500ms);

MODM_LOG_INFO << "loop: " << counter++ << modm::endl;
}

return 0;
}
9 changes: 9 additions & 0 deletions examples/nucleo_f446ze/blink/project.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<library>
<extends>modm:nucleo-f446ze</extends>
<options>
<option name="modm:build:build.path">../../../build/nucleo_f446ze/blink</option>
</options>
<modules>
<module>modm:build:scons</module>
</modules>
</library>
56 changes: 56 additions & 0 deletions examples/nucleo_f446ze/usbserial/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright (c) 2020, Erik Henriksson
* Copyright (c) 2020, Niklas Hauser
*
* 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 <tusb.h>

#include <modm/board.hpp>
#include <modm/io.hpp>
#include <modm/processing.hpp>

using namespace Board;

modm::IODeviceWrapper<UsbUart0, modm::IOBuffer::BlockIfFull> usb_io_device;
modm::IOStream usb_stream(usb_io_device);

modm::PeriodicTimer tmr{2.5s};

// Invoked when device is mounted
void tud_mount_cb() { tmr.restart(1s); }
// Invoked when device is unmounted
void tud_umount_cb() { tmr.restart(250ms); }
// Invoked when usb bus is suspended
// remote_wakeup_en : if host allow us to perform remote wakeup
// Within 7ms, device must draw an average of current less than 2.5 mA from bus
void tud_suspend_cb(bool) { tmr.restart(2.5s); }
// Invoked when usb bus is resumed
void tud_resume_cb() { tmr.restart(1s); }

int main()
{
Board::initialize();
Board::initializeUsbFs();

tusb_init();

uint8_t counter{0};
while (true)
{
tud_task();

if (tmr.execute())
{
Leds::toggle();
usb_stream << "Hello World from USB: " << (counter++) << modm::endl;
}
}

return 0;
}
13 changes: 13 additions & 0 deletions examples/nucleo_f446ze/usbserial/project.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<library>
<extends>modm:nucleo-f446ze</extends>
<options>
<option name="modm:build:build.path">../../../build/nucleo_f446ze/usbserial</option>
<option name="modm:tinyusb:config">device.cdc</option>
</options>
<modules>
<module>modm:build:scons</module>
<module>modm:tinyusb</module>
<module>modm:processing:timer</module>
<module>modm:io</module>
</modules>
</library>
4 changes: 2 additions & 2 deletions src/modm/board/disco_f429zi/board.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ struct SystemClock
.pllP = 2 // 360MHz / P=2 -> 180MHz = F_cpu
};
Rcc::enablePll(Rcc::PllSource::ExternalCrystal, pllFactors);
PWR->CR |= PWR_CR_ODEN; // Enable overdrive mode
while (not (PWR->CSR & PWR_CSR_ODRDY)) ;
// Required for 180 MHz clock
Rcc::enableOverdriveMode();
Rcc::setFlashLatency<Frequency>();
Rcc::enableSystemClock(Rcc::SystemClockSource::Pll);
Rcc::setApb1Prescaler(Rcc::Apb1Prescaler::Div4);
Expand Down
4 changes: 2 additions & 2 deletions src/modm/board/disco_f469ni/board.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ struct SystemClock
.pllP = 2, // 360MHz / P=2 -> 180MHz = F_cpu
};
Rcc::enablePll(Rcc::PllSource::ExternalCrystal, pllFactors);
PWR->CR |= PWR_CR_ODEN; // Enable overdrive mode
while (not (PWR->CSR & PWR_CSR_ODRDY)) ;
// Required for 180 MHz clock
Rcc::enableOverdriveMode();
Rcc::setFlashLatency<Frequency>();
Rcc::enableSystemClock(Rcc::SystemClockSource::Pll);
Rcc::setApb1Prescaler(Rcc::Apb1Prescaler::Div4);
Expand Down
4 changes: 2 additions & 2 deletions src/modm/board/disco_f746ng/board.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ struct SystemClock
.pllQ = 9 // 432MHz / Q=9 -> 48MHz = F_usb
};
Rcc::enablePll(Rcc::PllSource::ExternalClock, pllFactors);
PWR->CR1 |= PWR_CR1_ODEN; // Enable overdrive mode
while (not (PWR->CSR1 & PWR_CSR1_ODRDY)) ;
// Required for 216 MHz clock
Rcc::enableOverdriveMode();

Rcc::setFlashLatency<Frequency>();
Rcc::enableSystemClock(Rcc::SystemClockSource::Pll);
Expand Down
4 changes: 2 additions & 2 deletions src/modm/board/disco_f769ni/board.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ struct SystemClock
.pllP = 2 // 432MHz / P=2 -> 216MHz = F_cpu
};
Rcc::enablePll(Rcc::PllSource::ExternalClock, pllFactors);
PWR->CR1 |= PWR_CR1_ODEN; // Enable overdrive mode
while (not (PWR->CSR1 & PWR_CSR1_ODRDY)) ;
// Required for 216 MHz clock
Rcc::enableOverdriveMode();
Rcc::setFlashLatency<Frequency>();
Rcc::enableSystemClock(Rcc::SystemClockSource::Pll);
// APB1 is running only at 27MHz, since AHB / 4 = 54MHz > 45MHz limit!
Expand Down
2 changes: 2 additions & 0 deletions src/modm/board/nucleo_f446re/board.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ struct SystemClock {
.pllP = 2, // 360MHz / P= 2 -> 180MHz = F_cpu
};
Rcc::enablePll(Rcc::PllSource::InternalClock, pllFactors);
// Required for 180 MHz clock
Rcc::enableOverdriveMode();
// set flash latency
Rcc::setFlashLatency<Frequency>();
// switch system clock to PLL output
Expand Down
174 changes: 174 additions & 0 deletions src/modm/board/nucleo_f446ze/board.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
/*
* Copyright (c) 2016-2017, Sascha Schade
* Copyright (c) 2016-2018, Niklas Hauser
* Copyright (c) 2021, Christopher Durand
*
* 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_F446ZE_HPP
#define MODM_STM32_NUCLEO_F446ZE_HPP

#include <modm/platform.hpp>
#include <modm/architecture/interface/clock.hpp>
#include <modm/debug/logger.hpp>
/// @ingroup modm_board_nucleo_f446ze
#define MODM_BOARD_HAS_LOGGER

using namespace modm::platform;

/// @ingroup modm_board_nucleo_f446ze
namespace Board
{
using namespace modm::literals;

/// STM32F446 running at 180 MHz from external 8 MHz STLink clock
struct SystemClock
{
static constexpr uint32_t Frequency = 180_MHz;
static constexpr uint32_t Ahb = Frequency;
static constexpr uint32_t Apb1 = Frequency / 4;
static constexpr uint32_t Apb2 = Frequency / 2;

static constexpr uint32_t Adc = Apb2;

static constexpr uint32_t Spi1 = Apb2;
static constexpr uint32_t Spi2 = Apb1;
static constexpr uint32_t Spi3 = Apb1;
static constexpr uint32_t Spi4 = Apb2;
static constexpr uint32_t Spi5 = Apb2;

static constexpr uint32_t Usart1 = Apb2;
static constexpr uint32_t Usart2 = Apb1;
static constexpr uint32_t Usart3 = Apb1;
static constexpr uint32_t Uart4 = Apb1;
static constexpr uint32_t Uart5 = Apb1;
static constexpr uint32_t Usart6 = Apb2;

static constexpr uint32_t I2c1 = Apb1;
static constexpr uint32_t I2c2 = Apb1;
static constexpr uint32_t I2c3 = Apb1;

static constexpr uint32_t Apb1Timer = Apb1 * 2;
static constexpr uint32_t Apb2Timer = Apb2 * 1;
static constexpr uint32_t Timer1 = Apb2Timer;
static constexpr uint32_t Timer2 = Apb1Timer;
static constexpr uint32_t Timer3 = Apb1Timer;
static constexpr uint32_t Timer4 = Apb1Timer;
static constexpr uint32_t Timer5 = Apb1Timer;
static constexpr uint32_t Timer9 = Apb2Timer;
static constexpr uint32_t Timer10 = Apb2Timer;
static constexpr uint32_t Timer11 = Apb2Timer;

static constexpr uint32_t Usb = 48_MHz;

static bool inline
enable()
{
Rcc::enableExternalClock(); // 8MHz
const Rcc::PllFactors pllFactors{
.pllM = 4, // 8MHz / M= 4 -> 2MHz
.pllN = 180, // 2MHz * N=180 -> 360MHz
.pllP = 2, // 360MHz / P= 2 -> 180MHz = F_cpu
};
Rcc::enablePll(Rcc::PllSource::ExternalClock, pllFactors);

const Rcc::PllSaiFactors pllSaiFactors{
.pllSaiM = 4, // 8MHz / M= 4 -> 2MHz
.pllSaiN = 96, // 2MHz * N= 96 -> 192MHz
.pllSaiP = 4, // 192MHz / P= 4 -> 48MHz = F_usb
};
Rcc::enablePllSai(pllSaiFactors);

// "Overdrive" is required for guaranteed stable 180 MHz operation
Rcc::enableOverdriveMode();
Rcc::setFlashLatency<Frequency>();
// switch system clock to PLL output
Rcc::enableSystemClock(Rcc::SystemClockSource::Pll);
Rcc::setAhbPrescaler(Rcc::AhbPrescaler::Div1);
Rcc::setClock48Source(Rcc::Clock48Source::PllSaiP);
// APB1 has max. 45MHz
Rcc::setApb1Prescaler(Rcc::Apb1Prescaler::Div4);
Rcc::setApb2Prescaler(Rcc::Apb2Prescaler::Div2);
// update frequencies for busy-wait delay functions
Rcc::updateCoreFrequency<Frequency>();

return true;
}
};

// Arduino Footprint
#include "nucleo144_arduino.hpp"

using Button = GpioInputC13;

using LedGreen = GpioOutputB0; // LED1 [Green]
using LedBlue = GpioOutputB7; // LED2 [Blue]
using LedRed = GpioOutputB14; // LED3 [Red]
using Leds = SoftwareGpioPort< LedRed, LedBlue, LedGreen >;

namespace usb
{
using Vbus = GpioA9;
using Id = GpioA10;
using Dm = GpioA11;
using Dp = GpioA12;

using Overcurrent = GpioInputG7; // OTG_FS_OverCurrent
using Power = GpioOutputG6; // OTG_FS_PowerSwitchOn

using Device = UsbFs;
}

namespace stlink
{
using Tx = GpioOutputD8;
using Rx = GpioInputD9;
using Uart = Usart3;
}

using LoggerDevice = modm::IODeviceWrapper< stlink::Uart, modm::IOBuffer::BlockIfFull >;


inline void
initialize()
{
SystemClock::enable();
SysTickTimer::initialize<SystemClock>();

stlink::Uart::connect<stlink::Tx::Tx, stlink::Rx::Rx>();
stlink::Uart::initialize<SystemClock, 115200_Bd>();

LedGreen::setOutput(modm::Gpio::Low);
LedBlue::setOutput(modm::Gpio::Low);
LedRed::setOutput(modm::Gpio::Low);

Button::setInput();
Button::setInputTrigger(Gpio::InputTrigger::RisingEdge);
Button::enableExternalInterrupt();
// Button::enableExternalInterruptVector(12);
}

inline void
initializeUsbFs()
{
usb::Device::initialize<SystemClock>();
usb::Device::connect<usb::Dm::Dm, usb::Dp::Dp, usb::Id::Id>();

usb::Overcurrent::setInput();
usb::Vbus::setInput();
// Force device mode
USB_OTG_FS->GUSBCFG |= USB_OTG_GUSBCFG_FDMOD;
modm::delay_ms(25);
// Enable VBUS sense (B device) via pin PA9
USB_OTG_FS->GCCFG |= USB_OTG_GCCFG_VBDEN;
}

}

#endif // MODM_STM32_NUCLEO_F446ZE_HPP
16 changes: 16 additions & 0 deletions src/modm/board/nucleo_f446ze/board.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<library>
<repositories>
<repository>
<path>../../../../repo.lb</path>
</repository>
</repositories>

<options>
<option name="modm:target">stm32f446zet6</option>

<option name="modm:platform:uart:3:buffer.tx">2048</option>
</options>
<modules>
<module>modm:board:nucleo-f446ze</module>
</modules>
</library>
Loading