Skip to content

Commit e0c2372

Browse files
tmon-nordicfabiobaltieri
authored andcommitted
samples: usb: uac2: Implement feedback on nRF54H20
Add configuration and feedback implementation necessary to run UAC2 samples on nRF54H20. Limit nRF54H20 to Full-Speed only operation because the samples currently don't have necessary logic to support High-Speed. Signed-off-by: Tomasz Moń <[email protected]>
1 parent 45f1222 commit e0c2372

File tree

11 files changed

+253
-21
lines changed

11 files changed

+253
-21
lines changed

samples/subsys/usb/uac2_explicit_feedback/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ project(usb_audio_async_i2s)
77
include(${ZEPHYR_BASE}/samples/subsys/usb/common/common.cmake)
88
target_sources(app PRIVATE src/main.c)
99

10-
if (CONFIG_SOC_COMPATIBLE_NRF5340_CPUAPP)
11-
target_sources(app PRIVATE src/feedback_nrf53.c)
10+
if (CONFIG_SOC_COMPATIBLE_NRF5340_CPUAPP OR CONFIG_SOC_SERIES_NRF54HX)
11+
target_sources(app PRIVATE src/feedback_nrf.c)
1212
else()
1313
target_sources(app PRIVATE src/feedback_dummy.c)
1414
endif()

samples/subsys/usb/uac2_explicit_feedback/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ config APP_USE_I2S_LRCLK_EDGES_COUNTER
99
Use this to use I2S LRCLK edge counting for calculating feedback.
1010
On nRF53 this option requires externally connecting I2S LRCLK back to
1111
separate GPIOTE input pin (P1.09).
12+
On nRF54 this option requires externally connecting TDM FSYNC back to
13+
separate GPIOTE input pin (P0.08).
1214
endmenu
1315

1416
# Source common USB sample options used to initialize new experimental USB
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Enable timer for asynchronous feedback
2+
CONFIG_NRFX_GPPI=y
3+
CONFIG_NRFX_TIMER131=y
4+
CONFIG_NRFX_GPIOTE130=y
5+
6+
# Sample is Full-Speed only, prevent High-Speed enumeration
7+
CONFIG_UDC_DRIVER_HIGH_SPEED_SUPPORT_ENABLED=n
8+
CONFIG_USBD_MAX_SPEED_FULL=y
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
* Copyright (c) 2025 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include "../app.overlay"
8+
9+
&pinctrl {
10+
tdm130_default_alt: tdm130_default_alt {
11+
group1 {
12+
psels = <NRF_PSEL(TDM_SCK_M, 1, 3)>,
13+
<NRF_PSEL(TDM_FSYNC_M, 1, 6)>,
14+
<NRF_PSEL(TDM_SDOUT, 1, 4)>;
15+
};
16+
};
17+
};
18+
19+
i2s_tx: &tdm130 {
20+
status = "okay";
21+
pinctrl-0 = <&tdm130_default_alt>;
22+
pinctrl-names = "default";
23+
memory-regions = <&cpuapp_dma_region>;
24+
mck-clock-source = "ACLK";
25+
sck-clock-source = "ACLK";
26+
};
27+
28+
&audiopll {
29+
frequency = <NRFS_AUDIOPLL_FREQ_AUDIO_48K>;
30+
status = "okay";
31+
};
32+
33+
&cpuapp_dma_region {
34+
status = "okay";
35+
};
36+
37+
/* PPI channel 0 for TDM130 MAXCNT */
38+
&dppic132 {
39+
compatible = "nordic,nrf-dppic-global";
40+
owned-channels = <0>;
41+
source-channels = <0>;
42+
nonsecure-channels = <0>;
43+
status = "okay";
44+
};
45+
46+
/* PPI channel 1 for GPIOTE used for feedback in edge counter mode */
47+
&gpiote130 {
48+
status = "okay";
49+
owned-channels = <1>;
50+
};
51+
52+
/* GPIOTE130 and TDM130 PPI needs routing to TIMER131 through main APB */
53+
&dppic130 {
54+
compatible = "nordic,nrf-dppic-global";
55+
owned-channels = <0 1>;
56+
sink-channels = <0 1>;
57+
source-channels = <0 1>;
58+
nonsecure-channels = <0 1>;
59+
status = "okay";
60+
};
61+
62+
/* TIMER131 PPI channel 2 is used for SOF */
63+
&dppic133 {
64+
compatible = "nordic,nrf-dppic-global";
65+
owned-channels = <0 1 2>;
66+
sink-channels = <0 1 2>;
67+
status = "okay";
68+
};
69+
70+
&timer131 {
71+
status = "okay";
72+
};

samples/subsys/usb/uac2_explicit_feedback/sample.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,7 @@ tests:
88
tags:
99
- usb
1010
- i2s
11-
platform_allow: nrf5340dk/nrf5340/cpuapp
11+
platform_allow:
12+
- nrf5340dk/nrf5340/cpuapp
13+
- nrf54h20dk/nrf54h20/cpuapp
1214
harness: TBD

samples/subsys/usb/uac2_explicit_feedback/src/feedback_nrf53.c renamed to samples/subsys/usb/uac2_explicit_feedback/src/feedback_nrf.c

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,56 @@
1212
#include <nrfx_gpiote.h>
1313
#include <nrfx_timer.h>
1414
#include <hal/nrf_gpio.h>
15-
#include <hal/nrf_usbd.h>
16-
#include <hal/nrf_i2s.h>
1715
#include <helpers/nrfx_gppi.h>
1816

1917
LOG_MODULE_REGISTER(feedback, LOG_LEVEL_INF);
2018

21-
static const nrfx_gpiote_t gpiote = NRFX_GPIOTE_INSTANCE(0);
19+
#define FEEDBACK_TIMER_USBD_SOF_CAPTURE 0
20+
#define FEEDBACK_TIMER_I2S_FRAMESTART_CAPTURE 1
21+
22+
#if IS_ENABLED(CONFIG_SOC_COMPATIBLE_NRF5340_CPUAPP)
23+
24+
#include <hal/nrf_usbd.h>
25+
#include <hal/nrf_i2s.h>
2226

2327
#define FEEDBACK_PIN NRF_GPIO_PIN_MAP(1, 9)
28+
#define FEEDBACK_GPIOTE_INSTANCE_NUMBER 0
2429
#define FEEDBACK_TIMER_INSTANCE_NUMBER 2
25-
#define FEEDBACK_TIMER_USBD_SOF_CAPTURE 0
26-
#define FEEDBACK_TIMER_I2S_FRAMESTART_CAPTURE 1
30+
#define USB_SOF_EVENT_ADDRESS nrf_usbd_event_address_get(NRF_USBD, NRF_USBD_EVENT_SOF)
31+
#define I2S_FRAMESTART_EVENT_ADDRESS nrf_i2s_event_address_get(NRF_I2S0, NRF_I2S_EVENT_FRAMESTART)
32+
33+
static inline void feedback_target_init(void)
34+
{
35+
if (IS_ENABLED(CONFIG_APP_USE_I2S_LRCLK_EDGES_COUNTER)) {
36+
/* App core is using feedback pin */
37+
nrf_gpio_pin_control_select(FEEDBACK_PIN, NRF_GPIO_PIN_SEL_APP);
38+
}
39+
}
40+
41+
#elif IS_ENABLED(CONFIG_SOC_SERIES_NRF54HX)
42+
43+
#include <hal/nrf_tdm.h>
44+
45+
#define FEEDBACK_PIN NRF_GPIO_PIN_MAP(0, 8)
46+
#define FEEDBACK_GPIOTE_INSTANCE_NUMBER 130
47+
#define FEEDBACK_TIMER_INSTANCE_NUMBER 131
48+
#define USB_SOF_EVENT_ADDRESS nrf_timer_event_address_get(NRF_TIMER131, NRF_TIMER_EVENT_COMPARE5)
49+
#define I2S_FRAMESTART_EVENT_ADDRESS nrf_tdm_event_address_get(NRF_TDM130, NRF_TDM_EVENT_MAXCNT)
50+
51+
static inline void feedback_target_init(void)
52+
{
53+
/* Enable Start-of-Frame workaround in TIMER131 */
54+
*(volatile uint32_t *)0x5F9A3C04 = 0x00000002;
55+
*(volatile uint32_t *)0x5F9A3C04 = 0x00000003;
56+
*(volatile uint32_t *)0x5F9A3C80 = 0x00000082;
57+
}
58+
59+
#else
60+
#error "Unsupported target"
61+
#endif
62+
63+
static const nrfx_gpiote_t gpiote =
64+
NRFX_GPIOTE_INSTANCE(FEEDBACK_GPIOTE_INSTANCE_NUMBER);
2765

2866
static const nrfx_timer_t feedback_timer_instance =
2967
NRFX_TIMER_INSTANCE(FEEDBACK_TIMER_INSTANCE_NUMBER);
@@ -80,13 +118,12 @@ static nrfx_err_t feedback_edge_counter_setup(void)
80118
.trigger = NRFX_GPIOTE_TRIGGER_TOGGLE,
81119
.p_in_channel = &feedback_gpiote_channel,
82120
};
121+
nrf_gpio_pin_pull_t pull = NRF_GPIO_PIN_PULLUP;
83122
nrfx_gpiote_input_pin_config_t input_pin_config = {
123+
.p_pull_config = &pull,
84124
.p_trigger_config = &trigger_config,
85125
};
86126

87-
/* App core is using feedback pin */
88-
nrf_gpio_pin_control_select(FEEDBACK_PIN, NRF_GPIO_PIN_SEL_APP);
89-
90127
err = nrfx_gpiote_channel_alloc(&gpiote, &feedback_gpiote_channel);
91128
if (err != NRFX_SUCCESS) {
92129
return err;
@@ -151,6 +188,8 @@ struct feedback_ctx *feedback_init(void)
151188
uint8_t usbd_sof_gppi_channel;
152189
uint8_t i2s_framestart_gppi_channel;
153190

191+
feedback_target_init();
192+
154193
feedback_reset_ctx(&fb_ctx);
155194

156195
if (IS_ENABLED(CONFIG_APP_USE_I2S_LRCLK_EDGES_COUNTER)) {
@@ -171,7 +210,7 @@ struct feedback_ctx *feedback_init(void)
171210
}
172211

173212
nrfx_gppi_channel_endpoints_setup(usbd_sof_gppi_channel,
174-
nrf_usbd_event_address_get(NRF_USBD, NRF_USBD_EVENT_SOF),
213+
USB_SOF_EVENT_ADDRESS,
175214
nrfx_timer_capture_task_address_get(&feedback_timer_instance,
176215
FEEDBACK_TIMER_USBD_SOF_CAPTURE));
177216
nrfx_gppi_fork_endpoint_setup(usbd_sof_gppi_channel,
@@ -188,7 +227,7 @@ struct feedback_ctx *feedback_init(void)
188227
}
189228

190229
nrfx_gppi_channel_endpoints_setup(i2s_framestart_gppi_channel,
191-
nrf_i2s_event_address_get(NRF_I2S0, NRF_I2S_EVENT_FRAMESTART),
230+
I2S_FRAMESTART_EVENT_ADDRESS,
192231
nrfx_timer_capture_task_address_get(&feedback_timer_instance,
193232
FEEDBACK_TIMER_I2S_FRAMESTART_CAPTURE));
194233

samples/subsys/usb/uac2_implicit_feedback/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ project(usb_audio_async_i2s)
77
include(${ZEPHYR_BASE}/samples/subsys/usb/common/common.cmake)
88
target_sources(app PRIVATE src/main.c)
99

10-
if (CONFIG_SOC_COMPATIBLE_NRF5340_CPUAPP)
11-
target_sources(app PRIVATE src/feedback_nrf53.c)
10+
if (CONFIG_SOC_COMPATIBLE_NRF5340_CPUAPP OR CONFIG_SOC_SERIES_NRF54HX)
11+
target_sources(app PRIVATE src/feedback_nrf.c)
1212
else()
1313
target_sources(app PRIVATE src/feedback_dummy.c)
1414
endif()
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Enable timer for asynchronous feedback
2+
CONFIG_NRFX_GPPI=y
3+
CONFIG_NRFX_TIMER131=y
4+
5+
# Sample is Full-Speed only, prevent High-Speed enumeration
6+
CONFIG_UDC_DRIVER_HIGH_SPEED_SUPPORT_ENABLED=n
7+
CONFIG_USBD_MAX_SPEED_FULL=y
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Copyright (c) 2025 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include "../app.overlay"
8+
9+
&pinctrl {
10+
tdm130_default_alt: tdm130_default_alt {
11+
group1 {
12+
psels = <NRF_PSEL(TDM_SCK_M, 1, 3)>,
13+
<NRF_PSEL(TDM_FSYNC_M, 1, 6)>,
14+
<NRF_PSEL(TDM_SDOUT, 1, 4)>,
15+
<NRF_PSEL(TDM_SDIN, 1, 5)>;
16+
};
17+
};
18+
};
19+
20+
i2s_rxtx: &tdm130 {
21+
status = "okay";
22+
pinctrl-0 = <&tdm130_default_alt>;
23+
pinctrl-names = "default";
24+
memory-regions = <&cpuapp_dma_region>;
25+
mck-clock-source = "ACLK";
26+
sck-clock-source = "ACLK";
27+
};
28+
29+
&audiopll {
30+
frequency = <NRFS_AUDIOPLL_FREQ_AUDIO_48K>;
31+
status = "okay";
32+
};
33+
34+
&cpuapp_dma_region {
35+
status = "okay";
36+
};
37+
38+
/* PPI channel 0 for TDM130 MAXCNT */
39+
&dppic132 {
40+
compatible = "nordic,nrf-dppic-global";
41+
owned-channels = <0>;
42+
source-channels = <0>;
43+
nonsecure-channels = <0>;
44+
status = "okay";
45+
};
46+
47+
/* TDM130 PPI needs routing to TIMER131 through main APB */
48+
&dppic130 {
49+
compatible = "nordic,nrf-dppic-global";
50+
owned-channels = <0>;
51+
sink-channels = <0>;
52+
source-channels = <0>;
53+
nonsecure-channels = <0>;
54+
status = "okay";
55+
};
56+
57+
/* TIMER131 PPI channel 1 is used for SOF */
58+
&dppic133 {
59+
compatible = "nordic,nrf-dppic-global";
60+
owned-channels = <0 1>;
61+
sink-channels = <0 1>;
62+
status = "okay";
63+
};
64+
65+
&timer131 {
66+
status = "okay";
67+
};

samples/subsys/usb/uac2_implicit_feedback/sample.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,7 @@ tests:
88
tags:
99
- usb
1010
- i2s
11-
platform_allow: nrf5340dk/nrf5340/cpuapp
11+
platform_allow:
12+
- nrf5340dk/nrf5340/cpuapp
13+
- nrf54h20dk/nrf54h20/cpuapp
1214
harness: TBD

0 commit comments

Comments
 (0)