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

feat(tempdeck): grab reason for last reset #489

Open
wants to merge 2 commits into
base: edge
Choose a base branch
from
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ extern "C" {
*/
void thermal_hardware_init();

/**
* @brief Reports the reason for the last fimrware reset, according to
* the HAL RCC flag.
*
* */
uint16_t thermal_hardware_reset_reason();

/**
* @brief Enable the peltiers. If the peltiers are already enabled,
* this will have no real effect.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ class ThermalPolicy {

auto disable_peltier() -> void;

auto last_reset_reason() -> uint16_t;

auto set_peltier_heat_power(double power) -> bool;

auto set_peltier_cool_power(double power) -> bool;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,15 @@ struct SimThermalPolicy : public m24128_test_policy::TestM24128Policy {
return _fan * MAX_RPM;
}

auto last_reset_reason() -> uint16_t { return _reset_reason; }

auto set_reset_reason(uint16_t sim_reason) -> void {
_reset_reason = sim_reason;
}

private:
bool _enabled = false;
double _power = 0.0F; // Positive for heat, negative for cool
double _fan = 0.0F;
uint16_t _reset_reason = 0;
};
38 changes: 38 additions & 0 deletions stm32-modules/include/tempdeck-gen3/tempdeck-gen3/gcodes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,44 @@ struct GetSystemInfo {
}
};

struct GetResetReason {
/*
* M114- GetResetReason retrieves the value of the RCC reset flag
* that was captured at the beginning of the hardware setup
* */
using ParseResult = std::optional<GetResetReason>;
static constexpr auto prefix = std::array{'M', '1', '1', '4'};

template <typename InputIt, typename InLimit>
requires std::forward_iterator<InputIt> &&
std::sized_sentinel_for<InputIt, InLimit>
static auto write_response_into(InputIt buf, InLimit limit, uint16_t reason)
-> InputIt {
int res = 0;
// print a hexadecimal representation of the reset flags
res = snprintf(&*buf, (limit - buf), "M114 Last Reset Reason: %X OK\n",
reason);
if (res <= 0) {
return buf;
}
return buf + res;
}
template <typename InputIt, typename Limit>
requires std::forward_iterator<InputIt> &&
std::sized_sentinel_for<Limit, InputIt>
static auto parse(const InputIt& input, Limit limit)
-> std::pair<ParseResult, InputIt> {
auto working = prefix_matches(input, limit, prefix);
if (working == input) {
return std::make_pair(ParseResult(), input);
}
if (working != limit && !std::isspace(*working)) {
return std::make_pair(ParseResult(), input);
}
return std::make_pair(ParseResult(GetResetReason()), working);
}
};

struct SetSerialNumber {
using ParseResult = std::optional<SetSerialNumber>;
static constexpr auto prefix = std::array{'M', '9', '9', '6'};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,14 @@ class HostCommsTask {
using Aggregator = typename tasks::Tasks<QueueImpl>::QueueAggregator;

private:
using GCodeParser = gcode::GroupParser<
gcode::GetSystemInfo, gcode::EnterBootloader, gcode::SetSerialNumber,
gcode::GetTemperatureDebug, gcode::SetTemperature, gcode::DeactivateAll,
gcode::SetPeltierDebug, gcode::SetFanManual, gcode::SetFanAutomatic,
gcode::SetPIDConstants, gcode::SetOffsetConstants,
gcode::GetOffsetConstants, gcode::GetThermalPowerDebug>;
using GCodeParser =
gcode::GroupParser<gcode::GetSystemInfo, gcode::EnterBootloader,
gcode::SetSerialNumber, gcode::GetTemperatureDebug,
gcode::SetTemperature, gcode::DeactivateAll,
gcode::SetPeltierDebug, gcode::SetFanManual,
gcode::SetFanAutomatic, gcode::SetPIDConstants,
gcode::SetOffsetConstants, gcode::GetOffsetConstants,
gcode::GetThermalPowerDebug, gcode::GetResetReason>;
using AckOnlyCache =
// NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers)
AckCache<10, gcode::EnterBootloader, gcode::SetSerialNumber,
Expand All @@ -48,6 +50,7 @@ class HostCommsTask {
using GetTempDebugCache = AckCache<4, gcode::GetTemperatureDebug>;
using GetOffsetConstantsCache = AckCache<4, gcode::GetOffsetConstants>;
using GetThermalPowerDebugCache = AckCache<4, gcode::GetThermalPowerDebug>;
using GetResetReasonCache = AckCache<8, gcode::GetResetReason>;

public:
static constexpr size_t TICKS_TO_WAIT_ON_SEND = 10;
Expand All @@ -64,7 +67,9 @@ class HostCommsTask {
// NOLINTNEXTLINE(readability-redundant-member-init)
get_offset_constants_cache(),
// NOLINTNEXTLINE(readability-redundant-member-init)
get_thermal_power_debug_cache() {}
get_thermal_power_debug_cache(),
// NOLINTNEXTLINE(readability-redundant-member-init)
get_reset_reason_cache() {}
HostCommsTask(const HostCommsTask& other) = delete;
auto operator=(const HostCommsTask& other) -> HostCommsTask& = delete;
HostCommsTask(HostCommsTask&& other) noexcept = delete;
Expand Down Expand Up @@ -266,6 +271,28 @@ class HostCommsTask {
cache_entry);
}

template <typename InputIt, typename InputLimit>
requires std::forward_iterator<InputIt> &&
std::sized_sentinel_for<InputLimit, InputIt>
auto visit_message(const messages::GetResetReasonResponse& response,
InputIt tx_into, InputLimit tx_limit) -> InputIt {
auto cache_entry =
get_reset_reason_cache.remove_if_present(response.responding_to_id);
return std::visit(
[tx_into, tx_limit, response](auto cache_element) {
using T = std::decay_t<decltype(cache_element)>;
if constexpr (std::is_same_v<std::monostate, T>) {
return errors::write_into(
tx_into, tx_limit,
errors::ErrorCode::BAD_MESSAGE_ACKNOWLEDGEMENT);
} else {
return cache_element.write_response_into(tx_into, tx_limit,
response.reason);
}
},
cache_entry);
}

template <typename InputIt, typename InputLimit>
requires std::forward_iterator<InputIt> &&
std::sized_sentinel_for<InputLimit, InputIt>
Expand Down Expand Up @@ -398,6 +425,27 @@ class HostCommsTask {
return std::make_pair(true, tx_into);
}

template <typename InputIt, typename InputLimit>
requires std::forward_iterator<InputIt> &&
std::sized_sentinel_for<InputLimit, InputIt>
auto visit_gcode(const gcode::GetResetReason& gcode, InputIt tx_into,
InputLimit tx_limit) -> std::pair<bool, InputIt> {
auto id = get_reset_reason_cache.add(gcode);
if (id == 0) {
return std::make_pair(
false, errors::write_into(tx_into, tx_limit,
errors::ErrorCode::GCODE_CACHE_FULL));
}
auto message = messages::GetResetReasonMessage{.id = id};
if (!task_registry->send(message, TICKS_TO_WAIT_ON_SEND)) {
auto wrote_to = errors::write_into(
tx_into, tx_limit, errors::ErrorCode::INTERNAL_QUEUE_FULL);
get_reset_reason_cache.remove_if_present(id);
return std::make_pair(false, wrote_to);
}
return std::make_pair(true, tx_into);
}

template <typename InputIt, typename InputLimit>
requires std::forward_iterator<InputIt> &&
std::sized_sentinel_for<InputLimit, InputIt>
Expand Down Expand Up @@ -657,6 +705,7 @@ class HostCommsTask {
GetTempDebugCache get_temp_debug_cache;
GetOffsetConstantsCache get_offset_constants_cache;
GetThermalPowerDebugCache get_thermal_power_debug_cache;
GetResetReasonCache get_reset_reason_cache;
bool may_connect_latch = true;
};

Expand Down
13 changes: 11 additions & 2 deletions stm32-modules/include/tempdeck-gen3/tempdeck-gen3/messages.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,15 @@ struct EnterBootloaderMessage {
uint32_t id;
};

struct GetResetReasonMessage {
uint32_t id;
};

struct GetResetReasonResponse {
uint32_t responding_to_id;
uint16_t reason;
};

struct ForceUSBDisconnect {
uint32_t id;
size_t return_address;
Expand Down Expand Up @@ -174,7 +183,7 @@ using HostCommsMessage =
::std::variant<std::monostate, IncomingMessageFromHost, ForceUSBDisconnect,
ErrorMessage, AcknowledgePrevious, GetSystemInfoResponse,
GetTempDebugResponse, GetOffsetConstantsResponse,
GetThermalPowerDebugResponse>;
GetThermalPowerDebugResponse, GetResetReasonResponse>;
using SystemMessage =
::std::variant<std::monostate, AcknowledgePrevious, GetSystemInfoMessage,
SetSerialNumberMessage, EnterBootloaderMessage>;
Expand All @@ -185,5 +194,5 @@ using ThermalMessage =
SetFanAutomaticMessage, DeactivateAllMessage,
SetTemperatureMessage, SetPIDConstantsMessage,
GetOffsetConstantsMessage, SetOffsetConstantsMessage,
GetThermalPowerDebugMessage>;
GetThermalPowerDebugMessage, GetResetReasonMessage>;
}; // namespace messages
11 changes: 11 additions & 0 deletions stm32-modules/include/tempdeck-gen3/tempdeck-gen3/thermal_task.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,17 @@ class ThermalTask {
_task_registry->send_to_address(response, Queues::HostAddress));
}

template <ThermalPolicy Policy>
auto visit_message(const messages::GetResetReasonMessage& msg,
Policy& policy) -> void {
auto reason = policy.last_reset_reason();

auto response = messages::GetResetReasonResponse{
.responding_to_id = msg.id, .reason = reason};
static_cast<void>(
_task_registry->send_to_address(response, Queues::HostAddress));
}

/**
* @brief Updates control of the peltier and fan based off of the current
* state of the system.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ struct TestThermalPolicy : public m24128_test_policy::TestM24128Policy {
return true;
}

auto last_reset_reason() -> uint16_t { return _reset_reason; }

auto set_last_reset_reason(uint16_t sim_reason) {
_reset_reason = sim_reason;
}

auto get_fan_rpm() -> double { return _fan_rpm; }

// Test integration functions
Expand All @@ -48,4 +54,5 @@ struct TestThermalPolicy : public m24128_test_policy::TestM24128Policy {
double _power = 0.0F; // Positive for heat, negative for cool
double _fans = 0.0F;
double _fan_rpm = 0.0F; // Should be manually set by the test code
uint16_t _reset_reason = 0;
};
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,38 @@ static struct thermal_hardware hardware = {
.hot_side_power = 0.0F,
};

enum RCC_FLAGS {
_NONE,
// high speed internal clock ready
HSIRDY, // = 1
// high speed external clock ready
HSERDY, // = 2
// main phase-locked loop clock ready
PLLRDY, // = 3
// hsi48 clock ready
HSI48RDY, // = 4
// low-speed external clock ready
LSERDY, // = 5
// lse clock security system failure
LSECSSD, // = 6
// low-speed internal clock ready
LSIRDY, // = 7
// brown out
BORRST, // = 8
// option byte-loader reset
OBLRST, // = 9
// pin reset
PINRST, // = 10
// software reset
SFTRST, // = 11
// independent watchdog
IWDGRST, // = 12
// window watchdog
WWDGRST, // = 13
// low power reset
LPWRRST, // = 14
};

// ***************************************************************************
// Static function declaration

Expand All @@ -96,10 +128,13 @@ static void init_fan_timer();
*/
static void init_gpio();

static void save_reset_reason();

// ***************************************************************************
// Public function implementation

void thermal_hardware_init() {
save_reset_reason();
if(!hardware.initialized) {
init_gpio();
init_peltier_timer();
Expand All @@ -113,6 +148,12 @@ void thermal_hardware_init() {
}
}

uint16_t reset_reason;

uint16_t thermal_hardware_reset_reason() {
return reset_reason;
}

void thermal_hardware_enable_peltiers() {
if(!hardware.initialized) {
return;
Expand Down Expand Up @@ -348,3 +389,66 @@ static void init_gpio() {
init.Pin = EEPROM_WP_PIN;
HAL_GPIO_Init(EEPROM_WP_PORT, &init);
}

static void save_reset_reason() {
// check various reset flags to see if the HAL RCC
// reset flag matches any of them
reset_reason = 0;

// high speed internal clock ready
if (__HAL_RCC_GET_FLAG(RCC_FLAG_HSIRDY)) {
reset_reason |= HSIRDY;
}
// high speed external clock ready
else if (__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY)) {
reset_reason |= HSERDY;
}
// main phase-locked loop clock ready
else if (__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY)) {
reset_reason |= PLLRDY;
}
// hsi48 clock ready
else if (__HAL_RCC_GET_FLAG(RCC_FLAG_HSIRDY)) {
reset_reason |= HSI48RDY;
}
// low-speed external clock ready
else if (__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY)) {
reset_reason |= LSERDY;
}
// lse clock security system failure
else if (__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY)) {
reset_reason |= LSECSSD;
}
// low-speed internal clock ready
else if (__HAL_RCC_GET_FLAG(RCC_FLAG_LSIRDY)) {
reset_reason |= LSIRDY;
}
// brown out
else if (__HAL_RCC_GET_FLAG(RCC_FLAG_BORRST)) {
reset_reason |= BORRST;
}
// option byte-loader reset
else if (__HAL_RCC_GET_FLAG(RCC_FLAG_OBLRST)) {
reset_reason |= OBLRST;
}
// pin reset
else if (__HAL_RCC_GET_FLAG(RCC_FLAG_PINRST)) {
reset_reason |= PINRST;
}
// software reset
else if (__HAL_RCC_GET_FLAG(RCC_FLAG_SFTRST)) {
reset_reason |= SFTRST;
}
// independent watchdog
else if (__HAL_RCC_GET_FLAG(RCC_FLAG_IWDGRST)) {
reset_reason |= IWDGRST;
}
// window watchdog
else if (__HAL_RCC_GET_FLAG(RCC_FLAG_WWDGRST)) {
reset_reason |= WWDGRST;
}
// low power reset
else if (__HAL_RCC_GET_FLAG(RCC_FLAG_LPWRRST)) {
reset_reason |= LPWRRST;
}
}
Loading
Loading