@@ -182,6 +182,45 @@ UDPARD_PRIVATE TransferCRC crcValue(const TransferCRC crc)
182182 return (uint32_t ) (crc ^ CRC_XOR );
183183}
184184
185+ /// --------------------------------------------- CYPHAL HEADER CRC ---------------------------------------------
186+
187+ typedef uint16_t CyphalHeaderCRC ;
188+
189+ // Based on CRC-16-CCITT-FALSE Function
190+ #define CYPHAL_HEADER_CRC_INITIAL 0xFFFFU
191+ #define CYPHAL_HEADER_CRC_SIZE_BYTES 2U
192+
193+ UDPARD_PRIVATE CyphalHeaderCRC cyphalHeaderCrcAddByte (const CyphalHeaderCRC crc , const uint8_t byte )
194+ {
195+ // Based on CRC-16-CCITT-FALSE Function
196+ static const CyphalHeaderCRC Top = 0x8000U ;
197+ static const CyphalHeaderCRC Poly = 0x1021U ;
198+ CyphalHeaderCRC out = crc ^ (uint16_t ) ((uint16_t ) (byte ) << BITS_PER_BYTE );
199+ // Do not fold this into a loop because a size-optimizing compiler won't unroll it degrading the performance.
200+ out = (uint16_t ) ((uint16_t ) (out << 1U ) ^ (((out & Top ) != 0U ) ? Poly : 0U ));
201+ out = (uint16_t ) ((uint16_t ) (out << 1U ) ^ (((out & Top ) != 0U ) ? Poly : 0U ));
202+ out = (uint16_t ) ((uint16_t ) (out << 1U ) ^ (((out & Top ) != 0U ) ? Poly : 0U ));
203+ out = (uint16_t ) ((uint16_t ) (out << 1U ) ^ (((out & Top ) != 0U ) ? Poly : 0U ));
204+ out = (uint16_t ) ((uint16_t ) (out << 1U ) ^ (((out & Top ) != 0U ) ? Poly : 0U ));
205+ out = (uint16_t ) ((uint16_t ) (out << 1U ) ^ (((out & Top ) != 0U ) ? Poly : 0U ));
206+ out = (uint16_t ) ((uint16_t ) (out << 1U ) ^ (((out & Top ) != 0U ) ? Poly : 0U ));
207+ out = (uint16_t ) ((uint16_t ) (out << 1U ) ^ (((out & Top ) != 0U ) ? Poly : 0U ));
208+ return out ;
209+ }
210+
211+ UDPARD_PRIVATE CyphalHeaderCRC cyphalHeaderCrcAdd (const CyphalHeaderCRC crc , const size_t size , const void * const header )
212+ {
213+ UDPARD_ASSERT (header != NULL );
214+ CyphalHeaderCRC out = crc ;
215+ const uint8_t * p = (const uint8_t * ) header ;
216+ for (size_t i = 0 ; i < size ; i ++ )
217+ {
218+ out = cyphalHeaderCrcAddByte (out , * p );
219+ ++ p ;
220+ }
221+ return out ;
222+ }
223+
185224// --------------------------------------------- TRANSMISSION ---------------------------------------------
186225
187226/// This is a subclass of UdpardTxQueueItem. A pointer to this type can be cast to UdpardTxQueueItem safely.
@@ -324,11 +363,13 @@ UDPARD_PRIVATE void txMakeFrameHeader(UdpardFrameHeader* const header,
324363{
325364 UDPARD_ASSERT (frame_index <= UDPARD_MAX_FRAME_INDEX );
326365 uint32_t end_of_transfer_mask = (uint32_t ) (end_of_transfer ? 1 : 0 ) << (uint32_t ) UDPARD_END_OF_TRANSFER_OFFSET ;
366+ size_t cyphal_header_size_without_crc = sizeof (UdpardFrameHeader ) - CYPHAL_HEADER_CRC_SIZE_BYTES ;
327367 header -> transfer_id = transfer_id ;
328368 header -> priority = (uint8_t ) priority ;
329369 header -> frame_index_eot = end_of_transfer_mask | frame_index ;
330370 header -> source_node_id = src_node_id ;
331371 header -> destination_node_id = dst_node_id ;
372+ header -> cyphal_header_checksum = cyphalHeaderCrcAdd (CYPHAL_HEADER_CRC_INITIAL , cyphal_header_size_without_crc , header );
332373 if (transfer_kind == UdpardTransferKindMessage )
333374 {
334375 header -> data_specifier = (uint16_t ) UPDARD_DATA_SPECIFIER_MESSAGE & port_id ; // SNM (0) + Subject ID
0 commit comments