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 timeout ctor to hal::stm32f1::can_peripheral_manager #91

Merged
merged 1 commit into from
Jan 19, 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
45 changes: 45 additions & 0 deletions include/libhal-arm-mcu/stm32f1/can.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@

#pragma once

#include <chrono>
#include <libhal/can.hpp>
#include <libhal/steady_clock.hpp>
#include <libhal/units.hpp>

#include "pin.hpp"
Expand All @@ -41,6 +43,16 @@ class can final : public hal::can
*/
struct can_peripheral_manager final
{
/**
* @brief Named parameter for enabling self test at driver construction
*
*/
enum class self_test : hal::u8
{
off = 0,
on = 1,
};

/**
* @brief Contains a filter and word index, used by filter implementations to
* determine which bits in the filter registers to modify.
Expand Down Expand Up @@ -351,18 +363,51 @@ struct can_peripheral_manager final
u32 extended = 0;
};

/**
* @brief Construct a new can peripheral manager object
*
* @deprecated Calling this constructor is problematic as it can halt the
* system if a hardware can transceiver is not connected to the CAN RX and CAN
* TX pins. Use the constructor that accepts a `hal::steady_clock` and timeout
* time instead.
*
* @param p_baud_rate - set baud rate of the device
* @param p_pins - CAN bus RX and TX pin selection
* @param p_disabled_ids - IDs to use as filtering values when a filter is set
* to be disabled. Choose IDs you expect will never appear on the CAN BUS.
* @throw hal::operation_not_supported - if the baud rate is not usable
*/
[[deprecated("Calling this constructor is problematic as it can halt the "
"system if a hardware can transceiver is not connected to the "
"CAN RX and CAN TX pins. Use the constructor that accepts a "
"`hal::steady_clock` and timeout time instead.")]]
can_peripheral_manager(
hal::u32 p_baud_rate,
can_pins p_pins = can_pins::pa11_pa12,
disable_ids p_disabled_ids = disable_ids{ .standard = 0, .extended = 0 });

/**
* @brief Construct a new can peripheral manager object
*
* @param p_baud_rate - set baud rate of the device
* @param p_clock - a steady clock used to determine if initialization has
* exceeded the p_timeout_time.
* @param p_timeout_time - the amount of time to wait for initialization
* before throwing `hal::timed_out`.
* @param p_pins - CAN bus RX and TX pin selection
* @param p_enable_self_test - determines if self test is enabled at
* construction.
* @param p_disabled_ids - IDs to use as filtering values when a filter is set
* to be disabled. Choose IDs you expect will never appear on the CAN BUS.
* @throw hal::operation_not_supported - if the baud rate is not usable
* @throw hal::timed_out - if can peripheral initialization
*/
can_peripheral_manager(
hal::u32 p_baud_rate,
hal::steady_clock& p_clock,
hal::time_duration p_timeout_time = std::chrono::milliseconds(1),
can_pins p_pins = can_pins::pa11_pa12,
self_test p_enable_self_test = self_test::off,
disable_ids p_disabled_ids = disable_ids{ .standard = 0, .extended = 0 });

can_peripheral_manager(can_peripheral_manager const&) = delete;
Expand Down
81 changes: 81 additions & 0 deletions src/stm32f1/can.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

#include <bitset>
#include <cstdint>
#include <libhal/steady_clock.hpp>
#include <libhal/units.hpp>
#include <optional>

Expand All @@ -28,6 +29,7 @@
#include <libhal-util/can.hpp>
#include <libhal-util/enum.hpp>
#include <libhal-util/static_callable.hpp>
#include <libhal-util/steady_clock.hpp>
#include <libhal/can.hpp>
#include <libhal/error.hpp>
#include <nonstd/scope.hpp>
Expand Down Expand Up @@ -74,6 +76,21 @@ void exit_initialization()
}
}

void timed_exit_initialization(hal::steady_clock& p_clock,
hal::time_duration p_timeout_time)
{
// Leave Initialization mode
set_master_mode(master_control::initialization_request, false);

auto const deadline = hal::future_deadline(p_clock, p_timeout_time);
while (deadline > p_clock.uptime()) {
if (not get_master_status(master_status::initialization_acknowledge)) {
return;
}
}
hal::safe_throw(hal::timed_out(nullptr));
}

void configure_baud_rate(hal::u32 p_baud_rate)
{
auto const can_frequency = frequency(peripheral::can1);
Expand Down Expand Up @@ -329,6 +346,45 @@ void setup_can(hal::u32 p_baud_rate, can_pins p_pins)
remap_pins(p_pins);
}

void setup_can(hal::u32 p_baud_rate,
can_pins p_pins,
can_peripheral_manager::self_test p_enable_self_test,
hal::steady_clock& p_clock,
hal::time_duration p_timeout_time)
{
power_on(peripheral::can1);

set_master_mode(master_control::sleep_mode_request, false);
set_master_mode(master_control::no_automatic_retransmission, false);
set_master_mode(master_control::automatic_bus_off_management, false);

enter_initialization();

configure_baud_rate(p_baud_rate);

switch (p_pins) {
case can_pins::pa11_pa12:
configure_pin({ .port = 'A', .pin = 11 }, input_pull_up);
configure_pin({ .port = 'A', .pin = 12 }, push_pull_alternative_output);
break;
case can_pins::pb9_pb8:
configure_pin({ .port = 'B', .pin = 8 }, input_pull_up);
configure_pin({ .port = 'B', .pin = 9 }, push_pull_alternative_output);
break;
case can_pins::pd0_pd1:
configure_pin({ .port = 'D', .pin = 0 }, input_pull_up);
configure_pin({ .port = 'D', .pin = 1 }, push_pull_alternative_output);
break;
}

bit_modify(can1_reg->BTR)
.insert<bus_timing::loop_back_mode>(hal::value(p_enable_self_test));

remap_pins(p_pins);

timed_exit_initialization(p_clock, p_timeout_time);
}

can::message_t read_receive_mailbox()
{
can::message_t message{ .id = 0 };
Expand Down Expand Up @@ -686,6 +742,31 @@ can_peripheral_manager::can_peripheral_manager(hal::u32 p_baud_rate,
.set<interrupt_enable_register::fifo1_message_pending>();
}

can_peripheral_manager::can_peripheral_manager(
hal::u32 p_baud_rate,
hal::steady_clock& p_clock,
hal::time_duration p_timeout_time,
can_pins p_pins,
self_test p_enable_self_test,
disable_ids p_disabled_ids)
{
current_baud_rate = p_baud_rate;
disable_id = p_disabled_ids;
setup_can(p_baud_rate, p_pins, p_enable_self_test, p_clock, p_timeout_time);

initialize_interrupts();

// Setup interrupt service routines
cortex_m::enable_interrupt(irq::can1_rx0, handler_circular_buffer_interrupt);
cortex_m::enable_interrupt(irq::can1_rx1, handler_circular_buffer_interrupt);
cortex_m::enable_interrupt(irq::can1_sce, handler_status_change_interrupt);

bit_modify(can1_reg->IER)
.set<interrupt_enable_register::fifo0_message_pending>();
bit_modify(can1_reg->IER)
.set<interrupt_enable_register::fifo1_message_pending>();
}

void can_peripheral_manager::enable_self_test(bool p_enable)
{
enter_initialization();
Expand Down
Loading