Sending User-Defined Payload With the DWM3001CDK

Hello all,

I’ve been working on some extensions to the standard SDK firmware recently, I’ve added a couple of new commands allowing the user to add a name and number for each tag to NVM. These work very nicely, but I’m having some other issues when it comes to extending the INITF and RESPF commands.

What I’m attempting to do is attach the two data fields from my aforementioned NVM commands to the INITF and RESPF commands. I’m trying to use a DS-TWR FiRa session (BPRF set 3 → RFRAME_CONFIG_SP1) between an initiator and a responder. At every round, the responder should add a 10-byte proprietary payload to its SP1 RFRAME so the initiator prints:

0001,NAME,NUMBER,37,Ok (37 being the distance here)

To save you from reading my entire fira_app.c file, here are the relevant parts that I believe I may have messed up:

/* ---------- globals & helpers ----------------------------------------- */

#if PROPRIETARY_SP1_TWR_EXAMPLE_ENABLE
#include "tag_result.h"        /* 8-byte name + 2-byte activity (kBq LE) */
static tag_result_t            tx_tag_info;         /* packed payload   */
static struct data_parameters  data_params;         /* helper API arg   */
#endif

/* Convenience wrapper – called once in init() when we are the RESPONDER */
static void prepare_sp1_payload(void)
{
    memset(&tx_tag_info, 0, sizeof(tx_tag_info));

    /* Fill user data -------------------------------------------------- */
    strncpy(tx_tag_info.name, TagNameGet(), TAG_NAME_LEN_TX);          // “TAG”
    tx_tag_info.activity_kbq_le =
        DW_HTOLE16((uint16_t)(ActivityGetBq() / 1000));                // e.g 1000

    /* Copy into helper buffer ---------------------------------------- */
    memcpy(data_params.data_payload,
           &tx_tag_info,
           sizeof(tx_tag_info));

    data_params.data_payload_len = sizeof(tx_tag_info);                // 10 bytes
}

/* ---------- init() : RESPONDER branch -------------------------------- */

if (!controller                                                &&      /* RESP  */
    fira_param->session.rframe_config == FIRA_RFRAME_CONFIG_SP1)       /* set-1 */
{
    prepare_sp1_payload();

    /* Prime the helper once so it knows the buffer size.                 */
    if (fira_helper_send_data(&fira_ctx, session_id, &data_params))
        diag_printf("first fira_helper_send_data failed!\r\n");
}

/* ---------- RTOS task : resend every ranging round ------------------- */

static void data_task(void const *arg)
{
    static uint8_t cnt = 0;                 /* demo counter, byte[0]    */

    while (!dataTransferTask.Exit) {
        osSignalWait(dataTransferTask.SignalMask, osWaitForever);

        data_params.data_payload[0] = cnt++;            /* live change  */

        int r = fira_helper_send_data(&fira_ctx, session_id, &data_params);
        if (r)
            diag_printf("send_data err %d\r\n", r);
    }
}

/* ---------- report_cb : INITIATOR side, decode ----------------------- */

if (rm->sp1_data_len >= sizeof(tag_result_t)) {        /* got payload ? */
    const tag_result_t *info = (const tag_result_t *)rm->sp1_data;

    char tag[TAG_NAME_LEN_TX + 1];
    memcpy(tag, info->name, TAG_NAME_LEN_TX);
    tag[TAG_NAME_LEN_TX] = '\0';

    uint16_t act_kBq = DW_LETOH16(info->activity_kbq_le);

    diag_printf("SP1: tag=%s  activity=%u kBq  seq=%u\r\n",
                tag, act_kBq, rm->payload_seq_recv);
}

These are the serial commands I’m using:

RESPF 3 2400 200 25 5 42 01:02:03:04:05:06:07:08 0 0 0x0000 0x0001
INITF 3 2400 200 25 5 42 01:02:03:04:05:06:07:08 0 0 0x0000 0x0001

Field order = RFRAME BPRFset Slot_rstu Block_ms Round_slots RRusage SessionID ...

I set RRusage to 5 because the comment in scan_fira_params() says "5 = Unicast+SS+DS (SP1)".

What Works:

  • With BPRF set-3 (RFRAME_CONFIG_SP3, i.e. command value 4) I get stable ranging and “Ok” status → proves antennas, power, scheduler, etc.
  • FiRa helper accepts my first fira_helper_send_data() call (returns 0)

What Fails:

  • RFRAME_CONFIG_SP1 (set-1) with parameters as above – initiator prints 0001,UNKNOWN,0,-1,Err for every measurement. Responder log repeatedly says DEBUG: no SP1 payload in this result
  • If I keep the same parameters but change RRusage back to 2 – Board freezes my serial terminal (no more UART). After replacing every assert() with diag_print() I see uwbmac_err = -7 coming from fira_helper_set_partial_session_parameters()
  • Any typo that shortens the command (e.g. miss a colon in Vupper64) – Shell accepts it, then MCU hard-faults

Questions to the community

  1. Is RRusage=5 indeed mandatory to let the helper emit SP1 frames? The code comment says so, but the uwbstack returns -7 (invalid parameter) when I pass 5.
  2. Apart from data_vendor_oui (I use 0x0C0B0A) and the payload array, so I need to call any extra helper API so the Responder actually attaches the payload?
  3. In DS-TWR with SP1, does the Initiator also have to call fira_helper_send_data() to “arm” its receive buffer, or is the call on the Responder sufficient?
  4. Anything obviously wrong with my serial command?
  5. If SP1 data is officially not supported in the public SDK (saw this hinted on the forum), is there an example project/beta drop that demonstrates it?
  6. Am I perhaps massively overthinking this all?

Thanks for any responses,
Oscar