F´ Flight Software - C/C++ Documentation NASA-v1.6.0
A framework for building embedded system applications to NASA flight quality standards.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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.