Skip to content

Commit af43487

Browse files
nordic-seglkartben
authored andcommitted
tests: boards: nrf: i2s: i2s_divider: Confirm CLK divider value
Frame rate selected by the user may not be obtained due to PCLK frequency and finite number of clock divider values. In such case, driver shall select divider that results in frame clock rate closest to the requested value. There was a bug that was discarding perfect match divider. Add test which confirms correct clock divider selection. Signed-off-by: Sebastian Głąb <sebastian.glab@nordicsemi.no>
1 parent b991632 commit af43487

File tree

7 files changed

+299
-0
lines changed

7 files changed

+299
-0
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
cmake_minimum_required(VERSION 3.20.0)
4+
5+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
6+
project(i2s_divider)
7+
8+
FILE(GLOB app_sources src/*.c)
9+
target_sources(app PRIVATE ${app_sources})
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright (c) 2025 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
/ {
8+
aliases {
9+
i2s-node0 = &i2s0;
10+
};
11+
};
12+
13+
&pinctrl {
14+
i2s0_default_alt: i2s0_default_alt {
15+
group1 {
16+
psels = <NRF_PSEL(I2S_SCK_M, 1, 5)>,
17+
<NRF_PSEL(I2S_LRCK_M, 1, 6)>,
18+
<NRF_PSEL(I2S_SDOUT, 1, 1)>,
19+
<NRF_PSEL(I2S_SDIN, 1, 2)>;
20+
};
21+
};
22+
};
23+
24+
&i2s0 {
25+
status = "okay";
26+
pinctrl-0 = <&i2s0_default_alt>;
27+
pinctrl-names = "default";
28+
};
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright (c) 2025 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
/ {
8+
aliases {
9+
i2s-node0 = &i2s0;
10+
};
11+
};
12+
13+
&pinctrl {
14+
i2s0_default_alt: i2s0_default_alt {
15+
group1 {
16+
psels = <NRF_PSEL(I2S_SCK_M, 1, 6)>,
17+
<NRF_PSEL(I2S_LRCK_M, 1, 7)>,
18+
<NRF_PSEL(I2S_SDOUT, 0, 4)>,
19+
<NRF_PSEL(I2S_SDIN, 0, 5)>;
20+
};
21+
};
22+
};
23+
24+
&uart1 {
25+
status = "disabled";
26+
};
27+
28+
&i2s0 {
29+
status = "okay";
30+
pinctrl-0 = <&i2s0_default_alt>;
31+
pinctrl-names = "default";
32+
};
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright (c) 2025 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
/ {
8+
aliases {
9+
i2s-node0 = &i2s20;
10+
};
11+
};
12+
13+
&pinctrl {
14+
i2s20_default_alt: i2s20_default_alt {
15+
group1 {
16+
psels = <NRF_PSEL(I2S_SCK_M, 1, 11)>,
17+
<NRF_PSEL(I2S_LRCK_M, 1, 12)>,
18+
<NRF_PSEL(I2S_SDOUT, 1, 8)>,
19+
<NRF_PSEL(I2S_SDIN, 1, 9)>;
20+
};
21+
};
22+
};
23+
24+
&i2s20 {
25+
status = "okay";
26+
pinctrl-0 = <&i2s20_default_alt>;
27+
pinctrl-names = "default";
28+
};
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
CONFIG_ZTEST=y
2+
CONFIG_I2S=y
3+
CONFIG_I2S_LOG_LEVEL_INF=y
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
/*
2+
* Copyright (c) 2025 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr/kernel.h>
8+
#include <zephyr/ztest.h>
9+
#include <zephyr/drivers/i2s.h>
10+
#include <zephyr/sys/iterable_sections.h>
11+
12+
#define I2S_DEV_NODE DT_ALIAS(i2s_node0)
13+
14+
#define WORD_SIZE 16U
15+
#define NUMBER_OF_CHANNELS 2
16+
#define FRAME_CLK_FREQ 44100
17+
18+
#define NUM_BLOCKS 2
19+
#define TIMEOUT 1000
20+
21+
#define SAMPLES_COUNT 4
22+
/* Each word has one bit set */
23+
static const int16_t data[SAMPLES_COUNT] = {16, 32, 64, 128};
24+
25+
#define BLOCK_SIZE (2 * sizeof(data))
26+
27+
#ifdef CONFIG_NOCACHE_MEMORY
28+
#define MEM_SLAB_CACHE_ATTR __nocache
29+
#else
30+
#define MEM_SLAB_CACHE_ATTR
31+
#endif /* CONFIG_NOCACHE_MEMORY */
32+
33+
static char MEM_SLAB_CACHE_ATTR __aligned(WB_UP(32))
34+
_k_mem_slab_buf_tx_0_mem_slab[NUM_BLOCKS * WB_UP(BLOCK_SIZE)];
35+
STRUCT_SECTION_ITERABLE(k_mem_slab, tx_0_mem_slab) =
36+
Z_MEM_SLAB_INITIALIZER(tx_0_mem_slab, _k_mem_slab_buf_tx_0_mem_slab,
37+
WB_UP(BLOCK_SIZE), NUM_BLOCKS);
38+
39+
static const struct device *dev_i2s;
40+
41+
static const struct i2s_config default_i2s_cfg = {
42+
.word_size = WORD_SIZE,
43+
.channels = NUMBER_OF_CHANNELS,
44+
.format = I2S_FMT_DATA_FORMAT_I2S,
45+
.frame_clk_freq = FRAME_CLK_FREQ,
46+
.block_size = BLOCK_SIZE,
47+
.timeout = TIMEOUT,
48+
.options = I2S_OPT_FRAME_CLK_MASTER | I2S_OPT_BIT_CLK_MASTER,
49+
.mem_slab = &tx_0_mem_slab,
50+
};
51+
52+
/** @brief Check actual PCM rate at frame_clk_freq=8000.
53+
*
54+
* - Configure I2S stream.
55+
*/
56+
ZTEST(drivers_i2s_clk_div, test_i2s_frame_clk_freq_08000)
57+
{
58+
struct i2s_config i2s_cfg = default_i2s_cfg;
59+
int ret;
60+
61+
i2s_cfg.frame_clk_freq = 8000;
62+
63+
ret = i2s_configure(dev_i2s, I2S_DIR_TX, &i2s_cfg);
64+
zassert_ok(ret, "i2s_configure() returned %d", ret);
65+
}
66+
67+
/** @brief Check actual PCM rate at frame_clk_freq=16000.
68+
*
69+
* - Configure I2S stream.
70+
*/
71+
ZTEST(drivers_i2s_clk_div, test_i2s_frame_clk_freq_16000)
72+
{
73+
struct i2s_config i2s_cfg = default_i2s_cfg;
74+
int ret;
75+
76+
i2s_cfg.frame_clk_freq = 16000;
77+
78+
ret = i2s_configure(dev_i2s, I2S_DIR_TX, &i2s_cfg);
79+
zassert_ok(ret, "i2s_configure() returned %d", ret);
80+
}
81+
82+
/** @brief Check actual PCM rate at frame_clk_freq=32000.
83+
*
84+
* - Configure I2S stream.
85+
*/
86+
ZTEST(drivers_i2s_clk_div, test_i2s_frame_clk_freq_32000)
87+
{
88+
struct i2s_config i2s_cfg = default_i2s_cfg;
89+
int ret;
90+
91+
i2s_cfg.frame_clk_freq = 32000;
92+
93+
ret = i2s_configure(dev_i2s, I2S_DIR_TX, &i2s_cfg);
94+
zassert_ok(ret, "i2s_configure() returned %d", ret);
95+
}
96+
97+
/** @brief Check actual PCM rate at frame_clk_freq=44100.
98+
*
99+
* - Configure I2S stream.
100+
*/
101+
ZTEST(drivers_i2s_clk_div, test_i2s_frame_clk_freq_44100)
102+
{
103+
struct i2s_config i2s_cfg = default_i2s_cfg;
104+
int ret;
105+
106+
i2s_cfg.frame_clk_freq = 44100;
107+
108+
ret = i2s_configure(dev_i2s, I2S_DIR_TX, &i2s_cfg);
109+
zassert_ok(ret, "i2s_configure() returned %d", ret);
110+
}
111+
112+
/** @brief Check actual PCM rate at frame_clk_freq=48000.
113+
*
114+
* - Configure I2S stream.
115+
*/
116+
ZTEST(drivers_i2s_clk_div, test_i2s_frame_clk_freq_48000)
117+
{
118+
struct i2s_config i2s_cfg = default_i2s_cfg;
119+
int ret;
120+
121+
i2s_cfg.frame_clk_freq = 48000;
122+
123+
ret = i2s_configure(dev_i2s, I2S_DIR_TX, &i2s_cfg);
124+
zassert_ok(ret, "i2s_configure() returned %d", ret);
125+
}
126+
127+
/** @brief Check actual PCM rate at frame_clk_freq=88200.
128+
*
129+
* - Configure I2S stream.
130+
*/
131+
ZTEST(drivers_i2s_clk_div, test_i2s_frame_clk_freq_88200)
132+
{
133+
struct i2s_config i2s_cfg = default_i2s_cfg;
134+
int ret;
135+
136+
i2s_cfg.frame_clk_freq = 88200;
137+
138+
ret = i2s_configure(dev_i2s, I2S_DIR_TX, &i2s_cfg);
139+
zassert_ok(ret, "i2s_configure() returned %d", ret);
140+
}
141+
142+
/** @brief Check actual PCM rate at frame_clk_freq=96000.
143+
*
144+
* - Configure I2S stream.
145+
*/
146+
ZTEST(drivers_i2s_clk_div, test_i2s_frame_clk_freq_96000)
147+
{
148+
struct i2s_config i2s_cfg = default_i2s_cfg;
149+
int ret;
150+
151+
i2s_cfg.frame_clk_freq = 96000;
152+
153+
ret = i2s_configure(dev_i2s, I2S_DIR_TX, &i2s_cfg);
154+
zassert_ok(ret, "i2s_configure() returned %d", ret);
155+
}
156+
157+
static void *suite_setup(void)
158+
{
159+
/* Check I2S Device. */
160+
dev_i2s = DEVICE_DT_GET_OR_NULL(I2S_DEV_NODE);
161+
zassert_not_null(dev_i2s, "I2S device not found");
162+
zassert(device_is_ready(dev_i2s), "I2S device not ready");
163+
164+
return 0;
165+
}
166+
167+
ZTEST_SUITE(drivers_i2s_clk_div, NULL, suite_setup, NULL, NULL, NULL);
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
tests:
2+
boards.nrf.i2s.i2s_divider:
3+
tags:
4+
- drivers
5+
- i2s
6+
harness: console
7+
harness_config:
8+
type: multi_line
9+
ordered: true
10+
regex:
11+
- "test_i2s_frame_clk_freq_08000"
12+
- "I2S MCK frequency: 256000, actual PCM rate: 8000"
13+
- "test_i2s_frame_clk_freq_16000"
14+
- "I2S MCK frequency: 507936, actual PCM rate: 15873"
15+
- "test_i2s_frame_clk_freq_32000"
16+
- "I2S MCK frequency: 1032258, actual PCM rate: 32258"
17+
- "test_i2s_frame_clk_freq_44100"
18+
- "I2S MCK frequency: 1391304, actual PCM rate: 43478"
19+
- "test_i2s_frame_clk_freq_48000"
20+
- "I2S MCK frequency: 1523809, actual PCM rate: 47619"
21+
- "test_i2s_frame_clk_freq_88200"
22+
- "I2S MCK frequency: 2909090, actual PCM rate: 90909"
23+
- "test_i2s_frame_clk_freq_96000"
24+
- "I2S MCK frequency: 3200000, actual PCM rate: 100000"
25+
- "PROJECT EXECUTION SUCCESSFUL"
26+
platform_allow:
27+
- nrf52840dk/nrf52840
28+
- nrf5340dk/nrf5340/cpuapp
29+
- nrf54l15dk/nrf54l15/cpuapp
30+
integration_platforms:
31+
- nrf52840dk/nrf52840
32+
- nrf54l15dk/nrf54l15/cpuapp

0 commit comments

Comments
 (0)