| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // ====================================================================== | ||
| 2 | // \title Seq.hpp | ||
| 3 | // \author tumbar | ||
| 4 | // \brief hpp file for Seq component implementation class | ||
| 5 | // ====================================================================== | ||
| 6 | |||
| 7 | #ifndef Samd21_Seq_HPP | ||
| 8 | #define Samd21_Seq_HPP | ||
| 9 | |||
| 10 | #include "Fw/Types/Serializable.hpp" | ||
| 11 | #include "SeqConfig/SeqNamesEnumAc.hpp" | ||
| 12 | #include "fprime-samd/Svc/Seq/SeqComponentAc.hpp" | ||
| 13 | |||
| 14 | namespace Samd21 { | ||
| 15 | |||
| 16 | class Seq final : public SeqComponentBase { | ||
| 17 | public: | ||
| 18 | // ---------------------------------------------------------------------- | ||
| 19 | // Component construction and destruction | ||
| 20 | // ---------------------------------------------------------------------- | ||
| 21 | |||
| 22 | //! Construct Seq object | ||
| 23 | Seq(const char* const compName //!< The component name | ||
| 24 | ); | ||
| 25 | |||
| 26 | //! Destroy Seq object | ||
| 27 | ~Seq(); | ||
| 28 | |||
| 29 | //! A single hard-coded sequence: a pointer to its binary blob and the blob length | ||
| 30 | struct Sequence { | ||
| 31 | 81 | Sequence() : m_data(nullptr), m_len(0) {} | |
| 32 | 81 | Sequence(const U8* data, U32 len) : m_data(data), m_len(len) {} | |
| 33 | |||
| 34 | const U8* m_data; //!< Pointer to the sequence binary (typically in flash) | ||
| 35 | U32 m_len; //!< Length of the sequence binary in bytes | ||
| 36 | }; | ||
| 37 | |||
| 38 | //! Configure the sequence list. | ||
| 39 | //! \a sequences must point at an array of exactly SeqNames::NUM_CONSTANTS | ||
| 40 | //! entries, indexed by the SeqNames enum value. The array and the | ||
| 41 | //! binaries it references must remain valid for the lifetime of the component. | ||
| 42 | void configure(const Sequence* sequences); | ||
| 43 | |||
| 44 | //! Pend a sequence to run when the MCU boots into the main loop | ||
| 45 | void run(const Samd21::SeqNames& name); | ||
| 46 | |||
| 47 | private: | ||
| 48 | // ---------------------------------------------------------------------- | ||
| 49 | // Handler implementations for typed input ports | ||
| 50 | // ---------------------------------------------------------------------- | ||
| 51 | |||
| 52 | //! Handler implementation for activeIn | ||
| 53 | //! | ||
| 54 | //! Active in for dispatching the "next" action in the table or reseting | ||
| 55 | bool activeIn_handler(FwIndexType portNum, //!< The port number | ||
| 56 | U32 context //!< The call order | ||
| 57 | ) override; | ||
| 58 | |||
| 59 | //! Handler implementation for commandResponseIn | ||
| 60 | //! | ||
| 61 | //! Port to receive status of the currently executing action | ||
| 62 | void commandResponseIn_handler(FwIndexType portNum, //!< The port number | ||
| 63 | FwOpcodeType opCode, //!< Command Op Code | ||
| 64 | U32 cmdSeq, //!< Command Sequence | ||
| 65 | const Fw::CmdResponse& response //!< The command response argument | ||
| 66 | ) override; | ||
| 67 | |||
| 68 | //! Handler implementation for schedIn | ||
| 69 | //! | ||
| 70 | //! Check timers for wait/wait_until timeouts | ||
| 71 | void schedIn_handler(FwIndexType portNum, //!< The port number | ||
| 72 | U32 context //!< The call order | ||
| 73 | ) override; | ||
| 74 | |||
| 75 | private: | ||
| 76 | // ---------------------------------------------------------------------- | ||
| 77 | // Handler implementations for commands | ||
| 78 | // ---------------------------------------------------------------------- | ||
| 79 | |||
| 80 | //! Handler implementation for command RUN | ||
| 81 | //! | ||
| 82 | //! Run an action table after the current execution finishes | ||
| 83 | //! When this component enters idle, it will pick up this pending run | ||
| 84 | void RUN_cmdHandler(FwOpcodeType opCode, //!< The opcode | ||
| 85 | U32 cmdSeq, //!< The command sequence number | ||
| 86 | const Samd21::SeqNames& table) override; | ||
| 87 | |||
| 88 | //! Handler implementation for command RUN_ON_ERROR | ||
| 89 | //! | ||
| 90 | //! Set the table to run if we exit with an error (i.e. command failure). | ||
| 91 | //! The pending `RUN` is cleared. | ||
| 92 | void RUN_ON_ERROR_cmdHandler(FwOpcodeType opCode, //!< The opcode | ||
| 93 | U32 cmdSeq, //!< The command sequence number | ||
| 94 | const Samd21::SeqNames& table) override; | ||
| 95 | |||
| 96 | //! Handler implementation for command CANCEL | ||
| 97 | //! | ||
| 98 | //! Stop any executing or pending action and reset the program counter to the | ||
| 99 | //! start of the sequence without dispatching anything. A command response for | ||
| 100 | //! an already-dispatched action may still arrive afterwards; it is dropped. | ||
| 101 | void CANCEL_cmdHandler(FwOpcodeType opCode, //!< The opcode | ||
| 102 | U32 cmdSeq //!< The command sequence number | ||
| 103 | ) override; | ||
| 104 | |||
| 105 | //! Handler implementation for command WAIT_TICKS | ||
| 106 | //! | ||
| 107 | //! Block for a number of rate groups ticks before continuing | ||
| 108 | //! If n == 0, the sequence will resume on the NEXT rate group tick | ||
| 109 | void WAIT_TICKS_cmdHandler(FwOpcodeType opCode, //!< The opcode | ||
| 110 | U32 cmdSeq, //!< The command sequence number | ||
| 111 | U32 n) override; | ||
| 112 | |||
| 113 | //! Handler implementation for command WAIT_UNTIL | ||
| 114 | //! | ||
| 115 | //! Block the sequence until the given timeBase matches and the time >= seconds.useconds | ||
| 116 | void WAIT_UNTIL_cmdHandler(FwOpcodeType opCode, //!< The opcode | ||
| 117 | U32 cmdSeq, //!< The command sequence number | ||
| 118 | const TimeBase& timeBase, //!< Wait for the FSW to reach this timebase | ||
| 119 | U32 seconds, //!< Wait for FSW time to reach this time in seconds | ||
| 120 | U32 useconds //!< Microsecond offset to wait for FSW | ||
| 121 | ) override; | ||
| 122 | |||
| 123 | private: | ||
| 124 | // ---------------------------------------------------------------------- | ||
| 125 | // Helper functions | ||
| 126 | // ---------------------------------------------------------------------- | ||
| 127 | |||
| 128 | //! Whether the current action has more command bytes left to deserialize | ||
| 129 | bool hasMoreRecordsInternal() const; | ||
| 130 | |||
| 131 | //! Deserialize the next command from the current action into \a cmd. | ||
| 132 | //! \return the number of bytes consumed, or 0 on a malformed command. | ||
| 133 | U16 deserializeRecord(Fw::ExternalSerializeBuffer& cmd); | ||
| 134 | |||
| 135 | //! Dispatch the command held in \a cmdBuf out the commandOut port. | ||
| 136 | void dispatchRecord(const Fw::ExternalSerializeBuffer& cmdBuf, U32 cmdSeq); | ||
| 137 | |||
| 138 | //! Advance to and dispatch the next command. If the end of the action is | ||
| 139 | //! reached, finish successfully. On a malformed command, finish with failure. | ||
| 140 | void next(); | ||
| 141 | |||
| 142 | private: | ||
| 143 | // ---------------------------------------------------------------------- | ||
| 144 | // Member state | ||
| 145 | // ---------------------------------------------------------------------- | ||
| 146 | |||
| 147 | static_assert(SeqNames::NUM_CONSTANTS < 255, "Samd21::Seq does not support >255 tables"); | ||
| 148 | |||
| 149 | enum class State : U8 { | ||
| 150 | IDLE, | ||
| 151 | AWAITING_RESPONSE, | ||
| 152 | PENDING_NEXT, | ||
| 153 | SLEEPING, | ||
| 154 | }; | ||
| 155 | |||
| 156 | //! What the component is waiting on while SLEEPING. Set by the WAIT_TICKS / | ||
| 157 | //! WAIT_UNTIL command handlers (which run re-entrantly while the just-issued | ||
| 158 | //! wait command is AWAITING_RESPONSE) and consumed by commandResponseIn to | ||
| 159 | //! move the component into SLEEPING. | ||
| 160 | enum class SleepKind : U8 { | ||
| 161 | NONE, //!< Not waiting; the completed command advances to the next one | ||
| 162 | TICKS, //!< Waiting for a number of rate-group ticks (WAIT_TICKS) | ||
| 163 | UNTIL, //!< Waiting for the FSW clock to reach an absolute time (WAIT_UNTIL) | ||
| 164 | }; | ||
| 165 | |||
| 166 | const Sequence* m_sequences; //!< The configured action list (NUM_CONSTANTS long) | ||
| 167 | U16 m_offset; //!< Current offset in bytes from the active action table | ||
| 168 | U8 m_tableIdx; //!< Index of the active table | ||
| 169 | volatile State m_state; //!< Whether an action is currently executing | ||
| 170 | U8 m_pendingTableIdx; //!< NUM_CONSTANTS indicates nothing to run. Otherwise once this component enters idle, start | ||
| 171 | //!< this sequence | ||
| 172 | U8 m_runOnErrorTableIdx; //!< NUM_CONSTANTS indicates none. Otherwise the table to pend when a command fails | ||
| 173 | |||
| 174 | SleepKind m_sleepKind; //!< The kind of wait requested by the last WAIT_* command | ||
| 175 | U32 m_waitTicks; //!< Rate-group ticks remaining before a WAIT_TICKS sleep resumes | ||
| 176 | TimeBase m_waitTimeBase; //!< Time base a WAIT_UNTIL sleep waits on | ||
| 177 | U32 m_waitSeconds; //!< Seconds a WAIT_UNTIL sleep waits for | ||
| 178 | U32 m_waitUseconds; //!< Microsecond offset a WAIT_UNTIL sleep waits for | ||
| 179 | }; | ||
| 180 | |||
| 181 | } // namespace Samd21 | ||
| 182 | |||
| 183 | #endif | ||
| 184 |