Skyward boardcore
Loading...
Searching...
No Matches
HILTransceiver.h
Go to the documentation of this file.
1/* Copyright (c) 2020-2024 Skyward Experimental Rocketry
2 * Author: Emilio Corigliano
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23#pragma once
24
25#include <ActiveObject.h>
26#include <drivers/dma/DMA.h>
28#include <drivers/usart/USART.h>
29#include <utils/Debug.h>
30
31#include "HIL.h"
32#include "drivers/usart/USART.h"
33
34namespace Boardcore
35{
36
37template <class FlightPhases, class SimulatorData, class ActuatorData>
38class HIL;
39
41{
42public:
47
53 int getLostUpdates() const { return nLostUpdates; }
54
60
61protected:
66 {
67 miosix::Lock<miosix::FastMutex> l(mutex);
68 while (!updated)
69 condVar.wait(l);
70 updated = false;
71 }
72
74 bool receivedFirstPacket = false;
75 bool updated = false;
76 int nLostUpdates = 0;
77 int64_t timestampSimulatorData = 0; // timestamp of the last received
78 // simulatorData [ns]
79 miosix::FastMutex mutex;
80 miosix::ConditionVariable condVar;
82};
83
88template <class FlightPhases, class SimulatorData, class ActuatorData>
90{
91public:
98 HILPhasesManager<FlightPhases, SimulatorData,
99 ActuatorData>* hilPhasesManager)
100 : HILTransceiverBase(hilSerial), actuatorData(),
101 hilPhasesManager(hilPhasesManager),
102 dmaStreamTx(DMADriver::instance().acquireStreamForPeripheral(
103 // TODO: remove hardcoded UART
104 DMADefs::Peripherals::PE_UART4_TX, std::chrono::seconds(1)))
105 {
106 if (dmaStreamTx.isValid())
107 hilSerial.getPeripheral()->CR3 |=
108 USART_CR3_DMAT; // Enable DMA transmission
109 }
110
118 void setActuatorData(ActuatorData actuatorData)
119 {
120 miosix::Lock<miosix::FastMutex> l(mutex);
121
122 // If already updated increment lost updates
123 if (updated)
124 nLostUpdates++;
125
126 this->actuatorData = actuatorData;
127 updated = true;
128 condVar.signal();
129 }
130
136 const SimulatorData* getSensorData() const { return &simulatorData; }
137
138 bool isDmaEnabled() { return dmaStreamTx.isValid(); }
139
140private:
141 void run() override;
142
143 SimulatorData simulatorData;
144 ActuatorData actuatorData;
146 hilPhasesManager;
147
152 bool writeDma(void* buffer, uint16_t nBytes,
153 std::chrono::nanoseconds timeout);
154
155 DMAStreamGuard dmaStreamTx;
156};
157
168template <class FlightPhases, class SimulatorData, class ActuatorData>
169void HILTransceiver<FlightPhases, SimulatorData, ActuatorData>::run()
170{
171 LOG_INFO(logger, "HIL Transceiver started");
172 hilSerial.clearQueue();
173
174 miosix::led2On();
175 hilSerial.write(&actuatorData, sizeof(ActuatorData));
176 miosix::led2Off();
177
178 while (!shouldStop())
179 {
180 // Pausing the kernel in order to copy the data in the shared structure
181 {
182 SimulatorData tempData;
183 nLostUpdates = 0;
184 miosix::led3On();
185 size_t nRead = 0;
186 if (!hilSerial.readBlocking(&tempData, sizeof(SimulatorData),
187 nRead))
188 {
189 LOG_ERR(logger, "Failed serial read");
190 }
191
192 assert(nRead == sizeof(SimulatorData) &&
193 "Read less then SimulatorData bytes");
194
195 hilSerial.clearQueue();
196 miosix::led3Off();
197
198 miosix::PauseKernelLock kLock;
199 simulatorData = tempData;
200 timestampSimulatorData = miosix::getTime();
201 }
202
203 // If this is the first packet to be received, then update the flight
204 // phase manager
205 if (!receivedFirstPacket)
206 {
207 receivedFirstPacket = true;
208 hilPhasesManager->simulationStarted();
209 }
210
211 // Trigger events relative to the flight phases
212 hilPhasesManager->processFlags(simulatorData);
213
214 if (nLostUpdates > 0)
215 {
216 // This means also that the number of samples used for the mean sent
217 // to the HIL simulator is made up of more than the number of
218 // samples we though
219 LOG_WARN(logger, "{} lost updates", nLostUpdates);
220 }
221
222 waitActuatorData();
223 miosix::led2On();
224
225 if (isDmaEnabled())
226 writeDma(&actuatorData, sizeof(ActuatorData),
227 std::chrono::milliseconds(100));
228 else
229 hilSerial.write(&actuatorData, sizeof(ActuatorData));
230
231 miosix::led2Off();
232 }
233}
234
235template <class FlightPhases, class SimulatorData, class ActuatorData>
236bool HILTransceiver<FlightPhases, SimulatorData, ActuatorData>::writeDma(
237 void* buffer, uint16_t nBytes, std::chrono::nanoseconds timeout)
238{
239 USARTType* usart = hilSerial.getPeripheral();
240
241 DMATransaction setup{
246 .srcAddress = buffer,
247 .dstAddress = (void*)&(usart->TDR),
248 .numberOfDataItems = nBytes,
249 .srcIncrement = true,
250 .dstIncrement = false,
251 .enableTransferCompleteInterrupt = true,
252 .enableTransferErrorInterrupt = true,
253 };
254
255 dmaStreamTx->setup(setup);
256
257 // Clear the TC flag in the USART_ISR register by setting
258 // the TCCF bit in the USART_ICR register
259 usart->ICR |= USART_ICR_TCCF;
260
261 dmaStreamTx->enable();
262 bool ret = dmaStreamTx->timedWaitForTransferComplete(timeout);
263
264 /*
265 The TC flag can be monitored to make sure that the USART
266 communication is complete. This is required to avoid corrupting the last
267 transmission before disabling the USART or entering Stop mode. Software must
268 wait until TC=1. The TC flag remains cleared during all data transfers and
269 it is set by hardware at the end of transmission of the last frame.
270 */
271 while ((usart->ISR & USART_ISR_TC) == 0)
272 {
273 }
274
275 return ret;
276}
277} // namespace Boardcore
#define LOG_WARN(logger,...)
#define LOG_INFO(logger,...)
#define LOG_ERR(logger,...)
USART_TypeDef USARTType
Definition USART.h:36
This class is responsible for streams acquisition, streams release and interrupt handling.
Definition DMA.h:168
Simple RAII class to handle DMA streams.
Definition DMA.h:557
Singleton object that manages all the phases of the simulation. After his instantiation we need to se...
miosix::ConditionVariable condVar
void waitActuatorData()
Waits for the control algorithm(s) to update actuatorData.
int getLostUpdates() const
Returns the number of lost updates.
HILTransceiverBase(USART &hilSerial)
Construct a serial connection attached to a control algorithm.
int64_t getTimestampSimulatorData() const
Returns the value in ns of the timestamp of the last received simulatorData.
HILTransceiver is a Singleton and provides an easy interface for the control algorithms to send and r...
HILTransceiver(USART &hilSerial, HILPhasesManager< FlightPhases, SimulatorData, ActuatorData > *hilPhasesManager)
Construct a serial connection attached to a control algorithm.
const SimulatorData * getSensorData() const
returns the reference of the SimulatorData
void setActuatorData(ActuatorData actuatorData)
sets the actuator data and then wakes up the MatlabTransceiver thread in order to send the data back ...
static PrintLogger getLogger(const string &name)
Driver for STM32F4 low level USART/UART peripheral.
Definition USART.h:172
USARTType * getPeripheral()
Definition USART.h:134
Driver for the VN100S IMU.
Definition WIZ5500.h:339