This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Unable to make radio works with timeslot

I'm trying to send radio frame in timeslot but it's not working. From what I see with an spectrum analyzer, only the first frame is sent.

I am able to make the radio works but only when it's without using timeslot.

I use nRF Connect SDK v1.3.1.

Thank you for the help.

#include <assert.h>

#include <kernel.h>
#include <sys/printk.h>
#include <mpsl_timeslot.h>
#include <mpsl.h>
#include <nrfx_clock.h>
#include <hal/nrf_radio.h>

#define RADIO_FREQUENCY 0 // 2400 MHz
#define TIMESLOT_REQUEST_DISTANCE_US (20000)
#define TIMESLOT_LENGTH_US           (3000)

#define MPSL_THREAD_PRIO             CONFIG_MPSL_THREAD_COOP_PRIO
#define STACKSIZE                    CONFIG_MAIN_STACK_SIZE
#define THREAD_PRIORITY              K_LOWEST_APPLICATION_THREAD_PRIO

/* Timeslot requests */
static mpsl_timeslot_request_t timeslot_request_earliest = {
        .request_type = MPSL_TIMESLOT_REQ_TYPE_EARLIEST,
        .params.earliest.hfclk = MPSL_TIMESLOT_HFCLK_CFG_NO_GUARANTEE,
        .params.earliest.priority = MPSL_TIMESLOT_PRIORITY_NORMAL,
        .params.earliest.length_us = TIMESLOT_LENGTH_US,
        .params.earliest.timeout_us = 1000000
};

static mpsl_timeslot_request_t timeslot_request_normal = {
        .request_type = MPSL_TIMESLOT_REQ_TYPE_NORMAL,
        .params.normal.hfclk = MPSL_TIMESLOT_HFCLK_CFG_NO_GUARANTEE,
        .params.normal.priority = MPSL_TIMESLOT_PRIORITY_NORMAL,
        .params.normal.distance_us = TIMESLOT_REQUEST_DISTANCE_US,
        .params.normal.length_us = TIMESLOT_LENGTH_US
};

static mpsl_timeslot_signal_return_param_t signal_callback_return_param;

/* Message queue for printing the signal type from timeslot callback */
K_MSGQ_DEFINE(callback_msgq, sizeof(uint32_t), 16, 4);

static volatile struct {
    uint32_t counter;
    uint8_t data[200];
} m_sync_pkt;

static void radio_tx(void)
{
    NRF_RADIO->POWER     = (RADIO_POWER_POWER_Enabled << RADIO_POWER_POWER_Pos);

    // TX power
    NRF_RADIO->TXPOWER   = RADIO_TXPOWER_TXPOWER_0dBm   << RADIO_TXPOWER_TXPOWER_Pos;

    // RF bitrate
    NRF_RADIO->MODE      = RADIO_MODE_MODE_Nrf_1Mbit       << RADIO_MODE_MODE_Pos;

    // Fast startup mode
    NRF_RADIO->MODECNF0 = RADIO_MODECNF0_RU_Fast << RADIO_MODECNF0_RU_Pos;

    // CRC configuration
    NRF_RADIO->CRCCNF    = RADIO_CRCCNF_LEN_Three << RADIO_CRCCNF_LEN_Pos;
    NRF_RADIO->CRCINIT = 0xFFFFFFUL;      // Initial value
    NRF_RADIO->CRCPOLY = 0x11021UL;     // CRC poly: x^16+x^12^x^5+1

    // Packet format
    NRF_RADIO->PCNF0 = (0 << RADIO_PCNF0_S0LEN_Pos) | (0 << RADIO_PCNF0_LFLEN_Pos) | (0 << RADIO_PCNF0_S1LEN_Pos);
    NRF_RADIO->PCNF1 = (RADIO_PCNF1_WHITEEN_Disabled        << RADIO_PCNF1_WHITEEN_Pos) |
            (RADIO_PCNF1_ENDIAN_Big              << RADIO_PCNF1_ENDIAN_Pos)  |
            (4                                   << RADIO_PCNF1_BALEN_Pos)   |
            (sizeof(m_sync_pkt)                  << RADIO_PCNF1_STATLEN_Pos) |
            (sizeof(m_sync_pkt)                  << RADIO_PCNF1_MAXLEN_Pos);
    NRF_RADIO->PACKETPTR = (uint32_t)&m_sync_pkt;

    // Radio address config
    NRF_RADIO->PREFIX0 = 0xDE;
    NRF_RADIO->BASE0   = 0xADBEEF19;

    NRF_RADIO->TXADDRESS   = 0;
    NRF_RADIO->RXADDRESSES = (1 << 0);

    NRF_RADIO->FREQUENCY = RADIO_FREQUENCY;
    NRF_RADIO->TXPOWER   = RADIO_TXPOWER_TXPOWER_0dBm << RADIO_TXPOWER_TXPOWER_Pos;

    NRF_RADIO->INTENCLR = 0xFFFFFFFF;
    NRF_RADIO->INTENSET =  RADIO_INTENSET_DISABLED_Msk;

    NVIC_EnableIRQ(RADIO_IRQn);

    m_sync_pkt.counter++;

    NRF_RADIO->SHORTS     = RADIO_SHORTS_READY_START_Msk | RADIO_SHORTS_END_DISABLE_Msk;
    NRF_RADIO->TASKS_TXEN = 1;
}

static mpsl_timeslot_signal_return_param_t *mpsl_timeslot_callback(uint32_t signal_type)
{
    mpsl_timeslot_signal_return_param_t *p_ret_val = NULL;

    switch (signal_type) {
    case MPSL_TIMESLOT_SIGNAL_START:
        radio_tx();

        signal_callback_return_param.params.request.p_next =
                NULL;
        signal_callback_return_param.callback_action =
                MPSL_TIMESLOT_SIGNAL_ACTION_NONE;

        p_ret_val = &signal_callback_return_param;
        break;

    case MPSL_TIMESLOT_SIGNAL_RADIO:
        if (NRF_RADIO->EVENTS_DISABLED != 0) {
            NRF_RADIO->EVENTS_DISABLED = 0;

            /* Request new timeslot when callback returns */
            signal_callback_return_param.params.request.p_next =
                    &timeslot_request_normal;
            signal_callback_return_param.callback_action =
                    MPSL_TIMESLOT_SIGNAL_ACTION_REQUEST;

            p_ret_val = &signal_callback_return_param;
        }
        break;

    case MPSL_TIMESLOT_SIGNAL_SESSION_IDLE:
        break;
    case MPSL_TIMESLOT_SIGNAL_SESSION_CLOSED:
        break;

    case MPSL_TIMESLOT_SIGNAL_TIMER0:
        assert(0);
        break;
    case MPSL_TIMESLOT_SIGNAL_EXTEND_FAILED:
        assert(0);
        break;
    case MPSL_TIMESLOT_SIGNAL_EXTEND_SUCCEEDED:
        assert(0);
        break;
    case MPSL_TIMESLOT_SIGNAL_BLOCKED:
        assert(0);
        break;
    case MPSL_TIMESLOT_SIGNAL_CANCELLED:
        assert(0);
        break;
    case MPSL_TIMESLOT_SIGNAL_INVALID_RETURN:
        assert(0);
        break;
    default:
        assert(0);
        break;
    }

    /* Put callback info in the message queue. */
    int err = k_msgq_put(&callback_msgq, &signal_type, K_NO_WAIT);
    assert(err == 0);

    return p_ret_val;
}

static void clock_event(nrfx_clock_evt_type_t event)
{
}

static void clock_init(void)
{
    nrfx_err_t err_code = nrfx_clock_init(clock_event);
    assert(err_code == NRFX_SUCCESS);

    nrfx_clock_hfclk_start();
}

/* To ensure thread safe operation, call all MPSL APIs from a non-preemptible
 * thread.
 */
static void mpsl_nonpreemptible_thread(void)
{
    int err;

    err = mpsl_timeslot_session_open(mpsl_timeslot_callback);
    assert(err == 0);

    err = mpsl_timeslot_request(&timeslot_request_earliest);
    assert(err == 0);
}

void main(void)
{
    clock_init();

    while (1) {
        uint32_t signal_type;
        if (k_msgq_get(&callback_msgq, &signal_type, K_FOREVER) == 0) {
            printk("sig=%lu\n", signal_type);
        }
    }
}

K_THREAD_DEFINE(mpsl_nonpreemptible_thread_id, STACKSIZE,
        mpsl_nonpreemptible_thread, NULL, NULL, NULL,
        K_PRIO_COOP(MPSL_THREAD_PRIO), 0, 0);

Parents Reply Children
No Data
Related