Skip to content

Commit 8c1c740

Browse files
maje-embnordicjm
authored andcommitted
esb: Implement workaround for HMPAN-216
Added workaround for the hardware errata HMPAN-216 for the nRF54H20 SoC. Ref: NCSDK-32717 Signed-off-by: Marcin Jelinski <[email protected]>
1 parent 6081c42 commit 8c1c740

File tree

4 files changed

+120
-3
lines changed

4 files changed

+120
-3
lines changed

doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,10 @@ DECT NR+
202202
Enhanced ShockBurst (ESB)
203203
-------------------------
204204

205-
* Added loading of radio trims and a fix of a hardware errata for the nRF54H20 SoC to improve the RF performance.
205+
* Added:
206+
207+
* Loading of radio trims and a fix of a hardware errata for the nRF54H20 SoC to improve the RF performance.
208+
* Workaround for the hardware errata HMPAN-216 for the nRF54H20 SoC.
206209

207210
Gazell
208211
------

samples/esb/esb_prx/boards/nrf54h20dk_nrf54h20_cpurad.overlay

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,13 @@
3939
chosen {
4040
zephyr,console = &uart136;
4141
};
42+
43+
cpurad_cpusys_errata216_mboxes: errata216_mboxes {
44+
compatible = "zephyr,mbox-ipm";
45+
status = "okay";
46+
mboxes = < &cpusys_vevif 0x14 >, < &cpusys_vevif 0x15 >;
47+
mbox-names = "on_req", "off_req";
48+
};
4249
};
4350

4451
&gpio9 {

samples/esb/esb_ptx/boards/nrf54h20dk_nrf54h20_cpurad.overlay

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,13 @@
3939
chosen {
4040
zephyr,console = &uart136;
4141
};
42+
43+
cpurad_cpusys_errata216_mboxes: errata216_mboxes {
44+
compatible = "zephyr,mbox-ipm";
45+
status = "okay";
46+
mboxes = < &cpusys_vevif 0x14 >, < &cpusys_vevif 0x15 >;
47+
mbox-names = "on_req", "off_req";
48+
};
4249
};
4350

4451
&gpio9 {

subsys/esb/esb.c

Lines changed: 102 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <zephyr/kernel.h>
2424
#include <zephyr/sys/byteorder.h>
2525
#include <zephyr/drivers/gpio.h>
26+
#include <zephyr/drivers/mbox.h>
2627

2728
#include <mpsl_fem_protocol_api.h>
2829

@@ -113,6 +114,10 @@ LOG_MODULE_REGISTER(esb, CONFIG_ESB_LOG_LEVEL);
113114
/* Empty trim value */
114115
#define TRIM_VALUE_EMPTY 0xFFFFFFFF
115116

117+
#define ERRATA_216_PRESENT DT_NODE_HAS_STATUS(DT_NODELABEL(cpurad_cpusys_errata216_mboxes), okay)
118+
#define ERRATA_216_RADIO_ENABLE_DELAY_US 40
119+
#define ERRATA_216_MIN_TIME_TO_DISABLE_US 100
120+
116121
/* Internal Enhanced ShockBurst module state. */
117122
enum esb_state {
118123
ESB_STATE_IDLE, /* Idle. */
@@ -250,6 +255,20 @@ static struct esb_address esb_addr = {
250255
.rx_pipes_enabled = 0xFF
251256
};
252257

258+
enum {
259+
ERRATA_216_DISABLED,
260+
ERRATA_216_ENABLED,
261+
};
262+
static atomic_t errata_216_status = ATOMIC_INIT(ERRATA_216_DISABLED);
263+
static uint32_t errata_216_timer_shorts;
264+
265+
#if ERRATA_216_PRESENT
266+
static const struct mbox_dt_spec on_channel =
267+
MBOX_DT_SPEC_GET(DT_NODELABEL(cpurad_cpusys_errata216_mboxes), on_req);
268+
static const struct mbox_dt_spec off_channel =
269+
MBOX_DT_SPEC_GET(DT_NODELABEL(cpurad_cpusys_errata216_mboxes), off_req);
270+
#endif /* ERRATA_216_PRESENT */
271+
253272
static esb_event_handler event_handler;
254273
static struct esb_payload *current_payload;
255274

@@ -392,6 +411,32 @@ static inline void apply_errata143_workaround(void)
392411
}
393412
}
394413

414+
static void errata216_on(void)
415+
{
416+
#if ERRATA_216_PRESENT
417+
if (mbox_send_dt(&on_channel, NULL) != 0) {
418+
LOG_ERR("Failed to enable Errata 216");
419+
/* Should not happen. */
420+
__ASSERT_NO_MSG(false);
421+
} else {
422+
atomic_set(&errata_216_status, ERRATA_216_ENABLED);
423+
}
424+
#endif /* ERRATA_216_PRESENT */
425+
}
426+
427+
static void errata216_off(void)
428+
{
429+
#if ERRATA_216_PRESENT
430+
if (mbox_send_dt(&off_channel, NULL) != 0) {
431+
LOG_ERR("Failed to disable Errata 216");
432+
/* Should not happen. */
433+
__ASSERT_NO_MSG(false);
434+
} else {
435+
atomic_set(&errata_216_status, ERRATA_216_DISABLED);
436+
}
437+
#endif /* ERRATA_216_PRESENT */
438+
}
439+
395440
static void esb_fem_for_tx_set(bool ack)
396441
{
397442
uint32_t timer_shorts;
@@ -545,8 +590,23 @@ void esb_fem_for_tx_retry_clear(void)
545590

546591
static void radio_start(void)
547592
{
548-
/* Event generator unit is used to start radio and protocol timer if needed. */
549-
nrf_egu_task_trigger(ESB_EGU, ESB_EGU_TASK);
593+
if (IS_ENABLED(ERRATA_216_PRESENT) &&
594+
atomic_get(&errata_216_status) == ERRATA_216_DISABLED) {
595+
errata216_on();
596+
597+
nrfx_timer_compare(&esb_timer, NRF_TIMER_CC_CHANNEL3,
598+
nrfx_timer_us_to_ticks(&esb_timer, ERRATA_216_RADIO_ENABLE_DELAY_US), true);
599+
600+
errata_216_timer_shorts = esb_timer.p_reg->SHORTS;
601+
nrf_timer_shorts_set(esb_timer.p_reg,
602+
(NRF_TIMER_SHORT_COMPARE3_STOP_MASK |
603+
NRF_TIMER_SHORT_COMPARE3_CLEAR_MASK));
604+
nrfx_timer_clear(&esb_timer);
605+
nrf_timer_task_trigger(ESB_NRF_TIMER_INSTANCE, NRF_TIMER_TASK_START);
606+
} else {
607+
/* Event generator unit is used to start radio and protocol timer if needed. */
608+
nrf_egu_task_trigger(ESB_EGU, ESB_EGU_TASK);
609+
}
550610
}
551611

552612
static void update_rf_payload_format_esb_dpl(uint32_t payload_length)
@@ -1031,6 +1091,22 @@ static void esb_timer_handler(nrf_timer_event_t event_type, void *context)
10311091
on_timer_compare1();
10321092
}
10331093
}
1094+
1095+
if (IS_ENABLED(ERRATA_216_PRESENT) && event_type == NRF_TIMER_EVENT_COMPARE3) {
1096+
nrf_timer_int_disable(esb_timer.p_reg, NRF_TIMER_INT_COMPARE3_MASK);
1097+
1098+
if (atomic_get(&errata_216_status) == ERRATA_216_ENABLED) {
1099+
/* This case is triggered after calling the radio_start() function */
1100+
1101+
/* Restore timer shorts */
1102+
nrf_timer_shorts_set(esb_timer.p_reg, errata_216_timer_shorts);
1103+
1104+
nrf_egu_task_trigger(ESB_EGU, ESB_EGU_TASK);
1105+
} else {
1106+
/* This case is triggered during retransmission. */
1107+
errata216_on();
1108+
}
1109+
}
10341110
}
10351111

10361112
static int sys_timer_init(void)
@@ -1217,6 +1293,7 @@ static void on_radio_disabled_tx_noack(void)
12171293

12181294
if (tx_fifo.count == 0) {
12191295
esb_state = ESB_STATE_IDLE;
1296+
errata216_off();
12201297
set_evt_interrupt();
12211298
} else {
12221299
set_evt_interrupt();
@@ -1249,6 +1326,16 @@ static void on_radio_disabled_tx(void)
12491326
nrfx_timer_compare(&esb_timer, NRF_TIMER_CC_CHANNEL1,
12501327
(esb_cfg.retransmit_delay - ramp_up), false);
12511328

1329+
if (IS_ENABLED(ERRATA_216_PRESENT)) {
1330+
int32_t min_time = esb_cfg.retransmit_delay - wait_for_ack_timeout_us -
1331+
ramp_up - ADDR_EVENT_LATENCY_US;
1332+
if (min_time > ERRATA_216_MIN_TIME_TO_DISABLE_US) {
1333+
uint32_t cc_value = esb_cfg.retransmit_delay - ramp_up -
1334+
ERRATA_216_RADIO_ENABLE_DELAY_US;
1335+
nrfx_timer_compare(&esb_timer, NRF_TIMER_CC_CHANNEL3, cc_value, true);
1336+
}
1337+
}
1338+
12521339
nrf_timer_shorts_set(esb_timer.p_reg,
12531340
(NRF_TIMER_SHORT_COMPARE1_STOP_MASK | NRF_TIMER_SHORT_COMPARE1_CLEAR_MASK));
12541341

@@ -1303,6 +1390,7 @@ static void on_radio_disabled_tx_wait_for_ack(void)
13031390

13041391
if ((tx_fifo.count == 0) || (esb_cfg.tx_mode == ESB_TXMODE_MANUAL)) {
13051392
esb_state = ESB_STATE_IDLE;
1393+
errata216_off();
13061394
set_evt_interrupt();
13071395
} else {
13081396
set_evt_interrupt();
@@ -1320,6 +1408,7 @@ static void on_radio_disabled_tx_wait_for_ack(void)
13201408
interrupt_flags |= INT_TX_FAILED_MSK;
13211409

13221410
esb_state = ESB_STATE_IDLE;
1411+
errata216_off();
13231412
set_evt_interrupt();
13241413
} else {
13251414
bool radio_started = true;
@@ -1371,6 +1460,14 @@ static void on_radio_disabled_tx_wait_for_ack(void)
13711460
esb_fem_for_tx_set(true);
13721461

13731462
radio_start();
1463+
} else if (IS_ENABLED(ERRATA_216_PRESENT)) {
1464+
uint16_t ramp_up = esb_cfg.use_fast_ramp_up ?
1465+
TX_FAST_RAMP_UP_TIME_US : TX_RAMP_UP_TIME_US;
1466+
int32_t min_time = esb_cfg.retransmit_delay - ramp_up -
1467+
wait_for_ack_timeout_us - ADDR_EVENT_LATENCY_US;
1468+
if (min_time > ERRATA_216_MIN_TIME_TO_DISABLE_US) {
1469+
errata216_off();
1470+
}
13741471
}
13751472
}
13761473
}
@@ -1874,6 +1971,7 @@ int esb_suspend(void)
18741971
esb_ppi_disable_all();
18751972

18761973
esb_state = ESB_STATE_IDLE;
1974+
errata216_off();
18771975

18781976
return 0;
18791977
}
@@ -1890,6 +1988,7 @@ void esb_disable(void)
18901988
nrf_radio_fast_ramp_up_enable_set(NRF_RADIO, false);
18911989

18921990
esb_state = ESB_STATE_IDLE;
1991+
errata216_off();
18931992
esb_initialized = false;
18941993

18951994
reset_fifos();
@@ -2107,6 +2206,7 @@ int esb_stop_rx(void)
21072206
nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_DISABLED);
21082207

21092208
esb_state = ESB_STATE_IDLE;
2209+
errata216_off();
21102210

21112211
return 0;
21122212
}

0 commit comments

Comments
 (0)