/* * Copyright (c) 2025 Renesas Electronics Corporation * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include #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_WAIT_THREAD_ENTRY 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_WAIT_THREAD_ENTRY), 0); } /* Define result of CRC computation */ #define RESULT_CRC_8 0xB2 /** * @brief Test that crc8 works */ ZTEST(crc, test_crc_8) { #ifndef CONFIG_CRC_DRIVER_HAS_CRC8 ztest_test_skip(); #endif 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) { #ifndef CONFIG_CRC_DRIVER_HAS_CRC16 ztest_test_skip(); #endif 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) { #ifndef CONFIG_CRC_DRIVER_HAS_CRC16_CCITT ztest_test_skip(); #endif 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) { #ifndef CONFIG_CRC_DRIVER_HAS_CRC32_C ztest_test_skip(); #endif 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) { #ifndef CONFIG_CRC_DRIVER_HAS_CRC32_IEEE ztest_test_skip(); #endif 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) { #ifndef CONFIG_CRC_DRIVER_HAS_CRC8 ztest_test_skip(); #endif 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) { #ifndef CONFIG_CRC_DRIVER_HAS_CRC16 ztest_test_skip(); #endif 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) { #ifndef CONFIG_CRC_DRIVER_HAS_CRC16_CCITT ztest_test_skip(); #endif 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); } /* Select CRC test variant macros */ #ifdef CONFIG_CRC_DRIVER_HAS_CRC8 #define CRC_TEST_VARIANT CRC8 #define CRC_TEST_POLY CRC8_POLY #define CRC_TEST_INIT_VAL CRC8_INIT_VAL #define CRC_TEST_REVERSE_CONFIG (CRC_FLAG_REVERSE_INPUT | CRC_FLAG_REVERSE_OUTPUT) #define CRC_TEST_DISCONTINUOUS_BUF_EXPECTED 0x75 #elif defined(CONFIG_CRC_DRIVER_HAS_CRC16) #define CRC_TEST_VARIANT CRC16 #define CRC_TEST_POLY CRC16_POLY #define CRC_TEST_INIT_VAL CRC16_INIT_VAL #define CRC_TEST_REVERSE_CONFIG (CRC_FLAG_REVERSE_INPUT | CRC_FLAG_REVERSE_OUTPUT) #define CRC_TEST_DISCONTINUOUS_BUF_EXPECTED 0xBDE3 #else #define CRC_TEST_VARIANT CRC32_C #define CRC_TEST_POLY CRC32C_POLY #define CRC_TEST_INIT_VAL CRC32_C_INIT_VAL #define CRC_TEST_REVERSE_CONFIG (CRC_FLAG_REVERSE_INPUT | CRC_FLAG_REVERSE_OUTPUT) #define CRC_TEST_DISCONTINUOUS_BUF_EXPECTED 0x20477127 #endif /** * @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 = CRC_TEST_VARIANT, .polynomial = CRC_TEST_POLY, .seed = CRC_TEST_INIT_VAL, .reversed = CRC_TEST_REVERSE_CONFIG, }; 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, CRC_TEST_DISCONTINUOUS_BUF_EXPECTED), 0); } /* Define result of CRC computation */ #ifdef CONFIG_CRC_DRIVER_HAS_CRC8 #define CRC_TEST_THREADSAFE_EXPECTED 0xBB #elif defined(CONFIG_CRC_DRIVER_HAS_CRC16) #define CRC_TEST_THREADSAFE_EXPECTED 0x24CA #else #define CRC_TEST_THREADSAFE_EXPECTED 0x9BCEE9AB #endif /** * @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 = CRC_TEST_VARIANT, .polynomial = CRC_TEST_POLY, .seed = CRC_TEST_INIT_VAL, .reversed = CRC_TEST_REVERSE_CONFIG, }; /** * 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, CRC_TEST_THREADSAFE_EXPECTED), 0); } ZTEST_SUITE(crc, NULL, NULL, NULL, NULL, NULL);