tc_audio_main.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  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. * 2025-11-24 ChuanN-sudo add standardized utest documentation block
  10. */
  11. /**
  12. * Test Case Name: Audio Test
  13. *
  14. * Test Objectives:
  15. * - Validate RT-Thread audio driver framework registration and data flow mechanisms.
  16. * - Verify audio playback (TX) and recording (RX) data transmission correctness.
  17. * - Ensure proper buffer management and memory integrity during audio operations.
  18. * - Test core APIs: rt_audio_register(), rt_audio_tx_complete(), rt_audio_rx_done()
  19. *
  20. * Test Scenarios:
  21. * - Locate audio devices using SOUND_PLAYER_DEVICE_NAME and SOUND_MIC_DEVICE_NAME macros.
  22. * - Write known byte patterns (0xAA, 0x55) to simulate audio data flow through TX/RX buffers.
  23. * - Synchronize player and microphone test execution using audio_fsm_step state machine.
  24. * - Test two consecutive block transfers for both TX and RX paths.
  25. *
  26. * Verification Metrics:
  27. * - Written audio data appears correctly in device TX buffers with exact byte patterns.
  28. * - Data read from microphone device matches expected fill patterns (0xAA then 0x55) without corruption.
  29. * - Buffer boundaries are respected with no overflow or underflow conditions.
  30. * - Device open/close operations complete successfully without resource leaks.
  31. *
  32. * Dependencies:
  33. * - Hardware requirements: QEMU emulator or any hardware platform that supports RT-Thread.
  34. * - Software configuration:
  35. * - RT_USING_UTESTCASES must be enabled (select "RT-Thread Utestcases" in menuconfig).
  36. * - RT_USING_AUDIO must be enabled (enable via: RT-Thread Components -> Device Drivers -> Using Audio device drivers).
  37. * - RT_UTEST_USING_AUDIO_DRIVER must be enabled (enable via: RT-Thread Utestcases -> Kernel Components-> Drivers -> Audio Test).
  38. * - Environmental Assumptions: Audio devices registered and functional, sufficient memory available.
  39. *
  40. * Expected Results:
  41. * - Final output: "[ PASSED ] [ result ] testcase (components.drivers.audio.tc_audio_main)"
  42. * - No memory leaks detected during buffer allocation/deallocation.
  43. * - No assertions triggered during test execution.
  44. * - Buffer content verification passes for all test patterns.
  45. */
  46. #include "tc_audio_common.h"
  47. rt_uint8_t audio_fsm_step = 0;
  48. /* Allocate and initialize memory filled by fill_byte */
  49. static void *alloc_filled_mem(rt_uint8_t fill_byte, rt_size_t size)
  50. {
  51. void *ptr = rt_malloc(size);
  52. if (ptr != NULL)
  53. {
  54. rt_memset(ptr, fill_byte, size);
  55. }
  56. return ptr;
  57. }
  58. /* Check if the memory is filled with fill_byte */
  59. static rt_err_t check_filled_mem(rt_uint8_t fill_byte, rt_uint8_t *mem, size_t size)
  60. {
  61. rt_uint8_t *p = mem;
  62. for (size_t i = 0; i < size; ++i)
  63. {
  64. if (*(p+i) != fill_byte)
  65. {
  66. return -RT_ERROR;
  67. }
  68. }
  69. return RT_EOK;
  70. }
  71. static void player_test(void)
  72. {
  73. int res = 0;
  74. void* player_buffer = RT_NULL;
  75. rt_device_t dev_obj;
  76. dev_obj = rt_device_find(SOUND_PLAYER_DEVICE_NAME);
  77. if (dev_obj == RT_NULL)
  78. {
  79. uassert_not_null(dev_obj);
  80. goto __exit;
  81. }
  82. if (dev_obj->type != RT_Device_Class_Sound)
  83. {
  84. LOG_E("Not an audio player device\n");
  85. goto __exit;
  86. }
  87. res = rt_device_open(dev_obj, RT_DEVICE_OFLAG_WRONLY);
  88. if (res != RT_EOK)
  89. {
  90. LOG_E("Audio player device failed\n");
  91. uassert_true(0);
  92. goto __exit;
  93. }
  94. /* The sampling rate is set by the driver default, so there isn't configuration step */
  95. struct rt_audio_device *audio_dev = rt_container_of(dev_obj, struct rt_audio_device, parent);
  96. struct rt_audio_buf_info buf_info = audio_dev->replay->buf_info;
  97. struct sound_device *snd_dev = rt_container_of(audio_dev, struct sound_device, audio);
  98. player_buffer = alloc_filled_mem(0xAA, TX_DMA_BLOCK_SIZE);
  99. if (player_buffer == RT_NULL)
  100. {
  101. rt_kprintf("Allocate test memory failed\n");
  102. uassert_true(0);
  103. goto __exit;
  104. }
  105. if(snd_dev->tx_fifo == RT_NULL)
  106. {
  107. rt_kprintf("snd_dev->tx_fifo == RT_NULL ");
  108. uassert_true(0);
  109. goto __exit;
  110. }
  111. res = rt_device_write(dev_obj, 0, player_buffer, TX_DMA_BLOCK_SIZE);
  112. if (res != RT_EOK && res != TX_DMA_BLOCK_SIZE)
  113. {
  114. rt_kprintf("Failed to write data to the player device, res = %d\n",res);
  115. uassert_true(0);
  116. goto __exit;
  117. }
  118. audio_fsm_step = 1;
  119. while (1)
  120. {
  121. if(audio_fsm_step == 2)
  122. {
  123. break;
  124. }
  125. rt_thread_mdelay(10);
  126. }
  127. res = check_filled_mem(0xAA, &buf_info.buffer[0], TX_DMA_BLOCK_SIZE);
  128. if (res != RT_EOK)
  129. {
  130. rt_kprintf("The first memory check failed! Buffer dump\n");
  131. for (rt_size_t i = 0; i < TX_DMA_FIFO_SIZE; i++)
  132. {
  133. rt_kprintf("%02X ", buf_info.buffer[i]);
  134. if (i % 16 == 15) rt_kprintf("\n");
  135. }
  136. rt_kprintf("\n");
  137. uassert_true(0);
  138. goto __exit;
  139. }
  140. rt_free(player_buffer);
  141. player_buffer = RT_NULL;
  142. player_buffer = alloc_filled_mem(0x55, TX_DMA_BLOCK_SIZE);
  143. if (player_buffer == RT_NULL)
  144. {
  145. rt_kprintf("Allocate test memory failed\n");
  146. uassert_true(0);
  147. goto __exit;
  148. }
  149. res = rt_device_write(dev_obj, TX_DMA_BLOCK_SIZE, player_buffer, TX_DMA_BLOCK_SIZE);
  150. if (res != RT_EOK && res != TX_DMA_BLOCK_SIZE)
  151. {
  152. rt_kprintf("Failed to write data to the player device, res = %d\n",res);
  153. uassert_true(0);
  154. goto __exit;
  155. }
  156. audio_fsm_step = 2;
  157. while (res != RT_EOK)
  158. {
  159. if(audio_fsm_step == 3)
  160. {
  161. break;
  162. }
  163. rt_thread_mdelay(10);
  164. }
  165. res = check_filled_mem(0x55,&buf_info.buffer[TX_DMA_BLOCK_SIZE], TX_DMA_BLOCK_SIZE);
  166. if (res != RT_EOK)
  167. {
  168. rt_kprintf("The second memory check failed! Buffer dump\n");
  169. for (rt_size_t i = 0; i < TX_DMA_FIFO_SIZE; i++)
  170. {
  171. rt_kprintf("%02X ", buf_info.buffer[i]);
  172. if (i % 16 == 15) rt_kprintf("\n");
  173. }
  174. rt_kprintf("\n");
  175. uassert_true(0);
  176. goto __exit;
  177. }
  178. __exit:
  179. if (player_buffer)
  180. {
  181. rt_free(player_buffer);
  182. player_buffer = RT_NULL;
  183. }
  184. if (dev_obj != RT_NULL)
  185. {
  186. audio_fsm_step = 4;
  187. rt_device_close(dev_obj);
  188. }
  189. }
  190. static void mic_test(void)
  191. {
  192. rt_device_t dev_obj;
  193. rt_uint8_t *mic_buffer = RT_NULL;
  194. rt_ssize_t res = 0;
  195. rt_ssize_t length = 0;
  196. mic_buffer = (rt_uint8_t *)rt_malloc(RX_DMA_BLOCK_SIZE);
  197. if (mic_buffer == RT_NULL)
  198. {
  199. rt_kprintf("The mic_buffer memory allocate failed\n");
  200. uassert_true(0);
  201. goto __exit;
  202. }
  203. dev_obj = rt_device_find(SOUND_MIC_DEVICE_NAME);
  204. if (dev_obj == RT_NULL)
  205. {
  206. LOG_E("Not a mic device\n");
  207. uassert_true(0);
  208. goto __exit;
  209. }
  210. res = rt_device_open(dev_obj, RT_DEVICE_OFLAG_RDONLY);
  211. if (res != RT_EOK)
  212. {
  213. LOG_E("Audio player device failed\n");
  214. uassert_true(0);
  215. goto __exit;
  216. }
  217. length = rt_device_read(dev_obj, 0, mic_buffer,RX_DMA_BLOCK_SIZE);
  218. if(length < 0)
  219. {
  220. LOG_E("Mic device read err\n");
  221. }
  222. if(audio_fsm_step == 1)
  223. {
  224. res = check_filled_mem(0xAA, (rt_uint8_t*)(mic_buffer), length);
  225. }
  226. if (res != RT_EOK)
  227. {
  228. LOG_E("The first memory check failed! Buffer dump\n");
  229. for (rt_size_t i = 0; i < RX_DMA_FIFO_SIZE; i++)
  230. {
  231. rt_kprintf("%02X ",mic_buffer[i]);
  232. if (i % 16 == 15) rt_kprintf("\n");
  233. }
  234. rt_kprintf("\n");
  235. uassert_true(0);
  236. goto __exit;
  237. }
  238. audio_fsm_step = 2;
  239. while (1)
  240. {
  241. if(audio_fsm_step == 3)
  242. {
  243. length = rt_device_read(dev_obj, 0, mic_buffer, RX_DMA_FIFO_SIZE);
  244. if(length < 0)
  245. {
  246. LOG_E("Mic device read err\n");
  247. }
  248. res = check_filled_mem(0x55, (rt_uint8_t*)(&mic_buffer[0]), length);
  249. if(res != RT_EOK)
  250. {
  251. LOG_E("The second memory check failed! Buffer dump\n");
  252. for (rt_size_t i = 0; i < RX_DMA_FIFO_SIZE; i++)
  253. {
  254. rt_kprintf("%02X ",mic_buffer[i]);
  255. if (i % 16 == 15) rt_kprintf("\n");
  256. }
  257. rt_kprintf("\n");
  258. uassert_true(0);
  259. goto __exit;
  260. }
  261. break;
  262. }
  263. rt_thread_mdelay(100);
  264. }
  265. __exit:
  266. if (mic_buffer)
  267. {
  268. rt_free(mic_buffer);
  269. }
  270. if (dev_obj != RT_NULL)
  271. {
  272. audio_fsm_step = 4;
  273. rt_device_close(dev_obj);
  274. }
  275. }
  276. static void testcase(void)
  277. {
  278. UTEST_UNIT_RUN(player_test);
  279. UTEST_UNIT_RUN(mic_test);
  280. }
  281. static rt_err_t utest_tc_init(void)
  282. {
  283. return RT_EOK;
  284. }
  285. static rt_err_t utest_tc_cleanup(void)
  286. {
  287. return RT_EOK;
  288. }
  289. UTEST_TC_EXPORT(testcase, "components.drivers.audio.tc_audio_main", utest_tc_init, utest_tc_cleanup, 10);