Transmission fails with wrong TXLEN, SYS_STATUS TX bits not set


I am working on the implementation of a DS-TWR system using DWM1001-DEV boards, where devices periodically switch between the role of initiator and responder. I started from the DS-TWR examples using zephyr, and I combined the code of the initiator and responder examples, with a main loop in which the role is selected
according to a switch variable.
As a first step, I am testing the code by having a device always working in a fixed role, and another one switching periodically between the two roles when a zephyr timer expires.
Everything works properly, with ranging exchanges successfully completed when the two devices are in different roles, until the switching node goes back to initiator for the first time (so with a sequence RESP->INIT or INIT->RESP->INIT).
When this happens, the transmission of the poll packet does not take place, even if I get DWT_SUCCESS when I call


After the call, the code hangs on a while loop polling the SYS_STATUS_TXFRS. I tried replacing the SYS_STATUS polling with an interrupt, but the code still hangs, waiting for a callback to the TX OK event that never happens. I also tried polling a bit different from TXFRS, such as TXPHS, with same result. SPI seems to work properly, since I can read registers and results are reasonable. However, when checking the TX_FCTRL bits, the TXLEN is only 2 bytes instead of the 18 it should be.

I double checked everything and searched the forum for similar issues, but I still cannot get it to work.
This is the code I am using in the main loop (OP_MODE is switched between INIT_MODE and RESP_MODE by the my_timer_handler function):

*int dw_main(void)*


  • openspi();*

  • reset_DW1000();*

  • port_set_dw1000_slowrate();*

  • if (dwt_initialise(DWT_LOADUCODE) == DWT_ERROR) {*

  •    printk("INIT FAILED");*
  •    k_sleep(K_MSEC(500));*
  •    while (1)*
  •    { };*
  • }*

  • port_set_dw1000_fastrate();*

  • dwt_configure(&config);*

  • dwt_setrxantennadelay(RX_ANT_DLY);*

  • dwt_settxantennadelay(TX_ANT_DLY);*

  • k_timer_init(&my_timer, my_timer_handler, NULL);*

  • k_timer_start(&my_timer, K_SECONDS(10), K_SECONDS(10));*


  • /* Loop forever alternating between sending and responding to ranging requests. /

  • while (1) {*

  •    double distance_int=0;*
  •    *
  •    switch (OP_MODE) {*
  •        case INIT_MODE:*
  •           printk("Role: initiator\n");*
  •           *
  •            dwt_setrxaftertxdelay(POLL_TX_TO_RESP_RX_DLY_UUS);*
  •            dwt_setrxtimeout(RESP_RX_TIMEOUT_UUS);*
  •            distance_int=sd_init_mode();*
  •            *
  •            /* Execute a delay between ranging exchanges. */*
  •            Sleep(RNG_DELAY_MS);*
  •            break;*
  •            *
  •        case RESP_MODE:*
  •        	printk("Role: responder\n");*
  •            *
  •            dwt_setrxtimeout(0);*
  •            distance_int=sd_resp_mode();*
  •            break;*
  •            *
  •        default:*
  •            break;*
  •    }*
  • }*

and this is the portion of the sd_init_mode() function where the execution loops forever
in the last while.

double sd_init_mode() {

  • double distance; *

  • int poll_frame_nb;*

  • int ret;*

  • tx_poll_msg[ALL_MSG_SN_IDX] = frame_seq_nb; *

  • printk("%s\n",tx_poll_msg);*

  • dwt_writetxdata(sizeof(tx_poll_msg), tx_poll_msg, 0);*

  • dwt_writetxfctrl(sizeof(tx_poll_msg), 0, 1);*

  • dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_ALL_TX);*


  • if (ret == DWT_SUCCESS) {*

  •  int txlen=dwt_read32bitreg(SYS_STATUS_ID) & TX_FCTRL_TFLEN_MASK;*
  •  printk("TXLEN: %u\n",txlen);*
  •   while (!(dwt_read32bitreg(SYS_STATUS_ID) & SYS_STATUS_TXFRS))*
  •   {};*
  •   /* Clear TXFRS event. */*
  •   dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_TXFRS);*
  • }*

  • else {*

  •   printk("POLL message sending error - tx failed: %08lx\n", status_reg);*
  •   return(-1);*
  • }*

Any help is greatly appreciated!
Best regards,


I had a similar problem where the TX bits in the SYS_STATUS register did not get set.
For me, the problem was that RX was still enabled (can be checked by looking at the SYS_CTRL register).
In case someone else stumbles upon this thread while researching this issue :wink: