F´ Flight Software - C/C++ Documentation  devel
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 extern "C" {
15 }
16 
17 namespace Svc {
18 
20  CRC() :
21  m_computed(INITIAL_COMPUTED_VALUE),
22  m_stored(0)
23  {
24 
25  }
26 
28  init()
29  {
30  this->m_computed = INITIAL_COMPUTED_VALUE;
31  }
32 
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 = static_cast<U32>(update_crc_32(this->m_computed, static_cast<char>(buffer[index])));
39  }
40  }
41 
43  finalize()
44  {
45  this->m_computed = ~this->m_computed;
46  }
47 
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 
70  loadFile(const Fw::StringBase& 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 
88  hasMoreRecords() const
89  {
90  return this->m_buffer.getBuffLeft() > 0;
91  }
92 
94  nextRecord(Record& record)
95  {
96  Fw::SerializeStatus status = this->deserializeRecord(record);
97  FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
98  }
99 
101  reset()
102  {
103  this->m_buffer.resetDeser();
104  }
105 
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, static_cast<FwAssertArgType>(readLen));
168 
169  const NATIVE_UINT_TYPE capacity = buffer.getBuffCapacity();
170  FW_ASSERT(
171  capacity >= static_cast<NATIVE_UINT_TYPE>(readLen),
172  static_cast<FwAssertArgType>(capacity),
173  static_cast<FwAssertArgType>(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(
183  fileStatus
184  );
185  status = false;
186  }
187 
188  if (status and readLen != Sequence::Header::SERIALIZED_SIZE) {
189  this->m_events.fileInvalid(
191  static_cast<I32>(readLen)
192  );
193  status = false;
194  }
195 
196  if (status) {
197  const Fw::SerializeStatus serializeStatus =
198  buffer.setBuffLen(static_cast<Fw::Serializable::SizeType>(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(
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(
232  serializeStatus
233  );
234  return false;
235  }
236  // Time base
237  FwTimeBaseStoreType tbase;
238  serializeStatus = buffer.deserialize(tbase);
239  if (serializeStatus != Fw::FW_SERIALIZE_OK) {
240  this->m_events.fileInvalid(
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(
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  FwSignedSizeType 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(
275  fileStatus
276  );
277  return false;
278  }
279  // check read size
280  if (static_cast<NATIVE_INT_TYPE>(size) != readLen) {
281  this->m_events.fileInvalid(
283  static_cast<I32>(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(
307  static_cast<I32>(buffSize)
308  );
309  return false;
310  }
311  FW_ASSERT(buffSize >= crcSize, static_cast<FwAssertArgType>(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:14
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:56
PlatformAssertArgType FwAssertArgType
Definition: FpConfig.h:34
PlatformSignedSizeType FwSignedSizeType
Definition: FpConfig.h:25
U32 FwPacketDescriptorType
Definition: FpConfig.h:74
U16 FwTimeBaseStoreType
Definition: FpConfig.h:66
U8 * getBuffAddr()
gets buffer address for data filling
Definition: ComBuffer.cpp:40
External serialize buffer with no copy semantics.
NATIVE_UINT_TYPE SizeType
virtual U8 * getBuffAddr()=0
gets buffer address for data filling
SerializeStatus setBuffLen(Serializable::SizeType length)
sets buffer length manually after filling with data
void resetDeser()
reset deserialization to beginning
Serializable::SizeType getBuffLeft() const
returns how much deserialization buffer is left
void resetSer()
reset to beginning of buffer to reuse for serialization
Serializable::SizeType getBuffLength() const
returns current buffer size
SerializeStatus deserialize(U8 &val)
deserialize 8-bit unsigned int
virtual Serializable::SizeType getBuffCapacity() const =0
returns capacity, not current size, of buffer
Definition: Time.hpp:9
void set(U32 seconds, U32 useconds)
Definition: Time.cpp:25
Status read(U8 *buffer, FwSignedSizeType &size)
read data from this file into supplied buffer bounded by size
Definition: File.cpp:142
@ OP_OK
Operation was successful.
Definition: File.hpp:30
@ DOESNT_EXIST
File doesn't exist (for read)
Definition: File.hpp:31
@ OPEN_READ
Open file for reading.
Definition: File.hpp:21
FPrimeSequence(CmdSequencerComponentImpl &component)
Construct an FPrimeSequence.
bool loadFile(const Fw::StringBase &fileName)
A sequence with unspecified binary format.
unsigned long update_crc_32(unsigned long crc, char c)
Definition: lib_crc.c:271
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.
void update(const BYTE *buffer, NATIVE_UINT_TYPE bufferSize)
Update computed CRC.