| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328 |
- /*
- * Copyright (c) 2006-2025 RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2025-05-01 wumingzi first version
- * 2025-11-24 ChuanN-sudo add standardized utest documentation block
- */
- /**
- * Test Case Name: Audio Test
- *
- * Test Objectives:
- * - Validate RT-Thread audio driver framework registration and data flow mechanisms.
- * - Verify audio playback (TX) and recording (RX) data transmission correctness.
- * - Ensure proper buffer management and memory integrity during audio operations.
- * - Test core APIs: rt_audio_register(), rt_audio_tx_complete(), rt_audio_rx_done()
- *
- * Test Scenarios:
- * - Locate audio devices using SOUND_PLAYER_DEVICE_NAME and SOUND_MIC_DEVICE_NAME macros.
- * - Write known byte patterns (0xAA, 0x55) to simulate audio data flow through TX/RX buffers.
- * - Synchronize player and microphone test execution using audio_fsm_step state machine.
- * - Test two consecutive block transfers for both TX and RX paths.
- *
- * Verification Metrics:
- * - Written audio data appears correctly in device TX buffers with exact byte patterns.
- * - Data read from microphone device matches expected fill patterns (0xAA then 0x55) without corruption.
- * - Buffer boundaries are respected with no overflow or underflow conditions.
- * - Device open/close operations complete successfully without resource leaks.
- *
- * Dependencies:
- * - Hardware requirements: QEMU emulator or any hardware platform that supports RT-Thread.
- * - Software configuration:
- * - RT_USING_UTESTCASES must be enabled (select "RT-Thread Utestcases" in menuconfig).
- * - RT_USING_AUDIO must be enabled (enable via: RT-Thread Components -> Device Drivers -> Using Audio device drivers).
- * - RT_UTEST_USING_AUDIO_DRIVER must be enabled (enable via: RT-Thread Utestcases -> Kernel Components-> Drivers -> Audio Test).
- * - Environmental Assumptions: Audio devices registered and functional, sufficient memory available.
- *
- * Expected Results:
- * - Final output: "[ PASSED ] [ result ] testcase (components.drivers.audio.tc_audio_main)"
- * - No memory leaks detected during buffer allocation/deallocation.
- * - No assertions triggered during test execution.
- * - Buffer content verification passes for all test patterns.
- */
- #include "tc_audio_common.h"
- rt_uint8_t audio_fsm_step = 0;
- /* Allocate and initialize memory filled by fill_byte */
- static void *alloc_filled_mem(rt_uint8_t fill_byte, rt_size_t size)
- {
- void *ptr = rt_malloc(size);
- if (ptr != NULL)
- {
- rt_memset(ptr, fill_byte, size);
- }
- return ptr;
- }
- /* Check if the memory is filled with fill_byte */
- static rt_err_t check_filled_mem(rt_uint8_t fill_byte, rt_uint8_t *mem, size_t size)
- {
- rt_uint8_t *p = mem;
- for (size_t i = 0; i < size; ++i)
- {
- if (*(p+i) != fill_byte)
- {
- return -RT_ERROR;
- }
- }
- return RT_EOK;
- }
- static void player_test(void)
- {
- int res = 0;
- void* player_buffer = RT_NULL;
- rt_device_t dev_obj;
- dev_obj = rt_device_find(SOUND_PLAYER_DEVICE_NAME);
- if (dev_obj == RT_NULL)
- {
- uassert_not_null(dev_obj);
- goto __exit;
- }
- if (dev_obj->type != RT_Device_Class_Sound)
- {
- LOG_E("Not an audio player device\n");
- goto __exit;
- }
- res = rt_device_open(dev_obj, RT_DEVICE_OFLAG_WRONLY);
- if (res != RT_EOK)
- {
- LOG_E("Audio player device failed\n");
- uassert_true(0);
- goto __exit;
- }
- /* The sampling rate is set by the driver default, so there isn't configuration step */
- struct rt_audio_device *audio_dev = rt_container_of(dev_obj, struct rt_audio_device, parent);
- struct rt_audio_buf_info buf_info = audio_dev->replay->buf_info;
- struct sound_device *snd_dev = rt_container_of(audio_dev, struct sound_device, audio);
- player_buffer = alloc_filled_mem(0xAA, TX_DMA_BLOCK_SIZE);
- if (player_buffer == RT_NULL)
- {
- rt_kprintf("Allocate test memory failed\n");
- uassert_true(0);
- goto __exit;
- }
- if(snd_dev->tx_fifo == RT_NULL)
- {
- rt_kprintf("snd_dev->tx_fifo == RT_NULL ");
- uassert_true(0);
- goto __exit;
- }
- res = rt_device_write(dev_obj, 0, player_buffer, TX_DMA_BLOCK_SIZE);
- if (res != RT_EOK && res != TX_DMA_BLOCK_SIZE)
- {
- rt_kprintf("Failed to write data to the player device, res = %d\n",res);
- uassert_true(0);
- goto __exit;
- }
- audio_fsm_step = 1;
- while (1)
- {
- if(audio_fsm_step == 2)
- {
- break;
- }
- rt_thread_mdelay(10);
- }
- res = check_filled_mem(0xAA, &buf_info.buffer[0], TX_DMA_BLOCK_SIZE);
- if (res != RT_EOK)
- {
- rt_kprintf("The first memory check failed! Buffer dump\n");
- for (rt_size_t i = 0; i < TX_DMA_FIFO_SIZE; i++)
- {
- rt_kprintf("%02X ", buf_info.buffer[i]);
- if (i % 16 == 15) rt_kprintf("\n");
- }
- rt_kprintf("\n");
- uassert_true(0);
- goto __exit;
- }
- rt_free(player_buffer);
- player_buffer = RT_NULL;
- player_buffer = alloc_filled_mem(0x55, TX_DMA_BLOCK_SIZE);
- if (player_buffer == RT_NULL)
- {
- rt_kprintf("Allocate test memory failed\n");
- uassert_true(0);
- goto __exit;
- }
- res = rt_device_write(dev_obj, TX_DMA_BLOCK_SIZE, player_buffer, TX_DMA_BLOCK_SIZE);
- if (res != RT_EOK && res != TX_DMA_BLOCK_SIZE)
- {
- rt_kprintf("Failed to write data to the player device, res = %d\n",res);
- uassert_true(0);
- goto __exit;
- }
- audio_fsm_step = 2;
- while (res != RT_EOK)
- {
- if(audio_fsm_step == 3)
- {
- break;
- }
- rt_thread_mdelay(10);
- }
- res = check_filled_mem(0x55,&buf_info.buffer[TX_DMA_BLOCK_SIZE], TX_DMA_BLOCK_SIZE);
- if (res != RT_EOK)
- {
- rt_kprintf("The second memory check failed! Buffer dump\n");
- for (rt_size_t i = 0; i < TX_DMA_FIFO_SIZE; i++)
- {
- rt_kprintf("%02X ", buf_info.buffer[i]);
- if (i % 16 == 15) rt_kprintf("\n");
- }
- rt_kprintf("\n");
- uassert_true(0);
- goto __exit;
- }
- __exit:
- if (player_buffer)
- {
- rt_free(player_buffer);
- player_buffer = RT_NULL;
- }
- if (dev_obj != RT_NULL)
- {
- audio_fsm_step = 4;
- rt_device_close(dev_obj);
- }
- }
- static void mic_test(void)
- {
- rt_device_t dev_obj;
- rt_uint8_t *mic_buffer = RT_NULL;
- rt_ssize_t res = 0;
- rt_ssize_t length = 0;
- mic_buffer = (rt_uint8_t *)rt_malloc(RX_DMA_BLOCK_SIZE);
- if (mic_buffer == RT_NULL)
- {
- rt_kprintf("The mic_buffer memory allocate failed\n");
- uassert_true(0);
- goto __exit;
- }
- dev_obj = rt_device_find(SOUND_MIC_DEVICE_NAME);
- if (dev_obj == RT_NULL)
- {
- LOG_E("Not a mic device\n");
- uassert_true(0);
- goto __exit;
- }
- res = rt_device_open(dev_obj, RT_DEVICE_OFLAG_RDONLY);
- if (res != RT_EOK)
- {
- LOG_E("Audio player device failed\n");
- uassert_true(0);
- goto __exit;
- }
- length = rt_device_read(dev_obj, 0, mic_buffer,RX_DMA_BLOCK_SIZE);
- if(length < 0)
- {
- LOG_E("Mic device read err\n");
- }
- if(audio_fsm_step == 1)
- {
- res = check_filled_mem(0xAA, (rt_uint8_t*)(mic_buffer), length);
- }
- if (res != RT_EOK)
- {
- LOG_E("The first memory check failed! Buffer dump\n");
- for (rt_size_t i = 0; i < RX_DMA_FIFO_SIZE; i++)
- {
- rt_kprintf("%02X ",mic_buffer[i]);
- if (i % 16 == 15) rt_kprintf("\n");
- }
- rt_kprintf("\n");
- uassert_true(0);
- goto __exit;
- }
- audio_fsm_step = 2;
- while (1)
- {
- if(audio_fsm_step == 3)
- {
- length = rt_device_read(dev_obj, 0, mic_buffer, RX_DMA_FIFO_SIZE);
- if(length < 0)
- {
- LOG_E("Mic device read err\n");
- }
- res = check_filled_mem(0x55, (rt_uint8_t*)(&mic_buffer[0]), length);
- if(res != RT_EOK)
- {
- LOG_E("The second memory check failed! Buffer dump\n");
- for (rt_size_t i = 0; i < RX_DMA_FIFO_SIZE; i++)
- {
- rt_kprintf("%02X ",mic_buffer[i]);
- if (i % 16 == 15) rt_kprintf("\n");
- }
- rt_kprintf("\n");
- uassert_true(0);
- goto __exit;
- }
- break;
- }
- rt_thread_mdelay(100);
- }
- __exit:
- if (mic_buffer)
- {
- rt_free(mic_buffer);
- }
- if (dev_obj != RT_NULL)
- {
- audio_fsm_step = 4;
- rt_device_close(dev_obj);
- }
- }
- static void testcase(void)
- {
- UTEST_UNIT_RUN(player_test);
- UTEST_UNIT_RUN(mic_test);
- }
- static rt_err_t utest_tc_init(void)
- {
- return RT_EOK;
- }
- static rt_err_t utest_tc_cleanup(void)
- {
- return RT_EOK;
- }
- UTEST_TC_EXPORT(testcase, "components.drivers.audio.tc_audio_main", utest_tc_init, utest_tc_cleanup, 10);
|