/** * \brief 16-bit checksum of data block test * * This test does a checksum of a data block with a known checksum, * and verifies that they are equal. It then appends the 16-bit CRC * to the end of the data, and does another checksum operation, which * should result in the zero flag being set. * * \param test Current test case */ static void run_16bit_io_test(const struct test_case *test) { uint8_t tmp_buffer[LENGTH(data_8bit) + sizeof(uint16_t)]; int i; uint16_t checksum; crc_io_checksum_byte_start(CRC_16BIT); for(i = 0;i < LENGTH(data_8bit); ++i) crc_io_checksum_byte_add(data_8bit[i]); checksum = crc_io_checksum_byte_stop(); test_assert_true(test, checksum == CRC_CHECKSUM_16BIT, "Checksum mismatch on IO CRC-16 test"); memcpy(tmp_buffer, data_8bit, LENGTH(data_8bit)); crc16_append_value(checksum, &tmp_buffer[LENGTH(tmp_buffer) - sizeof(uint16_t)]); checksum = crc_io_checksum(tmp_buffer, LENGTH(tmp_buffer), CRC_16BIT); test_assert_true(test, checksum == 0, "Checksum fail check failed on IO CRC-16 test"); }
/** * \brief Calculate the CRC checksum for data in a buffer * * This function initializes the CRC module, calculates the checksum for the * selected number of bytes in a data buffer, disables the module and returns * the calculated checksum. * * \param data Data buffer to perform CRC on * \param len The number of bytes to perform CRC on * \param crc_16_32 Indicator for whether CRC-32 or CRC-16 shall be used * * \return checksum checksum */ uint32_t crc_io_checksum(void *data, uint16_t len, enum crc_16_32_t crc_16_32) { /* Initialize CRC calculations on I/O interface */ crc_io_checksum_byte_start(crc_16_32); /* Write data to DATAIN register */ while (len--) { crc_io_checksum_byte_add(*(uint8_t*)data); data = (uint8_t*)data + 1; } /* Return checksum */ return crc_io_checksum_byte_stop(); }
/** * \brief Compute 16-bit CRC for Flash address range using hardware CRC module. * * This function returns the 16-bit CRC of the specified Flash address range. * * \param origDataptr Address of Flash location to start CRC computation at. * \param numBytes Number of bytes of the data. * \param pchecksum Pointer to the checksum stored in EEPROM. * * \note 16-bit flash CRC is much slower than 32-bit for flash checking. * \note No sanity checking of addresses is done. */ uint16_t CLASSB_CRC16_Flash_HW(flashptr_t origDataptr, crcbytenum_t numBytes, eeprom_uint16ptr_t pchecksum) { uint32_t checksum; flash_uint8ptr_t dataptr = origDataptr; uint8_t dataTemp; crc_set_initial_value(CRC16_INITIAL_REMAINDER); crc_io_checksum_byte_start(CRC_16BIT); /* Compute CRC for the specified data. */ for (; numBytes != 0; numBytes--) { #if (PROGMEM_SIZE >= 0x10000UL) dataTemp = PROGMEM_READ_BYTE(dataptr++); #else dataTemp = PROGMEM_READ_BYTE(dataptr++); #endif crc_io_checksum_byte_add(dataTemp); } checksum = crc_io_checksum_byte_stop(); #if defined(__ICCAVR__) /* Compare checksums and handle error if necessary. */ if (checksum != *pchecksum) { CLASSB_ERROR_HANDLER_CRC(); } #elif defined(__GCC__) /* Ensure that EEPROM is memory mapped. */ CLASSB_EEMAP_BEGIN(); /* Compare checksums and handle error if necessary. */ if (checksum != (*(eeprom_uint16ptr_t)(MAPPED_EEPROM_START + (uintptr_t)pchecksum))) { CLASSB_ERROR_HANDLER_CRC(); } /* Disable memory mapping of EEPROM, if necessary. */ CLASSB_EEMAP_END(); #endif /* Return 16 bits */ return checksum & (uint32_t)0x0000FFFF; }