Skip to content

Commit

Permalink
Addressed all review comments
Browse files Browse the repository at this point in the history
1. Change in location (drivers)
2. Non-templated class (soft/fast)
3. Change to enum/defines
4. data/width/top_bit macros are now protected functions

And fewer other comments
  • Loading branch information
Deepika committed Dec 21, 2017
1 parent c5c418a commit 122036a
Show file tree
Hide file tree
Showing 9 changed files with 722 additions and 555 deletions.
53 changes: 34 additions & 19 deletions features/crc/mbed_crc.h → drivers/BaseCRC.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBED_CRC_API_H
#define MBED_CRC_API_H
#ifndef BASE_CRC_API_H
#define BASE_CRC_API_H

#include <stdint.h>

namespace mbed {
/** \addtogroup crc */
/** \addtogroup drivers */
/** @{*/


Expand Down Expand Up @@ -48,18 +48,30 @@ typedef enum crc_width {
CRC_32 = 32,
} crc_width_t;

/** CRC Polynomial value
*
* Different polynomial values supported
*/
typedef enum crc_polynomial {
POLY_INVALID = 0,
POLY_8BIT_CCITT = 0x07, // x8+x2+x+1
POLY_7BIT_SD = 0x9, // x7+x3+1;
POLY_16BIT_CCITT = 0x1021, // x16+x12+x5+1
POLY_16BIT_IBM = 0x8005, // x16+x15+x2+1
POLY_32BIT_ANSI = 0x04C11DB7, // x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
POLY_32BIT_ANSI_REVERSE = 0xEDB88320, // x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
} crc_polynomial_t;

/** CRC object provides CRC generation through hardware/software
*/
class CRC
class BaseCRC
{
public:
typedef uint64_t crc_data_size_t;
typedef uint32_t crc_polynomial_t;
typedef uint32_t crc_size_t;

/** Lifetime of CRC object
*/
virtual ~CRC() {};
virtual ~BaseCRC() {};

/** Initialize CRC module
*
Expand Down Expand Up @@ -87,29 +99,30 @@ class CRC

/** Get the current CRC polynomial
*
* @return Polynomial value
* @return Polynomial value, 0 when polynomial type is incorrect
* or not supported
*/
virtual crc_polynomial_t get_polynomial(void) const
{
crc_polynomial_type_t polynomial = this->get_polynomial_type();

if (CRC_7BIT_SD == polynomial) {
return 0x9; // x7+x3+1;
return POLY_7BIT_SD;
} else if (CRC_8BIT_CCITT == polynomial) {
return 0x07; // x8+x2+x+1
return POLY_8BIT_CCITT;
} else if ((CRC_16BIT_SD == polynomial) || (CRC_16BIT_CCITT == polynomial)) {
return 0x1021; // x16+x12+x5+1
return POLY_16BIT_CCITT;
} else if (CRC_16BIT_IBM == polynomial) {
return 0x8005; // x16+x15+x2+1
return POLY_16BIT_IBM;
} else if (CRC_32BIT == polynomial) {
return 0x04C11DB7; // x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
return POLY_32BIT_ANSI;
}
return 0;
return POLY_INVALID;
}

/** Get the current CRC width
*
* @return CRC width
* @return CRC width, 0 when polynomial type is incorrect or not supported.
*/
virtual crc_width_t get_width(void) const
{
Expand All @@ -136,7 +149,7 @@ class CRC
* @param [OUT] crc CRC
* @return 0 on success, negative error code on failure
*/
virtual int32_t compute(void *buffer, crc_data_size_t size, crc_size_t *crc) = 0;
virtual int32_t compute(void *buffer, crc_data_size_t size, uint32_t *crc) = 0;

/** Compute partial start, indicate start of partial computation
*
Expand All @@ -148,7 +161,7 @@ class CRC
* @note: CRC is an out parameter and must be reused with compute_partial
* and compute_partial_stop without any modifications in application.
*/
virtual int32_t compute_partial_start(crc_size_t *crc) const
virtual int32_t compute_partial_start(uint32_t *crc)
{
return -1;
}
Expand All @@ -167,7 +180,7 @@ class CRC
* @note: CRC as output in compute_partial is not final CRC value, call @ref compute_partial_stop
* to get final correct CRC value.
*/
virtual int32_t compute_partial(void *buffer, crc_data_size_t size, crc_size_t *crc)
virtual int32_t compute_partial(void *buffer, crc_data_size_t size, uint32_t *crc)
{
return -1;
}
Expand All @@ -180,11 +193,13 @@ class CRC
*
* @param[OUT] crc CRC result
*/
virtual int32_t compute_partial_stop(crc_size_t *crc)
virtual int32_t compute_partial_stop(uint32_t *crc)
{
return -1;
}

protected:

/** Get the current CRC data size
*
* @return CRC data size in bytes
Expand Down
184 changes: 184 additions & 0 deletions drivers/FastCRC.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
/* mbed Microcontroller Library
* Copyright (c) 2017 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "platform/mbed_assert.h"
#include "FastCRC.h"
#include <stdio.h>

namespace mbed {

FastCRC::FastCRC(crc_polynomial_type_t polynomial) :
_polynomial_type(polynomial), _inital_value(0x0),
_final_xor(0x0), _reflect_data(false), _reflect_remainder(false)
{
// Set the non-default polynomial specific parameters
if (CRC_16BIT_CCITT == _polynomial_type) {
_inital_value = ~(0x0);
} else if (CRC_16BIT_IBM == _polynomial_type) {
_reflect_data = true;
_reflect_remainder = true;
} else if (CRC_32BIT == _polynomial_type) {
_inital_value = ~(0x0);
_final_xor = ~(0x0);
_reflect_data = true;
_reflect_remainder = true;
}
}

FastCRC::~FastCRC() {
deinit();
}

int32_t FastCRC::init(void)
{
uint32_t crc;
uint8_t data_size = get_data_size();
crc_width_t width = get_width();
uint32_t polynomial = get_polynomial();

_crc_table = new uint32_t[64*data_size];
uint8_t *crc_table = (uint8_t *)_crc_table;

if (width < 8) {
polynomial <<= (8 - width);
}

for (int32_t dividend = 0; dividend < 256; ++dividend) {
if (width < 8) {
crc = dividend;
} else {
crc = dividend << (width - 8);
}
for (uint8_t bit = 8; bit > 0; --bit) {
if (crc & get_top_bit()) {
crc = (crc << 1) ^ polynomial;
} else {
crc = (crc << 1);
}
}

for (int i = 0; i < data_size; i++) {
crc_table[(dividend*data_size)+i] = (crc >> (8*i)) & 0xFF;
}
}
return 0;
}

int32_t FastCRC::deinit(void)
{
delete []_crc_table;
return 0;
}

crc_polynomial_type_t FastCRC::get_polynomial_type(void) const
{
return _polynomial_type;
}

int32_t FastCRC::compute_partial(void *buffer, crc_data_size_t size, uint32_t *crc)
{
MBED_ASSERT(crc != NULL);
MBED_ASSERT(buffer != NULL);

uint8_t *data = static_cast<uint8_t *>(buffer);
crc_width_t width = this->get_width();
uint32_t p_crc = *crc;
uint8_t data_byte;

if (width < 8) {
uint8_t *crc_table = (uint8_t *)_crc_table;
for (crc_data_size_t byte = 0; byte < size; byte++) {
p_crc = crc_table[(data[byte] ^ p_crc)];
}
} else if (width <= 16) {
uint16_t *crc_table = (uint16_t *)_crc_table;
for (crc_data_size_t byte = 0; byte < size; byte++) {
data_byte = reflect_bytes(data[byte]) ^ (p_crc >> (width - 8));
p_crc = crc_table[data_byte] ^ (p_crc << 8);
}
} else {
for (crc_data_size_t byte = 0; byte < size; byte++) {
data_byte = reflect_bytes(data[byte]) ^ (p_crc >> (width - 8));
p_crc = _crc_table[data_byte] ^ (p_crc << 8);
}
}
if (width < 8) {
p_crc >>= (8 - width);
}
*crc = p_crc & get_crc_mask();
return 0;
}

int32_t FastCRC::compute(void *buffer, crc_data_size_t size, uint32_t *crc)
{
MBED_ASSERT(crc != NULL);
int32_t status;
*crc = _inital_value;
status = compute_partial(buffer, size, crc);
*crc = (reflect_remainder(*crc) ^ _final_xor) & get_crc_mask();
return status;
}

int32_t FastCRC::compute_partial_start(uint32_t *crc)
{
MBED_ASSERT(crc != NULL);
*crc = _inital_value;
return 0;
}

int32_t FastCRC::compute_partial_stop(uint32_t *crc)
{
MBED_ASSERT(crc != NULL);
*crc = (reflect_remainder(*crc) ^ _final_xor) & get_crc_mask();
return 0;
}

uint32_t FastCRC::reflect_remainder(uint32_t data)
{
crc_width_t width = get_width();
if (_reflect_remainder) {
uint32_t reflection = 0x0;
uint8_t const nBits = (width < 8 ? 8 : width);

for (uint8_t bit = 0; bit < nBits; ++bit) {
if (data & 0x01) {
reflection |= (1 << ((nBits - 1) - bit));
}
data = (data >> 1);
}
return (reflection);
} else {
return data;
}
}

uint32_t FastCRC::reflect_bytes(uint32_t data)
{
if(_reflect_data) {
uint32_t reflection = 0x0;

for (uint8_t bit = 0; bit < 8; ++bit) {
if (data & 0x01) {
reflection |= (1 << (7 - bit));
}
data = (data >> 1);
}
return (reflection);
} else {
return data;
}
}
}
Loading

0 comments on commit 122036a

Please sign in to comment.