Skip to content

Commit 6e25989

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 <[email protected]>
1 parent f0609c1 commit 6e25989

File tree

6 files changed

+666
-0
lines changed

6 files changed

+666
-0
lines changed

components/drivers/audio/Kconfig

+4
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,8 @@ config RT_USING_AUDIO
1414
config RT_AUDIO_RECORD_PIPE_SIZE
1515
int "Record pipe size"
1616
default 2048
17+
18+
config RT_UTEST_USING_AUDIO_DRIVER
19+
bool "Enable rt_audio_api testcase"
20+
default n
1721
endif
+13
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('RT_UTEST_USING_ALL_CASES') or GetDepend('RT_UTEST_USING_AUDIO_DRIVER'):
9+
src += Glob('TC_*.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,51 @@
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+
#include "utest.h"
15+
16+
/* DMA buffer of audio player device refresh is triggered only when the amount of transmitted data is
17+
* greater than the size of a single block in the data queue */
18+
#define TX_DMA_BLOCK_SIZE RT_AUDIO_REPLAY_MP_BLOCK_SIZE
19+
#define TX_DMA_FIFO_SIZE (RT_AUDIO_REPLAY_MP_BLOCK_SIZE * 2)
20+
#define RX_DMA_BLOCK_SIZE RT_AUDIO_RECORD_PIPE_SIZE
21+
#define RX_DMA_FIFO_SIZE (RT_AUDIO_RECORD_PIPE_SIZE * 2)
22+
23+
#define SOUND_PLAYER_DEVICE_NAME "sound0"
24+
#define SOUND_MIC_DEVICE_NAME "mic0"
25+
26+
#define PLAYER_SAMPLEBITS 16
27+
#define PLAYER_SAMPLERATE 16000
28+
#define PLAYER_CHANNEL 2
29+
#define PLAYER_VOLUME 30
30+
31+
#define MIC_SAMPLEBITS 16
32+
#define MIC_SAMPLERATE 16000
33+
#define MIC_CHANNEL 2
34+
#define MIC_TIME_MS 5000
35+
36+
extern rt_uint8_t mic_flag;
37+
extern rt_uint8_t player_flag ;
38+
39+
struct mic_device
40+
{
41+
struct rt_audio_device audio;
42+
struct rt_audio_configure config;
43+
rt_uint8_t *rx_fifo;
44+
};
45+
struct sound_device
46+
{
47+
struct rt_audio_device audio;
48+
struct rt_audio_configure config;
49+
rt_uint8_t volume;
50+
rt_uint8_t *tx_fifo;
51+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
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 "TC_rt_audio_common.h"
12+
13+
#define THREAD_PRIORITY 9
14+
#define THREAD_TIMESLICE 5
15+
#define thread_simulate_intr_create_stacksize 1024
16+
static rt_thread_t thread_simulate_intr_handle;
17+
18+
struct mic_device mic_dev;
19+
20+
rt_uint8_t mic_flag = 0;
21+
22+
/* Simulate callback function */
23+
static void thread_simulate_intr(void *parameter)
24+
{
25+
/* Send the data(0xAA) from DMA buffer to kernel */
26+
rt_memset((void*)&mic_dev.rx_fifo[0], 0xAA, RX_DMA_BLOCK_SIZE);
27+
rt_audio_rx_done((struct rt_audio_device *)&(mic_dev.audio), mic_dev.rx_fifo, RX_DMA_BLOCK_SIZE);
28+
mic_flag = 1;
29+
30+
while (1)
31+
{
32+
if(mic_flag == 2)
33+
{
34+
/* Send the the data(0x55) from DMA buffer to kernel */
35+
rt_memset((void*)&mic_dev.rx_fifo[RX_DMA_BLOCK_SIZE], 0x55, RX_DMA_BLOCK_SIZE);
36+
rt_audio_rx_done(&mic_dev.audio, &mic_dev.rx_fifo[RX_DMA_BLOCK_SIZE], RX_DMA_BLOCK_SIZE);
37+
mic_flag = 3;
38+
break;
39+
}
40+
if(mic_flag == 4)
41+
{
42+
rt_thread_mdelay(10);
43+
rt_audio_rx_done(&mic_dev.audio, &mic_dev.rx_fifo[RX_DMA_BLOCK_SIZE], RX_DMA_BLOCK_SIZE);
44+
break;
45+
}
46+
rt_thread_mdelay(10);
47+
}
48+
49+
while(1)
50+
{
51+
rt_thread_mdelay(10);
52+
}
53+
}
54+
55+
static void thread_simulate_intr_create(void)
56+
{
57+
thread_simulate_intr_handle = rt_thread_create(
58+
"thread_simulate_intr",
59+
thread_simulate_intr,
60+
RT_NULL,
61+
thread_simulate_intr_create_stacksize,
62+
THREAD_PRIORITY - 1, THREAD_TIMESLICE);
63+
64+
if (thread_simulate_intr_handle == RT_NULL)
65+
{
66+
rt_kprintf("Error: Failed to create thread!\n");
67+
return;
68+
}
69+
if (rt_thread_startup(thread_simulate_intr_handle) != RT_EOK)
70+
{
71+
rt_kprintf("Error: Failed to start thread!\n");
72+
thread_simulate_intr_handle = RT_NULL;
73+
}
74+
75+
}
76+
77+
static rt_err_t mic_device_init(struct rt_audio_device *audio)
78+
{
79+
return RT_EOK;
80+
}
81+
82+
/* Simulate DMA interrupt */
83+
static rt_err_t mic_device_start(struct rt_audio_device *audio, int stream)
84+
{
85+
thread_simulate_intr_create();
86+
return RT_EOK;
87+
}
88+
89+
static rt_err_t mic_device_stop(struct rt_audio_device *audio, int stream)
90+
{
91+
if (thread_simulate_intr_handle != RT_NULL)
92+
{
93+
rt_thread_delete(thread_simulate_intr_handle);
94+
thread_simulate_intr_handle = RT_NULL;
95+
}
96+
return RT_EOK;
97+
}
98+
99+
static rt_err_t mic_device_getcaps(struct rt_audio_device *audio, struct rt_audio_caps *caps)
100+
{
101+
return RT_EOK;
102+
}
103+
104+
static rt_err_t mic_device_configure(struct rt_audio_device *audio, struct rt_audio_caps *caps)
105+
{
106+
return RT_EOK;
107+
}
108+
109+
static struct rt_audio_ops _mic_audio_ops =
110+
{
111+
.getcaps = mic_device_getcaps,
112+
.configure = mic_device_configure,
113+
.init = mic_device_init,
114+
.start = mic_device_start,
115+
.stop = mic_device_stop,
116+
.transmit = RT_NULL,
117+
.buffer_info = RT_NULL,
118+
};
119+
120+
static int rt_hw_mic_init(void)
121+
{
122+
struct rt_audio_device *audio = &mic_dev.audio;
123+
/* mic default */
124+
mic_dev.rx_fifo = rt_malloc(RX_DMA_FIFO_SIZE);
125+
if (mic_dev.rx_fifo == RT_NULL)
126+
{
127+
return -RT_ENOMEM;
128+
}
129+
mic_dev.config.channels = MIC_CHANNEL;
130+
mic_dev.config.samplerate = MIC_SAMPLERATE;
131+
mic_dev.config.samplebits = MIC_SAMPLEBITS;
132+
133+
/* register mic device */
134+
audio->ops = &_mic_audio_ops;
135+
rt_audio_register(audio, SOUND_MIC_DEVICE_NAME, RT_DEVICE_FLAG_RDONLY, (void *)&mic_dev);
136+
137+
return RT_EOK;
138+
}
139+
INIT_DEVICE_EXPORT(rt_hw_mic_init);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
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 "TC_rt_audio_common.h"
12+
13+
#define THREAD_PRIORITY 9
14+
#define THREAD_TIMESLICE 5
15+
#define thread_simulate_intr_create_stacksize 1024
16+
static rt_thread_t thread_simulate_intr_handle;
17+
static struct sound_device snd_dev;
18+
19+
static void thread_simulate_intr(void *parameter)
20+
{
21+
rt_flag_t exec_once = 0;
22+
while(1)
23+
{
24+
if(player_flag == 1 && exec_once == 0)
25+
{
26+
/* Move the data(0xAA) from kernel to DMA buffer */
27+
rt_audio_tx_complete(&snd_dev.audio);
28+
player_flag = 2;
29+
exec_once = 1;
30+
rt_thread_mdelay(10);
31+
}
32+
else if(player_flag == 2 && exec_once == 1)
33+
{
34+
/* Move the data(0x55) from kernel to DMA buffer */
35+
rt_audio_tx_complete(&snd_dev.audio);
36+
player_flag = 3;
37+
rt_thread_mdelay(10);
38+
}
39+
else if(player_flag == 4)
40+
{
41+
/* rt_device_close will call rt_completion_wait(FOREVER), so we need delay to
42+
* let system run the point */
43+
rt_thread_mdelay(10);
44+
rt_audio_tx_complete(&snd_dev.audio);
45+
break;
46+
}
47+
rt_thread_mdelay(10);
48+
}
49+
while (1)
50+
{
51+
rt_thread_mdelay(10);
52+
}
53+
}
54+
55+
static void thread_simulate_intr_create(void)
56+
{
57+
thread_simulate_intr_handle = rt_thread_create(
58+
"thread_simulate_intr",
59+
thread_simulate_intr,
60+
RT_NULL,
61+
thread_simulate_intr_create_stacksize,
62+
THREAD_PRIORITY - 1, THREAD_TIMESLICE);
63+
64+
rt_thread_startup(thread_simulate_intr_handle);
65+
}
66+
67+
static rt_err_t player_device_init(struct rt_audio_device *audio)
68+
{
69+
return RT_EOK;
70+
}
71+
72+
/* Simulate DMA interrupt */
73+
static rt_err_t player_device_start(struct rt_audio_device *audio, int stream)
74+
{
75+
thread_simulate_intr_create();
76+
return RT_EOK;
77+
}
78+
79+
static rt_err_t player_device_stop(struct rt_audio_device *audio, int stream)
80+
{
81+
rt_thread_delete(thread_simulate_intr_handle);
82+
return RT_EOK;
83+
}
84+
85+
static rt_err_t player_device_getcaps(struct rt_audio_device *audio, struct rt_audio_caps *caps)
86+
{
87+
return RT_EOK;
88+
}
89+
90+
static rt_err_t player_device_configure(struct rt_audio_device *audio, struct rt_audio_caps *caps)
91+
{
92+
return RT_EOK;
93+
}
94+
95+
static rt_ssize_t player_device_transmit(struct rt_audio_device *audio, const void *writeBuf, void *readBuf, rt_size_t size)
96+
{
97+
return size;
98+
}
99+
100+
static void player_device_buffer_info(struct rt_audio_device *audio, struct rt_audio_buf_info *info)
101+
{
102+
RT_ASSERT(audio != RT_NULL);
103+
/**
104+
* TX_FIFO
105+
* +----------------+----------------+
106+
* | block1 | block2 |
107+
* +----------------+----------------+
108+
* \ block_size /
109+
*/
110+
info->buffer = snd_dev.tx_fifo;
111+
info->total_size = TX_DMA_FIFO_SIZE;
112+
info->block_size = TX_DMA_BLOCK_SIZE;
113+
info->block_count = RT_AUDIO_REPLAY_MP_BLOCK_COUNT;
114+
}
115+
116+
static struct rt_audio_ops audio_ops =
117+
{
118+
.getcaps = player_device_getcaps,
119+
.configure = player_device_configure,
120+
.init = player_device_init,
121+
.start = player_device_start,
122+
.stop = player_device_stop,
123+
.transmit = player_device_transmit,
124+
.buffer_info = player_device_buffer_info,
125+
};
126+
127+
static int rt_hw_sound_init(void)
128+
{
129+
rt_uint8_t *tx_fifo = RT_NULL;
130+
131+
tx_fifo = rt_malloc(TX_DMA_FIFO_SIZE);
132+
if (tx_fifo == NULL)
133+
{
134+
return -RT_ENOMEM;
135+
}
136+
snd_dev.tx_fifo = tx_fifo;
137+
138+
/* Init default configuration */
139+
{
140+
snd_dev.config.samplerate = PLAYER_SAMPLERATE;
141+
snd_dev.config.channels = PLAYER_CHANNEL;
142+
snd_dev.config.samplebits = PLAYER_SAMPLEBITS;
143+
snd_dev.volume = PLAYER_VOLUME;
144+
}
145+
146+
snd_dev.audio.ops = &audio_ops;
147+
rt_audio_register(&snd_dev.audio, SOUND_PLAYER_DEVICE_NAME, RT_DEVICE_FLAG_WRONLY, &snd_dev);
148+
return RT_EOK;
149+
}
150+
INIT_DEVICE_EXPORT(rt_hw_sound_init);

0 commit comments

Comments
 (0)