All Data Structures Functions Variables Typedefs Enumerations Enumerator Groups Pages
CRC: Cyclic Redundancy Check Driver

## Overview

The Kinetis SDK provides the Peripheral driver for the Cyclic Redundancy Check (CRC) module of Kinetis devices.
The cyclic redundancy check (CRC) module generates 16/32-bit CRC code for error detection. The CRC module provides a programmable polynomial, seed, and other parameters required to implement a 16-bit or 32-bit CRC standard.

# CRC Driver Initialization and Configuration

CRC_Init() function enables the clock gate for the CRC module in the Kinetis SIM module and fully (re-)configures the CRC module according to configuration structure. The seed member of the configuration structure is the initial checksum for which new data can be added to. When starting new checksum computation, the seed shall be set to the initial checksum per the CRC protocol specification. For continued checksum operation, the seed shall be set to the intermediate checksum value as obtained from previous calls to CRC_Get16bitResult() or CRC_Get32bitResult() function. After CRC_Init(), one or multiple CRC_WriteData() calls follow to update checksum with data, then CRC_Get16bitResult() or CRC_Get32bitResult() follows to read the result. The crcResult member of configuration structure determines if CRC_Get16bitResult() or CRC_Get32bitResult() return value is final checksum or intermediate checksum. CRC_Init() can be called as many times as required, thus, allows for runtime changes of CRC protocol.

CRC_GetDefaultConfig() function can be used to set the module configuration structure with parameters for CRC-16/CCIT-FALSE protocol.

# CRC Write Data

The CRC_WriteData() function is used to add data to actual CRC. Internally it tries to use 32-bit reads and writes for all aligned data in the user buffer and it uses 8-bit reads and writes for all unaligned data in the user buffer. This function can update CRC with user supplied data chunks of arbitrary size, so one can update CRC byte by byte or with all bytes at once. Prior call CRC configuration function CRC_Init() fully specifies the CRC module configuration for CRC_WriteData() call.

# CRC Get Checksum

The CRC_Get16bitResult() or CRC_Get32bitResult() function is used to read the CRC module data register. Depending on prior CRC module usage the return value is either intermediate checksum or final checksum. Example: for 16-bit CRCs the following call sequences can be used:

CRC_Init() / CRC_WriteData() / CRC_Get16bitResult() to get final checksum.

CRC_Init() / CRC_WriteData() / ... / CRC_WriteData() / CRC_Get16bitResult() to get final checksum.

CRC_Init() / CRC_WriteData() / CRC_Get16bitResult() to get intermediate checksum.

CRC_Init() / CRC_WriteData() / ... / CRC_WriteData() / CRC_Get16bitResult() to get intermediate checksum.

# Comments about API usage in RTOS

If multiple RTOS tasks share the CRC module to compute checksums with different data and/or protocols, the following needs to be implemented by the user:

The triplets

CRC_Init() / CRC_WriteData() / CRC_Get16bitResult() or CRC_Get32bitResult()

shall be protected by RTOS mutex to protect CRC module against concurrent accesses from different tasks. Example:

CRC_Module_RTOS_Mutex_Lock;
CRC_Init();
CRC_WriteData();
CRC_Get16bitResult();
CRC_Module_RTOS_Mutex_Unlock;

# Comments about API usage in interrupt handler

All APIs can be used from interrupt handler although execution time shall be considered (interrupt latency of equal and lower priority interrupts increases). Protection against concurrent accesses from different interrupt handlers and/or tasks shall be assured by the user.

# CRC Driver Examples

## Simple examples

Simple example with default CRC-16/CCIT-FALSE protocol

crc_config_t config;
CRC_Type *base;
uint8_t data[] = {0x00, 0x01, 0x02, 0x03, 0x04};
uint16_t checksum;
base = CRC0;
CRC_GetDefaultConfig(base, &config); /* default gives CRC-16/CCIT-FALSE */
CRC_Init(base, &config);
CRC_WriteData(base, data, sizeof(data));
checksum = CRC_Get16bitResult(base);

Simple example with CRC-32 protocol configuration

crc_config_t config;
uint32_t checksum;
config.polynomial = 0x04C11DB7u;
config.seed = 0xFFFFFFFFu;
config.crcBits = kCrcBits32;
config.reflectIn = true;
config.reflectOut = true;
config.complementChecksum = true;
config.crcResult = kCrcFinalChecksum;
CRC_Init(base, &config);
/* example: update by 1 byte at time */
while (dataSize)
{
uint8_t c = GetCharacter();
CRC_WriteData(base, &c, 1);
dataSize--;
}
checksum = CRC_Get32bitResult(base);

## Advanced examples

Per-partes data updates with context switch between. Assuming there are 3 tasks/threads, each using the CRC module to compute checksums of a different protocol, with context switches.

First, prepare three CRC module initialization functions for three different protocols: CRC-16 (ARC), CRC-16/CCIT-FALSE and CRC-32. Table below lists the individual protocol specifications. See also: http://reveng.sourceforge.net/crc-catalogue/

| CRC-16/CCIT-FALSE | CRC-16 | CRC-32
--- | --- | --- | ---
Width | 16 bits | 16 bits | 32 bits
Polynomial | 0x1021 | 0x8005 | 0x04C11DB7
Initial seed | 0xFFFF | 0x0000 | 0xFFFFFFFF
Complement checksum | No | No | Yes
Reflect In | No | Yes | Yes
Reflect Out | No | Yes | Yes

Corresponding init functions:

void InitCrc16_CCIT(CRC_Type *base, uint32_t seed, bool isLast)
{
crc_config_t config;
config.polynomial = 0x1021;
config.seed = seed;
config.reflectIn = false;
config.reflectOut = false;
config.complementChecksum = false;
config.crcBits = kCrcBits16;
config.crcResult = isLast?kCrcFinalChecksum:kCrcIntermediateChecksum;
CRC_Init(base, &config);
}
void InitCrc16(CRC_Type *base, uint32_t seed, bool isLast)
{
crc_config_t config;
config.polynomial = 0x8005;
config.seed = seed;
config.reflectIn = true;
config.reflectOut = true;
config.complementChecksum = false;
config.crcBits = kCrcBits16;
config.crcResult = isLast?kCrcFinalChecksum:kCrcIntermediateChecksum;
CRC_Init(base, &config);
}
void InitCrc32(CRC_Type *base, uint32_t seed, bool isLast)
{
crc_config_t config;
config.polynomial = 0x04C11DB7U;
config.seed = seed;
config.reflectIn = true;
config.reflectOut = true;
config.complementChecksum = true;
config.crcBits = kCrcBits32;
config.crcResult = isLast?kCrcFinalChecksum:kCrcIntermediateChecksum;
CRC_Init(base, &config);
}

The following context switches show possible API usage:

uint16_t checksumCrc16;
uint32_t checksumCrc32;
uint16_t checksumCrc16Ccit;
checksumCrc16 = 0x0;
checksumCrc32 = 0xFFFFFFFFU;
checksumCrc16Ccit = 0xFFFFU;
/* Task A bytes[0-3] */
InitCrc16(base, checksumCrc16, false);
CRC_WriteData(base, &data[0], 4);
checksumCrc16 = CRC_Get16bitResult(base);
/* Task B bytes[0-3] */
InitCrc16_CCIT(base, checksumCrc16Ccit, false);
CRC_WriteData(base, &data[0], 4);
checksumCrc16Ccit = CRC_Get16bitResult(base);
/* Task C 4 bytes[0-3] */
InitCrc32(base, checksumCrc32, false);
CRC_WriteData(base, &data[0], 4);
checksumCrc32 = CRC_Get32bitResult(base);
/* Task B add final 5 bytes[4-8] */
InitCrc16_CCIT(base, checksumCrc16Ccit, true);
CRC_WriteData(base, &data[4], 5);
checksumCrc16Ccit = CRC_Get16bitResult(base);
/* Task C 3 bytes[4-6] */
InitCrc32(base, checksumCrc32, false);
CRC_WriteData(base, &data[4], 3);
checksumCrc32 = CRC_Get32bitResult(base);
/* Task A 3 bytes[4-6] */
InitCrc16(base, checksumCrc16, false);
CRC_WriteData(base, &data[4], 3);
checksumCrc16 = CRC_Get16bitResult(base);
/* Task C add final 2 bytes[7-8] */
InitCrc32(base, checksumCrc32, true);
CRC_WriteData(base, &data[7], 2);
checksumCrc32 = CRC_Get32bitResult(base);
/* Task A add final 2 bytes[7-8] */
InitCrc16(base, checksumCrc16, true);
CRC_WriteData(base, &data[7], 2);
checksumCrc16 = CRC_Get16bitResult(base);

## Data Structures

struct | crc_config_t
| CRC protocol configuration. More...

## Macros

#define | CRC_DRIVER_USE_CRC16_CCIT_FALSE_AS_DEFAULT 1
| Default configuration structure filled by CRC_GetDefaultConfig(). More...

## Enumerations

enum | crc_bits_t { kCrcBits16 = 0U, kCrcBits32 = 1U }
| CRC bit width. More...
enum | crc_result_t { kCrcFinalChecksum = 0U, kCrcIntermediateChecksum = 1U }
| CRC result type. More...

## Functions

void | CRC_Init (CRC_Type *base, const crc_config_t *config)
| Enables and configures the CRC peripheral module. More...
static void | CRC_Deinit (CRC_Type *base)
| Disables the CRC peripheral module. More...
void | CRC_GetDefaultConfig (crc_config_t *config)
| Loads default values to CRC protocol configuration structure. More...
void | CRC_WriteData (CRC_Type *base, const uint8_t *data, size_t dataSize)
| Writes data to the CRC module. More...
uint32_t | CRC_Get32bitResult (CRC_Type *base)
| Reads 32-bit checksum from the CRC module. More...
uint16_t | CRC_Get16bitResult (CRC_Type *base)
| Reads 16-bit checksum from the CRC module. More...

## Driver version

#define | FSL_CRC_DRIVER_VERSION (MAKE_VERSION(2, 0, 1))
| CRC driver version. More...

## Data Structure Documentation

struct crc_config_t

This structure holds the configuration for the CRC protocol.

### Data Fields

uint32_t | polynomial
| CRC Polynomial, MSBit first. More...
uint32_t | seed
| Starting checksum value.
bool | reflectIn
| Reflect bits on input. More...
bool | reflectOut
| Reflect bits on output. More...
bool | complementChecksum
| True if the result shall be complement of the actual checksum. More...
crc_bits_t | crcBits
| Selects 16- or 32- bit CRC protocol. More...
crc_result_t | crcResult
| Selects final or intermediate checksum return from CRC_Get16bitResult() or CRC_Get32bitResult()

#### Field Documentation

uint32_t crc_config_t::polynomial

Example polynomial: 0x1021 = 1_0000_0010_0001 = x^12+x^5+1

bool crc_config_t::reflectIn

bool crc_config_t::reflectOut

bool crc_config_t::complementChecksum

crc_bits_t crc_config_t::crcBits

## Macro Definition Documentation

#define FSL_CRC_DRIVER_VERSION (MAKE_VERSION(2, 0, 1))

Version 2.0.1.

Current version: 2.0.1

Change log:

- Version 2.0.1
  - move DATA and DATALL macro definition from header file to source file

#define CRC_DRIVER_USE_CRC16_CCIT_FALSE_AS_DEFAULT 1

Use CRC16-CCIT-FALSE as defeault.

## Enumeration Type Documentation

enum crc_bits_t

Enumerator
kCrcBits16 | Generate 16-bit CRC code.
kCrcBits32 | Generate 32-bit CRC code.

enum crc_result_t

Enumerator
kCrcFinalChecksum | CRC data register read value is the final checksum. Reflect out and final xor protocol features are applied.
kCrcIntermediateChecksum | CRC data register read value is intermediate checksum (raw value). Reflect out and final xor protocol feature are not applied. Intermediate checksum can be used as a seed for CRC_Init() to continue adding data to this checksum.

## Function Documentation

void CRC_Init | ( | CRC_Type * | base,
|  | const crc_config_t * | config
| ) |  |

This functions enables the clock gate in the Kinetis SIM module for the CRC peripheral. It also configures the CRC module and starts checksum computation by writing the seed.

Parameters

  base | CRC peripheral address.
  config | CRC module configuration structure

static void CRC_Deinit | ( | CRC_Type * | base | ) |

inlinestatic

This functions disables the clock gate in the Kinetis SIM module for the CRC peripheral.

Parameters

  base | CRC peripheral address.

void CRC_GetDefaultConfig | ( | crc_config_t * | config | ) |

Loads default values to CRC protocol configuration structure. The default values are:

* config->polynomial = 0x1021;
* config->seed = 0xFFFF;
* config->reflectIn = false;
* config->reflectOut = false;
* config->complementChecksum = false;
* config->crcBits = kCrcBits16;
* config->crcResult = kCrcFinalChecksum;
*

Parameters

  config | CRC protocol configuration structure

void CRC_WriteData | ( | CRC_Type * | base,
|  | const uint8_t * | data,
|  | size_t | dataSize
| ) |  |

Writes input data buffer bytes to CRC data register. The configured type of transpose is applied.

Parameters

  base | CRC peripheral address.
  data | Input data stream, MSByte in data[0].
  dataSize | Size in bytes of the input data buffer.

uint32_t CRC_Get32bitResult | ( | CRC_Type * | base | ) |

Reads CRC data register (intermediate or final checksum). The configured type of transpose and complement are applied.

Parameters

  base | CRC peripheral address.

Returns
  intermediate or final 32-bit checksum, after configured transpose and complement operations.

uint16_t CRC_Get16bitResult | ( | CRC_Type * | base | ) |

Reads CRC data register (intermediate or final checksum). The configured type of transpose and complement are applied.

Parameters

  base | CRC peripheral address.

Returns
  intermediate or final 16-bit checksum, after configured transpose and complement operations.