Skip to content

Commit 5371c10

Browse files
author
Cruz Monrreal
authored
Merge pull request #6708 from scartmell-arm/feature-hal-hardware-crc
Add Hardware CRC HAL API specification
2 parents 7031ab1 + 824466d commit 5371c10

File tree

7 files changed

+443
-54
lines changed

7 files changed

+443
-54
lines changed

doxyfile_options

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2069,6 +2069,7 @@ PREDEFINED = DOXYGEN_ONLY \
20692069
DEVICE_ANALOGIN \
20702070
DEVICE_ANALOGOUT \
20712071
DEVICE_CAN \
2072+
DEVICE_CRC \
20722073
DEVICE_ETHERNET \
20732074
DEVICE_EMAC \
20742075
DEVICE_ETH \

doxygen_options.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"SEARCH_INCLUDES": "YES",
77
"INCLUDE_PATH": "",
88
"INCLUDE_FILE_PATTERNS": "",
9-
"PREDEFINED": "DOXYGEN_ONLY DEVICE_ANALOGIN DEVICE_ANALOGOUT DEVICE_CAN DEVICE_ETHERNET DEVICE_EMAC DEVICE_FLASH DEVICE_I2C DEVICE_I2CSLAVE DEVICE_I2C_ASYNCH DEVICE_INTERRUPTIN DEVICE_ITM DEVICE_LOWPOWERTIMER DEVICE_PORTIN DEVICE_PORTINOUT DEVICE_PORTOUT DEVICE_PWMOUT DEVICE_RTC DEVICE_TRNG DEVICE_SERIAL DEVICE_SERIAL_ASYNCH DEVICE_SERIAL_FC DEVICE_SLEEP DEVICE_SPI DEVICE_SPI_ASYNCH DEVICE_SPISLAVE DEVICE_STORAGE \"MBED_DEPRECATED_SINCE(f, g)=\" \"MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, M)=\" \"MBED_DEPRECATED(s)=\"",
9+
"PREDEFINED": "DOXYGEN_ONLY DEVICE_ANALOGIN DEVICE_ANALOGOUT DEVICE_CAN DEVICE_CRC DEVICE_ETHERNET DEVICE_EMAC DEVICE_FLASH DEVICE_I2C DEVICE_I2CSLAVE DEVICE_I2C_ASYNCH DEVICE_INTERRUPTIN DEVICE_ITM DEVICE_LOWPOWERTIMER DEVICE_PORTIN DEVICE_PORTINOUT DEVICE_PORTOUT DEVICE_PWMOUT DEVICE_RTC DEVICE_TRNG DEVICE_SERIAL DEVICE_SERIAL_ASYNCH DEVICE_SERIAL_FC DEVICE_SLEEP DEVICE_SPI DEVICE_SPI_ASYNCH DEVICE_SPISLAVE DEVICE_STORAGE \"MBED_DEPRECATED_SINCE(f, g)=\" \"MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, M)=\" \"MBED_DEPRECATED(s)=\"",
1010
"EXPAND_AS_DEFINED": "",
1111
"SKIP_FUNCTION_MACROS": "NO",
1212
"STRIP_CODE_COMMENTS": "NO",

drivers/MbedCRC.h

Lines changed: 61 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
#ifndef MBED_CRC_API_H
1717
#define MBED_CRC_API_H
1818

19-
#include <stdint.h>
2019
#include "drivers/TableCRC.h"
20+
#include "hal/crc_api.h"
2121
#include "platform/mbed_assert.h"
2222

2323
/* This is invalid warning from the compiler for below section of code
@@ -38,19 +38,6 @@ namespace mbed {
3838
/** \addtogroup drivers */
3939
/** @{*/
4040

41-
/** CRC Polynomial value
42-
*
43-
* Different polynomial values supported
44-
*/
45-
typedef enum crc_polynomial {
46-
POLY_OTHER = 0,
47-
POLY_8BIT_CCITT = 0x07, // x8+x2+x+1
48-
POLY_7BIT_SD = 0x9, // x7+x3+1;
49-
POLY_16BIT_CCITT = 0x1021, // x16+x12+x5+1
50-
POLY_16BIT_IBM = 0x8005, // x16+x15+x2+1
51-
POLY_32BIT_ANSI = 0x04C11DB7, // x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
52-
} crc_polynomial_t;
53-
5441
/** CRC object provides CRC generation through hardware/software
5542
*
5643
* ROM polynomial tables for supported polynomials (:: crc_polynomial_t) will be used for
@@ -106,6 +93,9 @@ typedef enum crc_polynomial {
10693
template <uint32_t polynomial=POLY_32BIT_ANSI, uint8_t width=32>
10794
class MbedCRC
10895
{
96+
public:
97+
enum CrcMode { HARDWARE = 0, TABLE, BITWISE };
98+
10999
public:
110100
typedef uint64_t crc_data_size_t;
111101

@@ -178,13 +168,21 @@ class MbedCRC
178168
*/
179169
int32_t compute_partial(void *buffer, crc_data_size_t size, uint32_t *crc)
180170
{
181-
if (NULL == _crc_table) {
182-
// Compute bitwise CRC
183-
return bitwise_compute_partial(buffer, size, crc);
184-
} else {
185-
// Table CRC
186-
return table_compute_partial(buffer, size, crc);
171+
switch (_mode)
172+
{
173+
case HARDWARE:
174+
#ifdef DEVICE_CRC
175+
hal_crc_compute_partial((uint8_t *)buffer, size);
176+
#endif // DEVICE_CRC
177+
*crc = 0;
178+
return 0;
179+
case TABLE:
180+
return table_compute_partial(buffer, size, crc);
181+
case BITWISE:
182+
return bitwise_compute_partial(buffer, size, crc);
187183
}
184+
185+
return -1;
188186
}
189187

190188
/** Compute partial start, indicate start of partial computation
@@ -200,6 +198,21 @@ class MbedCRC
200198
int32_t compute_partial_start(uint32_t *crc)
201199
{
202200
MBED_ASSERT(crc != NULL);
201+
202+
#ifdef DEVICE_CRC
203+
if (_mode == HARDWARE) {
204+
crc_mbed_config_t config;
205+
config.polynomial = polynomial;
206+
config.width = width;
207+
config.initial_xor = _initial_value;
208+
config.final_xor = _final_xor;
209+
config.reflect_in = _reflect_data;
210+
config.reflect_out = _reflect_remainder;
211+
212+
hal_crc_compute_partial_start(&config);
213+
}
214+
#endif // DEVICE_CRC
215+
203216
*crc = _initial_value;
204217
return 0;
205218
}
@@ -215,6 +228,16 @@ class MbedCRC
215228
int32_t compute_partial_stop(uint32_t *crc)
216229
{
217230
MBED_ASSERT(crc != NULL);
231+
232+
if (_mode == HARDWARE) {
233+
#ifdef DEVICE_CRC
234+
*crc = hal_crc_get_result();
235+
return 0;
236+
#else
237+
return -1;
238+
#endif
239+
}
240+
218241
uint32_t p_crc = *crc;
219242
if ((width < 8) && (NULL == _crc_table)) {
220243
p_crc = (uint32_t)(p_crc << (8 - width));
@@ -247,6 +270,7 @@ class MbedCRC
247270
bool _reflect_data;
248271
bool _reflect_remainder;
249272
uint32_t *_crc_table;
273+
CrcMode _mode;
250274

251275
/** Get the current CRC data size
252276
*
@@ -408,9 +432,25 @@ class MbedCRC
408432
/** Constructor init called from all specialized cases of constructor
409433
* Note: All construtor common code should be in this function.
410434
*/
411-
void mbed_crc_ctor(void) const
435+
void mbed_crc_ctor(void)
412436
{
413437
MBED_STATIC_ASSERT(width <= 32, "Max 32-bit CRC supported");
438+
439+
_mode = (_crc_table != NULL) ? TABLE : BITWISE;
440+
441+
#ifdef DEVICE_CRC
442+
crc_mbed_config_t config;
443+
config.polynomial = polynomial;
444+
config.width = width;
445+
config.initial_xor = _initial_value;
446+
config.final_xor = _final_xor;
447+
config.reflect_in = _reflect_data;
448+
config.reflect_out = _reflect_remainder;
449+
450+
if (hal_crc_is_supported(&config)) {
451+
_mode = HARDWARE;
452+
}
453+
#endif
414454
}
415455
};
416456

hal/crc_api.h

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
/** \addtogroup hal */
2+
/** @{*/
3+
/* mbed Microcontroller Library
4+
* Copyright (c) 2018 ARM Limited
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
#ifndef MBED_CRC_HAL_API_H
19+
#define MBED_CRC_HAL_API_H
20+
21+
#include <stdbool.h>
22+
#include <stddef.h>
23+
#include <stdint.h>
24+
25+
/** CRC Polynomial value
26+
*
27+
* Different polynomial values supported
28+
*/
29+
typedef enum crc_polynomial {
30+
POLY_OTHER = 0,
31+
POLY_8BIT_CCITT = 0x07, // x8+x2+x+1
32+
POLY_7BIT_SD = 0x9, // x7+x3+1;
33+
POLY_16BIT_CCITT = 0x1021, // x16+x12+x5+1
34+
POLY_16BIT_IBM = 0x8005, // x16+x15+x2+1
35+
POLY_32BIT_ANSI = 0x04C11DB7, // x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
36+
} crc_polynomial_t;
37+
38+
typedef struct crc_mbed_config {
39+
/** CRC Polynomial. Example polynomial: 0x21 = 0010_0011 = x^5+x+1 */
40+
uint32_t polynomial;
41+
/** CRC Bit Width */
42+
uint32_t width;
43+
/** Initial seed value for the computation. */
44+
uint32_t initial_xor;
45+
/** Final xor value for the computation. */
46+
uint32_t final_xor;
47+
/** Reflect bits on input. */
48+
bool reflect_in;
49+
/** Reflect bits in final result before returning. */
50+
bool reflect_out;
51+
} crc_mbed_config_t;
52+
53+
#ifdef DEVICE_CRC
54+
55+
#ifdef __cplusplus
56+
extern "C" {
57+
#endif
58+
59+
/**
60+
* \defgroup hal_crc Hardware CRC
61+
*
62+
* The Hardware CRC HAL API provides a low-level interface to the Hardware CRC
63+
* module of a target platform.
64+
*
65+
* @{
66+
*/
67+
68+
/** Determine if the current platform supports hardware CRC for given polynomial
69+
*
70+
* The purpose of this function is to inform the CRC Platform API whether the
71+
* current platform has a hardware CRC module and that it can support the
72+
* requested polynomial.
73+
*
74+
* Supported polynomials are restricted to the named polynomials that can be
75+
* constructed in the MbedCRC class, POLY_8BIT_CCITT, POLY_7BIT_SD,
76+
* POLY_16BIT_CCITT, POLY_16BIT_IBM and POLY_32BIT_ANSI.
77+
*
78+
* The current platform must support the given polynomials default parameters
79+
* in order to return a true response. These include: reflect in, reflect out,
80+
* initial xor and final xor. For example, POLY_32BIT_ANSI requires an initial
81+
* and final xor of 0xFFFFFFFF, and reflection of both input and output. If any
82+
* of these settings cannot be configured, the polynomial is not supported.
83+
*
84+
* This function is thread safe; it safe to call from multiple contexts if
85+
* required.
86+
*
87+
* \param config Contains CRC configuration parameters for initializing the
88+
* hardware CRC module. For example, polynomial and initial seed
89+
* values.
90+
*
91+
* \return True if running if the polynomial is supported, false if not.
92+
*/
93+
bool hal_crc_is_supported(const crc_mbed_config_t* config);
94+
95+
/** Initialize the hardware CRC module with the given polynomial
96+
*
97+
* After calling this function, the CRC HAL module is ready to receive data
98+
* using the hal_crc_compute_partial() function. The CRC module on the board
99+
* is configured internally with the specified configuration and is ready
100+
* to receive data.
101+
*
102+
* The platform configures itself based on the default configuration
103+
* parameters of the input polynomial.
104+
*
105+
* This function must be called before calling hal_crc_compute_partial().
106+
*
107+
* This function must be called with a valid polynomial supported by the
108+
* platform. The polynomial must be checked for support using the
109+
* hal_crc_is_supported() function.
110+
*
111+
* Calling hal_crc_compute_partial_start() multiple times without finalizing the
112+
* CRC calculation with hal_crc_get_result() overrides the current
113+
* configuration and state, and the intermediate result of the computation is
114+
* lost.
115+
*
116+
* This function is not thread safe. A CRC calculation must not be started from
117+
* two different threads or contexts at the same time; calling this function
118+
* from two different contexts may lead to configurations being overwritten and
119+
* results being lost.
120+
*
121+
* \param config Contains CRC configuration parameters for initializing the
122+
* hardware CRC module. For example, polynomial and initial seed
123+
* values.
124+
*/
125+
void hal_crc_compute_partial_start(const crc_mbed_config_t* config);
126+
127+
/** Writes data to the current CRC module.
128+
*
129+
* Writes input data buffer bytes to the CRC data register. The CRC module
130+
* must interpret the data as an array of bytes.
131+
*
132+
* The final transformations are not applied to the data; the CRC module must
133+
* retain the intermediate result so that additional calls to this function
134+
* can be made, appending the additional data to the calculation.
135+
*
136+
* To obtain the final result of the CRC calculation, hal_crc_get_result() is
137+
* called to apply the final transformations to the data.
138+
*
139+
* If the function is passed an undefined pointer, or the size of the buffer is
140+
* specified to be 0, this function does nothing and returns.
141+
*
142+
* This function can be called multiple times in succession. This can be used
143+
* to calculate the CRC result of streamed data.
144+
*
145+
* This function is not thread safe. There is only one instance of the CRC
146+
* module active at a time. Calling this function from multiple contexts
147+
* appends different data to the same, single instance of the module, which causes an
148+
* erroneous value to be calculated.
149+
*
150+
* \param data Input data stream to be written into the CRC calculation
151+
* \param size Size of the data stream in bytes
152+
*/
153+
void hal_crc_compute_partial(const uint8_t *data, const size_t size);
154+
155+
/* Reads the checksum result from the CRC module.
156+
*
157+
* Reads the final checksum result for the final checksum value. The returned
158+
* value is cast as an unsigned 32-bit integer. The actual size of the returned
159+
* result depends on the polynomial used to configure the CRC module.
160+
*
161+
* Additional transformations that are used in the default configuration of the
162+
* input polynomial are applied to the result before it is returned from this
163+
* function. These transformations include: the final xor being appended to the
164+
* calculation, and the result being reflected if required.
165+
*
166+
* Calling this function multiple times is undefined. The first call to this
167+
* function returns the final result of the CRC calculation. The return
168+
* value on successive calls is undefined because the contents of the register after
169+
* accessing them is platform-specific.
170+
*
171+
* This function is not thread safe. There is only one instance of the CRC
172+
* module active at a time. Calling this function from multiple contexts may
173+
* return incorrect data or affect the current state of the module.
174+
*
175+
* \return The final CRC checksum after the reflections and final calculations
176+
* have been applied.
177+
*/
178+
uint32_t hal_crc_get_result(void);
179+
180+
/**@}*/
181+
182+
#ifdef __cplusplus
183+
};
184+
#endif
185+
186+
#endif // DEVICE_CRC
187+
#endif // MBED_CRC_HAL_API_H
188+
189+
/**@}*/

0 commit comments

Comments
 (0)