Skip to content

Commit 374389f

Browse files
committed
[RFC][utest] Add audio driver test framework
Achieve driver framework by operating memory to simulate audio peripheral drivers. And it could be as a draft standrad for other drivers test framework. Signed-off-by: 1078249029 <1078249029@qq.com>
1 parent f05f344 commit 374389f

File tree

7 files changed

+458
-0
lines changed

7 files changed

+458
-0
lines changed

examples/utest/testcases/Kconfig

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ rsource "kernel/Kconfig"
1212
rsource "cpp11/Kconfig"
1313
rsource "drivers/serial_v2/Kconfig"
1414
rsource "drivers/serial_bypass/Kconfig"
15+
rsource "drivers/audio/Kconfig"
1516
rsource "drivers/ipc/Kconfig"
1617
rsource "posix/Kconfig"
1718
rsource "mm/Kconfig"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
menu "Utest Driver Framewaork API Testcase"
2+
3+
config UTEST_AUDIO_TC
4+
bool "rt_audio_api testcase"
5+
default n
6+
7+
endmenu
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Import('rtconfig')
2+
from building import *
3+
4+
cwd = GetCurrentDir()
5+
src = []
6+
CPPPATH = [cwd]
7+
8+
if GetDepend(['UTEST_AUDIO_TC']):
9+
src += ['audio_tc.c', 'mic_drv.c', 'player_drv.c']
10+
11+
group = DefineGroup('utestcases', src, depend = ['RT_USING_UTESTCASES'], CPPPATH = CPPPATH)
12+
13+
Return('group')
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
/*
2+
* Copyright (c) 2006-2025 RT-Thread Development Team
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*
6+
* Change Logs:
7+
* Date Author Notes
8+
* 2025-05-01 wumingzi first version
9+
*/
10+
11+
#include "utest.h"
12+
#include "common.h"
13+
#include <string.h>
14+
15+
static rt_device_t dev_obj; /* Audio device handler */
16+
17+
/* Allocate and initialize memory filled by fill_byte */
18+
static void *alloc_filled_mem(rt_uint8_t fill_byte, size_t size)
19+
{
20+
void *ptr = malloc(size);
21+
if (ptr != NULL)
22+
{
23+
memset(ptr, fill_byte, size);
24+
}
25+
return ptr;
26+
}
27+
28+
/* Check if the memory is filled with fill_byte */
29+
static rt_err_t check_filled_mem(rt_uint8_t fill_byte, rt_uint8_t *mem, size_t size)
30+
{
31+
rt_uint8_t *p = mem;
32+
for (size_t i = 0; i < size; ++i)
33+
{
34+
if (p[i] != fill_byte)
35+
{
36+
return -RT_ERROR;
37+
}
38+
}
39+
return RT_EOK;
40+
}
41+
42+
static void player_test(void)
43+
{
44+
int fd = -1;
45+
int res = 0;
46+
uint8_t *buffer = NULL;
47+
void* player_buffer = NULL;struct rt_audio_caps caps = {0};
48+
49+
dev_obj = rt_device_find(SOUND_PLAYER_DEVICE_NAME);
50+
if (dev_obj == RT_NULL)
51+
{
52+
uassert_not_null(dev_obj);
53+
goto __exit;
54+
}
55+
if (dev_obj->type != RT_Device_Class_Sound)
56+
{
57+
LOG_I("Not an audio device!\n");
58+
goto __exit;
59+
}
60+
61+
res = rt_device_open(dev_obj, RT_DEVICE_OFLAG_WRONLY);
62+
if (res !=RT_EOK)
63+
{
64+
uassert_true(0);
65+
goto __exit;
66+
}
67+
68+
/* The sampling rate is set by the driver default, so there isn't configuration step */
69+
70+
struct rt_audio_device *audio_dev = (struct rt_audio_device *)dev_obj;
71+
72+
while (1)
73+
{
74+
rt_thread_mdelay(500);
75+
/* Init playerbuffer, it has 2 data blocks*/
76+
player_buffer = alloc_filled_mem(0xAA, BUFSZ);
77+
rt_device_write(dev_obj, 0, player_buffer, BUFSZ);
78+
player_buffer = alloc_filled_mem(0x55, BUFSZ);
79+
rt_device_write(dev_obj, BUFSZ, player_buffer, BUFSZ);
80+
81+
struct rt_audio_buf_info buf_info = audio_dev->replay->buf_info;
82+
83+
/* Check whether blocks is filled correctly */
84+
res = check_filled_mem(0xAA, &buf_info.buffer[0], BUFSZ);
85+
if (res !=RT_EOK)
86+
{
87+
LOG_I("Memory filled check init failurein player_test!\n");
88+
uassert_true(0);
89+
goto __exit;
90+
}
91+
res = check_filled_mem(0x55, &buf_info.buffer[BUFSZ], BUFSZ);
92+
if (res !=RT_EOK)
93+
{
94+
LOG_I("Memory filled check init failure in player_test!\n");
95+
uassert_true(0);
96+
goto __exit;
97+
}
98+
rt_thread_mdelay(1500);
99+
100+
/* Cover the first data block with 0x55 */
101+
player_buffer = alloc_filled_mem(0x55, BUFSZ);
102+
rt_device_write(dev_obj, 0, player_buffer, BUFSZ);
103+
/* Check rt_audio_rx_done is working properly or not. If it's working, the first block
104+
* in &buf_info->buffer will remained the value, 0x55 */
105+
res = check_filled_mem(0x55, &buf_info.buffer[0], BUFSZ);
106+
if (res !=RT_EOK)
107+
{
108+
LOG_I("Memory filled check init failure in player_test!\n");
109+
uassert_true(0);
110+
goto __exit;
111+
}
112+
}
113+
114+
rt_device_close(dev_obj);
115+
116+
__exit:
117+
118+
if (buffer)
119+
rt_free(buffer);
120+
121+
if (player_buffer)
122+
rt_free(player_buffer);
123+
}
124+
125+
static void mic_test(void)
126+
{
127+
int fd = -1;
128+
int res = 0;
129+
uint8_t *mic_buffer = NULL;
130+
struct rt_audio_caps caps = {0};
131+
int length, total_length = 0;
132+
133+
mic_buffer = rt_malloc(RX_DMA_FIFO_SIZE);
134+
if (mic_buffer == RT_NULL)
135+
goto __exit;
136+
137+
dev_obj = rt_device_find(SOUND_MIC_DEVICE_NAME);
138+
if (dev_obj == RT_NULL)
139+
goto __exit;
140+
141+
rt_device_open(dev_obj, RT_DEVICE_OFLAG_RDONLY);
142+
143+
rt_device_control(dev_obj, AUDIO_CTL_CONFIGURE, &caps);
144+
145+
while (1)
146+
{
147+
struct rt_audio_device *audio_dev = (struct rt_audio_device *)dev_obj;
148+
struct mic_device *mic_dev = (struct mic_device *)audio_dev->parent.user_data;
149+
150+
/* Delay for preparing the data(0xAA) provided by driver */
151+
rt_thread_mdelay(500);
152+
length = rt_device_read(dev_obj, 0, mic_buffer, RX_DMA_FIFO_SIZE);
153+
/* Check the memory has been changed whether or not */
154+
res = check_filled_mem(0x55, (rt_uint8_t*)(&mic_dev->rx_fifo[0]), length);
155+
if (res !=RT_EOK)
156+
{
157+
LOG_I("Memory filled check init failure in mic_test!\n");
158+
uassert_true(0);
159+
goto __exit;
160+
}
161+
/* Delay for changing the data from 0xAA to 0x55 provided by driver */
162+
rt_thread_mdelay(1000);
163+
length = rt_device_read(dev_obj, 0, mic_buffer, RX_DMA_FIFO_SIZE);
164+
res = check_filled_mem(0x55, (rt_uint8_t*)(&mic_dev->rx_fifo[0]), length);
165+
if (res !=RT_EOK)
166+
{
167+
LOG_I("Memory filled check init failure in mic_test!\n");
168+
uassert_true(0);
169+
goto __exit;
170+
}
171+
}
172+
173+
rt_device_close(dev_obj);
174+
175+
__exit:
176+
if (mic_buffer)
177+
rt_free(mic_buffer);
178+
}
179+
180+
static void testcase(void)
181+
{
182+
UTEST_UNIT_RUN(player_test);
183+
UTEST_UNIT_RUN(mic_test);
184+
}
185+
186+
static rt_err_t utest_tc_init(void)
187+
{
188+
return RT_EOK;
189+
}
190+
191+
static rt_err_t utest_tc_cleanup(void)
192+
{
193+
return RT_EOK;
194+
}
195+
196+
UTEST_TC_EXPORT(testcase, "testcases.drivers.audio.audio_tc", utest_tc_init, utest_tc_cleanup, 10);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright (c) 2006-2025 RT-Thread Development Team
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*
6+
* Change Logs:
7+
* Date Author Notes
8+
* 2025-05-02 wumingzi first version
9+
*/
10+
11+
#include <rtthread.h>
12+
#include <rtdevice.h>
13+
#include <rttypes.h>
14+
15+
#define BUFSZ TX_DMA_FIFO_SIZE / 2
16+
#define SOUND_PLAYER_DEVICE_NAME "sound0" /* Audio 设备名称 */
17+
18+
#define MIC_SAMPLEBITS 16
19+
#define MIC_SAMPLERATE 16000
20+
#define MIC_CHANNEL 2
21+
#define RX_DMA_FIFO_SIZE 2048
22+
#define MIC_TIME_MS 5000
23+
24+
#define PLAYER_SAMPLEBITS 16
25+
#define PLAYER_SAMPLERATE 16000
26+
#define PLAYER_CHANNEL 2
27+
#define TX_DMA_FIFO_SIZE 2048
28+
#define PLAYER_VOLUME 30
29+
#define SOUND_MIC_DEVICE_NAME "mic0" /* Audio 设备名称 */
30+
31+
struct mic_device
32+
{
33+
struct rt_audio_device audio;
34+
struct rt_audio_configure config;
35+
rt_uint8_t *rx_fifo;
36+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/*
2+
* Copyright (c) 2006-2025 RT-Thread Development Team
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*
6+
* Change Logs:
7+
* Date Author Notes
8+
* 2025-05-02 wumingzi First version
9+
*/
10+
11+
#include "common.h"
12+
#include <string.h>
13+
14+
struct mic_device mic_dev;
15+
16+
/* Simulate callback function */
17+
void dmic_dma_transfer_callback_test(void *userData)
18+
{
19+
struct mic_device *mic_dev = (struct mic_device *)userData;
20+
21+
rt_audio_rx_done(&mic_dev->audio, mic_dev->rx_fifo, RX_DMA_FIFO_SIZE);
22+
}
23+
24+
rt_err_t mic_device_init(struct rt_audio_device *audio)
25+
{
26+
return RT_EOK;
27+
}
28+
29+
/* Simulate generating mic data */
30+
rt_err_t mic_device_start(struct rt_audio_device *audio, int stream)
31+
{
32+
struct mic_device *mic_dev = (struct mic_device *)audio->parent.user_data;
33+
if (stream == AUDIO_STREAM_RECORD)
34+
{
35+
memset((void*)&mic_dev->rx_fifo[0], 0xAA, RX_DMA_FIFO_SIZE);
36+
dmic_dma_transfer_callback_test((void*)&mic_dev);
37+
rt_thread_mdelay(1000);
38+
memset((void*)&mic_dev->rx_fifo[0], 0x55, RX_DMA_FIFO_SIZE);
39+
dmic_dma_transfer_callback_test((void*)&mic_dev);
40+
}
41+
return RT_EOK;
42+
}
43+
44+
rt_err_t mic_device_stop(struct rt_audio_device *audio, int stream)
45+
{
46+
return RT_EOK;
47+
}
48+
49+
rt_err_t mic_device_getcaps(struct rt_audio_device *audio, struct rt_audio_caps *caps)
50+
{
51+
return RT_EOK;
52+
}
53+
54+
rt_err_t mic_device_configure(struct rt_audio_device *audio, struct rt_audio_caps *caps)
55+
{
56+
return RT_EOK;
57+
}
58+
59+
static struct rt_audio_ops _mic_audio_ops =
60+
{
61+
.getcaps = mic_device_getcaps,
62+
.configure = mic_device_configure,
63+
.init = mic_device_init,
64+
.start = mic_device_start,
65+
.stop = mic_device_stop,
66+
.transmit = RT_NULL,
67+
.buffer_info = RT_NULL,
68+
};
69+
70+
int rt_hw_mic_init(void)
71+
{
72+
struct rt_audio_device *audio = &mic_dev.audio;
73+
/* mic default */
74+
mic_dev.rx_fifo = rt_calloc(1, RX_DMA_FIFO_SIZE);
75+
if (mic_dev.rx_fifo == RT_NULL)
76+
{
77+
return -RT_ENOMEM;
78+
}
79+
mic_dev.config.channels = MIC_CHANNEL;
80+
mic_dev.config.samplerate = MIC_SAMPLERATE;
81+
mic_dev.config.samplebits = MIC_SAMPLEBITS;
82+
83+
/* register mic device */
84+
audio->ops = &_mic_audio_ops;
85+
rt_audio_register(audio, SOUND_MIC_DEVICE_NAME, RT_DEVICE_FLAG_RDONLY, (void *)&mic_dev);
86+
87+
return RT_EOK;
88+
}
89+
INIT_DEVICE_EXPORT(rt_hw_mic_init);

0 commit comments

Comments
 (0)