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 UART to stm32f411 #85

Merged
merged 4 commits into from
Jan 14, 2025
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
6 changes: 5 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ libhal_test_and_make_library(

# stm32_generic
src/stm32_generic/spi.cpp
src/stm32_generic/uart.cpp

# stm32f1
src/stm32f1/can_reg.hpp
Expand All @@ -66,12 +67,15 @@ libhal_test_and_make_library(
src/stm32f1/spi.cpp

# stm32f411
src/stm32f411/clock.cpp
src/stm32f411/dma.cpp
src/stm32f411/input_pin.cpp
src/stm32f411/interrupt.cpp
src/stm32f411/output_pin.cpp
src/stm32f411/pin.cpp
src/stm32f411/power.cpp
src/stm32f411/spi.cpp
src/stm32f411/clock.cpp
src/stm32f411/uart.cpp

# stm32f40
src/stm32f40/output_pin.cpp
Expand Down
3 changes: 2 additions & 1 deletion demos/applications/uart.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#include <array>
FluffyFTW marked this conversation as resolved.
Show resolved Hide resolved
#include <libhal-util/serial.hpp>
#include <libhal-util/steady_clock.hpp>

#include <libhal/timeout.hpp>
#include <resource_list.hpp>

void application(resource_list& p_map)
Expand All @@ -31,7 +33,6 @@ void application(resource_list& p_map)

std::string_view message = "Hello, World!\n";
hal::print(console, message);

// Echo anything received
std::array<hal::byte, 64> read_buffer;
console.write(console.read(read_buffer).data);
Expand Down
5 changes: 5 additions & 0 deletions demos/platforms/stm32f411re.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@
#include <libhal-arm-mcu/startup.hpp>
#include <libhal-arm-mcu/stm32f411/clock.hpp>
#include <libhal-arm-mcu/stm32f411/constants.hpp>
#include <libhal-arm-mcu/stm32f411/dma.hpp>
#include <libhal-arm-mcu/stm32f411/input_pin.hpp>
#include <libhal-arm-mcu/stm32f411/output_pin.hpp>
#include <libhal-arm-mcu/stm32f411/pin.hpp>
#include <libhal-arm-mcu/stm32f411/spi.hpp>
#include <libhal-arm-mcu/stm32f411/uart.hpp>
#include <libhal-arm-mcu/system_control.hpp>
#include <libhal/initializers.hpp>
#include <libhal/output_pin.hpp>
Expand All @@ -47,6 +49,9 @@ void initialize_platform(resource_list& p_resources)
hal::stm32f411::output_pin chip_select(hal::stm32f411::peripheral::gpio_b,
13);

static hal::stm32f411::uart uart2(
hal::port<2>, hal::buffer<128>, { .baud_rate = 115200 });
p_resources.console = &uart2;
p_resources.reset = []() { hal::cortex_m::reset(); };
p_resources.status_led = &led;
p_resources.clock = &steady_clock;
Expand Down
63 changes: 63 additions & 0 deletions include/libhal-arm-mcu/stm32_generic/uart.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright 2024 Khalil Estell
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma once

#include <cstdint>

#include <libhal/initializers.hpp>
#include <libhal/serial.hpp>

namespace hal::stm32_generic {
class uart
{
public:
uart(void* p_uart, std::span<hal::byte> p_receive_buffer);
/**
* @brief STM32 Common write function
*
* @param p_data Writes the data to the UART registers
* @return serial::write_t
*/
serial::write_t uart_write(std::span<hal::byte const> p_data);
/**
* @brief
*
* @param p_data Where the data gets copied to
* @param p_dma_cursor_position Where the DMA is set to
* @return serial::read_t
*/
serial::read_t uart_read(std::span<hal::byte>& p_data,
std::uint32_t const& p_dma_cursor_position);
/**
* @brief Configures the UART to the set settings
*
* @param p_settings UART settings
* @param p_frequency Bus frequency
*/
void configure(serial::settings const& p_settings, hertz p_frequency);
uint32_t volatile* data_register();
void flush(std::uint32_t p_dma_cursor_position);
std::uint32_t buffer_size();

private:
void configure_baud_rate(hal::hertz p_frequency,
serial::settings const& p_settings);
void configure_format(serial::settings const& p_settings);

void* m_uart;
std::span<hal::byte> m_receive_buffer;
std::uint16_t m_read_index;
};
} // namespace hal::stm32_generic
4 changes: 3 additions & 1 deletion include/libhal-arm-mcu/stm32f411/constants.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

#include <cstdint>

#include <libhal-armcortex/interrupt.hpp>

namespace hal::stm32f411 {

/// Number of bits between each enable register
Expand Down Expand Up @@ -82,7 +84,7 @@ enum class peripheral : std::uint32_t
};

/// List of interrupt request numbers for this platform
enum class irq : std::uint16_t
enum class irq : cortex_m::irq_t
{
/// Window WatchDog
window_watchdog = 0,
Expand Down
42 changes: 42 additions & 0 deletions include/libhal-arm-mcu/stm32f411/dma.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright 2024 Khalil Estell
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma once

#include <cstdint>

#include <libhal/units.hpp>

#include "constants.hpp"

namespace hal::stm32f411 {
enum class dma : std::uint32_t
{
dma1 = static_cast<uint32_t>(peripheral::dma1),
dma2 = static_cast<uint32_t>(peripheral::dma2),
};
/**
* @brief Sets up the DMA memory to memory transfer mode
*
* @param p_dma Select DMA
FluffyFTW marked this conversation as resolved.
Show resolved Hide resolved
* @param p_source source span of bytes
* @param p_destination destination span of bytes
*/
void set_dma_memory_transfer(dma p_dma,
std::span<byte const> const p_source,
FluffyFTW marked this conversation as resolved.
Show resolved Hide resolved
std::span<byte> const p_destination);
/// Maximum length of a buffer that the stm32f411 series dma controller can
/// handle.
constexpr std::uint32_t max_dma_length = 65'535;
} // namespace hal::stm32f411
26 changes: 26 additions & 0 deletions include/libhal-arm-mcu/stm32f411/interrupt.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright 2024 Khalil Estell
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma once

namespace hal::stm32f411 {
/**
* @brief Initialize interrupts for the stm32f411 series processors
*
* Only initializes after the first call. Does nothing afterwards. Can be
* called multiple times without issue.
*
*/
void initialize_interrupts();
} // namespace hal::stm32f411
78 changes: 78 additions & 0 deletions include/libhal-arm-mcu/stm32f411/uart.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// Copyright 2024 Khalil Estell
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma once

#include <cstdint>

#include <libhal-arm-mcu/stm32_generic/uart.hpp>
#include <libhal/initializers.hpp>
#include <libhal/serial.hpp>

#include "constants.hpp"
#include "dma.hpp"

namespace hal::stm32f411 {
class uart final : public hal::serial
{
public:
/**
* @brief Construct a new uart object
*
* @param p_port - desired port number
* @param p_buffer - receive buffer size (statically allocated buffer)
* @param p_settings - initial serial settings
*/
uart(hal::port_param auto p_port,
hal::buffer_param auto p_buffer,
serial::settings const& p_settings = {})
: uart(p_port(), hal::create_unique_static_buffer(p_buffer), p_settings)
{
static_assert(p_buffer() <= max_dma_length,
"Buffer size cannot exceed 65,535 bytes,");
static_assert((1 <= p_port() and p_port() <= 2) or p_port() == 6,
"stm32f411 only supports ports from 1 to 2");
}

/**
* @brief Construct a new uart object using runtime values
*
* @param p_port - runtime value for p_port
* @param p_buffer - external buffer to be used as the receive buffer
* @param p_settings - initial serial settings
* @throws hal::operation_not_supported - if the port is not supported or the
* buffer is outside of the maximum dma length.
*/
uart(hal::runtime,
std::uint8_t p_port,
std::span<hal::byte> p_buffer,
serial::settings const& p_settings = {});

private:
uart(std::uint8_t p_port,
std::span<hal::byte> p_receive_buffer,
serial::settings const& p_settings);

void driver_configure(settings const& p_settings) override;
write_t driver_write(std::span<hal::byte const> p_data) override;
read_t driver_read(std::span<hal::byte> p_data) override;
void driver_flush() override;

std::uint32_t dma_cursor_position();
stm32_generic::uart m_stm32_uart;
peripheral m_dma;
uint8_t m_dma_stream;
peripheral m_id;
};
} // namespace hal::stm32f411
Loading
Loading