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. */
117122enum 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+
253272static esb_event_handler event_handler ;
254273static 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+
395440static 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
546591static 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
552612static 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
10361112static 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