F´ Flight Software - C/C++ Documentation  devel
A framework for building embedded system applications to NASA flight quality standards.
AMPCSSequence.cpp
Go to the documentation of this file.
1 // \title AMPCSSequence.cpp
2 // \author Rob Bocchino
3 // \brief AMPCSSequence implementation
4 //
5 // \copyright
6 // Copyright (C) 2009-2018 California Institute of Technology.
7 // ALL RIGHTS RESERVED. United States Government Sponsorship
8 // acknowledged.
9 //
10 // ======================================================================
11 
12 #include "Fw/Com/ComPacket.hpp"
13 #include "Fw/Types/Assert.hpp"
14 #include "Os/FileSystem.hpp"
16 extern "C" {
18 }
19 
20 namespace Svc {
21 
24  CmdSequencerComponentImpl::Sequence(component)
25  {
26 
27  }
28 
30  loadFile(const Fw::StringBase& fileName)
31  {
32  // Make sure there is a buffer allocated
34 
35  Fw::CmdStringArg crcFileName(fileName);
36  crcFileName += ".CRC32";
37 
40 
41  const bool status = this->readCRCFile(crcFileName)
42  and this->getFileSize(fileName)
43  and this->readSequenceFile(fileName)
44  and this->validateCRC()
45  and this->m_header.validateTime(this->m_component)
46  and this->validateRecords();
47 
48  return status;
49  }
50 
51  bool AMPCSSequence ::
52  readCRCFile(Fw::CmdStringArg& crcFileName)
53  {
54 
55  bool result;
56 
57  this->setFileName(crcFileName);
58 
59  Os::File::Status status = this->m_crcFile.open(
60  crcFileName.toChar(),
62  );
63 
64  if (status == Os::File::OP_OK) {
65  result = this->readCRC() and this->deserializeCRC();
66  } else if (status == Os::File::DOESNT_EXIST) {
67  this->m_events.fileNotFound();
68  result = false;
69  } else {
70  this->m_events.fileReadError();
71  result = false;
72  }
73 
74  this->m_crcFile.close();
75  return result;
76 
77  }
78 
79  bool AMPCSSequence ::
80  getFileSize(const Fw::StringBase& seqFileName)
81  {
82  bool status = true;
83  FwSignedSizeType fileSize;
84  this->setFileName(seqFileName);
85  const Os::FileSystem::Status fileStatus =
87  if (
88  fileStatus == Os::FileSystem::OP_OK and
89  fileSize >= static_cast<FwSignedSizeType>(sizeof(this->m_sequenceHeader))
90  ) {
91  this->m_header.m_fileSize =
92  static_cast<U32>(fileSize - static_cast<FwSignedSizeType>(sizeof(this->m_sequenceHeader)));
93  }
94  else {
95  this->m_events.fileInvalid(
97  );
98  status = false;
99  }
100  return status;
101  }
102 
103  bool AMPCSSequence ::
104  readSequenceFile(const Fw::StringBase& seqFileName)
105  {
106 
107  bool result;
108 
109  this->setFileName(seqFileName);
110  Os::File::Status status = this->m_sequenceFile.open(
111  this->m_fileName.toChar(),
113  );
114 
115  if (status == Os::File::OP_OK) {
116  result = this->readOpenSequenceFile();
117  } else if (status == Os::File::DOESNT_EXIST) {
118  this->m_events.fileNotFound();
119  result = false;
120  } else {
121  this->m_events.fileReadError();
122  result = false;
123  }
124 
125  this->m_sequenceFile.close();
126  return result;
127 
128  }
129 
130  bool AMPCSSequence ::
131  validateCRC()
132  {
133  bool result = true;
134  if (this->m_crc.m_stored != this->m_crc.m_computed) {
135  this->m_events.fileCRCFailure(
136  this->m_crc.m_stored,
137  this->m_crc.m_computed
138  );
139  result = false;
140  }
141  return result;
142  }
143 
144  bool AMPCSSequence ::
145  validateRecords()
146  {
147  Fw::SerializeBufferBase& buffer = this->m_buffer;
148  Sequence::Record record;
149 
150  // Deserialize all records and count the records
151  const NATIVE_UINT_TYPE loopBound = buffer.getBuffLeft();
152  U32 numRecords = 0;
153  for ( ; numRecords < loopBound; ++numRecords) {
154  if (not this->hasMoreRecords()) {
155  break;
156  }
157  Fw::SerializeStatus status = this->deserializeRecord(record);
158  if (status != Fw::FW_SERIALIZE_OK) {
159  this->m_events.recordInvalid(numRecords, status);
160  return false;
161  }
162  }
163  // Set the number of records
164  this->m_header.m_numRecords = numRecords;
165  // Reset deserialization
166  this->reset();
167 
168  return true;
169  }
170 
172  hasMoreRecords() const
173  {
174  return this->m_buffer.getBuffLeft() > 0;
175  }
176 
178  nextRecord(Sequence::Record& record)
179  {
180  Fw::SerializeStatus status = this->deserializeRecord(record);
181  FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
182  }
183 
185  reset()
186  {
187  this->m_buffer.resetDeser();
188  }
189 
191  clear()
192  {
193  this->m_buffer.resetSer();
194  }
195 
196  bool AMPCSSequence ::
197  readCRC()
198  {
199 
200  Os::File& file = this->m_crcFile;
201  Fw::SerializeBufferBase& buffer = this->m_buffer;
202  bool status = true;
203  Fw::SerializeStatus ser_status;
204 
205  FwSignedSizeType readLen = sizeof(U32);
206  FW_ASSERT(readLen >= 0, static_cast<FwAssertArgType>(readLen));
207 
208  ser_status = buffer.setBuffLen(static_cast<Fw::Serializable::SizeType>(readLen));
209  FW_ASSERT(ser_status == Fw::FW_SERIALIZE_OK, ser_status);
210 
211  U8 *const addr = buffer.getBuffAddr();
212  Os::File::Status fileStatus = file.read(addr, readLen);
213 
214  if (fileStatus != Os::File::OP_OK) {
215  this->m_events.fileInvalid(
217  fileStatus
218  );
219  status = false;
220  }
221 
222  return status;
223 
224  }
225 
226  bool AMPCSSequence ::
227  deserializeCRC()
228  {
229  bool status = true;
230  Fw::SerializeStatus serializeStatus =
231  this->m_buffer.deserialize(this->m_crc.m_stored);
232  if (serializeStatus != Fw::FW_SERIALIZE_OK) {
233  this->m_events.fileInvalid(
235  serializeStatus
236  );
237  status = false;
238  }
239  return status;
240  }
241 
242  bool AMPCSSequence ::
243  readOpenSequenceFile()
244  {
245  this->m_buffer.resetSer();
246  this->m_crc.init();
247  bool status = this->readSequenceHeader();
248  if (status) {
249  this->m_crc.update(
250  this->m_sequenceHeader,
251  sizeof(this->m_sequenceHeader)
252  );
253  status = this->readRecords();
254  }
255  if (status) {
256  U8 *const buffAddr = this->m_buffer.getBuffAddr();
257  const NATIVE_UINT_TYPE buffLen = this->m_buffer.getBuffLength();
258  FW_ASSERT(
259  buffLen == this->m_header.m_fileSize,
260  static_cast<FwAssertArgType>(buffLen),
261  static_cast<FwAssertArgType>(this->m_header.m_fileSize)
262  );
263  this->m_crc.update(buffAddr, buffLen);
264  this->m_crc.finalize();
265  }
266  return status;
267  }
268 
269  bool AMPCSSequence ::
270  readSequenceHeader()
271  {
272 
273  Os::File& file = this->m_sequenceFile;
274 
275  bool status = true;
276 
277  FwSignedSizeType readLen = sizeof this->m_sequenceHeader;
278  const Os::File::Status fileStatus = file.read(
279  this->m_sequenceHeader,
280  readLen
281  );
282 
283  if (fileStatus != Os::File::OP_OK) {
284  this->m_events.fileInvalid(
286  fileStatus
287  );
288  status = false;
289  }
290 
291  if (status and readLen != sizeof this->m_sequenceHeader) {
292  this->m_events.fileInvalid(
294  static_cast<I32>(readLen)
295  );
296  status = false;
297  }
298 
299  return status;
300 
301  }
302 
303 
304  bool AMPCSSequence ::
305  readRecords()
306  {
307  Os::File& file = this->m_sequenceFile;
308  const NATIVE_UINT_TYPE size = this->m_header.m_fileSize;
309  Fw::SerializeBufferBase& buffer = this->m_buffer;
310  U8 *const addr = buffer.getBuffAddr();
311 
312  // Check file size
313  if (size > this->m_buffer.getBuffCapacity()) {
314  this->m_events.fileSizeError(size);
315  return false;
316  }
317 
318  FwSignedSizeType readLen = size;
319  const Os::File::Status fileStatus = file.read(addr, readLen);
320  // Check read status
321  if (fileStatus != Os::File::OP_OK) {
322  this->m_events.fileInvalid(
324  fileStatus
325  );
326  return false;
327  }
328  // Check read size
329  const NATIVE_UINT_TYPE readLenUint = static_cast<NATIVE_UINT_TYPE>(readLen);
330  if (readLenUint != size) {
331  this->m_events.fileInvalid(
333  static_cast<I32>(readLen)
334  );
335  return false;
336  }
337  // set buffer size
338  const Fw::SerializeStatus serializeStatus = buffer.setBuffLen(size);
339  FW_ASSERT(serializeStatus == Fw::FW_SERIALIZE_OK, serializeStatus);
340  return true;
341  }
342 
343  Fw::SerializeStatus AMPCSSequence ::
344  deserializeRecord(Sequence::Record& record)
345  {
346 
347  Record::CmdLength::t cmdLength;
348 
349  Fw::SerializeStatus status =
350  this->deserializeTimeFlag(record.m_descriptor);
351 
352  if (status == Fw::FW_SERIALIZE_OK) {
353  status = this->deserializeTime(record.m_timeTag);
354  }
355  if (status == Fw::FW_SERIALIZE_OK) {
356  status = this->deserializeCmdLength(cmdLength);
357  }
358  if (status == Fw::FW_SERIALIZE_OK) {
359  status = this->translateCommand(record.m_command, cmdLength);
360  }
361 
362  return status;
363 
364  }
365 
366  Fw::SerializeStatus AMPCSSequence ::
367  deserializeTimeFlag(Sequence::Record::Descriptor& descriptor)
368  {
369  Fw::SerializeBufferBase& buffer = this->m_buffer;
370  Record::TimeFlag::Serial::t timeFlagSerial;
371  Fw::SerializeStatus status = buffer.deserialize(timeFlagSerial);
372  if (status == Fw::FW_SERIALIZE_OK) {
373  switch (timeFlagSerial) {
375  descriptor = Sequence::Record::ABSOLUTE;
376  break;
378  descriptor = Sequence::Record::RELATIVE;
379  break;
380  default:
382  break;
383  }
384  }
385  return status;
386  }
387 
388  Fw::SerializeStatus AMPCSSequence ::
389  deserializeTime(Fw::Time& timeTag)
390  {
391  Record::Time::t time;
392  Fw::SerializeBufferBase& buffer = this->m_buffer;
393  Fw::SerializeStatus status = buffer.deserialize(time);
394  if (status == Fw::FW_SERIALIZE_OK) {
395  timeTag.set(time, 0);
396  }
397  return status;
398  }
399 
400  Fw::SerializeStatus AMPCSSequence ::
401  deserializeCmdLength(Record::CmdLength::t& cmdLength)
402  {
403  Fw::SerializeBufferBase& buffer = this->m_buffer;
404  Fw::SerializeStatus status = buffer.deserialize(cmdLength);
405  if (status == Fw::FW_SERIALIZE_OK and cmdLength > buffer.getBuffLeft()) {
406  // Not enough data left
408  }
409  if (
410  status == Fw::FW_SERIALIZE_OK and
411  sizeof(FwPacketDescriptorType) + sizeof(U16) + cmdLength > Fw::ComBuffer::SERIALIZED_SIZE
412  ) {
413  // Record size is too big for com buffer
415  }
416  return status;
417  }
418 
419  Fw::SerializeStatus AMPCSSequence ::
420  translateCommand(
421  Fw::ComBuffer& comBuffer,
422  const Record::CmdLength::t cmdLength
423  )
424  {
425  Fw::SerializeBufferBase& buffer = this->m_buffer;
426  comBuffer.resetSer();
427  // Serialize the command packet descriptor
429  Fw::SerializeStatus status = comBuffer.serialize(cmdDescriptor);
430  FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
431  // Zero-extend the two-byte AMPCS opcode by two bytes
432  const U16 zeros = 0;
433  status = comBuffer.serialize(zeros);
434  FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
435  // Set the buffer length
436  const U32 fixedBuffLen = comBuffer.getBuffLength();
437  FW_ASSERT(
438  fixedBuffLen == sizeof(cmdDescriptor) + sizeof(zeros),
439  static_cast<FwAssertArgType>(fixedBuffLen)
440  );
441  const U32 totalBuffLen = fixedBuffLen + cmdLength;
442  status = comBuffer.setBuffLen(totalBuffLen);
443  FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
444  // Copy the opcode and argument bytes
445  NATIVE_UINT_TYPE size = cmdLength;
446  U8 *const addr = comBuffer.getBuffAddr();
447  FW_ASSERT(addr != nullptr);
448  // true means "don't serialize the length"
449  status = buffer.deserialize(&addr[fixedBuffLen], size, true);
450  return status;
451  }
452 
453 }
454 
#define FW_ASSERT(...)
Definition: Assert.hpp:14
uint8_t U8
8-bit unsigned integer
Definition: BasicTypes.h:26
PlatformUIntType NATIVE_UINT_TYPE
Definition: BasicTypes.h:52
@ TB_DONT_CARE
Don't care value for sequences. If FwTimeBaseStoreType is changed, value should be changed.
Definition: FpConfig.h:60
PlatformAssertArgType FwAssertArgType
Definition: FpConfig.h:34
PlatformSignedSizeType FwSignedSizeType
Definition: FpConfig.h:25
#define FW_CONTEXT_DONT_CARE
Don't care value for time contexts in sequences.
Definition: FpConfig.h:63
U32 FwPacketDescriptorType
Definition: FpConfig.h:74
const char * toChar() const
Definition: CmdString.hpp:50
U8 * getBuffAddr()
gets buffer address for data filling
Definition: ComBuffer.cpp:40
U8 * getBuffAddr()
gets buffer address for data filling
Serializable::SizeType getBuffCapacity() const
returns capacity, not current size, of buffer
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
SerializeStatus serialize(U8 val)
serialize 8-bit unsigned int
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
void close() override
close the file, if not opened then do nothing
Definition: File.cpp:69
Os::FileInterface::Status open(const char *path, Mode mode)
open file with supplied path and mode
Definition: File.cpp:45
@ 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
bool loadFile(const Fw::StringBase &fileName)
bool hasMoreRecords() const
AMPCSSequence(CmdSequencerComponentImpl &component)
Construct an AMPCSSequence.
void nextRecord(Sequence::Record &record)
void fileSizeError(const U32 size)
File size error.
Definition: Events.cpp:68
void fileCRCFailure(const U32 storedCRC, const U32 computedCRC)
File CRC failure.
Definition: Events.cpp:24
void recordInvalid(const U32 recordNumber, const I32 error)
Record invalid.
Definition: Events.cpp:80
void fileInvalid(const CmdSequencer_FileReadStage::t stage, const I32 error)
File invalid.
Definition: Events.cpp:37
bool validateTime(CmdSequencerComponentImpl &component)
Definition: Sequence.cpp:42
FwTimeContextStoreType m_timeContext
The context of the sequence.
U32 m_numRecords
The number of records in the sequence.
TimeBase m_timeBase
The time base of the sequence.
Fw::ExternalSerializeBuffer m_buffer
Serialize buffer to hold the binary sequence data.
void setFileName(const Fw::StringBase &fileName)
Set the file name. Also sets the log file name.
Definition: Sequence.cpp:111
CmdSequencerComponentImpl & m_component
The enclosing component.
Fw::CmdStringArg m_fileName
The sequence file name.
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.
Status getFileSize(const char *path, FwSizeType &size)
Definition: FileSystem.cpp:38
@ OP_OK
Operation was successful.
Definition: FileSystem.hpp:15
U16 t
The type of the command length field.
U32 t
The type of the time field.
void update(const BYTE *buffer, NATIVE_UINT_TYPE bufferSize)
Update computed CRC.