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 =
×lot_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(×lot_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);