mirror of
https://git.intern.spaceteamaachen.de/ALPAKA/TACOS.git
synced 2025-06-10 16:45:59 +00:00
Merge pull request 'statemachine-rework' (#10) from statemachine-rework into main
Reviewed-on: https://git.intern.spaceteamaachen.de/ALPAKA/TACOS/pulls/10 Reviewed-by: carlwachter <carlwachter@noreply.git.intern.spaceteamaachen.de>
This commit is contained in:
commit
f73cd47215
@ -25,6 +25,7 @@
|
||||
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_board.1523528544" name="Board" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_board" useByScannerDiscovery="false" value="genericBoard" valueType="string"/>
|
||||
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.defaults.1559967274" name="Defaults" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.defaults" useByScannerDiscovery="false" value="com.st.stm32cube.ide.common.services.build.inputs.revA.1.0.6 || Debug || true || Executable || com.st.stm32cube.ide.mcu.gnu.managedbuild.option.toolchain.value.workspace || STM32F411RETx || 0 || 0 || arm-none-eabi- || ${gnu_tools_for_stm32_compiler_path} || ../Core/Inc | ../Drivers/STM32F4xx_HAL_Driver/Inc | ../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy | ../Drivers/CMSIS/Device/ST/STM32F4xx/Include | ../Drivers/CMSIS/Include | ../Middlewares/Third_Party/FreeRTOS/Source/include | ../Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2 | ../Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F || || || USE_HAL_DRIVER | STM32F411xE || || Drivers | Core/Startup | Middlewares | Core || || || ${workspace_loc:/${ProjName}/STM32F411RETX_FLASH.ld} || true || NonSecure || || secure_nsclib.o || || None || || || " valueType="string"/>
|
||||
<option id="com.st.stm32cube.ide.mcu.debug.option.cpuclock.1388963198" name="Cpu clock frequence" superClass="com.st.stm32cube.ide.mcu.debug.option.cpuclock" useByScannerDiscovery="false" value="16" valueType="string"/>
|
||||
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.nanoprintffloat.2054601156" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.nanoprintffloat" value="true" valueType="boolean"/>
|
||||
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.targetplatform.682707397" isAbstract="false" osList="all" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.targetplatform"/>
|
||||
<builder buildPath="${workspace_loc:/TACOS}/Debug" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.builder.1663759602" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.builder"/>
|
||||
<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.1268227203" name="MCU GCC Assembler" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler">
|
||||
|
@ -5,7 +5,7 @@
|
||||
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
|
||||
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
|
||||
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
|
||||
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="1090266248531783773" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true">
|
||||
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="1366383323889271194" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true">
|
||||
<language-scope id="org.eclipse.cdt.core.gcc"/>
|
||||
<language-scope id="org.eclipse.cdt.core.g++"/>
|
||||
</provider>
|
||||
@ -16,7 +16,7 @@
|
||||
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
|
||||
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
|
||||
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
|
||||
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="1090266248531783773" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true">
|
||||
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="1366383323889271194" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true">
|
||||
<language-scope id="org.eclipse.cdt.core.gcc"/>
|
||||
<language-scope id="org.eclipse.cdt.core.g++"/>
|
||||
</provider>
|
||||
|
@ -33,7 +33,7 @@
|
||||
#define STA_TACOS_STATEMACHINE_PRIORITY osPriorityNormal
|
||||
|
||||
// Statemachine settings. Here, we only have a single state which is also the initial state.
|
||||
#define STA_TACOS_NUM_STATES 1
|
||||
#define STA_TACOS_NUM_STATES 3
|
||||
#define STA_TACOS_INITIAL_STATE 0
|
||||
|
||||
#endif /* INC_STA_CONFIG_HPP_ */
|
||||
|
26
App/Inc/tasks/disturb.hpp
Normal file
26
App/Inc/tasks/disturb.hpp
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* disturb.hpp
|
||||
*
|
||||
* Created on: Nov 20, 2023
|
||||
* Author: Dario
|
||||
*/
|
||||
|
||||
#ifndef INC_TASKS_DISTURB_HPP_
|
||||
#define INC_TASKS_DISTURB_HPP_
|
||||
|
||||
#include <sta/tacos/thread.hpp>
|
||||
|
||||
namespace demo
|
||||
{
|
||||
class DisturbTask : public sta::tacos::TacosThread {
|
||||
public:
|
||||
DisturbTask();
|
||||
|
||||
void init() override;
|
||||
|
||||
void func() override;
|
||||
};
|
||||
} // namespace demo
|
||||
|
||||
|
||||
#endif /* INC_TASKS_DISTURB_HPP_ */
|
@ -15,7 +15,6 @@ namespace demo
|
||||
class DummyTask : public sta::tacos::TacosThread {
|
||||
public:
|
||||
DummyTask(const char* name);
|
||||
~DummyTask() override;
|
||||
|
||||
void init() override;
|
||||
|
||||
|
26
App/Inc/tasks/toggle.hpp
Normal file
26
App/Inc/tasks/toggle.hpp
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* toggle.hpp
|
||||
*
|
||||
* Created on: Nov 10, 2023
|
||||
* Author: Dario
|
||||
*/
|
||||
|
||||
#ifndef INC_STA_TOGGLE_HPP_
|
||||
#define INC_STA_TOGGLE_HPP_
|
||||
|
||||
#include <sta/tacos/thread.hpp>
|
||||
|
||||
namespace demo
|
||||
{
|
||||
class Toggle : public sta::tacos::TacosThread
|
||||
{
|
||||
public:
|
||||
Toggle();
|
||||
|
||||
void init() override;
|
||||
|
||||
void func() override;
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* INC_STA_TOGGLE_HPP_ */
|
@ -12,8 +12,11 @@
|
||||
#include <sta/tacos/manager.hpp>
|
||||
#include <sta/tacos/statemachine.hpp>
|
||||
#include <tasks/dummy.hpp>
|
||||
#include <tasks/toggle.hpp>
|
||||
#include <tasks/disturb.hpp>
|
||||
#include <gpio.h>
|
||||
#include <sta/devices/stm32/gpio_pin.hpp>
|
||||
#include <sta/rtos/debug/heap_stats.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
@ -24,38 +27,6 @@ namespace sta
|
||||
{
|
||||
void onStatemachineInit()
|
||||
{
|
||||
Statemachine::instance()->setStateFunction([](uint16_t state) -> uint16_t {
|
||||
// ###### Implement your state transition function here! ######
|
||||
|
||||
/**
|
||||
* This function should return some state within 0 and STA_TACOS_NUM_STATES (specified in the config.hpp).
|
||||
* Return the same state as given as the argument for no state transition. Make sure, that this function is not
|
||||
* computationally expensive.
|
||||
*/
|
||||
|
||||
return state;
|
||||
});
|
||||
|
||||
Statemachine::instance()->setTimerFunction([](uint16_t state, uint16_t lastState, uint32_t event) {
|
||||
// ###### Set the failsafe and lockout timers here ######
|
||||
|
||||
/**
|
||||
* This function is called after a state transition from lastState to state. Event corresponds to EventFlag enum in the Statemachine
|
||||
* and encode how the state change happened.
|
||||
*
|
||||
* Setting a timer here is fully optional and depends on your system's specifications.
|
||||
*/
|
||||
|
||||
uint32_t someFailsafeMillis = 42;
|
||||
uint16_t someNextState = STA_TACOS_INITIAL_STATE;
|
||||
uint32_t someLockoutMillis = 21;
|
||||
|
||||
// Start the failsafe timer to force a state transition to someNextState after someFailsafeMillis milliseconds.
|
||||
Statemachine::instance()->setFailsafeTimer(someFailsafeMillis, someNextState);
|
||||
|
||||
// Start the lockout timer to block a state transition for the first someLockoutMillis milliseconds.
|
||||
Statemachine::instance()->setLockoutTimer(someLockoutMillis);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@ -64,7 +35,15 @@ namespace sta
|
||||
// ###### Register different threads for different states here. ######
|
||||
|
||||
// The dummy task runs for state 0.
|
||||
Manager::instance()->registerThread(std::make_shared<demo::DummyTask>("Dummy"), {0});
|
||||
Manager::instance()->registerThread(std::make_shared<demo::DummyTask>("State 0"), {0});
|
||||
Manager::instance()->registerThread(std::make_shared<demo::DummyTask>("State 1"), {1});
|
||||
Manager::instance()->registerThread(std::make_shared<demo::DummyTask>("State 2 - FAIL"), {2});
|
||||
Manager::instance()->registerThread(std::make_shared<demo::Toggle>(), {0, 1});
|
||||
// Manager::instance()->registerThread(std::make_shared<demo::DisturbTask>(), {0, 1});
|
||||
|
||||
STA_DEBUG_PRINTF("The answer to everything is %d", 42);
|
||||
|
||||
STA_DEBUG_HEAP_STATS();
|
||||
}
|
||||
} // namespace tacos
|
||||
} // namespace sta
|
||||
|
35
App/Src/tasks/disturb.cpp
Normal file
35
App/Src/tasks/disturb.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* disturb.cpp
|
||||
*
|
||||
* Created on: Nov 20, 2023
|
||||
* Author: Dario
|
||||
*/
|
||||
|
||||
#include <tasks/disturb.hpp>
|
||||
#include <sta/tacos/statemachine.hpp>
|
||||
#include <sta/debug/debug.hpp>
|
||||
|
||||
namespace demo
|
||||
{
|
||||
DisturbTask::DisturbTask()
|
||||
: sta::tacos::TacosThread("Disturb", osPriorityNormal)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void DisturbTask::init()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void DisturbTask::func()
|
||||
{
|
||||
STA_DEBUG_PRINTLN(this->getName());
|
||||
|
||||
sta::tacos::Statemachine::instance()->stateChangeEvent.wait(sta::tacos::EventFlags::ALL, osWaitForever);
|
||||
|
||||
uint16_t currentState = sta::tacos::Statemachine::instance()->getCurrentState();
|
||||
sta::tacos::Statemachine::instance()->requestTimedStateTransition(currentState, 2, 4000, 0);
|
||||
}
|
||||
} // namespace demo
|
||||
|
@ -19,8 +19,6 @@ namespace demo
|
||||
|
||||
}
|
||||
|
||||
DummyTask::~DummyTask(){}
|
||||
|
||||
void DummyTask::init()
|
||||
{
|
||||
|
||||
|
34
App/Src/tasks/toggle.cpp
Normal file
34
App/Src/tasks/toggle.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* toggle.cpp
|
||||
*
|
||||
* Created on: Nov 10, 2023
|
||||
* Author: Dario
|
||||
*/
|
||||
|
||||
#include <tasks/toggle.hpp>
|
||||
#include <sta/tacos/statemachine.hpp>
|
||||
#include <sta/debug/debug.hpp>
|
||||
|
||||
namespace demo
|
||||
{
|
||||
Toggle::Toggle()
|
||||
: sta::tacos::TacosThread{ "Toggle", osPriorityNormal }
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Toggle::init()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Toggle::func()
|
||||
{
|
||||
uint16_t state = sta::tacos::Statemachine::instance()->getCurrentState();
|
||||
uint16_t next = 1 - state;
|
||||
|
||||
sta::tacos::Statemachine::instance()->requestStateTransition(state, next, 5000);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 0e96b2ec29fde1e56e12fc9f0dceb80012e0caf3
|
||||
Subproject commit b1d6456dd88f881f68674824339483f69dd280f0
|
@ -1 +1 @@
|
||||
Subproject commit 4da1f0bb7dd48f89e9dd5ee0ec181638894e55e2
|
||||
Subproject commit c4692287cf88e518d22078c1d284be343fc82fba
|
@ -20,6 +20,8 @@
|
||||
# define STA_TACOS_INITIAL_STATE 0
|
||||
#endif
|
||||
|
||||
#define STA_TACOS_STATEMACHINE_QUEUE_LENGTH 4
|
||||
|
||||
// State transition happened because of
|
||||
#define STA_TACOS_STATE_CHANGE_NORMAL_FLAG ( 0x1U )
|
||||
#define STA_TACOS_STATE_CHANGE_FORCED_FLAG ( 0x1U << 1)
|
||||
@ -29,34 +31,41 @@
|
||||
|
||||
|
||||
#include <sta/tacos/thread.hpp>
|
||||
#include <sta/rtos/queue.hpp>
|
||||
#include <sta/rtos/timer.hpp>
|
||||
#include <sta/rtos/event.hpp>
|
||||
#include <sta/event.hpp>
|
||||
#include <sta/debug/assert.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <tuple>
|
||||
|
||||
|
||||
namespace sta
|
||||
{
|
||||
namespace tacos
|
||||
{
|
||||
typedef std::function<uint16_t(uint16_t)> state_fn;
|
||||
typedef std::function<void(uint16_t, uint16_t, uint32_t)> timer_fn;
|
||||
enum EventFlags
|
||||
{
|
||||
NORMAL = 0x1U,
|
||||
FORCED = 0x1U << 1,
|
||||
TIMEOUT = 0x1U << 2,
|
||||
STARTUP = 0x1U << 3,
|
||||
ALL = NORMAL | FORCED | TIMEOUT | STARTUP
|
||||
};
|
||||
|
||||
struct StateTransition
|
||||
{
|
||||
uint16_t from;
|
||||
uint16_t to;
|
||||
EventFlags event;
|
||||
uint32_t lockout;
|
||||
};
|
||||
|
||||
|
||||
class Statemachine : public TacosThread
|
||||
{
|
||||
public:
|
||||
enum EventFlags
|
||||
{
|
||||
NORMAL = 0x1U,
|
||||
FORCED = 0x1U << 1,
|
||||
TIMEOUT = 0x1U << 2,
|
||||
STARTUP = 0x1U << 3,
|
||||
ALL = NORMAL | FORCED | TIMEOUT | STARTUP
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The global event signaling a state change.
|
||||
*/
|
||||
@ -84,29 +93,23 @@ namespace sta
|
||||
uint16_t getCurrentState() const;
|
||||
|
||||
/**
|
||||
* @brief Registers a new state transition function. This is a function for the user to implement state transition rules.
|
||||
* @brief Request a state transition from a state to another.
|
||||
*
|
||||
* @param from The state which we want to leave. This is used to filter out obsolete transitions.
|
||||
* @param to The state to transition to.
|
||||
* @param lockout The minimum number of milliseconds we expect to stay in this state. This is used to block premature transitions.
|
||||
*/
|
||||
void setStateFunction(state_fn func);
|
||||
void requestStateTransition(uint32_t from, uint32_t to, uint32_t lockout = 0);
|
||||
|
||||
/**
|
||||
* @brief Registers a new timer function. This is a function for the user to set the timers after a state change.
|
||||
* @brief Request a state transition after a given time has passed.
|
||||
*
|
||||
* @param from The state which we want to leave. This is used to filter out obsolete transitions.
|
||||
* @param to The state to transition to.
|
||||
* @param millis the number of milliseconds to wait before triggering the transition.
|
||||
* @param lockout The minimum number of milliseconds we expect to stay in this state. This is used to block premature transitions.
|
||||
*/
|
||||
void setTimerFunction(timer_fn func);
|
||||
|
||||
/**
|
||||
* @brief Starts the failsafe timer for the desired duration and the desired next state.
|
||||
*/
|
||||
void setFailsafeTimer(uint32_t millis, uint16_t nextState);
|
||||
|
||||
/**
|
||||
* @brief Starts the lockoutTimer for the desired duration.
|
||||
*/
|
||||
void setLockoutTimer(uint32_t millis);
|
||||
|
||||
/**
|
||||
* @brief this function call allows forced state transitions from external and internal sources.
|
||||
*/
|
||||
void forceStateTransition(uint16_t state);
|
||||
void requestTimedStateTransition(uint32_t from, uint32_t to, uint32_t millis, uint32_t lockout = 0);
|
||||
|
||||
void init() override;
|
||||
void func() override;
|
||||
@ -133,15 +136,19 @@ namespace sta
|
||||
|
||||
~Statemachine() {}
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Starts the lockoutTimer for the desired duration.
|
||||
*/
|
||||
void setLockoutTimer(uint32_t millis);
|
||||
|
||||
private:
|
||||
uint16_t currentState_;
|
||||
uint16_t failsafeState_;
|
||||
|
||||
RtosTimer lockoutTimer_;
|
||||
RtosTimer failsafeTimer_;
|
||||
|
||||
state_fn transitionFunc_;
|
||||
timer_fn timerFunc_;
|
||||
RtosQueue<StateTransition> queue_;
|
||||
};
|
||||
} // namespace tacos
|
||||
} // namespace sta
|
||||
|
@ -80,7 +80,7 @@ namespace sta
|
||||
|
||||
void Manager::func()
|
||||
{
|
||||
Statemachine::stateChangeEvent.wait(Statemachine::EventFlags::ALL, osWaitForever);
|
||||
Statemachine::stateChangeEvent.wait(EventFlags::ALL, osWaitForever);
|
||||
|
||||
HeapStats_t stats;
|
||||
vPortGetHeapStats(&stats);
|
||||
|
@ -17,47 +17,46 @@ namespace sta
|
||||
Statemachine::Statemachine()
|
||||
: TacosThread{"Statemachine", STA_TACOS_STATEMACHINE_PRIORITY},
|
||||
currentState_{STA_TACOS_INITIAL_STATE},
|
||||
failsafeState_{STA_TACOS_INITIAL_STATE},
|
||||
lockoutTimer_{[](void *){}, nullptr},
|
||||
failsafeTimer_{[](void *){}, nullptr},
|
||||
transitionFunc_{[](uint16_t) -> uint16_t { return Statemachine::instance()->getCurrentState(); }},
|
||||
timerFunc_{[](uint16_t, uint16_t, uint16_t) {}}
|
||||
queue_{STA_TACOS_STATEMACHINE_QUEUE_LENGTH}
|
||||
{
|
||||
STA_ASSERT(STA_TACOS_INITIAL_STATE < STA_TACOS_NUM_STATES);
|
||||
}
|
||||
|
||||
void Statemachine::init()
|
||||
{
|
||||
timerFunc_(0, 0, EventFlags::STARTUP);
|
||||
|
||||
}
|
||||
|
||||
void Statemachine::func()
|
||||
{
|
||||
if (!lockoutTimer_.isRunning())
|
||||
// Wait for a message to be added to the queue.
|
||||
StateTransition transition;
|
||||
queue_.get(&transition, osWaitForever);
|
||||
|
||||
// Check if the transition isn't blocked and is legal.
|
||||
if (!lockoutTimer_.isRunning() && transition.from == currentState_)
|
||||
{
|
||||
uint16_t next = transitionFunc_(currentState_);
|
||||
STA_ASSERT(transition.to < STA_TACOS_NUM_STATES);
|
||||
|
||||
STA_ASSERT(next < STA_TACOS_NUM_STATES);
|
||||
// Perform the transition and notify the threads. The event flags are set
|
||||
// here in order to allow threads to react immediately.
|
||||
currentState_ = transition.to;
|
||||
Statemachine::stateChangeEvent.set(transition.event);
|
||||
Statemachine::stateChangeEvent.clear(EventFlags::ALL);
|
||||
|
||||
// Check if a state change is desired. Block if the lockoutTimer is still running.
|
||||
if (next != currentState_)
|
||||
if (failsafeTimer_.isRunning())
|
||||
{
|
||||
if (failsafeTimer_.isRunning())
|
||||
{
|
||||
failsafeTimer_.stop();
|
||||
}
|
||||
failsafeTimer_.stop();
|
||||
}
|
||||
|
||||
// Call user space code to set the timers again.
|
||||
timerFunc_(next, currentState_, EventFlags::NORMAL);
|
||||
|
||||
// Update the state and trigger the global state changed event.
|
||||
currentState_ = next;
|
||||
Statemachine::stateChangeEvent.set(EventFlags::NORMAL);
|
||||
Statemachine::stateChangeEvent.clear(EventFlags::ALL);
|
||||
// Start the lockout timer if requested.
|
||||
if (transition.lockout != 0)
|
||||
{
|
||||
setLockoutTimer(transition.lockout);
|
||||
}
|
||||
}
|
||||
|
||||
osThreadYield();
|
||||
}
|
||||
|
||||
uint16_t Statemachine::getCurrentState() const
|
||||
@ -65,28 +64,27 @@ namespace sta
|
||||
return currentState_;
|
||||
}
|
||||
|
||||
void Statemachine::setStateFunction(state_fn func)
|
||||
void Statemachine::requestStateTransition(uint32_t from, uint32_t to, uint32_t lockout /* = 0 */)
|
||||
{
|
||||
STA_ASSERT(func != nullptr);
|
||||
StateTransition transition;
|
||||
transition.from = from;
|
||||
transition.to = to;
|
||||
transition.event = EventFlags::NORMAL;
|
||||
transition.lockout = lockout;
|
||||
|
||||
transitionFunc_ = func;
|
||||
// Try to add a state transition request to the queue. Don't wait if another
|
||||
// thread is already requesting a state change.
|
||||
queue_.put(transition, 0);
|
||||
}
|
||||
|
||||
void Statemachine::setTimerFunction(timer_fn func)
|
||||
void Statemachine::requestTimedStateTransition(uint32_t from, uint32_t to, uint32_t millis, uint32_t lockout /* = 0 */)
|
||||
{
|
||||
STA_ASSERT(func != nullptr);
|
||||
|
||||
timerFunc_ = func;
|
||||
}
|
||||
|
||||
void Statemachine::setFailsafeTimer(uint32_t millis, uint16_t nextState)
|
||||
{
|
||||
STA_ASSERT(nextState < STA_TACOS_NUM_STATES);
|
||||
STA_ASSERT(to < STA_TACOS_NUM_STATES);
|
||||
STA_ASSERT(!failsafeTimer_.isRunning());
|
||||
|
||||
failsafeTimer_.setCallback([nextState](void* arg) {
|
||||
Statemachine::instance()->forceStateTransition(nextState);
|
||||
}, &failsafeState_);
|
||||
failsafeTimer_.setCallback([from, to, lockout](void* arg) {
|
||||
Statemachine::instance()->requestStateTransition(from, to, lockout);
|
||||
}, NULL);
|
||||
|
||||
failsafeTimer_.start(millis);
|
||||
}
|
||||
@ -99,25 +97,6 @@ namespace sta
|
||||
lockoutTimer_.start(millis);
|
||||
}
|
||||
|
||||
void Statemachine::forceStateTransition(uint16_t state)
|
||||
{
|
||||
if (failsafeTimer_.isRunning())
|
||||
{
|
||||
failsafeTimer_.stop();
|
||||
}
|
||||
|
||||
if (lockoutTimer_.isRunning())
|
||||
{
|
||||
lockoutTimer_.stop();
|
||||
}
|
||||
|
||||
timerFunc_(state, currentState_, EventFlags::FORCED);
|
||||
currentState_ = state;
|
||||
|
||||
Statemachine::stateChangeEvent.set(EventFlags::FORCED);
|
||||
Statemachine::stateChangeEvent.clear(EventFlags::ALL);
|
||||
}
|
||||
|
||||
Statemachine* Statemachine::_instance = nullptr;
|
||||
|
||||
RtosEvent Statemachine::stateChangeEvent;
|
||||
|
@ -81,21 +81,26 @@ namespace sta
|
||||
// Infinite loop allowing quick restarts of this thread after termination.
|
||||
while (true)
|
||||
{
|
||||
// The thread has to wait until the startup has been completed.
|
||||
// The thread has to wait until the system startup has been completed.
|
||||
rtos::waitForStartupEvent();
|
||||
|
||||
// Wait for a thread start flag.
|
||||
wait(STA_RTOS_THREAD_FLAG_START);
|
||||
|
||||
// Call user-defined initialization code.
|
||||
running_ = true;
|
||||
init();
|
||||
|
||||
// Run the thread until the termination flag is set.
|
||||
while (!resetTerminationRequest())
|
||||
// Run the thread until the termination flag is set. Reset this
|
||||
while (!isTerminationRequested())
|
||||
{
|
||||
func();
|
||||
}
|
||||
|
||||
// Clear the termination request flag for this thread.
|
||||
deleteTerminationRequest();
|
||||
|
||||
// Call user-defined cleanup code.
|
||||
cleanup();
|
||||
running_ = false;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user