/* * crc_calc.c * * Created: 2/15/2022 3:38:31 PM * Author: david */ #include "main.h" __attribute__((__aligned__(512))) crccu_dscr_type_t crc_dscr; uint8_t crc8(uint8_t initcrc, const uint8_t* input_data, uint32_t len) { uint32_t i; uint8_t j; const uint8_t* l_input; l_input = input_data; for(i = 0; i < len; i++) { initcrc ^= *l_input; l_input++; for(j = 0; j < 8; j++) { if(initcrc & 0x80) { initcrc = (initcrc << 1) ^ CRC8POLY; } else { initcrc = (initcrc << 1); } } } return initcrc; } uint32_t crc32(uint32_t initcrc, const uint8_t* input_data, uint32_t len) { uint32_t i; uint8_t j; const uint8_t* l_input; initcrc = ~initcrc; // Invert input l_input = input_data; for(i = 0; i < len; i++) { initcrc ^= (((uint32_t)(*l_input)) << 24); l_input++; for(j = 0; j < 8; j++) { if(initcrc & 0x80000000) { initcrc = (initcrc << 1) ^ CRC32POLY; } else { initcrc = (initcrc << 1); } } } return ~initcrc; // And invert output } static bool _runcrchw(void) { uint32_t ul_starttime; // Track duration ul_starttime = board_millis(); // Start the CRC calculation CRCCU->CRCCU_DMA_EN = 0x01; // Enable DMA transfer (starts calculation) // Wait for calculation ready while(((CRCCU->CRCCU_DMA_SR) & 0x01) != 0) { if(board_millis() > ul_starttime + MAX_CRC_TIME) { // Stop transfer CRCCU->CRCCU_DMA_DIS = 0x01; // return bad value return false; } } return true; } uint32_t crc32_hw(const uint8_t* input_data, uint32_t len) { uint32_t done_so_far = 0; // Uses internal hardware CRC calculator unit to perform faster CRC // Enable clock to CRC unit PMC->PMC_PCER1 = (1 << (ID_CRCCU-32)); // Reset CRC CRCCU->CRCCU_CR = CRCCU_CR_RESET; memset((void *)&crc_dscr, 0, sizeof(crccu_dscr_type_t)); while(len > done_so_far) { crc_dscr.ul_tr_addr = (uint32_t) input_data + done_so_far; // Transfer width: byte, interrupt enable if((len - done_so_far) > 0xFFF8) { crc_dscr.ul_tr_ctrl = 0xFFF8; done_so_far += 0xFFF8; } else { crc_dscr.ul_tr_ctrl = len - done_so_far; done_so_far = len; } // Configure the CRCCU descriptor CRCCU->CRCCU_DSCR = (uint32_t)(&crc_dscr); // Configure CRCCU mode CRCCU->CRCCU_MR = 0x01; // Enable, polynomial is CCITT802.3 (0x04C11DB7), MSB first // Run CRC on this block if(_runcrchw() == false) { return 0; } } // Get CRC value return CRCCU->CRCCU_SR; }