world leader in high performance signal processing
Trace: » bfin_crc

CRC peripheral driver

The CRC peripheral in BF60x family processors is a hardware block used to compute the CRC of the block of data. This is based on a CRC32 engine which computes the CRC value of 32-bit data words presented to it. For data words of < 32-bit in size, it is the responsibility of application to pack the data into 32-bit data units.

The main features of the CRC peripheral are:

  1. Memory Scan mode
  2. Memory Transfer mode
  3. Data Verify mode
  4. Data Fill mode
  5. 32b CRC polynomial (Programmable polynomials)
  6. Bit/Byte Mirroring option
  7. Fault/Error interrupt mechanisms

There are 2 types of drivers: simple char driver and crypto framework driver.

Crypto Framework CRC hw driver

The Scatterlist Crypto API takes page vectors (scatterlists) as arguments, and works directly on pages. The crypto bfin crc hardware accelerator driver implements the asyn hash interface. CRC results are calculated via array descriptor based DMA operation, which is generated at run time. If input buffer length is not the multiply of 32 bits, this driver append 0 automatically. The framework only support Memory Scan mode.

This driver can be found at Linux-kernel/drivers/crypto/bfin_crc.c

Configuration Crypto CRC driver

To enable this driver in Linux kernel:

Cryptographic API  --->
-*-   Cryptographic algorithm manager
<*>   HMAC support
[*]   Hardware crypto devices  --->
    <*>   Support for Blackfin CRC hareware accelerator

To include a CRC test suite module in kernel:

Cryptographic API  --->
[ ]   Disable run-time self tests
<*>   Testing module

Run Crypto CRC test

When kernel boot up on BF60x, check if the Crypto CRC driver probes devices correctly.

Blackfin hardware CRC crypto driver
bfin-hmac-crc bfin-hmac-crc.0: initialized

Run a full test by tcrypt module. This test module is always not loaded. If any error occurs, “tcrypt: one or more tests failed” is printed out.

root:/> modprobe tcrypt mode=110
modprobe: can't load module tcrypt (kernel/crypto/tcrypt.ko): Resource temporarily unavailable

Simple Char CRC hw driver

The simple char crc hw accelerator driver registers char misc devices. It enables all 4 operation modes. But, application should ensure the input buffer is 32 bit aligned and its length is the multiply of 32 bits. Otherwise, error reports.

This driver can be found under at Linux-kernel/drivers/char/bfin_crc.c

Configuration Char CRC driver

To enable this driver in Linux kernel:

Device Drivers  --->
<*> Blackfin hardware CRC driver

To include a CRC test application in buildroot:

Package Selection for the target  --->
    Miscellaneous  --->
    [*] bfin CRC test

ICTOL command interface

The crc_info structure is defined for application to configure the behavior of the CRC driver via ioctl interface. Variants defined in 2 unions are for different CRC function commands. data addresses should be 4 byte aligned and datasize should be times of 4. CRC mirror flags are defined in CRC spec to mirror data order.

struct crc_info {
        /* Input data address */
        unsigned char *in_addr;
        /* Output data address */
        unsigned char *out_addr;
        /* Input or output bytes */
        unsigned long datasize;
        union {
        /* CRC to compare with that of input buffer */
        unsigned long crc_compare;
        /* Value to compare with input data */
        unsigned long val_verify;
        /* Value to fill */
        unsigned long val_fill;
        };
        /* Value to program the 32b CRC Polynomial */
        unsigned long crc_poly;
        union {
        /* CRC calculated from the input data */
        unsigned long crc_result;
        /* First failed position to verify input data */
        unsigned long pos_verify;
        };
        /* CRC mirror flags */
        unsigned int bitmirr:1;
        unsigned int bytmirr:1;
        unsigned int w16swp:1;
        unsigned int fdsel:1;
        unsigned int rsltmirr:1;
        unsigned int polymirr:1;
        unsigned int cmpmirr:1;
};

4 types of CRC functions are available to user application.

#define CRC_IOC_MAGIC           'C'
#define CRC_IOC_CALC_CRC        _IOWR('C', 0x01, unsigned int)
#define CRC_IOC_MEMCPY_CRC      _IOWR('C', 0x02, unsigned int)
#define CRC_IOC_VERIFY_VAL      _IOWR('C', 0x03, unsigned int)
#define CRC_IOC_FILL_VAL        _IOWR('C', 0x04, unsigned int)

To run a CRC function, application should set the crc_info structure properly and call ioctl interface against the CRC device node with proper command.

info.crc_compare = expected_crc;
info.crc_result = 0;
ret = ioctl(crc_fd, CRC_IOC_CALC_CRC, &info);
printf("CRC = 0x%x\n", info.crc_result);

Run Char CRC test

When kernel boot up on BF60x, check if the char CRC driver probes devices correctly.

Blackfin hardware CRC driver
bfin-crc bfin-crc.0: initialized
bfin-crc bfin-crc.1: initialized

bfin_crc_test application has following parameters

root:/> bfin_crc_test 
Usage: bfin_crc_test [options] <crc device path>

Options:
  -m <mode>   Test crc device in <mode>.
        0 - test all
        1 - calculate crc
        2 - memory copy with crc
        3 - verify value
        4 - fill value
  -s <words>  buffer size to run the test
  -c <crc>    expected CRC
  -v <val>    fill val
  -h          This help.

Run a full test without expected CRC value:

root:/> bfin_crc_test -m 0 /dev/bfin-crc0 
Start calculate CRC:
End Calculate CRC: pass, crc=0x47300

Start compare CRC(0x12345678):
End compare CRC(0x47300): fail

Start memory copy with CRC:
End memory copy with CRC: pass, crc=0x57200

Start verify with right value:
End verify value: pass

Start verify with wrong value:
End verify value: detect wrong value at position 127, pass

Start fill value(0x12345678):
End fill value: pass

Run a full test with expected CRC:

root:/> bfin_crc_test -m 0 -c 0x47300 /dev/bfin-crc0 
Start calculate CRC:
End Calculate CRC: pass, crc=0x47300

Start compare CRC(0x47300):
End compare CRC(0x47300): pass

Start memory copy with CRC:
End memory copy with CRC: pass, crc=0x57200

Start verify with right value:
End verify value: pass

Start verify with wrong value:
End verify value: detect wrong value at position 127, pass

Start fill value(0x12345678):
End fill value: pass