summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhathach <[email protected]>2025-11-21 12:58:28 +0700
committerhathach <[email protected]>2025-11-21 12:58:28 +0700
commitd4cdc096caa9c662f77f5633a792335f74fdad97 (patch)
tree1a0a53871738c45d47822d778e94057bac47731d
parent30198b2ab9e69c120e5b49c063dad3d2d3889d79 (diff)
add more unit tests for tu_fifo
-rw-r--r--.clang-format1
-rw-r--r--src/common/tusb_fifo.c6
-rw-r--r--src/common/tusb_mcu.h9
-rw-r--r--src/tusb_option.h26
-rw-r--r--test/unit-test/CMakeLists.txt132
-rw-r--r--test/unit-test/project.yml1
-rw-r--r--test/unit-test/test/test_fifo.c363
7 files changed, 429 insertions, 109 deletions
diff --git a/.clang-format b/.clang-format
index 924516e13..2cd0e1554 100644
--- a/.clang-format
+++ b/.clang-format
@@ -84,6 +84,7 @@ MaxEmptyLinesToKeep: 2
NamespaceIndentation: All
PenaltyBreakBeforeFirstCallParameter: 1000000
PenaltyBreakOpenParenthesis: 1000000
+PPIndentWidth: 2
QualifierAlignment: Custom
QualifierOrder: ['static', 'const', 'volatile', 'restrict', 'type']
SpaceAfterTemplateKeyword: false
diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c
index a3e89bbc2..ef2344801 100644
--- a/src/common/tusb_fifo.c
+++ b/src/common/tusb_fifo.c
@@ -85,7 +85,7 @@ bool tu_fifo_config(tu_fifo_t *f, void *buffer, uint16_t depth, uint16_t item_si
// Pull & Push
//--------------------------------------------------------------------+
-#ifdef TUP_MEM_CONST_ADDR
+#ifdef CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_RW32
// Intended to be used to read from hardware USB FIFO in e.g. STM32 where all data is read from a constant address
// Code adapted from dcd_synopsys.c
// TODO generalize with configurable 1 byte or 4 byte each read
@@ -164,7 +164,7 @@ static void _ff_push_n(tu_fifo_t *f, const void *app_buf, uint16_t n, uint16_t w
}
break;
-#ifdef TUP_MEM_CONST_ADDR
+#ifdef CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_RW32
case TU_FIFO_FIXED_ADDR_RW32:
// Intended for hardware buffers from which it can be read word by word only
if (n <= lin_count) {
@@ -244,7 +244,7 @@ static void _ff_pull_n(tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd_ptr,
}
break;
-#ifdef TUP_MEM_CONST_ADDR
+#ifdef CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_RW32
case TU_FIFO_FIXED_ADDR_RW32:
if (n <= lin_count) {
// Linear only
diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h
index 002cd3a0e..34977378c 100644
--- a/src/common/tusb_mcu.h
+++ b/src/common/tusb_mcu.h
@@ -24,8 +24,7 @@
* This file is part of the TinyUSB stack.
*/
-#ifndef TUSB_MCU_H_
-#define TUSB_MCU_H_
+#pragma once
//--------------------------------------------------------------------+
// Port/Platform Specific
@@ -697,9 +696,3 @@
#ifndef TUP_DCD_EDPT_CLOSE_API
#define TUP_DCD_EDPT_ISO_ALLOC
#endif
-
-#if defined(TUP_USBIP_DWC2) // && CFG_TUD_DWC2_DMA_ENABLE == 0
- #define TUP_MEM_CONST_ADDR
-#endif
-
-#endif
diff --git a/src/tusb_option.h b/src/tusb_option.h
index dd5f17dfc..e2eaecd2d 100644
--- a/src/tusb_option.h
+++ b/src/tusb_option.h
@@ -24,8 +24,7 @@
* This file is part of the TinyUSB stack.
*/
-#ifndef TUSB_OPTION_H_
-#define TUSB_OPTION_H_
+#pragma once
#include "common/tusb_compiler.h"
@@ -305,15 +304,26 @@
#define CFG_TUH_DWC2_DMA_ENABLE CFG_TUH_DWC2_DMA_ENABLE_DEFAULT
#endif
-#if defined(TUP_USBIP_DWC2) && CFG_TUD_DWC2_SLAVE_ENABLE == 1
-#define TUP_DCD_EDPT_DEDICATED_FIFO
+#if defined(TUP_USBIP_DWC2)
+ #if CFG_TUD_DWC2_SLAVE_ENABLE
+ #define CFG_TUD_EDPT_DEDICATED_FIFO
+ #endif
+
+ #if CFG_TUD_DWC2_SLAVE_ENABLE
+ #define CFG_TUH_EDPT_DEDICATED_FIFO
+ #endif
+#endif
+
+#if defined(CFG_TUD_EDPT_DEDICATED_FIFO) || defined(CFG_TUH_EDPT_DEDICATED_FIFO)
+ #define CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_RW32
#endif
//------------- ChipIdea -------------//
-// Enable CI_HS VBUS Charge. Set this to 1 if the USB_VBUS pin is not connected to 5V VBUS (note: 3.3V is insufficient).
+// Enable CI_HS VBUS Charge. Set this to 1 if the USB_VBUS pin is not connected to 5V VBUS (note: 3.3V is
+// insufficient).
#ifndef CFG_TUD_CI_HS_VBUS_CHARGE
#ifndef CFG_TUD_CI_HS_VBUS_CHARGE_DEFAULT
- #define CFG_TUD_CI_HS_VBUS_CHARGE_DEFAULT 0
+ #define CFG_TUD_CI_HS_VBUS_CHARGE_DEFAULT 0
#endif
#define CFG_TUD_CI_HS_VBUS_CHARGE CFG_TUD_CI_HS_VBUS_CHARGE_DEFAULT
@@ -738,7 +748,3 @@
// To avoid GCC compiler warnings when -pedantic option is used (strict ISO C)
typedef int make_iso_compilers_happy;
-
-#endif /* TUSB_OPTION_H_ */
-
-/** @} */
diff --git a/test/unit-test/CMakeLists.txt b/test/unit-test/CMakeLists.txt
new file mode 100644
index 000000000..7172f5575
--- /dev/null
+++ b/test/unit-test/CMakeLists.txt
@@ -0,0 +1,132 @@
+cmake_minimum_required(VERSION 3.20)
+
+project(tinyusb_unit_tests LANGUAGES C)
+
+set(CMAKE_C_STANDARD 99)
+set(CMAKE_C_STANDARD_REQUIRED ON)
+set(CMAKE_C_EXTENSIONS ON)
+
+# Command to invoke Ceedling. Supports multi-word commands such as "bundle exec ceedling".
+set(CEEDLING_COMMAND "ceedling" CACHE STRING "Command used to invoke Ceedling (Ruby gem).")
+separate_arguments(CEEDLING_COMMAND_LIST NATIVE_COMMAND "${CEEDLING_COMMAND}")
+if (CEEDLING_COMMAND_LIST STREQUAL "")
+ message(FATAL_ERROR "CEEDLING_COMMAND is empty; set it to a valid Ceedling invocation.")
+endif ()
+
+list(GET CEEDLING_COMMAND_LIST 0 CEEDLING_LAUNCHER)
+find_program(CEEDLING_LAUNCHER_PATH NAMES ${CEEDLING_LAUNCHER})
+if (NOT CEEDLING_LAUNCHER_PATH)
+ message(FATAL_ERROR "Could not find '${CEEDLING_LAUNCHER}' on PATH; adjust CEEDLING_COMMAND or PATH.")
+endif ()
+list(REMOVE_AT CEEDLING_COMMAND_LIST 0)
+list(INSERT CEEDLING_COMMAND_LIST 0 ${CEEDLING_LAUNCHER_PATH})
+
+set(CEEDLING_WORKDIR ${CMAKE_CURRENT_LIST_DIR})
+set(CEEDLING_BUILD_DIR ${CEEDLING_WORKDIR}/_build)
+
+# Helper to add a Ceedling-backed test target that compiles into a real CMake executable.
+function(add_ceedling_test TARGET_NAME TEST_SOURCE PRODUCT_SOURCES MOCK_SOURCES)
+ set(runner ${CEEDLING_BUILD_DIR}/test/runners/${TARGET_NAME}_runner.c)
+
+ add_custom_target(ceedling_gen_${TARGET_NAME}
+ COMMAND ${CEEDLING_COMMAND_LIST} test:${TARGET_NAME}
+ WORKING_DIRECTORY ${CEEDLING_WORKDIR}
+ BYPRODUCTS ${runner}
+ USES_TERMINAL
+ COMMENT "Generate Ceedling runner/mocks for ${TARGET_NAME}"
+ )
+
+ add_executable(${TARGET_NAME}
+ ${TEST_SOURCE}
+ ${runner}
+ ${MOCK_SOURCES}
+ ${CEEDLING_BUILD_DIR}/vendor/unity/src/unity.c
+ ${CEEDLING_BUILD_DIR}/vendor/cmock/src/cmock.c
+ ${PRODUCT_SOURCES}
+ )
+
+ set_source_files_properties(
+ ${runner}
+ ${MOCK_SOURCES}
+ ${CEEDLING_BUILD_DIR}/vendor/unity/src/unity.c
+ ${CEEDLING_BUILD_DIR}/vendor/cmock/src/cmock.c
+ PROPERTIES GENERATED TRUE
+ )
+
+ add_dependencies(${TARGET_NAME} ceedling_gen_${TARGET_NAME})
+
+ target_include_directories(${TARGET_NAME} PRIVATE
+ ${CEEDLING_WORKDIR}/test
+ ${CEEDLING_WORKDIR}/test/support
+ ${CEEDLING_BUILD_DIR}/test/runners
+ ${CEEDLING_BUILD_DIR}/test/mocks/${TARGET_NAME}
+ ${CEEDLING_BUILD_DIR}/vendor/unity/src
+ ${CEEDLING_BUILD_DIR}/vendor/cmock/src
+ ${CEEDLING_WORKDIR}/../../src
+ ${CEEDLING_WORKDIR}/../../src/common
+ ${CEEDLING_WORKDIR}/../../src/device
+ ${CEEDLING_WORKDIR}/../../src/class
+ ${CEEDLING_WORKDIR}/../../src/class/msc
+ ${CEEDLING_WORKDIR}/../../src/host
+ ${CEEDLING_WORKDIR}/../../src/typec
+ ${CEEDLING_WORKDIR}/../../src/osal
+ )
+
+ target_compile_definitions(${TARGET_NAME} PRIVATE _UNITY_TEST_)
+ target_compile_options(${TARGET_NAME} PRIVATE -Wall -Wextra)
+ add_test(NAME ${TARGET_NAME} COMMAND ${TARGET_NAME})
+endfunction()
+
+# Custom targets to keep plain Ceedling entry-points available.
+add_custom_target(ceedling_all
+ COMMAND ${CEEDLING_COMMAND_LIST} test:all
+ WORKING_DIRECTORY ${CEEDLING_WORKDIR}
+ USES_TERMINAL
+ COMMENT "Run Ceedling (Unity) unit tests"
+ )
+
+add_custom_target(ceedling_clean
+ COMMAND ${CEEDLING_COMMAND_LIST} clean
+ WORKING_DIRECTORY ${CEEDLING_WORKDIR}
+ USES_TERMINAL
+ COMMENT "Clean Ceedling build outputs"
+ )
+
+add_custom_target(ceedling_clobber
+ COMMAND ${CEEDLING_COMMAND_LIST} clobber
+ WORKING_DIRECTORY ${CEEDLING_WORKDIR}
+ USES_TERMINAL
+ COMMENT "Clobber Ceedling build outputs"
+ )
+
+# Per-test wiring: mocks are generated under _build/test/mocks/<name>/.
+add_ceedling_test(
+ test_common_func
+ ${CEEDLING_WORKDIR}/test/test_common_func.c
+ ""
+ ""
+ )
+
+add_ceedling_test(
+ test_fifo
+ ${CEEDLING_WORKDIR}/test/test_fifo.c
+ ${CEEDLING_WORKDIR}/../../src/common/tusb_fifo.c
+ ""
+ )
+target_compile_definitions(test_fifo PRIVATE CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_RW32=1)
+
+add_ceedling_test(
+ test_usbd
+ ${CEEDLING_WORKDIR}/test/device/usbd/test_usbd.c
+ "${CEEDLING_WORKDIR}/../../src/tusb.c;${CEEDLING_WORKDIR}/../../src/device/usbd.c;${CEEDLING_WORKDIR}/../../src/device/usbd_control.c;${CEEDLING_WORKDIR}/../../src/common/tusb_fifo.c"
+ "${CEEDLING_BUILD_DIR}/test/mocks/test_usbd/mock_dcd.c;${CEEDLING_BUILD_DIR}/test/mocks/test_usbd/mock_msc_device.c"
+ )
+
+add_ceedling_test(
+ test_msc_device
+ ${CEEDLING_WORKDIR}/test/device/msc/test_msc_device.c
+ "${CEEDLING_WORKDIR}/../../src/tusb.c;${CEEDLING_WORKDIR}/../../src/device/usbd.c;${CEEDLING_WORKDIR}/../../src/device/usbd_control.c;${CEEDLING_WORKDIR}/../../src/class/msc/msc_device.c;${CEEDLING_WORKDIR}/../../src/common/tusb_fifo.c"
+ "${CEEDLING_BUILD_DIR}/test/mocks/test_msc_device/mock_dcd.c"
+ )
+
+enable_testing()
diff --git a/test/unit-test/project.yml b/test/unit-test/project.yml
index 6c86b0205..d971d098d 100644
--- a/test/unit-test/project.yml
+++ b/test/unit-test/project.yml
@@ -128,6 +128,7 @@
:defines:
:test:
- _UNITY_TEST_
+ - CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_RW32
:release: []
# Enable to inject name of a test as a unique compilation symbol into its respective executable build.
diff --git a/test/unit-test/test/test_fifo.c b/test/unit-test/test/test_fifo.c
index 3b4deb33e..83db10454 100644
--- a/test/unit-test/test/test_fifo.c
+++ b/test/unit-test/test/test_fifo.c
@@ -30,51 +30,52 @@
#include "osal/osal.h"
#include "tusb_fifo.h"
-#define FIFO_SIZE 64
-uint8_t tu_ff_buf[FIFO_SIZE * sizeof(uint8_t)];
+#define FIFO_SIZE 64
+uint8_t tu_ff_buf[FIFO_SIZE * sizeof(uint8_t)];
tu_fifo_t tu_ff = TU_FIFO_INIT(tu_ff_buf, FIFO_SIZE, uint8_t, false);
-tu_fifo_t* ff = &tu_ff;
+tu_fifo_t *ff = &tu_ff;
tu_fifo_buffer_info_t info;
uint8_t test_data[4096];
uint8_t rd_buf[FIFO_SIZE];
-void setUp(void)
-{
+void setUp(void) {
tu_fifo_clear(ff);
memset(&info, 0, sizeof(tu_fifo_buffer_info_t));
- for(int i=0; i<sizeof(test_data); i++) test_data[i] = i;
+ for (size_t i = 0; i < sizeof(test_data); i++) {
+ test_data[i] = i;
+ }
memset(rd_buf, 0, sizeof(rd_buf));
}
-void tearDown(void)
-{
+void tearDown(void) {
}
//--------------------------------------------------------------------+
// Tests
//--------------------------------------------------------------------+
-void test_normal(void)
-{
- for(uint8_t i=0; i < FIFO_SIZE; i++) tu_fifo_write(ff, &i);
+void test_normal(void) {
+ for (uint8_t i = 0; i < FIFO_SIZE; i++) {
+ tu_fifo_write(ff, &i);
+ }
- for(uint8_t i=0; i < FIFO_SIZE; i++)
- {
+ for (uint8_t i = 0; i < FIFO_SIZE; i++) {
uint8_t c;
tu_fifo_read(ff, &c);
TEST_ASSERT_EQUAL(i, c);
}
}
-void test_item_size(void)
-{
- uint8_t ff4_buf[FIFO_SIZE * sizeof(uint32_t)];
+void test_item_size(void) {
+ uint8_t ff4_buf[FIFO_SIZE * sizeof(uint32_t)];
tu_fifo_t ff4 = TU_FIFO_INIT(ff4_buf, FIFO_SIZE, uint32_t, false);
- uint32_t data4[2*FIFO_SIZE];
- for(uint32_t i=0; i<sizeof(data4)/4; i++) data4[i] = i;
+ uint32_t data4[2 * FIFO_SIZE];
+ for (uint32_t i = 0; i < sizeof(data4) / 4; i++) {
+ data4[i] = i;
+ }
// fill up fifo
tu_fifo_write_n(&ff4, data4, FIFO_SIZE);
@@ -84,78 +85,77 @@ void test_item_size(void)
// read 0 -> 4
rd_count = tu_fifo_read_n(&ff4, rd_buf4, 5);
- TEST_ASSERT_EQUAL( 5, rd_count );
- TEST_ASSERT_EQUAL_UINT32_ARRAY( data4, rd_buf4, rd_count ); // 0 -> 4
+ TEST_ASSERT_EQUAL(5, rd_count);
+ TEST_ASSERT_EQUAL_UINT32_ARRAY(data4, rd_buf4, rd_count); // 0 -> 4
- tu_fifo_write_n(&ff4, data4+FIFO_SIZE, 5);
+ tu_fifo_write_n(&ff4, data4 + FIFO_SIZE, 5);
// read all 5 -> 68
rd_count = tu_fifo_read_n(&ff4, rd_buf4, FIFO_SIZE);
- TEST_ASSERT_EQUAL( FIFO_SIZE, rd_count );
- TEST_ASSERT_EQUAL_UINT32_ARRAY( data4+5, rd_buf4, rd_count ); // 5 -> 68
+ TEST_ASSERT_EQUAL(FIFO_SIZE, rd_count);
+ TEST_ASSERT_EQUAL_UINT32_ARRAY(data4 + 5, rd_buf4, rd_count); // 5 -> 68
}
-void test_read_n(void)
-{
+void test_read_n(void) {
uint16_t rd_count;
// fill up fifo
- for(uint8_t i=0; i < FIFO_SIZE; i++) tu_fifo_write(ff, test_data+i);
+ for (uint8_t i = 0; i < FIFO_SIZE; i++) {
+ tu_fifo_write(ff, test_data + i);
+ }
// case 1: Read index + count < depth
// read 0 -> 4
rd_count = tu_fifo_read_n(ff, rd_buf, 5);
- TEST_ASSERT_EQUAL( 5, rd_count );
- TEST_ASSERT_EQUAL_MEMORY( test_data, rd_buf, rd_count ); // 0 -> 4
+ TEST_ASSERT_EQUAL(5, rd_count);
+ TEST_ASSERT_EQUAL_MEMORY(test_data, rd_buf, rd_count); // 0 -> 4
// case 2: Read index + count > depth
// write 10, 11, 12
- tu_fifo_write(ff, test_data+FIFO_SIZE);
- tu_fifo_write(ff, test_data+FIFO_SIZE+1);
- tu_fifo_write(ff, test_data+FIFO_SIZE+2);
+ tu_fifo_write(ff, test_data + FIFO_SIZE);
+ tu_fifo_write(ff, test_data + FIFO_SIZE + 1);
+ tu_fifo_write(ff, test_data + FIFO_SIZE + 2);
rd_count = tu_fifo_read_n(ff, rd_buf, 7);
- TEST_ASSERT_EQUAL( 7, rd_count );
+ TEST_ASSERT_EQUAL(7, rd_count);
- TEST_ASSERT_EQUAL_MEMORY( test_data+5, rd_buf, rd_count ); // 5 -> 11
+ TEST_ASSERT_EQUAL_MEMORY(test_data + 5, rd_buf, rd_count); // 5 -> 11
// Should only read until empty
- TEST_ASSERT_EQUAL( FIFO_SIZE-5+3-7, tu_fifo_read_n(ff, rd_buf, 100) );
+ TEST_ASSERT_EQUAL(FIFO_SIZE - 5 + 3 - 7, tu_fifo_read_n(ff, rd_buf, 100));
}
-void test_write_n(void)
-{
+void test_write_n(void) {
// case 1: wr + count < depth
tu_fifo_write_n(ff, test_data, 32); // wr = 32, count = 32
uint16_t rd_count;
rd_count = tu_fifo_read_n(ff, rd_buf, 16); // wr = 32, count = 16
- TEST_ASSERT_EQUAL( 16, rd_count );
- TEST_ASSERT_EQUAL_MEMORY( test_data, rd_buf, rd_count );
+ TEST_ASSERT_EQUAL(16, rd_count);
+ TEST_ASSERT_EQUAL_MEMORY(test_data, rd_buf, rd_count);
// case 2: wr + count > depth
- tu_fifo_write_n(ff, test_data+32, 40); // wr = 72 -> 8, count = 56
+ tu_fifo_write_n(ff, test_data + 32, 40); // wr = 72 -> 8, count = 56
- tu_fifo_read_n(ff, rd_buf, 32); // count = 24
- TEST_ASSERT_EQUAL_MEMORY( test_data+16, rd_buf, rd_count);
+ tu_fifo_read_n(ff, rd_buf, 32); // count = 24
+ TEST_ASSERT_EQUAL_MEMORY(test_data + 16, rd_buf, rd_count);
TEST_ASSERT_EQUAL(24, tu_fifo_count(ff));
}
-void test_write_double_overflowed(void)
-{
+void test_write_double_overflowed(void) {
tu_fifo_set_overwritable(ff, true);
- uint8_t rd_buf[FIFO_SIZE] = { 0 };
- uint8_t* buf = test_data;
+ uint8_t rd_buf[FIFO_SIZE] = {0};
+ uint8_t *buf = test_data;
// full
buf += tu_fifo_write_n(ff, buf, FIFO_SIZE);
TEST_ASSERT_EQUAL(FIFO_SIZE, tu_fifo_count(ff));
// write more, should still full
- buf += tu_fifo_write_n(ff, buf, FIFO_SIZE-8);
+ buf += tu_fifo_write_n(ff, buf, FIFO_SIZE - 8);
TEST_ASSERT_EQUAL(FIFO_SIZE, tu_fifo_count(ff));
// double overflowed: in total, write more than > 2*FIFO_SIZE
@@ -165,14 +165,13 @@ void test_write_double_overflowed(void)
// reading back should give back data from last FIFO_SIZE write
tu_fifo_read_n(ff, rd_buf, FIFO_SIZE);
- TEST_ASSERT_EQUAL_MEMORY(buf-16, rd_buf+FIFO_SIZE-16, 16);
+ TEST_ASSERT_EQUAL_MEMORY(buf - 16, rd_buf + FIFO_SIZE - 16, 16);
// TODO whole buffer should match, but we deliberately not implement it
// TEST_ASSERT_EQUAL_MEMORY(buf-FIFO_SIZE, rd_buf, FIFO_SIZE);
}
-static uint16_t help_write(uint16_t total, uint16_t n)
-{
+static uint16_t help_write(uint16_t total, uint16_t n) {
tu_fifo_write_n(ff, test_data, n);
total = tu_min16(FIFO_SIZE, total + n);
@@ -182,12 +181,11 @@ static uint16_t help_write(uint16_t total, uint16_t n)
return total;
}
-void test_write_overwritable2(void)
-{
- tu_fifo_set_overwritable(ff, true);
+void test_write_overwritable2(void) {
+tu_fifo_set_overwritable(ff, true);
- // based on actual crash tests detected by fuzzing
- uint16_t total = 0;
+// based on actual crash tests detected by fuzzing
+uint16_t total = 0;
total = help_write(total, 12);
total = help_write(total, 55);
@@ -202,13 +200,15 @@ void test_write_overwritable2(void)
total = help_write(total, 192);
}
-void test_peek(void)
-{
+void test_peek(void) {
uint8_t temp;
- temp = 10; tu_fifo_write(ff, &temp);
- temp = 20; tu_fifo_write(ff, &temp);
- temp = 30; tu_fifo_write(ff, &temp);
+ temp = 10;
+ tu_fifo_write(ff, &temp);
+ temp = 20;
+ tu_fifo_write(ff, &temp);
+ temp = 30;
+ tu_fifo_write(ff, &temp);
temp = 0;
@@ -222,12 +222,13 @@ void test_peek(void)
TEST_ASSERT_EQUAL(30, temp);
}
-void test_get_read_info_when_no_wrap()
-{
+void test_get_read_info_when_no_wrap() {
uint8_t ch = 1;
// write 6 items
- for(uint8_t i=0; i < 6; i++) tu_fifo_write(ff, &ch);
+ for (uint8_t i = 0; i < 6; i++) {
+ tu_fifo_write(ff, &ch);
+ }
// read 2 items
tu_fifo_read(ff, &ch);
@@ -238,19 +239,22 @@ void test_get_read_info_when_no_wrap()
TEST_ASSERT_EQUAL(4, info.len_lin);
TEST_ASSERT_EQUAL(0, info.len_wrap);
- TEST_ASSERT_EQUAL_PTR(ff->buffer+2, info.ptr_lin);
+ TEST_ASSERT_EQUAL_PTR(ff->buffer + 2, info.ptr_lin);
TEST_ASSERT_NULL(info.ptr_wrap);
}
-void test_get_read_info_when_wrapped()
-{
+void test_get_read_info_when_wrapped() {
uint8_t ch = 1;
// make fifo full
- for(uint8_t i=0; i < FIFO_SIZE; i++) tu_fifo_write(ff, &ch);
+ for (uint8_t i = 0; i < FIFO_SIZE; i++) {
+ tu_fifo_write(ff, &ch);
+ }
// read 6 items
- for(uint8_t i=0; i < 6; i++) tu_fifo_read(ff, &ch);
+ for (uint8_t i = 0; i < 6; i++) {
+ tu_fifo_read(ff, &ch);
+ }
// write 2 items
tu_fifo_write(ff, &ch);
@@ -258,15 +262,14 @@ void test_get_read_info_when_wrapped()
tu_fifo_get_read_info(ff, &info);
- TEST_ASSERT_EQUAL(FIFO_SIZE-6, info.len_lin);
+ TEST_ASSERT_EQUAL(FIFO_SIZE - 6, info.len_lin);
TEST_ASSERT_EQUAL(2, info.len_wrap);
- TEST_ASSERT_EQUAL_PTR(ff->buffer+6, info.ptr_lin);
+ TEST_ASSERT_EQUAL_PTR(ff->buffer + 6, info.ptr_lin);
TEST_ASSERT_EQUAL_PTR(ff->buffer, info.ptr_wrap);
}
-void test_get_write_info_when_no_wrap()
-{
+void test_get_write_info_when_no_wrap() {
uint8_t ch = 1;
// write 2 items
@@ -275,20 +278,21 @@ void test_get_write_info_when_no_wrap()
tu_fifo_get_write_info(ff, &info);
- TEST_ASSERT_EQUAL(FIFO_SIZE-2, info.len_lin);
+ TEST_ASSERT_EQUAL(FIFO_SIZE - 2, info.len_lin);
TEST_ASSERT_EQUAL(0, info.len_wrap);
- TEST_ASSERT_EQUAL_PTR(ff->buffer+2, info .ptr_lin);
+ TEST_ASSERT_EQUAL_PTR(ff->buffer + 2, info.ptr_lin);
// application should check len instead of ptr.
// TEST_ASSERT_NULL(info.ptr_wrap);
}
-void test_get_write_info_when_wrapped()
-{
+void test_get_write_info_when_wrapped() {
uint8_t ch = 1;
// write 6 items
- for(uint8_t i=0; i < 6; i++) tu_fifo_write(ff, &ch);
+ for (uint8_t i = 0; i < 6; i++) {
+ tu_fifo_write(ff, &ch);
+ }
// read 2 items
tu_fifo_read(ff, &ch);
@@ -296,15 +300,14 @@ void test_get_write_info_when_wrapped()
tu_fifo_get_write_info(ff, &info);
- TEST_ASSERT_EQUAL(FIFO_SIZE-6, info.len_lin);
+ TEST_ASSERT_EQUAL(FIFO_SIZE - 6, info.len_lin);
TEST_ASSERT_EQUAL(2, info.len_wrap);
- TEST_ASSERT_EQUAL_PTR(ff->buffer+6, info .ptr_lin);
+ TEST_ASSERT_EQUAL_PTR(ff->buffer + 6, info.ptr_lin);
TEST_ASSERT_EQUAL_PTR(ff->buffer, info.ptr_wrap);
}
-void test_empty(void)
-{
+void test_empty(void) {
uint8_t temp;
TEST_ASSERT_TRUE(tu_fifo_empty(ff));
@@ -323,7 +326,7 @@ void test_empty(void)
TEST_ASSERT_EQUAL(FIFO_SIZE, info.len_lin);
TEST_ASSERT_EQUAL(0, info.len_wrap);
- TEST_ASSERT_EQUAL_PTR(ff->buffer, info .ptr_lin);
+ TEST_ASSERT_EQUAL_PTR(ff->buffer, info.ptr_lin);
// application should check len instead of ptr.
// TEST_ASSERT_NULL(info.ptr_wrap);
@@ -332,11 +335,12 @@ void test_empty(void)
TEST_ASSERT_FALSE(tu_fifo_empty(ff));
}
-void test_full(void)
-{
+void test_full(void) {
TEST_ASSERT_FALSE(tu_fifo_full(ff));
- for(uint8_t i=0; i < FIFO_SIZE; i++) tu_fifo_write(ff, &i);
+ for (uint8_t i = 0; i < FIFO_SIZE; i++) {
+ tu_fifo_write(ff, &i);
+ }
TEST_ASSERT_TRUE(tu_fifo_full(ff));
@@ -353,11 +357,10 @@ void test_full(void)
// write info
}
-void test_rd_idx_wrap()
-{
+void test_rd_idx_wrap(void) {
tu_fifo_t ff10;
- uint8_t buf[10];
- uint8_t dst[10];
+ uint8_t buf[10];
+ uint8_t dst[10];
tu_fifo_config(&ff10, buf, 10, 1, 1);
@@ -376,3 +379,187 @@ void test_rd_idx_wrap()
TEST_ASSERT_EQUAL(n, 2);
TEST_ASSERT_EQUAL(ff10.rd_idx, 6);
}
+
+void test_advance_write_pointer_cases(void) {
+ tu_fifo_clear(ff);
+
+ tu_fifo_advance_write_pointer(ff, 3);
+ TEST_ASSERT_EQUAL(3, ff->wr_idx);
+ TEST_ASSERT_EQUAL(3, tu_fifo_count(ff));
+
+ // advance to cross depth but stay within 0..2*depth window
+ ff->wr_idx = FIFO_SIZE - 2; // 62
+ ff->rd_idx = 0;
+ tu_fifo_advance_write_pointer(ff, 10); // 62 + 10 = 72 within window
+ TEST_ASSERT_EQUAL(72, ff->wr_idx);
+ TEST_ASSERT_EQUAL(FIFO_SIZE, tu_fifo_count(ff));
+
+ // advance past the unused index space (beyond 2*depth)
+ ff->wr_idx = (uint16_t)(2 * FIFO_SIZE - 3); // 125
+ ff->rd_idx = 0;
+ tu_fifo_advance_write_pointer(ff, 6); // forces wrap across unused space
+ TEST_ASSERT_EQUAL(3, ff->wr_idx);
+ TEST_ASSERT_EQUAL(3, tu_fifo_count(ff));
+}
+
+void test_advance_read_pointer_cases(void) {
+ tu_fifo_clear(ff);
+
+ ff->wr_idx = 6;
+ tu_fifo_advance_read_pointer(ff, 3);
+ TEST_ASSERT_EQUAL(3, ff->rd_idx);
+ TEST_ASSERT_EQUAL(3, tu_fifo_count(ff));
+
+ ff->wr_idx = FIFO_SIZE + 10; // 74
+ ff->rd_idx = FIFO_SIZE - 10; // 54
+ tu_fifo_advance_read_pointer(ff, 20); // move to match write index within window
+ TEST_ASSERT_EQUAL(74, ff->rd_idx);
+ TEST_ASSERT_EQUAL(0, tu_fifo_count(ff));
+
+ ff->wr_idx = 9;
+ ff->rd_idx = (uint16_t)(2 * FIFO_SIZE - 1); // 127
+ tu_fifo_advance_read_pointer(ff, 6); // crosses unused index space
+ TEST_ASSERT_EQUAL(5, ff->rd_idx);
+ TEST_ASSERT_EQUAL(4, tu_fifo_count(ff));
+}
+
+void test_write_n_fixed_addr_rw32_nowrap(void) {
+ tu_fifo_clear(ff);
+
+ volatile uint32_t reg = 0x11223344;
+ uint8_t expected[8] = {0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11};
+
+ for (uint8_t n = 1; n <= 8; n++) {
+ tu_fifo_clear(ff);
+ uint16_t written = tu_fifo_write_n_access(ff, (const void *)&reg, n, TU_FIFO_FIXED_ADDR_RW32);
+ TEST_ASSERT_EQUAL(n, written);
+ TEST_ASSERT_EQUAL(n, tu_fifo_count(ff));
+
+ uint8_t out[8] = {0};
+ tu_fifo_read_n(ff, out, n);
+ TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, out, n);
+ }
+}
+
+void test_write_n_fixed_addr_rw32_wrapped(void) {
+ tu_fifo_clear(ff);
+
+ volatile uint32_t reg = 0xA1B2C3D4;
+ uint8_t expected[8] = {0xD4, 0xC3, 0xB2, 0xA1, 0xD4, 0xC3, 0xB2, 0xA1};
+
+ for (uint8_t n = 1; n <= 8; n++) {
+ tu_fifo_clear(ff);
+ // Position the fifo near the end so writes wrap
+ ff->wr_idx = FIFO_SIZE - 3;
+ ff->rd_idx = FIFO_SIZE - 3;
+
+ uint16_t written = tu_fifo_write_n_access(ff, (const void *)&reg, n, TU_FIFO_FIXED_ADDR_RW32);
+ TEST_ASSERT_EQUAL(n, written);
+ TEST_ASSERT_EQUAL(n, tu_fifo_count(ff));
+
+ uint8_t out[8] = {0};
+ tu_fifo_read_n(ff, out, n);
+ TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, out, n);
+ }
+}
+
+void test_read_n_fixed_addr_rw32_nowrap(void) {
+ uint8_t pattern[8] = {0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87};
+ uint32_t reg_expected[8] = {
+ 0x00000010, 0x00002110, 0x00322110, 0x43322110, 0x00000054, 0x00006554, 0x00766554, 0x87766554};
+
+ for (uint8_t n = 1; n <= 8; n++) {
+ tu_fifo_clear(ff);
+ tu_fifo_write_n(ff, pattern, 8);
+
+ uint32_t reg = 0;
+ uint16_t read_cnt = tu_fifo_read_n_access(ff, &reg, n, TU_FIFO_FIXED_ADDR_RW32);
+ TEST_ASSERT_EQUAL(n, read_cnt);
+ TEST_ASSERT_EQUAL(8 - n, tu_fifo_count(ff));
+
+ TEST_ASSERT_EQUAL_HEX32(reg_expected[n - 1], reg);
+ }
+}
+
+void test_read_n_fixed_addr_rw32_wrapped(void) {
+ uint8_t pattern[8] = {0xF0, 0xE1, 0xD2, 0xC3, 0xB4, 0xA5, 0x96, 0x87};
+ uint32_t reg_expected[8] = {
+ 0x000000F0, 0x0000E1F0, 0x00D2E1F0, 0xC3D2E1F0, 0x000000B4, 0x0000A5B4, 0x0096A5B4, 0x8796A5B4};
+
+ for (uint8_t n = 1; n <= 8; n++) {
+ tu_fifo_clear(ff);
+ ff->rd_idx = FIFO_SIZE - 2;
+ ff->wr_idx = (uint16_t)(ff->rd_idx + n);
+
+ for (uint8_t i = 0; i < n; i++) {
+ uint8_t idx = (uint8_t)((ff->rd_idx + i) % FIFO_SIZE);
+ ff->buffer[idx] = pattern[i];
+ }
+
+ uint32_t reg = 0;
+ uint16_t read_cnt = tu_fifo_read_n_access(ff, &reg, n, TU_FIFO_FIXED_ADDR_RW32);
+ TEST_ASSERT_EQUAL(n, read_cnt);
+ TEST_ASSERT_EQUAL(0, tu_fifo_count(ff));
+
+ TEST_ASSERT_EQUAL_HEX32(reg_expected[n - 1], reg);
+ }
+}
+
+void test_get_read_info_advanced_cases(void) {
+ tu_fifo_clear(ff);
+
+ ff->wr_idx = 20;
+ ff->rd_idx = 2;
+ tu_fifo_get_read_info(ff, &info);
+ TEST_ASSERT_EQUAL(18, info.len_lin);
+ TEST_ASSERT_EQUAL(0, info.len_wrap);
+ TEST_ASSERT_EQUAL_PTR(ff->buffer + 2, info.ptr_lin);
+ TEST_ASSERT_NULL(info.ptr_wrap);
+
+ ff->wr_idx = 68; // ptr = 4
+ ff->rd_idx = 56; // ptr = 56
+ tu_fifo_get_read_info(ff, &info);
+ TEST_ASSERT_EQUAL(8, info.len_lin);
+ TEST_ASSERT_EQUAL(4, info.len_wrap);
+ TEST_ASSERT_EQUAL_PTR(ff->buffer + 56, info.ptr_lin);
+ TEST_ASSERT_EQUAL_PTR(ff->buffer, info.ptr_wrap);
+}
+
+void test_get_write_info_advanced_cases(void) {
+ tu_fifo_clear(ff);
+
+ ff->wr_idx = 10;
+ ff->rd_idx = 104; // ptr = 40
+ tu_fifo_get_write_info(ff, &info);
+ TEST_ASSERT_EQUAL(30, info.len_lin);
+ TEST_ASSERT_EQUAL(0, info.len_wrap);
+ TEST_ASSERT_EQUAL_PTR(ff->buffer + 10, info.ptr_lin);
+ TEST_ASSERT_NULL(info.ptr_wrap);
+
+ ff->wr_idx = 60;
+ ff->rd_idx = 20;
+ tu_fifo_get_write_info(ff, &info);
+ TEST_ASSERT_EQUAL(4, info.len_lin);
+ TEST_ASSERT_EQUAL(20, info.len_wrap);
+ TEST_ASSERT_EQUAL_PTR(ff->buffer + 60, info.ptr_lin);
+ TEST_ASSERT_EQUAL_PTR(ff->buffer, info.ptr_wrap);
+}
+
+void test_correct_read_pointer_cases(void) {
+ tu_fifo_clear(ff);
+
+ // wr beyond depth: rd should be wr - depth
+ ff->wr_idx = FIFO_SIZE + 6; // 70
+ tu_fifo_correct_read_pointer(ff);
+ TEST_ASSERT_EQUAL(6, ff->rd_idx);
+
+ // wr exactly at depth: rd should wrap to zero
+ ff->wr_idx = FIFO_SIZE;
+ tu_fifo_correct_read_pointer(ff);
+ TEST_ASSERT_EQUAL(0, ff->rd_idx);
+
+ // wr below depth: rd should be wr + depth
+ ff->wr_idx = 10;
+ tu_fifo_correct_read_pointer(ff);
+ TEST_ASSERT_EQUAL(FIFO_SIZE + 10, ff->rd_idx);
+}