Receive error after wakeup from sleep

Hi all,
I am in charge of porting an application from DWM1000 to DWM3000.
Frame reception works fine in both polling and interrupt mode on the DWM3000 hardware with no error or timeout.
But a problem arise when I try to use SLEEP capability.
When receive is started in “spi ready” callback and a frame is transmitted by another device the error 0x04000107 is notified in “rx error” callback.
Active bits in cb_data->status are:

RXSTO - Receive SFD timeout
RXPRD - Receive preamble detected status
SPICRCE - Spi CRC error (always set when CRC mode disabled)
CPLOCK - Clock PLL lock
IRQS - Interrupt request status

I am using the following logic to keep most of the time DW3000 in SLEEP and wakeup when requested to check if any frame can be received:

/* Default communication configuration. We use default non-STS DW mode. /
static dwt_config_t config = {
5, /
Channel number. /
DWT_PLEN_128, /
Preamble length. Used in TX only. /
DWT_PAC8, /
Preamble acquisition chunk size. Used in RX only. /
9, /
TX preamble code. Used in TX only. /
9, /
RX preamble code. Used in RX only. /
1, /
0 to use standard 8 symbol SFD, 1 to use non-standard 8 symbol, 2 for non-standard 16 symbol SFD and 3 for 4z 8 symbol SDF type /
DWT_BR_6M8, /
Data rate. /
DWT_PHRMODE_STD, /
PHY header mode. /
DWT_PHRRATE_STD, /
PHY header rate. /
(129 + 8 - 8), /
SFD timeout (preamble length + 1 + SFD length - PAC size). Used in RX only. /
DWT_STS_MODE_OFF, /
STS disabled /
DWT_STS_LEN_64, /
STS length see allowed values in Enum dwt_sts_lengths_e /
DWT_PDOA_M0 /
PDOA mode off */
};

int dw3000intialization()
{

port_set_dw_ic_spi_fastrate();		/* Configure SPI rate, DW IC supports up to 38 MHz */
reset_DWIC(); 						/* Target specific drive of RSTn line into DW IC low for a period. */
Sleep(2); 							/* Time needed for DW3000 to start up (transition from INIT_RC to IDLE_RC, or could wait for SPIRDY event) */
while (!dwt_checkidlerc()) 			/* Need to make sure DW IC is in IDLE_RC before proceeding */
{ };
if (dwt_initialise(DWT_DW_INIT) == DWT_ERROR)
    return -1;
if(dwt_configure(&config)) 			/* Configure DW IC. */
    return -2;
dwt_setcallbacks(NULL, rx_ok_cb, rx_to_cb, 						/* Register RX call-back. */		
				 rx_err_cb, spi_err_cb, spi_ready_cb);	
dwt_setinterrupt(SYS_ENABLE_LO_SPIRDY_ENABLE_BIT_MASK | 		/* Enable wanted interrupts (SPI ready RX good frames and RX errors). */
				 SYS_ENABLE_LO_RXFCG_ENABLE_BIT_MASK | 
				 SYS_STATUS_ALL_RX_ERR, 0, DWT_ENABLE_INT);
dwt_write32bitreg(SYS_STATUS_ID, 								/*Clearing the SPI ready interrupt*/
				  SYS_STATUS_RCINIT_BIT_MASK | SYS_STATUS_SPIRDY_BIT_MASK);		
dwt_setrxtimeout (150 * 1000);									/* Configure RX timeout */
dwt_configuresleep(DWT_CONFIG, 									/* Configure DW1000 sleep and wake-up (through wake-up pin) parameters. */
				   DWT_PRES_SLEEP | DWT_WAKE_WUP | DWT_SLP_EN);	
dwt_entersleep (DWT_DW_IDLE);									/* Put DW3000 to sleep. */										

return 0;

}

static void rx_ok_cb(const dwt_cb_data_t cb_data)
{
GPIO_PinOutToggle(LED_G_PORT, LED_G_PIN); /
Toggle GREEN led /
dwt_entersleep (DWT_DW_IDLE); /
Put DW3000 to sleep. */
}

static void rx_err_cb(const dwt_cb_data_t cb_data)
{
GPIO_PinOutToggle(LED_B_PORT, LED_B_PIN); /
Toggle BLUE led /
dwt_entersleep (DWT_DW_IDLE); /
Put DW3000 to sleep. */

static void rx_to_cb(const dwt_cb_data_t *cb_data)
{

GPIO_PinOutToggle(LED_B_PORT, LED_B_PIN);						/* Toggle both leds */
GPIO_PinOutToggle(LED_G_PORT, LED_G_PIN);
dwt_entersleep (DWT_DW_IDLE);									/* Put DW3000 to sleep. */

}

static void spi_err_cb(const dwt_cb_data_t *cb_data)
{
while (1)
{ };
}

static void spi_ready_cb(const dwt_cb_data_t *cb_data)
{

while (!dwt_checkidlerc())				/* Need to make sure DW IC is in IDLE_RC before proceeding */
{ };
dwt_restoreconfig();					/* Restore the required configurations on wake */
dwt_rxenable(DWT_START_RX_IMMEDIATE);	/* Start receive */

}

void externalEventToWakeupDW3000(void)
{
GPIO_PinOutSet(DW1000_WAKEUP_PORT, DW1000_WAKEUP_PIN);
Sleep(2);
GPIO_PinOutClear(DW1000_WAKEUP_PORT, DW1000_WAKEUP_PIN);
}

Any suggestion will be greatly appreciated,
PaoloC

The issue was resolved enabling RX calibration on wakeup.
See note at pag. 166 of User Manual:

DTW_PGFCAL flag in sleep configuration magically solves the problem:

dwt_configuresleep(DWT_CONFIG | DWT_PGFCAL, DWT_PRES_SLEEP | DWT_WAKE_WUP | DWT_SLP_EN);

PaoloC

1 Like