Commit 127c1087 authored by Duy Vo's avatar Duy Vo Committed by Benjamin Cabé
Browse files

tests: drivers: crc: add ztests for CRC driver



Add ztests for CRC driver

Signed-off-by: default avatarDuy Vo <duy.vo.xc@bp.renesas.com>
parent e5dbc1d1
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})

project(drivers_crc_test)

target_sources(app PRIVATE src/main.c)
+3 −0
Original line number Diff line number Diff line
CONFIG_ZTEST=y
CONFIG_CRC=y
CONFIG_CRC_LOG_LEVEL_INF=y
+329 −0
Original line number Diff line number Diff line
/*
 * Copyright (c) 2025 Renesas Electronics Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/drivers/crc.h>

#include <zephyr/device.h>
#include <zephyr/ztest.h>
#include <zephyr/logging/log.h>

#define WAIT_THREAD_STACK_SIZE 1024
#define WAIT_THREAD_PRIO       -10

static void wait_thread_entry(void *a, void *b, void *c);

K_THREAD_STACK_DEFINE(wait_thread_stack_area, WAIT_THREAD_STACK_SIZE);
struct k_thread wait_thread_data;

/* Define result of CRC computation */
#define RESULT_CRC_16_THREADSAFE 0xD543

/**
 * 1) Take the semaphore
 * 2) Sleep for 50 ms (to allow ztest main thread to attempt to acquire semaphore)
 * 3) Give the semaphore
 */
static void wait_thread_entry(void *a, void *b, void *c)
{
	static const struct device *dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_crc));

	uint8_t data[8] = {0x0A, 0x2B, 0x4C, 0x6D, 0x8E, 0x49, 0x00, 0xC4};

	struct crc_ctx ctx = {
		.type = CRC16,
		.polynomial = CRC16_POLY,
		.seed = CRC16_INIT_VAL,
		.reversed = CRC_FLAG_REVERSE_OUTPUT | CRC_FLAG_REVERSE_INPUT,
	};

	crc_begin(dev, &ctx);

	k_sleep(K_MSEC(50));

	crc_update(dev, &ctx, data, sizeof(data));
	crc_finish(dev, &ctx);
	zassert_equal(crc_verify(&ctx, RESULT_CRC_16_THREADSAFE), 0);
}

/* Define result of CRC computation */
#define RESULT_CRC_8 0xB2

/**
 * @brief Test that crc8 works
 */
ZTEST(crc, test_crc_8)
{
	static const struct device *dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_crc));

	uint8_t data[8] = {0x0A, 0x2B, 0x4C, 0x6D, 0x8E, 0x49, 0x00, 0xC4};

	struct crc_ctx ctx = {
		.type = CRC8,
		.polynomial = CRC8_POLY,
		.seed = CRC8_INIT_VAL,
		.reversed = CRC_FLAG_REVERSE_OUTPUT | CRC_FLAG_REVERSE_INPUT,
	};

	crc_begin(dev, &ctx);

	k_sleep(K_MSEC(50));

	crc_update(dev, &ctx, data, sizeof(data));
	crc_finish(dev, &ctx);
	zassert_equal(crc_verify(&ctx, RESULT_CRC_8), 0);
}

/* Define result of CRC computation */
#define RESULT_CRC_16 0xD543

/**
 * @brief Test that crc16 works
 */
ZTEST(crc, test_crc_16)
{
	static const struct device *dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_crc));

	uint8_t data[8] = {0x0A, 0x2B, 0x4C, 0x6D, 0x8E, 0x49, 0x00, 0xC4};

	struct crc_ctx ctx = {
		.type = CRC16,
		.polynomial = CRC16_POLY,
		.seed = CRC16_INIT_VAL,
		.reversed = CRC_FLAG_REVERSE_OUTPUT | CRC_FLAG_REVERSE_INPUT,
	};

	zassert_equal(crc_begin(dev, &ctx), 0);
	zassert_equal(crc_update(dev, &ctx, data, sizeof(data)), 0);
	zassert_equal(crc_finish(dev, &ctx), 0);

	zassert_equal(crc_verify(&ctx, RESULT_CRC_16), 0);
}

/* Define result of CRC computation */
#define RESULT_CRC_CCITT 0x445C

/**
 * @brief Test that crc_16_ccitt works
 */
ZTEST(crc, test_crc_16_ccitt)
{
	static const struct device *dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_crc));

	uint8_t data[8] = {0x0A, 0x2B, 0x4C, 0x6D, 0x8E, 0x49, 0x00, 0xC4};

	struct crc_ctx ctx = {
		.type = CRC16_CCITT,
		.polynomial = CRC16_CCITT_POLY,
		.seed = CRC16_CCITT_INIT_VAL,
		.reversed = CRC_FLAG_REVERSE_OUTPUT | CRC_FLAG_REVERSE_INPUT,
	};

	zassert_equal(crc_begin(dev, &ctx), 0);
	zassert_equal(crc_update(dev, &ctx, data, sizeof(data)), 0);
	zassert_equal(crc_finish(dev, &ctx), 0);

	zassert_equal(crc_verify(&ctx, RESULT_CRC_CCITT), 0);
}

/* Define result of CRC computation */
#define RESULT_CRC_32_C 0xBB19ECB2

/**
 * @brief Test that crc_32_c works
 */
ZTEST(crc, test_crc_32_c)
{
	static const struct device *dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_crc));

	uint8_t data[8] = {0x0A, 0x2B, 0x4C, 0x6D, 0x8E, 0x49, 0x00, 0xC4};

	struct crc_ctx ctx = {
		.type = CRC32_C,
		.polynomial = CRC32C_POLY,
		.seed = CRC32_C_INIT_VAL,
		.reversed = CRC_FLAG_REVERSE_OUTPUT | CRC_FLAG_REVERSE_INPUT,
	};

	zassert_equal(crc_begin(dev, &ctx), 0);
	zassert_equal(crc_update(dev, &ctx, data, sizeof(data)), 0);
	zassert_equal(crc_finish(dev, &ctx), 0);

	zassert_equal(crc_verify(&ctx, RESULT_CRC_32_C), 0);
}

/* Define result of CRC computation */
#define RESULT_CRC_32_IEEE 0xCEA4A6C2

/**
 * @brief Test that crc_32_ieee works
 */
ZTEST(crc, test_crc_32_ieee)
{
	static const struct device *dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_crc));

	uint8_t data[8] = {0x0A, 0x2B, 0x4C, 0x6D, 0x8E, 0x49, 0x00, 0xC4};
	struct crc_ctx ctx = {
		.type = CRC32_IEEE,
		.polynomial = CRC32_IEEE_POLY,
		.seed = CRC32_IEEE_INIT_VAL,
		.reversed = CRC_FLAG_REVERSE_OUTPUT | CRC_FLAG_REVERSE_INPUT,
	};

	zassert_equal(crc_begin(dev, &ctx), 0);
	zassert_equal(crc_update(dev, &ctx, data, sizeof(data)), 0);
	zassert_equal(crc_finish(dev, &ctx), 0);
	zassert_equal(crc_verify(&ctx, RESULT_CRC_32_IEEE), 0);
}

/* Define result of CRC computation */
#define RESULT_CRC_8_REMAIN_3 0xBB

/**
 * @brief Test that crc_8_remain_3 works
 */
ZTEST(crc, test_crc_8_remain_3)
{
	static const struct device *dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_crc));

	uint8_t data[11] = {0x0A, 0x2B, 0x4C, 0x6D, 0x8E, 0x49, 0x00, 0xC4, 0x3D, 0x4D, 0x51};

	struct crc_ctx ctx = {
		.type = CRC8,
		.polynomial = CRC8_POLY,
		.seed = CRC8_INIT_VAL,
		.reversed = CRC_FLAG_REVERSE_OUTPUT | CRC_FLAG_REVERSE_INPUT,
	};

	zassert_equal(crc_begin(dev, &ctx), 0);
	zassert_equal(crc_update(dev, &ctx, data, sizeof(data)), 0);
	zassert_equal(crc_finish(dev, &ctx), 0);
	zassert_equal(crc_verify(&ctx, RESULT_CRC_8_REMAIN_3), 0);
}

/* Define result of CRC computation */
#define RESULT_CRC_16_REMAIN_1 0x2055

/**
 * @brief Test that crc_16_remain_1 works
 */
ZTEST(crc, test_crc_16_remain_1)
{
	static const struct device *dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_crc));

	uint8_t data[9] = {0x0A, 0x2B, 0x4C, 0x6D, 0x8E, 0x49, 0x00, 0xC4, 0x3D};

	struct crc_ctx ctx = {
		.type = CRC16,
		.polynomial = CRC16_POLY,
		.seed = CRC16_INIT_VAL,
		.reversed = CRC_FLAG_REVERSE_OUTPUT | CRC_FLAG_REVERSE_INPUT,
	};

	zassert_equal(crc_begin(dev, &ctx), 0);
	zassert_equal(crc_update(dev, &ctx, data, sizeof(data)), 0);
	zassert_equal(crc_finish(dev, &ctx), 0);

	zassert_equal(crc_verify(&ctx, RESULT_CRC_16_REMAIN_1), 0);
}

/* Define result of CRC computation */
#define RESULT_CRC_CCITT_REMAIN_2 0x24BD

/**
 * @brief Test that crc_16_ccitt works
 */
ZTEST(crc, test_crc_16_ccitt_remain_2)
{
	static const struct device *dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_crc));

	uint8_t data[10] = {0x0A, 0x2B, 0x4C, 0x6D, 0x8E, 0x49, 0x00, 0xC4, 0xFF, 0xA0};

	struct crc_ctx ctx = {
		.type = CRC16_CCITT,
		.polynomial = CRC16_CCITT_POLY,
		.seed = CRC16_CCITT_INIT_VAL,
		.reversed = CRC_FLAG_REVERSE_OUTPUT | CRC_FLAG_REVERSE_INPUT,
	};

	zassert_equal(crc_begin(dev, &ctx), 0);
	zassert_equal(crc_update(dev, &ctx, data, sizeof(data)), 0);
	zassert_equal(crc_finish(dev, &ctx), 0);

	zassert_equal(crc_verify(&ctx, RESULT_CRC_CCITT_REMAIN_2), 0);
}

/* Define result of CRC computation */
#define RESULT_DISCONTINUOUS_BUFFER 0x75

/**
 * @brief Test CRC calculation with discontinuous buffers.
 */
ZTEST(crc, test_discontinuous_buf)
{
	static const struct device *dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_crc));

	uint8_t data1[5] = {0x0A, 0x2B, 0x4C, 0x6D, 0x8E};
	uint8_t data2[5] = {0x49, 0x00, 0xC4, 0x3B, 0x78};

	struct crc_ctx ctx = {
		.type = CRC8,
		.polynomial = CRC8_POLY,
		.seed = CRC8_INIT_VAL,
		.reversed = CRC_FLAG_REVERSE_INPUT | CRC_FLAG_REVERSE_OUTPUT,
	};

	zassert_equal(crc_begin(dev, &ctx), 0);
	zassert_equal(crc_update(dev, &ctx, data1, sizeof(data1)), 0);
	zassert_equal(crc_update(dev, &ctx, data2, sizeof(data2)), 0);
	zassert_equal(crc_finish(dev, &ctx), 0);
	zassert_equal(crc_verify(&ctx, RESULT_DISCONTINUOUS_BUFFER), 0);
}

/* Define result of CRC computation */
#define RESULT_CRC_8_REMAIN_3_THREADSAFE 0xBB

/**
 * @brief Test CRC function semaphore wait for thread safety
 *
 * Verifies that CRC operations are blocked until a semaphore is released. A new thread
 * acquires the semaphore, and the main thread's CRC operations wait until it is released.
 */
ZTEST(crc, test_crc_threadsafe)
{
	static const struct device *dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_crc));

	uint8_t data[11] = {0x0A, 0x2B, 0x4C, 0x6D, 0x8E, 0x49, 0x00, 0xC4, 0x3D, 0x4D, 0x51};

	struct crc_ctx ctx = {
		.type = CRC8,
		.polynomial = CRC8_POLY,
		.seed = CRC8_INIT_VAL,
		.reversed = CRC_FLAG_REVERSE_OUTPUT | CRC_FLAG_REVERSE_INPUT,
	};

	/**
	 * Create new thread that will immediately take the semaphore
	 */
	k_thread_create(&wait_thread_data, wait_thread_stack_area,
			K_THREAD_STACK_SIZEOF(wait_thread_stack_area), wait_thread_entry, NULL,
			NULL, NULL, WAIT_THREAD_PRIO, 0, K_NO_WAIT);

	/**
	 * Sleep for 10 ms to ensure that new thread has taken lock
	 */
	k_sleep(K_MSEC(10));

	/**
	 * Attempt to take semaphore, this should wait for the new thread to give the semaphore
	 * before executing
	 */
	crc_begin(dev, &ctx);
	crc_update(dev, &ctx, data, sizeof(data));
	crc_finish(dev, &ctx);
	zassert_equal(crc_verify(&ctx, RESULT_CRC_8_REMAIN_3_THREADSAFE), 0);
}

ZTEST_SUITE(crc, NULL, NULL, NULL, NULL, NULL);
+7 −0
Original line number Diff line number Diff line
tests:
  drivers.crc:
    depends_on: crc
    tags:
      - drivers
      - crc
    harness: ztest