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

SPI support for stm32-extended USART #122

Merged
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
105 changes: 105 additions & 0 deletions examples/nucleo_l432kc/gyroscope/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
* Copyright (c) 2014-2018, Niklas Hauser
* Copyright (c) 2015, Kevin Läufer
* Copyright (c) 2015, Martin Esser
* Copyright (c) 2018, 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/.
*/
// ----------------------------------------------------------------------------

#include <modm/board.hpp>
#include <modm/driver/inertial/l3gd20.hpp>
#include <modm/processing.hpp>
#include <modm/math/filter.hpp>

// Example for L3gd20 gyroscope connected to SPI USART interface

struct UartSpi
{
using Ck = GpioA8;
using Tx = GpioA9;
using Rx = GpioA10;
using Cs = GpioA11;

using Master = UartSpiMaster1;
};

using Transport = modm::Lis3TransportSpi<UartSpi::Master, UartSpi::Cs>;

namespace
{
modm::l3gd20::Data data;
modm::L3gd20<Transport> gyro{data};
}

class ReaderThread : public modm::pt::Protothread
{
public:
bool
update()
{
PT_BEGIN();

// ping the device until it responds
while(true)
{
// we wait until the task started
if (PT_CALL(gyro.ping()))
break;
// otherwise, try again in 100ms
this->timeout.restart(100);
Board::LedD13::set();
PT_WAIT_UNTIL(this->timeout.isExpired());
Board::LedD13::reset();
}

PT_CALL(gyro.configure(gyro.Scale::Dps250, gyro.MeasurementRate::Hz380));

while (true)
{
PT_CALL(gyro.readRotation());

averageX.update(gyro.getData().getX());
averageY.update(gyro.getData().getY());
averageZ.update(gyro.getData().getZ());

MODM_LOG_INFO.printf("x: %.2f, y: %.2f, z: %.2f \n",
averageX.getValue(),
averageY.getValue(),
averageZ.getValue());

this->timeout.restart(50);
PT_WAIT_UNTIL(this->timeout.isExpired());
}

PT_END();
}

private:
modm::ShortTimeout timeout;
modm::filter::MovingAverage<float, 10> averageX;
modm::filter::MovingAverage<float, 10> averageY;
modm::filter::MovingAverage<float, 10> averageZ;
};

ReaderThread reader;

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

UartSpi::Master::connect<UartSpi::Ck::Ck, UartSpi::Tx::Tx, UartSpi::Rx::Rx>();
UartSpi::Master::initialize<Board::systemClock, 8'000'000, modm::Tolerance::Exact>();

while (1) {
reader.update();
}

return 0;
}
14 changes: 14 additions & 0 deletions examples/nucleo_l432kc/gyroscope/project.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<library>
<extends>modm:board:nucleo-l432kc</extends>
<options>
<option name=":build:build.path">../../../build/nucleo_l432kc/gyroscope</option>
</options>
<modules>
<module>:driver:l3gd20</module>
<module>:math:filter</module>
<module>:platform:uart.spi:1</module>
<module>:processing:timer</module>
<module>:processing:protothread</module>
<module>:build:scons</module>
</modules>
</library>
32 changes: 32 additions & 0 deletions examples/nucleo_l432kc/uart_spi/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright (c) 2013, Kevin Läufer
* Copyright (c) 2013-2018, Niklas Hauser
* Copyright (c) 2018, 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/.
*/
// ----------------------------------------------------------------------------

#include <modm/board.hpp>


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

// Enable Uart SPI 1
UartSpiMaster1::connect<GpioA8::Ck, GpioA9::Tx, GpioA10::Rx>();
UartSpiMaster1::initialize<Board::systemClock, 1'000'000, modm::Tolerance::Exact>();

while (1)
{
UartSpiMaster1::transferBlocking(0xF0);
}

return 0;
}
11 changes: 11 additions & 0 deletions examples/nucleo_l432kc/uart_spi/project.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<library>
<extends>modm:board:nucleo-l432kc</extends>
<options>
<option name=":build:build.path">../../../build/nucleo_l432kc/uart_spi</option>
</options>
<modules>
<module>:platform:gpio</module>
<module>:platform:uart.spi:1</module>
<module>:build:scons</module>
</modules>
</library>
15 changes: 11 additions & 4 deletions src/modm/platform/spi/stm32_uart/module.lb
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ def get_properties(env):
return properties

class Instance(Module):
def __init__(self, instance):
def __init__(self, instance, is_extended = False):
self.instance = instance
self.is_extended = is_extended

def init(self, module):
module.name = str(self.instance)
Expand All @@ -33,6 +34,7 @@ class Instance(Module):
def build(self, env):
properties = get_properties(env)
properties["id"] = self.instance
properties["extended"] = self.is_extended

env.substitutions = properties
env.outbasepath = "modm/src/modm/platform/spi"
Expand All @@ -47,7 +49,7 @@ def init(module):

def prepare(module, options):
device = options[":target"]
if not device.has_driver("usart:stm32"):
if not device.has_driver("usart:stm32") and not device.has_driver("usart:stm32-extended"):
return False

module.depends(
Expand All @@ -56,8 +58,13 @@ def prepare(module, options):
":platform:gpio",
":platform:uart")

for instance in device.get_driver("usart:stm32")["instance"]:
module.add_submodule(Instance(int(instance)))
if device.get_driver("usart:stm32-extended"):
for instance in device.get_driver("usart:stm32-extended")["instance"]:
module.add_submodule(Instance(int(instance), True))

if device.get_driver("usart:stm32"):
for instance in device.get_driver("usart:stm32")["instance"]:
module.add_submodule(Instance(int(instance)))

return True

Expand Down
7 changes: 7 additions & 0 deletions src/modm/platform/spi/stm32_uart/uart_spi_master.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,15 @@ public:
oversample);
%% endif

%% if extended
UsartHal{{ id }}::disableOperation();
%% endif
UsartHal{{ id }}::setLastBitClockPulse(UsartHal{{ id }}::LastBitClockPulse::Output);
UsartHal{{ id }}::setSpiClock(UsartHal{{ id }}::SpiClock::Enabled);
%% if extended
UsartHal{{ id }}::enableOperation();
%% endif

UsartHal{{ id }}::setTransmitterEnable(true);
UsartHal{{ id }}::setReceiverEnable(true);
dataOrder = DataOrder::MsbFirst;
Expand Down
8 changes: 8 additions & 0 deletions src/modm/platform/uart/stm32/uart_hal.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,14 @@ public:
static inline void
setReceiverEnable(bool enable);

/// Set the UE (USART enable) bit
static inline void
enableOperation();

/// Clear the UE (USART enable) bit
static inline void
disableOperation();

/// Returns true if data has been received
static inline bool
isReceiveRegisterNotEmpty();
Expand Down
77 changes: 77 additions & 0 deletions src/modm/platform/uart/stm32/uart_hal_impl.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@
void
modm::platform::{{ name }}::setParity(const Parity parity)
{
%% if "extended" in driver["type"]
const bool usartEnabled = ({{ peripheral }}->CR1 & USART_CR1_UE);
if(usartEnabled) {
disableOperation();
}
%% endif

uint32_t flags = {{ peripheral }}->CR1;
flags &= ~(USART_CR1_PCE | USART_CR1_PS | USART_CR1_M);
flags |= static_cast<uint32_t>(parity);
Expand All @@ -33,6 +40,12 @@ modm::platform::{{ name }}::setParity(const Parity parity)
flags |= USART_CR1_M;
}
{{ peripheral }}->CR1 = flags;

%% if "extended" in driver["type"]
if(usartEnabled) {
enableOperation();
}
%% endif
}

void
Expand Down Expand Up @@ -109,41 +122,93 @@ modm::platform::{{ name }}::initializeWithBrr(uint16_t brr, Parity parity)
void
modm::platform::{{ name }}::setOversamplingMode(OversamplingMode mode)
{
%% if "extended" in driver["type"]
const bool usartEnabled = ({{ peripheral }}->CR1 & USART_CR1_UE);
if(usartEnabled) {
disableOperation();
}
%% endif

if(mode == OversamplingMode::By16) {
{{ peripheral }}->CR1 &= ~static_cast<uint32_t>(OversamplingMode::By8);
} else {
{{ peripheral }}->CR1 |= static_cast<uint32_t>(OversamplingMode::By8);
}

%% if "extended" in driver["type"]
if(usartEnabled) {
enableOperation();
}
%% endif
}
%% endif
%% if uart_name == "Usart"

void
modm::platform::{{ name }}::setSpiClock(SpiClock clk)
{
%% if "extended" in driver["type"]
const bool usartEnabled = ({{ peripheral }}->CR1 & USART_CR1_UE);
if(usartEnabled) {
disableOperation();
}
%% endif

if(clk == SpiClock::Disabled) {
{{ peripheral }}->CR2 &= ~static_cast<uint32_t>(SpiClock::Enabled);
} else {
{{ peripheral }}->CR2 |= static_cast<uint32_t>(SpiClock::Enabled);
}

%% if "extended" in driver["type"]
if(usartEnabled) {
enableOperation();
}
%% endif
}

void
modm::platform::{{ name }}::setSpiDataMode(SpiDataMode mode)
{
%% if "extended" in driver["type"]
const bool usartEnabled = ({{ peripheral }}->CR1 & USART_CR1_UE);
if(usartEnabled) {
disableOperation();
}
%% endif

{{ peripheral }}->CR2 =
({{ peripheral }}->CR2 & ~static_cast<uint32_t>(SpiDataMode::Mode3))
| static_cast<uint32_t>(mode);

%% if "extended" in driver["type"]
if(usartEnabled) {
enableOperation();
}
%% endif
}

void
modm::platform::{{ name }}::setLastBitClockPulse(LastBitClockPulse pulse)
{
%% if "extended" in driver["type"]
const bool usartEnabled = ({{ peripheral }}->CR1 & USART_CR1_UE);
if(usartEnabled) {
disableOperation();
}
%% endif

if(pulse == LastBitClockPulse::DoNotOutput) {
{{ peripheral }}->CR2 &= ~static_cast<uint32_t>(LastBitClockPulse::Output);
} else {
{{ peripheral }}->CR2 |= static_cast<uint32_t>(LastBitClockPulse::Output);
}

%% if "extended" in driver["type"]
if(usartEnabled) {
enableOperation();
}
%% endif
}
%% endif

Expand Down Expand Up @@ -187,6 +252,18 @@ modm::platform::{{ name }}::setReceiverEnable(bool enable)
}
}

void
modm::platform::{{ name }}::enableOperation()
{
{{ peripheral }}->CR1 |= USART_CR1_UE;
}

void
modm::platform::{{ name }}::disableOperation()
{
{{ peripheral }}->CR1 &= ~USART_CR1_UE;
}

bool
modm::platform::{{ name }}::isReceiveRegisterNotEmpty()
{
Expand Down