Skip to content

Commit

Permalink
heater shaker reset reason
Browse files Browse the repository at this point in the history
  • Loading branch information
caila-marashaj committed Dec 3, 2024
1 parent 82d8c34 commit 9a34332
Show file tree
Hide file tree
Showing 10 changed files with 229 additions and 6 deletions.
101 changes: 101 additions & 0 deletions stm32-modules/heater-shaker/firmware/motor_task/motor_hardware.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,39 @@ motor_hardware_handles *MOTOR_HW_HANDLE = NULL;

static _Atomic int16_t motor_speed_buffer[MOTOR_SPEED_BUFFER_SIZE];
static _Atomic size_t motor_speed_buffer_itr = 0;
uint16_t reset_reason;

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 void MX_NVIC_Init(void)
{
Expand Down Expand Up @@ -814,6 +847,7 @@ void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* htim_base)
}

void motor_hardware_setup(motor_hardware_handles* handles) {
save_reset_reason();
MOTOR_HW_HANDLE = handles;
memset(motor_speed_buffer, 0, sizeof(motor_speed_buffer));
MX_GPIO_Init();
Expand All @@ -840,6 +874,73 @@ void motor_hardware_solenoid_release(DAC_HandleTypeDef* dac1) {
HAL_DAC_SetValue(dac1, SOLENOID_DAC_CHANNEL, DAC_ALIGN_8B_R, 0);
}

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_HSI48RDY)) {
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_LSECSSD)) {
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;
}
}

uint16_t motor_hardware_reset_reason() {
return reset_reason;
}

void motor_hardware_plate_lock_on(TIM_HandleTypeDef* tim3, float power) {
float power_scale = fabs(power);
if (power_scale > 1.f) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ bool motor_hardware_plate_lock_sensor_read(uint16_t GPIO_Pin);

void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim);

/**
* @brief Returns the reason saved upon startup for the last
* reset of the software.
* @return a flag containing the reason for reset.
* */
uint16_t motor_hardware_reset_reason();

/**
* @brief To be called every time the motor control library updates its speed
* measurement. This function adds new speed values to a circular buffer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ auto MotorPolicy::get_current_rpm() const -> int16_t {
return 0;
}

auto MotorPolicy::last_reset_reason() const -> uint16_t {
return motor_hardware_reset_reason();
}

auto MotorPolicy::get_target_rpm() const -> int16_t {
if (IDLE != MCI_GetSTMState(hw_handles->mci[0])) {
return -MCI_GetMecSpeedRefUnit(hw_handles->mci[0]) * _RPM / _01HZ;
Expand Down Expand Up @@ -131,3 +135,7 @@ auto MotorPolicy::get_serial_number(void)
-> std::array<char, SYSTEM_SERIAL_NUMBER_LENGTH> {
return _serial.get_serial_number();
}

auto MotorPolicy::last_reset_reason() const -> uint16_t {
return motor_hardware_reset_reason();
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class MotorPolicy {
auto plate_lock_closed_sensor_read() -> bool;
auto get_serial_number(void)
-> std::array<char, SYSTEM_SERIAL_NUMBER_LENGTH>;
auto last_reset_reason() const -> uint16_t;

private:
static constexpr uint16_t MAX_SOLENOID_CURRENT_MA = 330;
Expand Down
38 changes: 38 additions & 0 deletions stm32-modules/include/heater-shaker/heater-shaker/gcodes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,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 {
/*
** Set Serial Number uses a random gcode, M996, adjacent to the firmware
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class HostCommsTask {
gcode::GetPlateLockStateDebug, gcode::SetLEDDebug,
gcode::IdentifyModuleStartLED, gcode::IdentifyModuleStopLED,
gcode::SetOffsetConstants, gcode::GetOffsetConstants,
gcode::DeactivateHeater>;
gcode::DeactivateHeater, gcode::GetResetReason>;
using AckOnlyCache =
AckCache<8, gcode::SetRPM, gcode::SetTemperature,
gcode::SetAcceleration, gcode::SetPIDConstants,
Expand All @@ -66,6 +66,7 @@ class HostCommsTask {
using GetPlateLockStateDebugCache =
AckCache<8, gcode::GetPlateLockStateDebug>;
using GetOffsetConstantsCache = AckCache<8, gcode::GetOffsetConstants>;
using GetResetReasonCache = AckCache<8, gcode::GetResetReason>;

public:
static constexpr size_t TICKS_TO_WAIT_ON_SEND = 10;
Expand All @@ -88,7 +89,9 @@ class HostCommsTask {
// NOLINTNEXTLINE(readability-redundant-member-init)
get_plate_lock_state_debug_cache(),
// NOLINTNEXTLINE(readability-redundant-member-init)
get_offset_constants_cache() {}
get_offset_constants_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 @@ -478,6 +481,50 @@ 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_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>
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->motor->get_message_queue().try_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 @@ -1053,6 +1100,7 @@ class HostCommsTask {
GetPlateLockStateCache get_plate_lock_state_cache;
GetPlateLockStateDebugCache get_plate_lock_state_debug_cache;
GetOffsetConstantsCache get_offset_constants_cache;
GetResetReasonCache get_reset_reason_cache;
bool may_connect_latch = true;
};

Expand Down
14 changes: 12 additions & 2 deletions stm32-modules/include/heater-shaker/heater-shaker/messages.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,15 @@ struct GetOffsetConstantsResponse {
double const_b, const_c;
};

struct GetResetReasonMessage {
uint32_t id;
};

struct GetResetReasonResponse {
uint32_t responding_to_id;
uint16_t reason;
};

struct DeactivateHeaterMessage {
uint32_t id;
};
Expand All @@ -295,7 +304,7 @@ using MotorMessage = ::std::variant<
ActuateSolenoidMessage, SetPlateLockPowerMessage, OpenPlateLockMessage,
ClosePlateLockMessage, SetPIDConstantsMessage, PlateLockComplete,
GetPlateLockStateMessage, GetPlateLockStateDebugMessage,
CheckPlateLockStatusMessage>;
CheckPlateLockStatusMessage, GetResetReasonMessage>;
using SystemMessage =
::std::variant<std::monostate, EnterBootloaderMessage, AcknowledgePrevious,
SetSerialNumberMessage, GetSystemInfoMessage, SetLEDMessage,
Expand All @@ -307,5 +316,6 @@ using HostCommsMessage =
ErrorMessage, GetTemperatureResponse, GetRPMResponse,
GetTemperatureDebugResponse, ForceUSBDisconnectMessage,
GetPlateLockStateResponse, GetPlateLockStateDebugResponse,
GetSystemInfoResponse, GetOffsetConstantsResponse>;
GetSystemInfoResponse, GetOffsetConstantsResponse,
GetResetReasonResponse>;
}; // namespace messages
11 changes: 11 additions & 0 deletions stm32-modules/include/heater-shaker/heater-shaker/motor_task.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,17 @@ class MotorTask {
static_cast<void>(get_message_queue().try_send(check_state_message));
}

template <MotorExecutionPolicy 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->comms->get_message_queue().try_send(
messages::HostCommsMessage(response)));
}

template <typename Policy>
auto visit_message(const messages::CheckPlateLockStatusMessage& msg,
Policy& policy) -> void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ void motor_hardware_seal_switch_interrupt();
/**
* @brief Returns the reason saved upon startup for the last
* reset of the software.
* @return a string describing the reason for reset.
* @return a flag containing the reasons for reset.
* */
uint16_t motor_hardware_reset_reason();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,6 @@ static void init_tim2(TIM_HandleTypeDef* htim);
static void init_tim6(TIM_HandleTypeDef* htim);
static bool lid_active();
static void save_reset_reason();
//static char* reset_reason;
uint16_t reset_reason;

// ----------------------------------------------------------------------------
Expand Down

0 comments on commit 9a34332

Please sign in to comment.