mirror of
https://github.com/espressif/esp-idf.git
synced 2026-08-11 17:52:00 +03:00
Merge branch 'docs/esp_crc_rom_api' into 'master'
fix(esp_crc): clarify CRC ROM helper usage documentation Closes IDFGH-17804 See merge request espressif/esp-idf!50177
This commit is contained in:
@@ -210,3 +210,78 @@ TEST_CASE("async_crc multiple requests", "[async_crc]")
|
||||
TEST_ESP_OK(esp_async_crc_uninstall(driver));
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint32_t test_rom_crc32_le_reference(const uint8_t *data, size_t len)
|
||||
{
|
||||
uint32_t crc = (uint32_t)~UINT32_MAX;
|
||||
|
||||
crc = esp_crc32_le(crc, data, len);
|
||||
|
||||
return ~crc ^ UINT32_MAX;
|
||||
}
|
||||
|
||||
static uint16_t test_rom_crc16_xmodem_reference(const uint8_t *data, size_t len)
|
||||
{
|
||||
uint16_t crc = (uint16_t)~0x0000;
|
||||
|
||||
crc = esp_crc16_be(crc, data, len);
|
||||
|
||||
return (uint16_t)(~crc ^ 0x0000);
|
||||
}
|
||||
|
||||
static void test_async_crc_matches_rom_helper(async_crc_handle_t driver, bool supports_crc32)
|
||||
{
|
||||
static const char test_input_string[] __attribute__((aligned(16))) = "GDMACRC::TEST::LONGSTRING::REPEAT::GDMACRC::TEST::LONGSTRING::REPEAT::GDMACRC::TEST::LONGSTRING::REPEAT::GDMACRC::TEST::LONGSTRING::REPEAT::END!";
|
||||
size_t input_len = strlen(test_input_string);
|
||||
uint32_t async_result = 0;
|
||||
|
||||
if (supports_crc32) {
|
||||
async_crc_params_t crc32_params = {
|
||||
.width = 32,
|
||||
.polynomial = 0x04C11DB7,
|
||||
.init_value = UINT32_MAX,
|
||||
.final_xor_value = UINT32_MAX,
|
||||
.reverse_input = true,
|
||||
.reverse_output = true,
|
||||
};
|
||||
uint32_t crc32_rom_result = test_rom_crc32_le_reference((const uint8_t *)test_input_string, input_len);
|
||||
TEST_ESP_OK(esp_crc_calc_blocking(driver, test_input_string, input_len, &crc32_params, -1, &async_result));
|
||||
printf("CRC-32 async result: 0x%"PRIx32", ROM helper result: 0x%"PRIx32"\r\n", async_result, crc32_rom_result);
|
||||
TEST_ASSERT_EQUAL_HEX32(crc32_rom_result, async_result);
|
||||
}
|
||||
|
||||
async_crc_params_t crc16_params = {
|
||||
.width = 16,
|
||||
.polynomial = 0x1021,
|
||||
.init_value = 0x0000,
|
||||
.final_xor_value = 0x0000,
|
||||
.reverse_input = false,
|
||||
.reverse_output = false,
|
||||
};
|
||||
uint16_t crc16_rom_result = test_rom_crc16_xmodem_reference((const uint8_t *)test_input_string, input_len);
|
||||
TEST_ESP_OK(esp_crc_calc_blocking(driver, test_input_string, input_len, &crc16_params, -1, &async_result));
|
||||
printf("CRC-16/XMODEM async result: 0x%"PRIx32", ROM helper result: 0x%04x\r\n", async_result, crc16_rom_result);
|
||||
TEST_ASSERT_EQUAL_HEX16(crc16_rom_result, async_result);
|
||||
}
|
||||
|
||||
TEST_CASE("async_crc matches ROM helper results for standard CRC flavors", "[async_crc]")
|
||||
{
|
||||
async_crc_config_t config = {
|
||||
.backlog = 1,
|
||||
.dma_burst_size = 16,
|
||||
};
|
||||
async_crc_handle_t driver = NULL;
|
||||
#if SOC_HAS(AHB_GDMA)
|
||||
printf("Testing async CRC against ROM helper by AHB GDMA\r\n");
|
||||
TEST_ESP_OK(esp_async_crc_install_gdma_ahb(&config, &driver));
|
||||
test_async_crc_matches_rom_helper(driver, true);
|
||||
TEST_ESP_OK(esp_async_crc_uninstall(driver));
|
||||
#endif
|
||||
|
||||
#if SOC_HAS(AXI_GDMA)
|
||||
printf("Testing async CRC against ROM helper by AXI GDMA\r\n");
|
||||
TEST_ESP_OK(esp_async_crc_install_gdma_axi(&config, &driver));
|
||||
test_async_crc_matches_rom_helper(driver, false);
|
||||
TEST_ESP_OK(esp_async_crc_uninstall(driver));
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -14,10 +14,25 @@ extern "C" {
|
||||
// This header is only a wrapper on ROM CRC API
|
||||
#include "esp_rom_crc.h"
|
||||
|
||||
/**
|
||||
* @brief Convenience wrappers for the ROM CRC helpers.
|
||||
*
|
||||
* These wrappers keep the ROM helper behavior unchanged: each call bitwise
|
||||
* inverts the CRC value before and after processing. To start a calculation,
|
||||
* pass the bitwise inverse of the CRC flavor's initial value. To continue over
|
||||
* another buffer, pass the previous return value. After the last chunk, bitwise
|
||||
* invert the return value again and then apply the CRC flavor's final XOR.
|
||||
*
|
||||
* The correct initial value and final XOR depend on the CRC flavor that you are
|
||||
* implementing, so there is no single universal `INITIAL` or `FINAL_XOR`
|
||||
* constant for a given helper.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief CRC32 value in little endian.
|
||||
*
|
||||
* @param crc: Initial CRC value (result of last calculation or 0 for the first time)
|
||||
* @param crc: Bitwise inverse of the CRC variant's initial value on the first
|
||||
* call, or the previous return value to continue a calculation
|
||||
* @param buf: Data buffer that used to calculate the CRC value
|
||||
* @param len: Length of the data buffer
|
||||
* @return CRC32 value
|
||||
@@ -30,7 +45,8 @@ static inline uint32_t esp_crc32_le(uint32_t crc, uint8_t const *buf, uint32_t l
|
||||
/**
|
||||
* @brief CRC32 value in big endian.
|
||||
*
|
||||
* @param crc: Initial CRC value (result of last calculation or 0 for the first time)
|
||||
* @param crc: Bitwise inverse of the CRC variant's initial value on the first
|
||||
* call, or the previous return value to continue a calculation
|
||||
* @param buf: Data buffer that used to calculate the CRC value
|
||||
* @param len: Length of the data buffer
|
||||
* @return CRC32 value
|
||||
@@ -43,7 +59,8 @@ static inline uint32_t esp_crc32_be(uint32_t crc, uint8_t const *buf, uint32_t l
|
||||
/**
|
||||
* @brief CRC16 value in little endian.
|
||||
*
|
||||
* @param crc: Initial CRC value (result of last calculation or 0 for the first time)
|
||||
* @param crc: Bitwise inverse of the CRC variant's initial value on the first
|
||||
* call, or the previous return value to continue a calculation
|
||||
* @param buf: Data buffer that used to calculate the CRC value
|
||||
* @param len: Length of the data buffer
|
||||
* @return CRC16 value
|
||||
@@ -56,7 +73,8 @@ static inline uint16_t esp_crc16_le(uint16_t crc, uint8_t const *buf, uint32_t l
|
||||
/**
|
||||
* @brief CRC16 value in big endian.
|
||||
*
|
||||
* @param crc: Initial CRC value (result of last calculation or 0 for the first time)
|
||||
* @param crc: Bitwise inverse of the CRC variant's initial value on the first
|
||||
* call, or the previous return value to continue a calculation
|
||||
* @param buf: Data buffer that used to calculate the CRC value
|
||||
* @param len: Length of the data buffer
|
||||
* @return CRC16 value
|
||||
@@ -69,7 +87,8 @@ static inline uint16_t esp_crc16_be(uint16_t crc, uint8_t const *buf, uint32_t l
|
||||
/**
|
||||
* @brief CRC8 value in little endian.
|
||||
*
|
||||
* @param crc: Initial CRC value (result of last calculation or 0 for the first time)
|
||||
* @param crc: Bitwise inverse of the CRC variant's initial value on the first
|
||||
* call, or the previous return value to continue a calculation
|
||||
* @param buf: Data buffer that used to calculate the CRC value
|
||||
* @param len: Length of the data buffer
|
||||
* @return CRC8 value
|
||||
@@ -82,7 +101,8 @@ static inline uint8_t esp_crc8_le(uint8_t crc, uint8_t const *buf, uint32_t len)
|
||||
/**
|
||||
* @brief CRC8 value in big endian.
|
||||
*
|
||||
* @param crc: Initial CRC value (result of last calculation or 0 for the first time)
|
||||
* @param crc: Bitwise inverse of the CRC variant's initial value on the first
|
||||
* call, or the previous return value to continue a calculation
|
||||
* @param buf: Data buffer that used to calculate the CRC value
|
||||
* @param len: Length of the data buffer
|
||||
* @return CRC8 value
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "unity.h"
|
||||
#include "esp_crc.h"
|
||||
#include "esp_random.h"
|
||||
|
||||
/* Note: these are just sanity tests, the implementation of esp_random() relies on getentropy() on Linux.
|
||||
@@ -123,6 +124,32 @@ TEST_CASE("esp_fill_random() fills exactly 257 bytes", "[random]")
|
||||
TEST_ASSERT_GREATER_THAN(0, one_buf[0]);
|
||||
}
|
||||
|
||||
TEST_CASE("esp_crc32_le supports continuous buffers with standard CRC-32 parameters", "[crc]")
|
||||
{
|
||||
static const uint8_t buf0[] = "1234";
|
||||
static const uint8_t buf1[] = "56789";
|
||||
uint32_t crc = (uint32_t)~UINT32_MAX;
|
||||
|
||||
crc = esp_crc32_le(crc, buf0, sizeof(buf0) - 1);
|
||||
crc = esp_crc32_le(crc, buf1, sizeof(buf1) - 1);
|
||||
crc = ~crc ^ UINT32_MAX;
|
||||
|
||||
TEST_ASSERT_EQUAL_HEX32(0xCBF43926, crc);
|
||||
}
|
||||
|
||||
TEST_CASE("esp_crc16_be supports continuous buffers with CRC-16/XMODEM parameters", "[crc]")
|
||||
{
|
||||
static const uint8_t buf0[] = "1234";
|
||||
static const uint8_t buf1[] = "56789";
|
||||
uint16_t crc = (uint16_t)~0x0000;
|
||||
|
||||
crc = esp_crc16_be(crc, buf0, sizeof(buf0) - 1);
|
||||
crc = esp_crc16_be(crc, buf1, sizeof(buf1) - 1);
|
||||
crc = (uint16_t)(~crc ^ 0x0000);
|
||||
|
||||
TEST_ASSERT_EQUAL_HEX16(0x31C3, crc);
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
printf("Running hw support linux API host test app");
|
||||
|
||||
@@ -1,16 +1,8 @@
|
||||
// Copyright 2010-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// 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.
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2010-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
@@ -21,48 +13,49 @@ extern "C" {
|
||||
#include <stdint.h>
|
||||
|
||||
/** Notes about CRC API
|
||||
* The ESP32 ROM include some CRC tables and CRC APIs to speed up CRC calculation.
|
||||
* The CRC APIs include CRC8, CRC16, CRC32 algorithms for both little endian and big endian modes.
|
||||
* Here are the polynomials for the algorithms:
|
||||
* The ROM CRC helpers accelerate CRC-8, CRC-16, and CRC-32 calculations for
|
||||
* the following base polynomials:
|
||||
* CRC-8 x8+x2+x1+1 0x07
|
||||
* CRC16-CCITT x16+x12+x5+1 0x1021
|
||||
* CRC32 x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x1+1 0x04c11db7
|
||||
*
|
||||
* These group of CRC APIs are designed to calculate the data in buffers either continuous or not.
|
||||
* To make it easy, we had added a `~` at the beginning and the end of the functions.
|
||||
* To calculate non-continuous buffers, we can write the code like this:
|
||||
* init = ~init;
|
||||
* crc = crc32_le(init, buf0, length0);
|
||||
* The `_le` and `_be` suffixes describe the bit processing order:
|
||||
* - use the little-endian helper when `refin == true` and `refout == true`
|
||||
* - use the big-endian helper when `refin == false` and `refout == false`
|
||||
*
|
||||
* These helpers invert the CRC register before and after processing each call.
|
||||
* As a result:
|
||||
* - the first call must receive the bitwise inverse of the CRC variant's
|
||||
* initial value
|
||||
* - each later call must receive the previous helper's return value so
|
||||
* non-contiguous buffers can be chained
|
||||
* - the final CRC value must be bitwise inverted again before applying the
|
||||
* CRC variant's `xorout`
|
||||
*
|
||||
* The initial value and final XOR depend on the CRC flavor that you are
|
||||
* implementing, so these helpers do not define a single universal
|
||||
* INITIAL/FINAL_XOR pair.
|
||||
*
|
||||
* Example for a CRC-32 flavor with `init = 0xffffffff`, `refin = true`,
|
||||
* `refout = true`, `xorout = 0xffffffff`:
|
||||
* uint32_t crc = (uint32_t)~0xffffffff;
|
||||
* crc = crc32_le(crc, buf0, length0);
|
||||
* crc = crc32_le(crc, buf1, length1);
|
||||
* crc = ~crc;
|
||||
*
|
||||
* However, it is not easy to select which API to use and give the correct parameters.
|
||||
* A specific CRC algorithm will include this parameters: width, polynomials, init, refin, refout, xorout
|
||||
* refin and refout show the endian of the algorithm:
|
||||
* if both of them are true, please use the little endian API.
|
||||
* if both of them are false, please use the big endian API.
|
||||
* xorout is the value which you need to be xored to the raw result.
|
||||
* However, these group of APIs need one '~' before and after the APIs.
|
||||
*
|
||||
* Here are some examples for CRC16:
|
||||
* CRC-16/CCITT, poly = 0x1021, init = 0x0000, refin = true, refout = true, xorout = 0x0000
|
||||
* crc = ~crc16_le((uint16_t)~0x0000, buf, length);
|
||||
*
|
||||
* CRC-16/CCITT-FALSE, poly = 0x1021, init = 0xffff, refin = false, refout = false, xorout = 0x0000
|
||||
* crc = ~crc16_be((uint16_t)~0xffff, buf, length);
|
||||
*
|
||||
* CRC-16/X25, poly = 0x1021, init = 0xffff, refin = true, refout = true, xorout = 0xffff
|
||||
* crc = (~crc16_le((uint16_t)~(0xffff), buf, length))^0xffff;
|
||||
*
|
||||
* CRC-16/XMODEM, poly= 0x1021, init = 0x0000, refin = false, refout = false, xorout = 0x0000
|
||||
* crc = ~crc16_be((uint16_t)~0x0000, buf, length);
|
||||
* crc = ~crc ^ 0xffffffff;
|
||||
*
|
||||
* Example for CRC-16/XMODEM with `init = 0x0000`, `refin = false`,
|
||||
* `refout = false`, `xorout = 0x0000`:
|
||||
* uint16_t crc = (uint16_t)~0x0000;
|
||||
* crc = crc16_be(crc, buf0, length0);
|
||||
* crc = crc16_be(crc, buf1, length1);
|
||||
* crc = (uint16_t)(~crc ^ 0x0000);
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief CRC32 value in little endian.
|
||||
*
|
||||
* @param crc: Initial CRC value (result of last calculation or 0 for the first time)
|
||||
* @param crc: Bitwise inverse of the CRC variant's initial value on the first
|
||||
* call, or the previous return value to continue a calculation
|
||||
* @param buf: Data buffer that used to calculate the CRC value
|
||||
* @param len: Length of the data buffer
|
||||
* @return CRC32 value
|
||||
@@ -72,7 +65,8 @@ uint32_t esp_rom_crc32_le(uint32_t crc, uint8_t const *buf, uint32_t len);
|
||||
/**
|
||||
* @brief CRC32 value in big endian.
|
||||
*
|
||||
* @param crc: Initial CRC value (result of last calculation or 0 for the first time)
|
||||
* @param crc: Bitwise inverse of the CRC variant's initial value on the first
|
||||
* call, or the previous return value to continue a calculation
|
||||
* @param buf: Data buffer that used to calculate the CRC value
|
||||
* @param len: Length of the data buffer
|
||||
* @return CRC32 value
|
||||
@@ -82,7 +76,8 @@ uint32_t esp_rom_crc32_be(uint32_t crc, uint8_t const *buf, uint32_t len);
|
||||
/**
|
||||
* @brief CRC16 value in little endian.
|
||||
*
|
||||
* @param crc: Initial CRC value (result of last calculation or 0 for the first time)
|
||||
* @param crc: Bitwise inverse of the CRC variant's initial value on the first
|
||||
* call, or the previous return value to continue a calculation
|
||||
* @param buf: Data buffer that used to calculate the CRC value
|
||||
* @param len: Length of the data buffer
|
||||
* @return CRC16 value
|
||||
@@ -92,7 +87,8 @@ uint16_t esp_rom_crc16_le(uint16_t crc, uint8_t const *buf, uint32_t len);
|
||||
/**
|
||||
* @brief CRC16 value in big endian.
|
||||
*
|
||||
* @param crc: Initial CRC value (result of last calculation or 0 for the first time)
|
||||
* @param crc: Bitwise inverse of the CRC variant's initial value on the first
|
||||
* call, or the previous return value to continue a calculation
|
||||
* @param buf: Data buffer that used to calculate the CRC value
|
||||
* @param len: Length of the data buffer
|
||||
* @return CRC16 value
|
||||
@@ -102,7 +98,8 @@ uint16_t esp_rom_crc16_be(uint16_t crc, uint8_t const *buf, uint32_t len);
|
||||
/**
|
||||
* @brief CRC8 value in little endian.
|
||||
*
|
||||
* @param crc: Initial CRC value (result of last calculation or 0 for the first time)
|
||||
* @param crc: Bitwise inverse of the CRC variant's initial value on the first
|
||||
* call, or the previous return value to continue a calculation
|
||||
* @param buf: Data buffer that used to calculate the CRC value
|
||||
* @param len: Length of the data buffer
|
||||
* @return CRC8 value
|
||||
@@ -112,7 +109,8 @@ uint8_t esp_rom_crc8_le(uint8_t crc, uint8_t const *buf, uint32_t len);
|
||||
/**
|
||||
* @brief CRC8 value in big endian.
|
||||
*
|
||||
* @param crc: Initial CRC value (result of last calculation or 0 for the first time)
|
||||
* @param crc: Bitwise inverse of the CRC variant's initial value on the first
|
||||
* call, or the previous return value to continue a calculation
|
||||
* @param buf: Data buffer that used to calculate the CRC value
|
||||
* @param len: Length of the data buffer
|
||||
* @return CRC8 value
|
||||
|
||||
@@ -1,16 +1,8 @@
|
||||
// Copyright 2010-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// 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.
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2010-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "esp_rom_caps.h"
|
||||
|
||||
@@ -409,10 +409,8 @@ components/esp_rom/esp32s3/ld/esp32s3.rom.ld
|
||||
components/esp_rom/esp32s3/ld/esp32s3.rom.libgcc.ld
|
||||
components/esp_rom/esp32s3/ld/esp32s3.rom.newlib-nano.ld
|
||||
components/esp_rom/esp32s3/ld/esp32s3.rom.version.ld
|
||||
components/esp_rom/include/esp_rom_crc.h
|
||||
components/esp_rom/linux/esp_rom_crc.c
|
||||
components/esp_rom/linux/esp_rom_md5.c
|
||||
components/esp_rom/patches/esp_rom_crc.c
|
||||
components/esp_rom/patches/esp_rom_longjmp.S
|
||||
components/esp_system/ubsan.c
|
||||
components/esp_wifi/src/mesh_event.c
|
||||
|
||||
Reference in New Issue
Block a user