helper: Add generic little endian CRC32 function
This generalizes the little endian CRC32 function used in the OR1K target and moves it to a common helper, so that other places do not need to reinvent the wheel. It is directly used in the OR1K target. Change-Id: I0e55340281a5bfd80669bb1994f3a96fecc1248a Signed-off-by: Marian Buschsieweke <marian.buschsieweke@ovgu.de> Reviewed-on: https://review.openocd.org/c/openocd/+/7415 Tested-by: jenkins Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
This commit is contained in:
parent
92dd917f5a
commit
6e67f1473a
|
@ -9,6 +9,7 @@ noinst_LTLIBRARIES += %D%/libhelper.la
|
|||
%D%/configuration.c \
|
||||
%D%/log.c \
|
||||
%D%/command.c \
|
||||
%D%/crc32.c \
|
||||
%D%/time_support.c \
|
||||
%D%/replacements.c \
|
||||
%D%/fileio.c \
|
||||
|
@ -24,6 +25,7 @@ noinst_LTLIBRARIES += %D%/libhelper.la
|
|||
%D%/types.h \
|
||||
%D%/log.h \
|
||||
%D%/command.h \
|
||||
%D%/crc32.h \
|
||||
%D%/time_support.h \
|
||||
%D%/replacements.h \
|
||||
%D%/fileio.h \
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2013-2014 by Franck Jullien *
|
||||
* elec4fun@gmail.com *
|
||||
* *
|
||||
* Copyright (C) 2022 Otto-von-Guericke-Universität Magdeburg *
|
||||
* marian.buschsieweke@ovgu.de *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "crc32.h"
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
static uint32_t crc_le_step(uint32_t poly, uint32_t crc, uint32_t data_in,
|
||||
unsigned int data_bits)
|
||||
{
|
||||
for (unsigned int i = 0; i < data_bits; i++) {
|
||||
uint32_t d, c;
|
||||
d = ((data_in >> i) & 0x1) ? 0xffffffff : 0;
|
||||
c = (crc & 0x1) ? 0xffffffff : 0;
|
||||
crc = crc >> 1;
|
||||
crc = crc ^ ((d ^ c) & poly);
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
uint32_t crc32_le(uint32_t poly, uint32_t seed, const void *_data,
|
||||
size_t data_len)
|
||||
{
|
||||
if (((uintptr_t)_data & 0x3) || (data_len & 0x3)) {
|
||||
/* data is unaligned, processing data one byte at a time */
|
||||
const uint8_t *data = _data;
|
||||
for (size_t i = 0; i < data_len; i++)
|
||||
seed = crc_le_step(poly, seed, data[i], 8);
|
||||
} else {
|
||||
/* data is aligned, processing 32 bit at a time */
|
||||
data_len >>= 2;
|
||||
const uint32_t *data = _data;
|
||||
for (size_t i = 0; i < data_len; i++)
|
||||
seed = crc_le_step(poly, seed, data[i], 32);
|
||||
}
|
||||
|
||||
return seed;
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2022 Otto-von-Guericke-Universität Magdeburg *
|
||||
* marian.buschsieweke@ovgu.de *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef OPENOCD_HELPER_CRC32_H
|
||||
#define OPENOCD_HELPER_CRC32_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/** @file
|
||||
* A generic CRC32 implementation
|
||||
*/
|
||||
|
||||
/**
|
||||
* CRC32 polynomial commonly used for little endian CRC32
|
||||
*/
|
||||
#define CRC32_POLY_LE 0xedb88320
|
||||
|
||||
/**
|
||||
* Calculate the CRC32 value of the given data
|
||||
* @param poly The polynomial of the CRC
|
||||
* @param seed The seed to use (mostly either `0` or `0xffffffff`)
|
||||
* @param data The data to calculate the CRC32 of
|
||||
* @param data_len The length of the data in @p data in bytes
|
||||
* @return The CRC value of the first @p data_len bytes at @p data
|
||||
* @note This function can be used to incrementally compute the CRC one
|
||||
* chunk of data at a time by using the CRC32 of the previous chunk
|
||||
* as @p seed for the next chunk.
|
||||
*/
|
||||
uint32_t crc32_le(uint32_t poly, uint32_t seed, const void *data,
|
||||
size_t data_len);
|
||||
|
||||
#endif /* OPENOCD_HELPER_CRC32_H */
|
|
@ -22,8 +22,9 @@
|
|||
#include "or1k_du.h"
|
||||
#include "jsp_server.h"
|
||||
|
||||
#include <target/target.h>
|
||||
#include <helper/crc32.h>
|
||||
#include <jtag/jtag.h>
|
||||
#include <target/target.h>
|
||||
|
||||
#define JSP_BANNER "\n\r" \
|
||||
"******************************\n\r" \
|
||||
|
@ -67,13 +68,6 @@
|
|||
#define DBG_CPU_CR_STALL 0x01
|
||||
#define DBG_CPU_CR_RESET 0x02
|
||||
|
||||
/* Polynomial for the CRC calculation
|
||||
* Yes, it's backwards. Yes, this is on purpose.
|
||||
* The hardware is designed this way to save on logic and routing,
|
||||
* and it's really all the same to us here.
|
||||
*/
|
||||
#define ADBG_CRC_POLY 0xedb88320
|
||||
|
||||
/* These are for the internal registers in the Wishbone module
|
||||
* The first is the length of the index register,
|
||||
* the indexes of the various registers are defined after that.
|
||||
|
@ -133,20 +127,6 @@ static struct or1k_du or1k_du_adv;
|
|||
|
||||
static const char * const chain_name[] = {"WISHBONE", "CPU0", "CPU1", "JSP"};
|
||||
|
||||
static uint32_t adbg_compute_crc(uint32_t crc, uint32_t data_in,
|
||||
int length_bits)
|
||||
{
|
||||
for (int i = 0; i < length_bits; i++) {
|
||||
uint32_t d, c;
|
||||
d = ((data_in >> i) & 0x1) ? 0xffffffff : 0;
|
||||
c = (crc & 0x1) ? 0xffffffff : 0;
|
||||
crc = crc >> 1;
|
||||
crc = crc ^ ((d ^ c) & ADBG_CRC_POLY);
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
static int find_status_bit(void *_buf, int len)
|
||||
{
|
||||
int i = 0;
|
||||
|
@ -522,9 +502,8 @@ retry_read_full:
|
|||
memcpy(data, in_buffer, total_size_bytes);
|
||||
memcpy(&crc_read, &in_buffer[total_size_bytes], 4);
|
||||
|
||||
uint32_t crc_calc = 0xffffffff;
|
||||
for (int i = 0; i < total_size_bytes; i++)
|
||||
crc_calc = adbg_compute_crc(crc_calc, data[i], 8);
|
||||
uint32_t crc_calc = crc32_le(CRC32_POLY_LE, 0xffffffff, data,
|
||||
total_size_bytes);
|
||||
|
||||
if (crc_calc != crc_read) {
|
||||
LOG_WARNING("CRC ERROR! Computed 0x%08" PRIx32 ", read CRC 0x%08" PRIx32, crc_calc, crc_read);
|
||||
|
@ -650,9 +629,8 @@ retry_full_write:
|
|||
field[0].out_value = &value;
|
||||
field[0].in_value = NULL;
|
||||
|
||||
uint32_t crc_calc = 0xffffffff;
|
||||
for (int i = 0; i < (count * size); i++)
|
||||
crc_calc = adbg_compute_crc(crc_calc, data[i], 8);
|
||||
uint32_t crc_calc = crc32_le(CRC32_POLY_LE, 0xffffffff, data,
|
||||
count * size);
|
||||
|
||||
field[1].num_bits = count * size * 8;
|
||||
field[1].out_value = data;
|
||||
|
|
Loading…
Reference in New Issue