F´ Flight Software - C/C++ Documentation
A framework for building embedded system applications to NASA flight quality standards.
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"
13 
14 namespace Svc {
15 
17 
19  this->m_computed.init();
20 }
21 
23  FW_ASSERT(buffer != nullptr);
24  this->m_computed.update(buffer, bufferSize);
25 }
26 
28  U32 computed = 0;
29  this->m_computed.finalize(computed);
30  return computed;
31 }
32 
34  : Sequence(component) {}
35 
36 bool CmdSequencerComponentImpl::FPrimeSequence ::validateCRC() {
37  bool result = true;
38  U32 computed = this->m_crc.finalize();
39  if (this->m_crc.m_stored != computed) {
40  this->m_events.fileCRCFailure(this->m_crc.m_stored, computed);
41  result = false;
42  }
43  return result;
44 }
45 
47  // make sure there is a buffer allocated
48  FW_ASSERT(this->m_buffer.getBuffAddr() != nullptr);
49 
50  this->setFileName(fileName);
51 
52  const bool status = this->readFile() and this->validateCRC() and this->m_header.validateTime(this->m_component) and
53  this->validateRecords();
54 
55  return status;
56 }
57 
59  return this->m_buffer.getDeserializeSizeLeft() > 0;
60 }
61 
63  Fw::SerializeStatus status = this->deserializeRecord(record);
64  FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
65 }
66 
68  this->m_buffer.resetDeser();
69 }
70 
72  this->m_buffer.resetSer();
73 }
74 
75 bool CmdSequencerComponentImpl::FPrimeSequence ::readFile() {
76  bool result;
77 
78  Os::File::Status status = this->m_sequenceFile.open(this->m_fileName.toChar(), Os::File::OPEN_READ);
79 
80  if (status == Os::File::OP_OK) {
81  result = this->readOpenFile();
82  } else if (status == Os::File::DOESNT_EXIST) {
83  this->m_events.fileNotFound();
84  result = false;
85  } else {
86  this->m_events.fileReadError();
87  result = false;
88  }
89 
90  this->m_sequenceFile.close();
91  return result;
92 }
93 
94 bool CmdSequencerComponentImpl::FPrimeSequence ::readOpenFile() {
95  U8* const buffAddr = this->m_buffer.getBuffAddr();
96  this->m_crc.init();
97  bool status = this->readHeader();
98  if (status) {
99  this->m_crc.update(buffAddr, Sequence::Header::SERIALIZED_SIZE);
100  status = this->deserializeHeader() and this->readRecordsAndCRC() and this->extractCRC();
101  }
102  if (status) {
103  const FwSizeType buffLen = this->m_buffer.getSize();
104  this->m_crc.update(buffAddr, buffLen);
105  }
106  return status;
107 }
108 
109 bool CmdSequencerComponentImpl::FPrimeSequence ::readHeader() {
110  Os::File& file = this->m_sequenceFile;
111  Fw::LinearBufferBase& buffer = this->m_buffer;
112  bool status = true;
113 
115 
116  const FwSizeType capacity = buffer.getCapacity();
117  FW_ASSERT(capacity >= readLen, static_cast<FwAssertArgType>(capacity), static_cast<FwAssertArgType>(readLen));
118  Os::File::Status fileStatus = file.read(buffer.getBuffAddr(), readLen);
119 
120  if (fileStatus != Os::File::OP_OK) {
121  this->m_events.fileInvalid(CmdSequencer_FileReadStage::READ_HEADER, fileStatus);
122  status = false;
123  }
124 
125  if (status and readLen != Sequence::Header::SERIALIZED_SIZE) {
126  this->m_events.fileInvalid(CmdSequencer_FileReadStage::READ_HEADER_SIZE, static_cast<I32>(readLen));
127  status = false;
128  }
129 
130  if (status) {
131  const Fw::SerializeStatus serializeStatus = buffer.setBuffLen(static_cast<Fw::Serializable::SizeType>(readLen));
132  FW_ASSERT(serializeStatus == Fw::FW_SERIALIZE_OK, serializeStatus);
133  }
134 
135  return status;
136 }
137 
138 bool CmdSequencerComponentImpl::FPrimeSequence ::deserializeHeader() {
139  Fw::LinearBufferBase& buffer = this->m_buffer;
140  Header& header = this->m_header;
141 
142  // File size
143  Fw::SerializeStatus serializeStatus = buffer.deserializeTo(header.m_fileSize);
144  if (serializeStatus != Fw::FW_SERIALIZE_OK) {
145  this->m_events.fileInvalid(CmdSequencer_FileReadStage::DESER_SIZE, serializeStatus);
146  return false;
147  }
148  if (header.m_fileSize > buffer.getCapacity()) {
149  this->m_events.fileSizeError(header.m_fileSize);
150  return false;
151  }
152  // Number of records
153  serializeStatus = buffer.deserializeTo(header.m_numRecords);
154  if (serializeStatus != Fw::FW_SERIALIZE_OK) {
155  this->m_events.fileInvalid(CmdSequencer_FileReadStage::DESER_NUM_RECORDS, serializeStatus);
156  return false;
157  }
158  // Time base
159  TimeBase tbase;
160  serializeStatus = buffer.deserializeTo(tbase);
161  if (serializeStatus != Fw::FW_SERIALIZE_OK) {
162  this->m_events.fileInvalid(CmdSequencer_FileReadStage::DESER_TIME_BASE, serializeStatus);
163  return false;
164  }
165  header.m_timeBase = (tbase);
166  // Time context
167  serializeStatus = buffer.deserializeTo(header.m_timeContext);
168  if (serializeStatus != Fw::FW_SERIALIZE_OK) {
169  this->m_events.fileInvalid(CmdSequencer_FileReadStage::DESER_TIME_CONTEXT, serializeStatus);
170  return false;
171  }
172  return true;
173 }
174 
175 bool CmdSequencerComponentImpl::FPrimeSequence ::readRecordsAndCRC() {
176  Os::File& file = this->m_sequenceFile;
177  const FwSizeType size = this->m_header.m_fileSize;
178  Fw::LinearBufferBase& buffer = this->m_buffer;
179 
180  FwSizeType readLen = size;
181  Os::File::Status fileStatus = file.read(buffer.getBuffAddr(), readLen);
182  // check read status
183  if (fileStatus != Os::File::OP_OK) {
184  this->m_events.fileInvalid(CmdSequencer_FileReadStage::READ_SEQ_DATA, fileStatus);
185  return false;
186  }
187  // check read size
188  if (size != static_cast<FwSizeType>(readLen)) {
189  this->m_events.fileInvalid(CmdSequencer_FileReadStage::READ_SEQ_DATA_SIZE, static_cast<I32>(readLen));
190  return false;
191  }
192  // set buffer size
193  Fw::SerializeStatus serializeStatus = buffer.setBuffLen(size);
194  FW_ASSERT(serializeStatus == Fw::FW_SERIALIZE_OK, serializeStatus);
195  return true;
196 }
197 
198 bool CmdSequencerComponentImpl::FPrimeSequence ::extractCRC() {
199  Fw::LinearBufferBase& buffer = this->m_buffer;
200  U32& crc = this->m_crc.m_stored;
201 
202  // Compute the data size
203  const FwSizeType buffSize = buffer.getSize();
204  const FwSizeType crcSize = sizeof(crc);
205  U8* const buffAddr = buffer.getBuffAddr();
206  if (buffSize < crcSize) {
207  this->m_events.fileInvalid(CmdSequencer_FileReadStage::READ_SEQ_CRC, static_cast<I32>(buffSize));
208  return false;
209  }
210  FW_ASSERT(buffSize >= crcSize, static_cast<FwAssertArgType>(buffSize), crcSize);
211  const FwSizeType dataSize = buffSize - crcSize;
212  // Create a CRC buffer pointing at the CRC in the main buffer, after the data
213  Fw::ExternalSerializeBuffer crcBuff(&buffAddr[dataSize], crcSize);
214  Fw::SerializeStatus status = crcBuff.setBuffLen(crcSize);
215  FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
216  // Deserialize the CRC from the CRC buffer
217  status = crcBuff.deserializeTo(crc);
218  FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
219  // Set the main buffer size to the data size
220  status = buffer.setBuffLen(dataSize);
221  FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
222  return true;
223 }
224 
225 Fw::SerializeStatus CmdSequencerComponentImpl::FPrimeSequence ::deserializeRecord(Record& record) {
226  U32 recordSize;
227 
228  Fw::SerializeStatus status = this->deserializeDescriptor(record.m_descriptor);
229 
230  if (status == Fw::FW_SERIALIZE_OK and record.m_descriptor == Record::END_OF_SEQUENCE) {
231  return Fw::FW_SERIALIZE_OK;
232  }
233 
234  if (status == Fw::FW_SERIALIZE_OK) {
235  status = this->deserializeTimeTag(record.m_timeTag);
236  }
237  if (status == Fw::FW_SERIALIZE_OK) {
238  status = this->deserializeRecordSize(recordSize);
239  }
240  if (status == Fw::FW_SERIALIZE_OK) {
241  status = this->copyCommand(record.m_command, recordSize);
242  }
243 
244  return status;
245 }
246 
247 Fw::SerializeStatus CmdSequencerComponentImpl::FPrimeSequence ::deserializeDescriptor(Record::Descriptor& descriptor) {
248  Fw::LinearBufferBase& buffer = this->m_buffer;
249  U8 descEntry;
250 
251  Fw::SerializeStatus status = buffer.deserializeTo(descEntry);
252  if (status != Fw::FW_SERIALIZE_OK) {
253  return status;
254  }
255 
256  if (descEntry > Sequence::Record::END_OF_SEQUENCE) {
258  }
259 
260  descriptor = static_cast<Record::Descriptor>(descEntry);
261  return Fw::FW_SERIALIZE_OK;
262 }
263 
264 Fw::SerializeStatus CmdSequencerComponentImpl::FPrimeSequence ::deserializeTimeTag(Fw::Time& timeTag) {
265  Fw::LinearBufferBase& buffer = this->m_buffer;
266  U32 seconds;
267  U32 useconds;
268  Fw::SerializeStatus status = buffer.deserializeTo(seconds);
269  if (status == Fw::FW_SERIALIZE_OK) {
270  status = buffer.deserializeTo(useconds);
271  }
272  if (status == Fw::FW_SERIALIZE_OK) {
273  timeTag.set(seconds, useconds);
274  }
275  return status;
276 }
277 
278 Fw::SerializeStatus CmdSequencerComponentImpl::FPrimeSequence ::deserializeRecordSize(U32& recordSize) {
279  Fw::LinearBufferBase& buffer = this->m_buffer;
280  Fw::SerializeStatus status = buffer.deserializeTo(recordSize);
281  if (status == Fw::FW_SERIALIZE_OK and recordSize > buffer.getDeserializeSizeLeft()) {
282  // Not enough data left
284  }
285  if (status == Fw::FW_SERIALIZE_OK and
287  // Record size is too big for com buffer
289  }
290  return status;
291 }
292 
293 Fw::SerializeStatus CmdSequencerComponentImpl::FPrimeSequence ::copyCommand(Fw::ComBuffer& comBuffer,
294  const U32 recordSize) {
295  Fw::LinearBufferBase& buffer = this->m_buffer;
296  comBuffer.resetSer();
297  FwSizeType size = recordSize;
298  Fw::SerializeStatus status = comBuffer.setBuffLen(recordSize);
299  FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
300  status = buffer.deserializeTo(comBuffer.getBuffAddr(), size, Fw::Serialization::OMIT_LENGTH);
301  return status;
302 }
303 
304 bool CmdSequencerComponentImpl::FPrimeSequence ::validateRecords() {
305  Fw::LinearBufferBase& buffer = this->m_buffer;
306  const U32 numRecords = this->m_header.m_numRecords;
307  Sequence::Record record;
308 
309  if (numRecords == 0) {
310  this->m_events.noRecords();
311  return false;
312  }
313 
314  // Deserialize all records
315  for (U32 recordNumber = 0; recordNumber < numRecords; recordNumber++) {
316  Fw::SerializeStatus status = this->deserializeRecord(record);
317  if (status != Fw::FW_SERIALIZE_OK) {
318  this->m_events.recordInvalid(recordNumber, status);
319  return false;
320  }
321  }
322  // Check there is no data left
323  const FwSizeType buffLeftSize = buffer.getDeserializeSizeLeft();
324  if (buffLeftSize > 0) {
325  this->m_events.recordMismatch(numRecords, static_cast<U32>(buffLeftSize));
326  return false;
327  }
328  // Rewind deserialization
329  buffer.resetDeser();
330 
331  return true;
332 }
333 
334 } // namespace Svc
Serialization/Deserialization operation was successful.
U16 FwPacketDescriptorType
The width of packet descriptors when they are serialized by the framework.
PlatformSizeType FwSizeType
Serializable::SizeType getSize() const override
Get current buffer size.
virtual U8 * getBuffAddr()=0
Get buffer address for data filling (non-const version)
Deserialization data had incorrect values (unexpected data types)
SerializeStatus
forward declaration for string
void set(U32 seconds, U32 useconds)
Definition: Time.cpp:29
Omit length from serialization.
A sequence with unspecified binary format.
File doesn&#39;t exist (for read)
Definition: File.hpp:43
bool loadFile(const Fw::ConstStringBase &fileName)
void update(const BYTE *buffer, FwSizeType bufferSize)
Update computed CRC.
Data was left in the buffer, but not enough to deserialize.
Serializable::SizeType getDeserializeSizeLeft() const override
Get remaining deserialization buffer size.
External serialize buffer with no copy semantics.
void resetDeser() override
Reset deserialization pointer to beginning of buffer.
void resetSer() override
Reset serialization pointer to beginning of buffer.
Serializable::SizeType getCapacity() const override=0
Get buffer capacity.
FPrimeSequence(CmdSequencerComponentImpl &component)
Construct an FPrimeSequence.
uint8_t U8
8-bit unsigned integer
Definition: BasicTypes.h:54
Status read(U8 *buffer, FwSizeType &size)
read data from this file into supplied buffer bounded by size
Definition: File.cpp:187
Operation was successful.
Definition: File.hpp:42
A read-only abstract superclass for StringBase.
Open file for reading.
Definition: File.hpp:33
RateGroupDivider component implementation.
U8 * getBuffAddr() override
Get buffer address for data filling (non-const version)
SerializeStatus deserializeTo(U8 &val, Endianness mode=Endianness::BIG) override
Deserialize an 8-bit unsigned integer value.
U8 BYTE
byte type
Definition: BasicTypes.h:57
SerializeStatus setBuffLen(Serializable::SizeType length) override
Set buffer length manually.
Define enumeration for Time base types.
#define FW_ASSERT(...)
Definition: Assert.hpp:14