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);
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());
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, useconds;
267  Fw::SerializeStatus status = buffer.deserializeTo(seconds);
268  if (status == Fw::FW_SERIALIZE_OK) {
269  status = buffer.deserializeTo(useconds);
270  }
271  if (status == Fw::FW_SERIALIZE_OK) {
272  timeTag.set(seconds, useconds);
273  }
274  return status;
275 }
276 
277 Fw::SerializeStatus CmdSequencerComponentImpl::FPrimeSequence ::deserializeRecordSize(U32& recordSize) {
278  Fw::LinearBufferBase& buffer = this->m_buffer;
279  Fw::SerializeStatus status = buffer.deserializeTo(recordSize);
280  if (status == Fw::FW_SERIALIZE_OK and recordSize > buffer.getDeserializeSizeLeft()) {
281  // Not enough data left
283  }
284  if (status == Fw::FW_SERIALIZE_OK and
286  // Record size is too big for com buffer
288  }
289  return status;
290 }
291 
292 Fw::SerializeStatus CmdSequencerComponentImpl::FPrimeSequence ::copyCommand(Fw::ComBuffer& comBuffer,
293  const U32 recordSize) {
294  Fw::LinearBufferBase& buffer = this->m_buffer;
295  comBuffer.resetSer();
296  FwSizeType size = recordSize;
297  Fw::SerializeStatus status = comBuffer.setBuffLen(recordSize);
298  FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
299  status = buffer.deserializeTo(comBuffer.getBuffAddr(), size, Fw::Serialization::OMIT_LENGTH);
300  return status;
301 }
302 
303 bool CmdSequencerComponentImpl::FPrimeSequence ::validateRecords() {
304  Fw::LinearBufferBase& buffer = this->m_buffer;
305  const U32 numRecords = this->m_header.m_numRecords;
306  Sequence::Record record;
307 
308  if (numRecords == 0) {
309  this->m_events.noRecords();
310  return false;
311  }
312 
313  // Deserialize all records
314  for (U32 recordNumber = 0; recordNumber < numRecords; recordNumber++) {
315  Fw::SerializeStatus status = this->deserializeRecord(record);
316  if (status != Fw::FW_SERIALIZE_OK) {
317  this->m_events.recordInvalid(recordNumber, status);
318  return false;
319  }
320  }
321  // Check there is no data left
322  const FwSizeType buffLeftSize = buffer.getDeserializeSizeLeft();
323  if (buffLeftSize > 0) {
324  this->m_events.recordMismatch(numRecords, static_cast<U32>(buffLeftSize));
325  return false;
326  }
327  // Rewind deserialization
328  buffer.resetDeser();
329 
330  return true;
331 }
332 
333 } // 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