Skip to content

[RFC][utest] Add audio driver test framework #10243

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/utest/testcases/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ rsource "kernel/Kconfig"
rsource "cpp11/Kconfig"
rsource "drivers/serial_v2/Kconfig"
rsource "drivers/serial_bypass/Kconfig"
rsource "drivers/audio/Kconfig"
rsource "drivers/ipc/Kconfig"
rsource "posix/Kconfig"
rsource "mm/Kconfig"
Expand Down
7 changes: 7 additions & 0 deletions examples/utest/testcases/drivers/audio/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
menu "Utest Driver Framewaork API Testcase"

config UTEST_AUDIO_TC
bool "rt_audio_api testcase"
default n

endmenu
13 changes: 13 additions & 0 deletions examples/utest/testcases/drivers/audio/SConscript
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Import('rtconfig')
from building import *

cwd = GetCurrentDir()
src = []
CPPPATH = [cwd]

if GetDepend(['UTEST_AUDIO_TC']):
src += ['audio_tc.c', 'drv_mic.c', 'drv_player.c']

group = DefineGroup('utestcases', src, depend = ['RT_USING_UTESTCASES'], CPPPATH = CPPPATH)

Return('group')
291 changes: 291 additions & 0 deletions examples/utest/testcases/drivers/audio/audio_tc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,291 @@
/*
* 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
*/

#include "common.h"

rt_uint8_t player_flag = 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;
}

player_flag = 1;
while (1)
{
if(player_flag == 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;
}

player_flag = 2;
while (res != RT_EOK)
{
if(player_flag == 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)
{
player_flag = 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(mic_flag == 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;
}
mic_flag = 2;

while (1)
{
if(mic_flag == 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)
{
mic_flag = 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, "testcases.drivers.audio.audio_tc", utest_tc_init, utest_tc_cleanup, 10);
51 changes: 51 additions & 0 deletions examples/utest/testcases/drivers/audio/common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright (c) 2006-2025 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2025-05-02 wumingzi first version
*/

#include <rtthread.h>
#include <rtdevice.h>
#include <rttypes.h>
#include "utest.h"

/* DMA buffer of audio player device refresh is triggered only when the amount of transmitted data is
* greater than the size of a single block in the data queue */
#define TX_DMA_BLOCK_SIZE RT_AUDIO_REPLAY_MP_BLOCK_SIZE
#define TX_DMA_FIFO_SIZE (RT_AUDIO_REPLAY_MP_BLOCK_SIZE * 2)
#define RX_DMA_BLOCK_SIZE RT_AUDIO_RECORD_PIPE_SIZE
#define RX_DMA_FIFO_SIZE (RT_AUDIO_RECORD_PIPE_SIZE * 2)

#define SOUND_PLAYER_DEVICE_NAME "sound0"
#define SOUND_MIC_DEVICE_NAME "mic0"

#define PLAYER_SAMPLEBITS 16
#define PLAYER_SAMPLERATE 16000
#define PLAYER_CHANNEL 2
#define PLAYER_VOLUME 30

#define MIC_SAMPLEBITS 16
#define MIC_SAMPLERATE 16000
#define MIC_CHANNEL 2
#define MIC_TIME_MS 5000

extern rt_uint8_t mic_flag;
extern rt_uint8_t player_flag ;

struct mic_device
{
struct rt_audio_device audio;
struct rt_audio_configure config;
rt_uint8_t *rx_fifo;
};
struct sound_device
{
struct rt_audio_device audio;
struct rt_audio_configure config;
rt_uint8_t volume;
rt_uint8_t *tx_fifo;
};
Loading
Loading