F´ Flight Software - C/C++ Documentation NASA-v1.6.0
A framework for building embedded system applications to NASA flight quality standards.
Loading...
Searching...
No Matches
FPrimeSequence.cpp
Go to the documentation of this file.
1// ======================================================================
2// \title FPrimeSequence.cpp
3// \author Bocchino/Canham
4// \brief CmdSequencerComponentImpl::FPrimeSequence implementation
5//
6// Copyright (C) 2009-2018 California Institute of Technology.
7// ALL RIGHTS RESERVED. United States Government Sponsorship
8// acknowledged.
9// ======================================================================
10
11#include "Fw/Types/Assert.hpp"
13extern "C" {
15}
16
17namespace Svc {
18
19 CmdSequencerComponentImpl::FPrimeSequence::CRC ::
20 CRC() :
21 m_computed(INITIAL_COMPUTED_VALUE),
22 m_stored(0)
23 {
24
25 }
26
27 void CmdSequencerComponentImpl::FPrimeSequence::CRC ::
28 init()
29 {
30 this->m_computed = INITIAL_COMPUTED_VALUE;
31 }
32
33 void CmdSequencerComponentImpl::FPrimeSequence::CRC ::
34 update(const BYTE* buffer, NATIVE_UINT_TYPE bufferSize)
35 {
36 FW_ASSERT(buffer);
37 for(NATIVE_UINT_TYPE index = 0; index < bufferSize; index++) {
38 this->m_computed = update_crc_32(this->m_computed, buffer[index]);
39 }
40 }
41
42 void CmdSequencerComponentImpl::FPrimeSequence::CRC ::
43 finalize()
44 {
45 this->m_computed = ~this->m_computed;
46 }
47
48 CmdSequencerComponentImpl::FPrimeSequence ::
49 FPrimeSequence(CmdSequencerComponentImpl& component) :
50 Sequence(component)
51 {
52
53 }
54
55 bool CmdSequencerComponentImpl::FPrimeSequence ::
56 validateCRC()
57 {
58 bool result = true;
59 if (this->m_crc.m_stored != this->m_crc.m_computed) {
60 this->m_events.fileCRCFailure(
61 this->m_crc.m_stored,
62 this->m_crc.m_computed
63 );
64 result = false;
65 }
66 return result;
67 }
68
69 bool CmdSequencerComponentImpl::FPrimeSequence ::
70 loadFile(const Fw::CmdStringArg& fileName)
71 {
72
73 // make sure there is a buffer allocated
74 FW_ASSERT(this->m_buffer.getBuffAddr());
75
76 this->setFileName(fileName);
77
78 const bool status = this->readFile()
79 and this->validateCRC()
80 and this->m_header.validateTime(this->m_component)
81 and this->validateRecords();
82
83 return status;
84
85 }
86
87 bool CmdSequencerComponentImpl::FPrimeSequence ::
88 hasMoreRecords() const
89 {
90 return this->m_buffer.getBuffLeft() > 0;
91 }
92
93 void CmdSequencerComponentImpl::FPrimeSequence ::
94 nextRecord(Record& record)
95 {
96 Fw::SerializeStatus status = this->deserializeRecord(record);
97 FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
98 }
99
100 void CmdSequencerComponentImpl::FPrimeSequence ::
101 reset()
102 {
103 this->m_buffer.resetDeser();
104 }
105
106 void CmdSequencerComponentImpl::FPrimeSequence ::
107 clear()
108 {
109 this->m_buffer.resetSer();
110 }
111
112 bool CmdSequencerComponentImpl::FPrimeSequence ::
113 readFile()
114 {
115
116 bool result;
117
118 Os::File::Status status = this->m_sequenceFile.open(
119 this->m_fileName.toChar(),
121 );
122
123 if (status == Os::File::OP_OK) {
124 result = this->readOpenFile();
125 } else if (status == Os::File::DOESNT_EXIST) {
126 this->m_events.fileNotFound();
127 result = false;
128 } else {
129 this->m_events.fileReadError();
130 result = false;
131 }
132
133 this->m_sequenceFile.close();
134 return result;
135
136 }
137
138 bool CmdSequencerComponentImpl::FPrimeSequence ::
139 readOpenFile()
140 {
141 U8 *const buffAddr = this->m_buffer.getBuffAddr();
142 this->m_crc.init();
143 bool status = this->readHeader();
144 if (status) {
145 this->m_crc.update(buffAddr, Sequence::Header::SERIALIZED_SIZE);
146 status = this->deserializeHeader()
147 and this->readRecordsAndCRC()
148 and this->extractCRC();
149 }
150 if (status) {
151 const NATIVE_UINT_TYPE buffLen = this->m_buffer.getBuffLength();
152 this->m_crc.update(buffAddr, buffLen);
153 this->m_crc.finalize();
154 }
155 return status;
156 }
157
158 bool CmdSequencerComponentImpl::FPrimeSequence ::
159 readHeader()
160 {
161
162 Os::File& file = this->m_sequenceFile;
163 Fw::SerializeBufferBase& buffer = this->m_buffer;
164 bool status = true;
165
167 FW_ASSERT(readLen >= 0, readLen);
168
169 const NATIVE_UINT_TYPE capacity = buffer.getBuffCapacity();
170 FW_ASSERT(
171 capacity >= static_cast<NATIVE_UINT_TYPE>(readLen),
172 capacity,
173 readLen
174 );
175 Os::File::Status fileStatus = file.read(
176 buffer.getBuffAddr(),
177 readLen
178 );
179
180 if (fileStatus != Os::File::OP_OK) {
181 this->m_events.fileInvalid(
182 CmdSequencer_FileReadStage::READ_HEADER,
183 file.getLastError()
184 );
185 status = false;
186 }
187
188 if (status and readLen != Sequence::Header::SERIALIZED_SIZE) {
189 this->m_events.fileInvalid(
190 CmdSequencer_FileReadStage::READ_HEADER_SIZE,
191 readLen
192 );
193 status = false;
194 }
195
196 if (status) {
197 const Fw::SerializeStatus serializeStatus =
198 buffer.setBuffLen(readLen);
199 FW_ASSERT(
200 serializeStatus == Fw::FW_SERIALIZE_OK,
201 serializeStatus
202 );
203 }
204
205 return status;
206 }
207
208 bool CmdSequencerComponentImpl::FPrimeSequence ::
209 deserializeHeader()
210 {
211 Fw::SerializeBufferBase& buffer = this->m_buffer;
212 Header& header = this->m_header;
213
214 // File size
215 Fw::SerializeStatus serializeStatus = buffer.deserialize(header.m_fileSize);
216 if (serializeStatus != Fw::FW_SERIALIZE_OK) {
217 this->m_events.fileInvalid(
218 CmdSequencer_FileReadStage::DESER_SIZE,
219 serializeStatus
220 );
221 return false;
222 }
223 if (header.m_fileSize > buffer.getBuffCapacity()) {
224 this->m_events.fileSizeError(header.m_fileSize);
225 return false;
226 }
227 // Number of records
228 serializeStatus = buffer.deserialize(header.m_numRecords);
229 if (serializeStatus != Fw::FW_SERIALIZE_OK) {
230 this->m_events.fileInvalid(
231 CmdSequencer_FileReadStage::DESER_NUM_RECORDS,
232 serializeStatus
233 );
234 return false;
235 }
236 // Time base
238 serializeStatus = buffer.deserialize(tbase);
239 if (serializeStatus != Fw::FW_SERIALIZE_OK) {
240 this->m_events.fileInvalid(
241 CmdSequencer_FileReadStage::DESER_TIME_BASE,
242 serializeStatus
243 );
244 return false;
245 }
246 header.m_timeBase = static_cast<TimeBase>(tbase);
247 // Time context
248 serializeStatus = buffer.deserialize(header.m_timeContext);
249 if (serializeStatus != Fw::FW_SERIALIZE_OK) {
250 this->m_events.fileInvalid(
251 CmdSequencer_FileReadStage::DESER_TIME_CONTEXT,
252 serializeStatus
253 );
254 return false;
255 }
256 return true;
257 }
258
259 bool CmdSequencerComponentImpl::FPrimeSequence ::
260 readRecordsAndCRC()
261 {
262 Os::File& file = this->m_sequenceFile;
263 const NATIVE_UINT_TYPE size = this->m_header.m_fileSize;
264 Fw::SerializeBufferBase& buffer = this->m_buffer;
265
266 NATIVE_INT_TYPE readLen = size;
267 Os::File::Status fileStatus = file.read(
268 buffer.getBuffAddr(),
269 readLen
270 );
271 // check read status
272 if (fileStatus != Os::File::OP_OK) {
273 this->m_events.fileInvalid(
274 CmdSequencer_FileReadStage::READ_SEQ_DATA,
275 file.getLastError()
276 );
277 return false;
278 }
279 // check read size
280 if (static_cast<NATIVE_INT_TYPE>(size) != readLen) {
281 this->m_events.fileInvalid(
282 CmdSequencer_FileReadStage::READ_SEQ_DATA_SIZE,
283 readLen
284 );
285 return false;
286 }
287 // set buffer size
288 Fw::SerializeStatus serializeStatus =
289 buffer.setBuffLen(size);
290 FW_ASSERT(serializeStatus == Fw::FW_SERIALIZE_OK, serializeStatus);
291 return true;
292 }
293
294 bool CmdSequencerComponentImpl::FPrimeSequence ::
295 extractCRC()
296 {
297 Fw::SerializeBufferBase& buffer = this->m_buffer;
298 U32& crc = this->m_crc.m_stored;
299
300 // Compute the data size
301 const U32 buffSize = buffer.getBuffLength();
302 const U32 crcSize = sizeof(crc);
303 U8 *const buffAddr = buffer.getBuffAddr();
304 if (buffSize < crcSize) {
305 this->m_events.fileInvalid(
306 CmdSequencer_FileReadStage::READ_SEQ_CRC,
307 buffSize
308 );
309 return false;
310 }
311 FW_ASSERT(buffSize >= crcSize, buffSize, crcSize);
312 const NATIVE_UINT_TYPE dataSize = buffSize - crcSize;
313 // Create a CRC buffer pointing at the CRC in the main buffer, after the data
314 Fw::ExternalSerializeBuffer crcBuff(&buffAddr[dataSize], crcSize);
315 Fw::SerializeStatus status = crcBuff.setBuffLen(crcSize);
316 FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
317 // Deserialize the CRC from the CRC buffer
318 status = crcBuff.deserialize(crc);
319 FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
320 // Set the main buffer size to the data size
321 status = buffer.setBuffLen(dataSize);
322 FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
323 return true;
324 }
325
326 Fw::SerializeStatus CmdSequencerComponentImpl::FPrimeSequence ::
327 deserializeRecord(Record& record)
328 {
329 U32 recordSize;
330
331 Fw::SerializeStatus status =
332 this->deserializeDescriptor(record.m_descriptor);
333
334 if (
335 status == Fw::FW_SERIALIZE_OK and
336 record.m_descriptor == Record::END_OF_SEQUENCE
337 ) {
338 return Fw::FW_SERIALIZE_OK;
339 }
340
341 if (status == Fw::FW_SERIALIZE_OK) {
342 status = this->deserializeTimeTag(record.m_timeTag);
343 }
344 if (status == Fw::FW_SERIALIZE_OK) {
345 status = this->deserializeRecordSize(recordSize);
346 }
347 if (status == Fw::FW_SERIALIZE_OK) {
348 status = this->copyCommand(record.m_command, recordSize);
349 }
350
351 return status;
352 }
353
354 Fw::SerializeStatus CmdSequencerComponentImpl::FPrimeSequence ::
355 deserializeDescriptor(Record::Descriptor& descriptor)
356 {
357 Fw::SerializeBufferBase& buffer = this->m_buffer;
358 U8 descEntry;
359
360 Fw::SerializeStatus status = buffer.deserialize(descEntry);
361 if (status != Fw::FW_SERIALIZE_OK) {
362 return status;
363 }
364
365 if (descEntry > Sequence::Record::END_OF_SEQUENCE) {
367 }
368
369 descriptor = static_cast<Record::Descriptor>(descEntry);
370 return Fw::FW_SERIALIZE_OK;
371 }
372
373 Fw::SerializeStatus CmdSequencerComponentImpl::FPrimeSequence ::
374 deserializeTimeTag(Fw::Time& timeTag)
375 {
376 Fw::SerializeBufferBase& buffer = this->m_buffer;
377 U32 seconds, useconds;
378 Fw::SerializeStatus status = buffer.deserialize(seconds);
379 if (status == Fw::FW_SERIALIZE_OK) {
380 status = buffer.deserialize(useconds);
381 }
382 if (status == Fw::FW_SERIALIZE_OK) {
383 timeTag.set(seconds,useconds);
384 }
385 return status;
386 }
387
388 Fw::SerializeStatus CmdSequencerComponentImpl::FPrimeSequence ::
389 deserializeRecordSize(U32& recordSize)
390 {
391 Fw::SerializeBufferBase& buffer = this->m_buffer;
392 Fw::SerializeStatus status = buffer.deserialize(recordSize);
393 if (status == Fw::FW_SERIALIZE_OK and recordSize > buffer.getBuffLeft()) {
394 // Not enough data left
396 }
397 if (
398 status == Fw::FW_SERIALIZE_OK and
400 ) {
401 // Record size is too big for com buffer
403 }
404 return status;
405 }
406
407 Fw::SerializeStatus CmdSequencerComponentImpl::FPrimeSequence ::
408 copyCommand(Fw::ComBuffer& comBuffer, const U32 recordSize)
409 {
410 Fw::SerializeBufferBase& buffer = this->m_buffer;
411 comBuffer.resetSer();
412 NATIVE_UINT_TYPE size = recordSize;
413 Fw::SerializeStatus status = comBuffer.setBuffLen(recordSize);
414 FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
415 status = buffer.deserialize(comBuffer.getBuffAddr(), size, true);
416 return status;
417 }
418
419 bool CmdSequencerComponentImpl::FPrimeSequence ::
420 validateRecords()
421 {
422 Fw::SerializeBufferBase& buffer = this->m_buffer;
423 const U32 numRecords = this->m_header.m_numRecords;
424 Sequence::Record record;
425
426 // Deserialize all records
427 for (NATIVE_UINT_TYPE recordNumber = 0; recordNumber < numRecords; recordNumber++) {
428 Fw::SerializeStatus status = this->deserializeRecord(record);
429 if (status != Fw::FW_SERIALIZE_OK) {
430 this->m_events.recordInvalid(recordNumber, status);
431 return false;
432 }
433 }
434 // Check there is no data left
435 const U32 buffLeftSize = buffer.getBuffLeft();
436 if (buffLeftSize > 0) {
437 this->m_events.recordMismatch(numRecords, buffLeftSize);
438 return false;
439 }
440 // Rewind deserialization
441 buffer.resetDeser();
442
443 return true;
444 }
445
446}
447
#define FW_ASSERT(...)
Definition Assert.hpp:7
PlatformIntType NATIVE_INT_TYPE
Definition BasicTypes.h:51
U8 BYTE
byte type
Definition BasicTypes.h:27
uint8_t U8
8-bit unsigned integer
Definition BasicTypes.h:26
PlatformUIntType NATIVE_UINT_TYPE
Definition BasicTypes.h:52
TimeBase
Definition FpConfig.h:38
U32 FwPacketDescriptorType
Definition FpConfig.h:53
U16 FwTimeBaseStoreType
Definition FpConfig.h:47
U8 * getBuffAddr()
gets buffer address for data filling
Definition ComBuffer.cpp:40
NATIVE_UINT_TYPE getBuffLeft() const
returns how much deserialization buffer is left
void resetDeser()
reset deserialization to beginning
SerializeStatus setBuffLen(NATIVE_UINT_TYPE length)
sets buffer length manually after filling with data
void resetSer()
reset to beginning of buffer to reuse for serialization
virtual NATIVE_UINT_TYPE getBuffCapacity() const =0
returns capacity, not current size, of buffer
SerializeStatus deserialize(U8 &val)
deserialize 8-bit unsigned int
virtual U8 * getBuffAddr()=0
gets buffer address for data filling
NATIVE_UINT_TYPE getBuffLength() const
returns current buffer size
void set(U32 seconds, U32 useconds)
Definition Time.cpp:25
@ DOESNT_EXIST
File doesn't exist (for read)
Definition File.hpp:25
@ OP_OK
Operation was successful.
Definition File.hpp:24
@ OPEN_READ
Open file for reading.
Definition File.hpp:15
NATIVE_INT_TYPE getLastError()
read back last error code (typically errno)
Definition File.cpp:38
Status read(void *buffer, NATIVE_INT_TYPE &size, bool waitForFull=true)
waitForFull = true to wait for all bytes to be read
Definition File.cpp:28
A sequence with unspecified binary format.
unsigned long update_crc_32(unsigned long crc, char c)
Definition lib_crc.c:269
SerializeStatus
forward declaration for string
@ FW_DESERIALIZE_FORMAT_ERROR
Deserialization data had incorrect values (unexpected data types)
@ FW_SERIALIZE_OK
Serialization/Deserialization operation was successful.
@ FW_DESERIALIZE_SIZE_MISMATCH
Data was left in the buffer, but not enough to deserialize.