e-mail: mikael.rosbacke@gmail.com
github: http://www.github.com/rosbacke
http://www.akaza.se
#define PERIPH_BASE ((uint32_t)0x40000000) /*!< Peripheral base address in the alias region */
#define AHB1PERIPH_BASE (PERIPH_BASE + 0x00020000)
#define GPIOA_BASE (AHB1PERIPH_BASE + 0x0000)
//...
#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)
//...
typedef struct {
__IO uint32_t MODER; /*!< GPIO port mode register, Address offset: 0x00 */
__IO uint32_t OTYPER; /*!< GPIO port output type register, Address offset: 0x04 */
// ...
} GPIO_TypeDef;
/****************** Bits definition for GPIO_MODER register *****************/
#define GPIO_MODER_MODER0 ((uint32_t)0x00000003)
#define GPIO_MODER_MODER0_0 ((uint32_t)0x00000001)
#define GPIO_MODER_MODER0_1 ((uint32_t)0x00000002)
#define GPIO_MODER_MODER1 ((uint32_t)0x0000000C)
...
#include <stm32f4xx.h>
// GPIO setup.
GPIOA->ODR |= GPIO_ODR_ODR_9;
uint32_t t = GPIOA->MODER;
t &= ~(GPIO_MODER_MODER9 | GPIO_MODER_MODER10);
t |= GPIO_MODER_MODER9_1 | GPIO_MODER_MODER10_1;
GPIOA->MODER = t;
// Alternate function 7 (usart1) to pin 9 + 10.
t = GPIOA->AFR[1];
t &= ~((uint32_t)0xff0);
t |= (uint32_t)0x770;
GPIOA->AFR[1] = t;
// Set bit flag 'te' in register 'cr1' in devicetype 'Usart' to '1'.
// Writing to device module usart1.
// Type safe writes, various degress of static typing.
write<Usart::cr1::te>(Addr::usart1, 1);
write<Usart::cr1::te, Addr::usart1>(1);
write<Usart::cr1::te, Addr::usart1, 1>();
// Read out status bit rxne from 'st' register.
auto t = read<Usart::sr::rxne, Addr::usart1>();
What do we want?
template<>
struct DeviceType<DeviceTypes::usart> {
// Universal synchronous asynchronous receiver transmitter
using DevType = DeviceType<DeviceTypes::usart>;
using devices = Devices::Devices_e;
using DeviceData = DeviceDataTpl<true>;;
struct sr_reg {
// Status register
enum { addressOffset = 0 };
using DeviceType = DevType;
using Register = DevType::sr_reg;
using RegStorage = uint32_t;
struct cts_f {
// CTS flag
using Field = bitops::BitField<RegStorage, int, 9, 1>;
using FieldName = cts_f;
using Register = sr_reg;
};
using cts = struct cts_f;
};
using sr = struct sr_reg;
};
#include "MyFsm.h"
int main()
{
// The state machine is an ordinary object.
MyFsm fsm;
// Perform initial jump to start state. entry events called.
fsm.setStartState<state1>();
MyEvent ev1;
fsm.postEvent(ev1);
// ...
fsm.postEvent(ev1);
}
// Upon destruction, relevant exit events are called.
#include <StateChart.h>
// Ordinary class, needs to inherit from FsmBase.
// MyFsmDesc contain configuration information about the fsm.
class MyFsm : public FsmBase<MyFsmDesc> {
public:
// No special requirements on constructors.
MyFsm() {}
// Additional user defined data.
// Can be accessed from state classes.
int myFsmData = 0;
// FsmBase contain the 'postEvent' function.
};
// State classes inherits StateBase with needed template arguments.
class MyState1 : public StateBase<MyFsmDesc, States::state1> {
public:
// Required constructor. Use body for entry event code.
MyState1(StateArgs& args) : StateBase(args), stateData(0)
{ /* entry event code */ }
// Optional destructor. default is fine.
~MyState1() { /* exit event code */ }
// Handle all incoming events.
bool event(const MyEvent& ev) {
if (ev.foo()) {
transition<MyState2>();
return true; // We want to stop processing this event.
}
return false; // We want parent state to see the event.
}
int stateData; // Additional data possible as normal.
};
// States represented both with a type and an enum value.
enum class States { myState1, myState2, /* ... */ };
class MyEvent;
class MyFsm;
class MyFsmDesc {
public:
using Event = MyEvent; // Event class. Can be primitive.
using Fsm = MyFsm; // State machine class.
// Called during setup. Will build up the state hierarchy.
// Forward declared here.
static void setupStates(FsmSetup<MyFsmDesc>& sc);
};
void MyFsmDesc::setupStates(FsmSetup<UserFsmDesc>& sc)
{
// Add a root state. (level 0)
sc.addState<State1>();
// Another root state.
sc.addState<State2>();
// sub state to state 1. (level 1)
sc.addState<State3, State1>();
// sub state to state 2. (level 1)
sc.addState<State4, State2>();
}
// Typical support functions inherited from statebase
template </* ... */ > class StateBase
{
// All copy/move/assign deleted.
// Transition to new state once eventprocessing is done.
template <typename TargetState>
void transition();
void transition(StateId id);
/// Reference to our state machine object. (MyFsm in our case)
Fsm& fsm();
// Return a reference to the parent state.
template <class ParentState>
ParentState& parent();
};
// Typical support functions inherited from FsmBase
template </* ... */ > class FsmBase {
// Currently active state id.
StateId currentStateId() const;
// Get current active state object. nullptr if type mismatch.
template <class State>
const State* currentState() const;
// Get any of the currently active state object.
template <class State>
const State* activeState() const;
// (Planned): Set a callback to be called upon state change.
using StateCB = std::function<void(Fsm&, StateId)>;
void setStatechangedCB(StateCB cb);
};
Current status
Thank you for your attention
Code available at github:
http://www.github.com/rosbacke/MCU-tools
To get in touch:
email: mikael.rosbacke@gmail.com
web: http://www.akaza.se