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