/** * \file Ifx_Crc.c * \brief CRC algorithm * * \version disabled * \copyright Copyright (c) 2013 Infineon Technologies AG. All rights reserved. * * * IMPORTANT NOTICE * * * Use of this file is subject to the terms of use agreed between (i) you or * the company in which ordinary course of business you are acting and (ii) * Infineon Technologies AG or its licensees. If and as long as no such * terms of use are agreed, use of this file is subject to following: * Boost Software License - Version 1.0 - August 17th, 2003 * Permission is hereby granted, free of charge, to any person or * organization obtaining a copy of the software and accompanying * documentation covered by this license (the "Software") to use, reproduce, * display, distribute, execute, and transmit the Software, and to prepare * derivative works of the Software, and to permit third-parties to whom the * Software is furnished to do so, all subject to the following: * The copyright notices in the Software and this entire statement, including * the above license grant, this restriction and the following disclaimer, must * be included in all copies of the Software, in whole or in part, and all * derivative works of the Software, unless such copies or derivative works are * solely in the form of machine-executable object code generated by a source * language processor. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * */ #include "Ifx_Crc.h" uint32 Ifx_Crc_reflect(uint32 crc, sint32 bitnum); boolean Ifx_Crc_init(Ifc_Crc *driver, const Ifc_Crc_Table *table, sint32 direct, sint32 refout, uint32 crcinit, uint32 crcxor) { sint32 i; uint32 bit, crc; if (crcinit != (crcinit & table->crcmask)) { //IfxStdIf_DPipe_print(io,"ERROR, invalid crcinit."ENDL); return FALSE; } if (crcxor != (crcxor & table->crcmask)) { //IfxStdIf_DPipe_print(io,"ERROR, invalid crcxor."ENDL); return FALSE; } driver->table = table; driver->crcxor = crcxor; driver->refout = refout; // compute missing initial CRC value if (!direct) { driver->crcinit_nondirect = crcinit; crc = crcinit; for (i = 0; i < table->order; i++) { bit = crc & table->crchighbit; crc <<= 1; if (bit) { crc ^= table->polynom; } } crc &= table->crcmask; driver->crcinit_direct = crc; } else { driver->crcinit_direct = crcinit; crc = crcinit; for (i = 0; i < table->order; i++) { bit = crc & 1; if (bit) { crc ^= table->polynom; } crc >>= 1; if (bit) { crc |= table->crchighbit; } } driver->crcinit_nondirect = crc; } return TRUE; } boolean Ifx_Crc_createTable(Ifc_Crc_Table *table, sint32 order, uint32 polynom, sint32 refin) { uint32 crcmask; // at first, compute constant bit masks for whole CRC and CRC high bit crcmask = ((((uint32)1 << (order - 1)) - 1) << 1) | 1; // check parameters if ((order < 1) || (order > 32)) { //IfxStdIf_DPipe_print(io,"ERROR, invalid order, it must be between 1..32."ENDL); return FALSE; } if (polynom != (polynom & crcmask)) { //IfxStdIf_DPipe_print(io,"ERROR, invalid polynom."ENDL); return FALSE; } table->order = order; table->polynom = polynom; table->refin = refin; table->crchighbit = (uint32)1 << (order - 1); table->crcmask = crcmask; // generate lookup table // make CRC lookup table used by table algorithms { sint32 i, j; uint32 bit, crc; for (i = 0; i < 256; i++) { crc = (uint32)i; if (refin) { crc = Ifx_Crc_reflect(crc, 8); } crc <<= order - 8; for (j = 0; j < 8; j++) { bit = crc & table->crchighbit; crc <<= 1; if (bit) { crc ^= polynom; } } if (refin) { crc = Ifx_Crc_reflect(crc, order); } crc &= crcmask; if (order <= 8) { uint8 *crctab = (uint8 *)((uint32)table + sizeof(Ifc_Crc_Table)); crctab[i] = (uint8)crc; } else if (order <= 16) { uint16 *crctab = (uint16 *)((uint32)table + sizeof(Ifc_Crc_Table)); crctab[i] = (uint16)crc; } else { uint32 *crctab = (uint32 *)((uint32)table + sizeof(Ifc_Crc_Table)); crctab[i] = crc; } } } return TRUE; } // subroutines uint32 Ifx_Crc_reflect(uint32 crc, sint32 bitnum) { // reflects the lower 'bitnum' bits of 'crc' uint32 i, j = 1, crcout = 0; for (i = (uint32)1 << (bitnum - 1); i; i >>= 1) { if (crc & i) { crcout |= j; } j <<= 1; } return crcout; } uint32 Ifx_Crc_tableFast(Ifc_Crc *driver, uint8 *p, uint32 len) { // fast lookup table algorithm without augmented zero bytes, e.g. used in pkzip. // only usable with polynom orders of 8, 16, 24 or 32. uint32 crc = driver->crcinit_direct; sint32 orderMinusHeight = driver->table->order - 8; if (driver->table->refin) { crc = Ifx_Crc_reflect(crc, driver->table->order); } if (driver->table->order <= 8) { uint8 *crctab = (uint8 *)((uint32)driver->table + sizeof(Ifc_Crc_Table)); if (!driver->table->refin) { while (len--) { crc = (crc << 8) ^ crctab[((crc >> (orderMinusHeight)) & 0xff) ^ *p++]; } } else { while (len--) { crc = (crc >> 8) ^ crctab[(crc & 0xff) ^ *p++]; } } } else if (driver->table->order <= 16) { uint16 *crctab = (uint16 *)((uint32)driver->table + sizeof(Ifc_Crc_Table)); if (!driver->table->refin) { while (len--) { crc = (crc << 8) ^ crctab[((crc >> (orderMinusHeight)) & 0xff) ^ *p++]; } } else { while (len--) { crc = (crc >> 8) ^ crctab[(crc & 0xff) ^ *p++]; } } } else { uint32 *crctab = (uint32 *)((uint32)driver->table + sizeof(Ifc_Crc_Table)); if (!driver->table->refin) { while (len--) { crc = (crc << 8) ^ crctab[((crc >> (orderMinusHeight)) & 0xff) ^ *p++]; } } else { while (len--) { crc = (crc >> 8) ^ crctab[(crc & 0xff) ^ *p++]; } } } if (driver->refout ^ driver->table->refin) { crc = Ifx_Crc_reflect(crc, driver->table->order); } crc ^= driver->crcxor; crc &= driver->table->crcmask; return crc; } uint32 Ifx_Crc_table(Ifc_Crc *driver, uint8 *p, uint32 len) { // normal lookup table algorithm with augmented zero bytes. // only usable with polynom orders of 8, 16, 24 or 32. uint32 crc = driver->crcinit_nondirect; sint32 orderMinusHeight = driver->table->order - 8; if (driver->table->refin) { crc = Ifx_Crc_reflect(crc, driver->table->order); } if (driver->table->order <= 8) { uint8 *crctab = (uint8 *)((uint32)driver->table + sizeof(Ifc_Crc_Table)); if (!driver->table->refin) { while (len--) { crc = ((crc << 8) | *p++) ^ crctab[(crc >> (orderMinusHeight)) & 0xff]; } } else { while (len--) { crc = ((crc >> 8) | (*p++ << (orderMinusHeight))) ^ crctab[crc & 0xff]; } } if (!driver->table->refin) { while (++len < (driver->table->order >> 3)) { crc = (crc << 8) ^ crctab[(crc >> (orderMinusHeight)) & 0xff]; } } else { while (++len < (driver->table->order >> 3)) { crc = (crc >> 8) ^ crctab[crc & 0xff]; } } } else if (driver->table->order <= 16) { uint16 *crctab = (uint16 *)((uint32)driver->table + sizeof(Ifc_Crc_Table)); if (!driver->table->refin) { while (len--) { crc = ((crc << 8) | *p++) ^ crctab[(crc >> (orderMinusHeight)) & 0xff]; } } else { while (len--) { crc = ((crc >> 8) | (*p++ << (orderMinusHeight))) ^ crctab[crc & 0xff]; } } if (!driver->table->refin) { while (++len < (driver->table->order >> 3)) { crc = (crc << 8) ^ crctab[(crc >> (orderMinusHeight)) & 0xff]; } } else { while (++len < (driver->table->order >> 3)) { crc = (crc >> 8) ^ crctab[crc & 0xff]; } } } else if (driver->table->order <= 32) { uint32 *crctab = (uint32 *)((uint32)driver->table + sizeof(Ifc_Crc_Table)); if (!driver->table->refin) { while (len--) { crc = ((crc << 8) | *p++) ^ crctab[(crc >> (orderMinusHeight)) & 0xff]; } } else { while (len--) { crc = ((crc >> 8) | (*p++ << (orderMinusHeight))) ^ crctab[crc & 0xff]; } } if (!driver->table->refin) { while (++len < (driver->table->order >> 3)) { crc = (crc << 8) ^ crctab[(crc >> (orderMinusHeight)) & 0xff]; } } else { while (++len < (driver->table->order >> 3)) { crc = (crc >> 8) ^ crctab[crc & 0xff]; } } } if (driver->refout ^ driver->table->refin) { crc = Ifx_Crc_reflect(crc, driver->table->order); } crc ^= driver->crcxor; crc &= driver->table->crcmask; return crc; } uint32 Ifx_Crc_bitByBit(Ifc_Crc *driver, uint8 *p, uint32 len) { // bit by bit algorithm with augmented zero bytes. // does not use lookup table, suited for polynom driver->table->orders between 1...32. uint32 i, j, c, bit; uint32 crc = driver->crcinit_nondirect; for (i = 0; i < len; i++) { c = (uint32)*p++; if (driver->table->refin) { c = Ifx_Crc_reflect(c, 8); } for (j = 0x80; j; j >>= 1) { bit = crc & driver->table->crchighbit; crc <<= 1; if (c & j) { crc |= 1; } if (bit) { crc ^= driver->table->polynom; } } } for (i = 0; i < driver->table->order; i++) { bit = crc & driver->table->crchighbit; crc <<= 1; if (bit) { crc ^= driver->table->polynom; } } if (driver->refout) { crc = Ifx_Crc_reflect(crc, driver->table->order); } crc ^= driver->crcxor; crc &= driver->table->crcmask; return crc; } uint32 Ifx_Crc_bitByBitFast(Ifc_Crc *driver, uint8 *p, uint32 len) { // fast bit by bit algorithm without augmented zero bytes. // does not use lookup table, suited for polynom driver->table->orders between 1...32. uint32 i, j, c, bit; uint32 crc = driver->crcinit_direct; for (i = 0; i < len; i++) { c = (uint32)*p++; if (driver->table->refin) { c = Ifx_Crc_reflect(c, 8); } for (j = 0x80; j; j >>= 1) { bit = crc & driver->table->crchighbit; crc <<= 1; if (c & j) { bit ^= driver->table->crchighbit; } if (bit) { crc ^= driver->table->polynom; } } } if (driver->refout) { crc = Ifx_Crc_reflect(crc, driver->table->order); } crc ^= driver->crcxor; crc &= driver->table->crcmask; return crc; } #if CRC_ENABLE_DPIPE void Ifx_Crc_printTable(Ifc_Crc_Table *table, IfxStdIf_DPipe *io) { sint32 i = 0; uint32 typeSize; if (table->order <= 8) { typeSize = 8; } else if (table->order <= 16) { typeSize = 16; } else { typeSize = 32; } IfxStdIf_DPipe_print(io, ENDL "Ifc_Crc_Table%d = {"ENDL, typeSize); IfxStdIf_DPipe_print(io, " .data.order=%d,"ENDL, table->order); IfxStdIf_DPipe_print(io, " .data.polynom=0x%X,"ENDL, table->polynom); IfxStdIf_DPipe_print(io, " .data.refin=%d,"ENDL, table->refin); IfxStdIf_DPipe_print(io, " .data.crchighbit=%d,"ENDL, table->crchighbit); IfxStdIf_DPipe_print(io, " .data.crcmask=0x%X,"ENDL, table->crcmask); IfxStdIf_DPipe_print(io, " .crctab={"ENDL); IfxStdIf_DPipe_print(io, " "); while (i < 256) { if (table->order <= 4) { uint8 *crctab = (uint8 *)((uint32)table + sizeof(Ifc_Crc_Table)); IfxStdIf_DPipe_print(io, "0x%01X, ", crctab[i]); } else if (table->order <= 8) { uint8 *crctab = (uint8 *)((uint32)table + sizeof(Ifc_Crc_Table)); IfxStdIf_DPipe_print(io, "0x%02X, ", crctab[i]); } else if (table->order <= 16) { uint16 *crctab = (uint16 *)((uint32)table + sizeof(Ifc_Crc_Table)); IfxStdIf_DPipe_print(io, "0x%04X, ", crctab[i]); } else if (table->order <= 24) { uint32 *crctab = (uint32 *)((uint32)table + sizeof(Ifc_Crc_Table)); IfxStdIf_DPipe_print(io, "0x%06X, ", crctab[i]); } else { uint32 *crctab = (uint32 *)((uint32)table + sizeof(Ifc_Crc_Table)); IfxStdIf_DPipe_print(io, "0x%08X, ", crctab[i]); } i++; if ((i % 16) == 0) { IfxStdIf_DPipe_print(io, ENDL " "); } } IfxStdIf_DPipe_print(io, " }"ENDL); IfxStdIf_DPipe_print(io, "};"ENDL); } boolean Ifx_Crc_Test(Ifc_Crc *driver, uint8 *string, uint32 length, IfxStdIf_DPipe *io) { IfxStdIf_DPipe_print(io, ""ENDL); IfxStdIf_DPipe_print(io, "CRC tester v1.1 written on 13/01/2003 by Sven Reifegerste (zorc/reflex)"ENDL); IfxStdIf_DPipe_print(io, "-----------------------------------------------------------------------"ENDL); IfxStdIf_DPipe_print(io, ""ENDL); IfxStdIf_DPipe_print(io, "Parameters:"ENDL); IfxStdIf_DPipe_print(io, ""ENDL); IfxStdIf_DPipe_print(io, " polynom : 0x%x"ENDL, driver->table->polynom); IfxStdIf_DPipe_print(io, " order : %d"ENDL, driver->table->order); IfxStdIf_DPipe_print(io, " crcinit : 0x%x direct, 0x%x nondirect"ENDL, driver->crcinit_direct, driver->crcinit_nondirect); IfxStdIf_DPipe_print(io, " crcxor : 0x%x"ENDL, driver->crcxor); IfxStdIf_DPipe_print(io, " refin : %d"ENDL, driver->table->refin); IfxStdIf_DPipe_print(io, " refout : %d"ENDL, driver->refout); IfxStdIf_DPipe_print(io, ""ENDL); // IfxStdIf_DPipe_print(io," data string : '%s' (%d bytes)"ENDL, string, stringLength); IfxStdIf_DPipe_print(io, ""ENDL); IfxStdIf_DPipe_print(io, "Results:"ENDL); IfxStdIf_DPipe_print(io, ""ENDL); #if 0 IfxCpu_Perf perf; uint32 result; IfxCpu_resetAndStartCounters(IfxCpu_CounterMode_normal); result = Ifx_Crc_bitByBit(driver, (uint8 *)string, length); perf = IfxCpu_stopCounters(); IfxStdIf_DPipe_print(io, " crc bit by bit : 0x%X, %d cycles"ENDL, result, perf.clock.counter); IfxCpu_resetAndStartCounters(IfxCpu_CounterMode_normal); result = Ifx_Crc_bitByBitFast(driver, (uint8 *)string, length); perf = IfxCpu_stopCounters(); IfxStdIf_DPipe_print(io, " crc bit by bit fast : 0x%X, %d cycles"ENDL, result, perf.clock.counter); IfxCpu_resetAndStartCounters(IfxCpu_CounterMode_normal); result = Ifx_Crc_table(driver, (uint8 *)string, length); perf = IfxCpu_stopCounters(); IfxStdIf_DPipe_print(io, " crc table : 0x%X, %d cycles"ENDL, result, perf.clock.counter); IfxCpu_resetAndStartCounters(IfxCpu_CounterMode_normal); result = Ifx_Crc_tableFast(driver, (uint8 *)string, length); perf = IfxCpu_stopCounters(); IfxStdIf_DPipe_print(io, " crc table fast : 0x%X, %d cycles"ENDL, result, perf.clock.counter); #endif return TRUE; } #endif