This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CC1352P: EasyLink: BusyError when transmitting after aborting an asynchronous receive command

Part Number: CC1352P

Hi,

I've got some problems making EasyLink work for my application. What I am basically trying is to initialize EasyLink and enter (and stay in) the asynchronous receive mode. Only when I am transmitting a packet (which is triggered by a timer) I want to disable the receive mode, send my packet and upon completion re-enter the asynchronous receive mode again.

The problem is that after calling the EasyLink_Abort()-function for aborting the receive command, the receive callback is called with the status EasyLink_Status_Aborted (as I would expect) and yet, the following call to EasyLink_transmitAsync() returns an EasyLink_Status_BusyError, suggesting that the RF Core is still in receive mode. From my understanding, EasyLink_Abort() is a blocking call, so once I call transmitAsync(), the abortion should already been done.

Below you will find my code, where I have removed the irrelevant parts in the interest of clarity.

/*
 * mac.c
 *
 *  Created on: 14.07.2022
 *      Author: ----
 */

#include <mac/mac.h>

static macCallback_t callbackFxn = NULL;

static void timerCallback(Timer_Handle myHandle, int_fast16_t status);
static void timerInit(void);
static void echoRxDoneCb(EasyLink_RxPacket * rxPacket, EasyLink_Status status);
static void echoTxDoneCb(EasyLink_Status status);
static void sendMacPdu(void);

/* Timer variables */
static Timer_Handle timer0;
static Timer_Params params;


void macInit(macCallback_t cb)
{
    timerInit();
    callbackFxn = cb;

    // Initialize the EasyLink parameters to their default values
    EasyLink_Params easyLink_params;
    EasyLink_Params_init(&easyLink_params);

    /*
     * Initialize EasyLink with the settings found in ti_easylink_config.h
     * Modify EASYLINK_PARAM_CONFIG in ti_easylink_config.h to change the default
     * PHY
     */
    if(EasyLink_init(&easyLink_params) != EasyLink_Status_Success)
    {
        // callback for application error handling
    }

    dispHandle = Display_open(Display_Type_ANY, NULL);
    Display_clear(dispHandle);

    /* Listen for incoming packets */
    enableRx();
	
	/* Start timer that will trigger transmission */
    startTimer();
}


static void timerCallback(Timer_Handle myHandle, int_fast16_t status)
{
	/* Send a Sync PDU */
    sendMacPdu();
}

static EasyLink_Status enableRx(void)
{
    EasyLink_Status status;
    if(!bOngoingRx)
    {
        /* wait for next packet */
        status = EasyLink_receiveAsync(echoRxDoneCb, 0);
        bOngoingRx = true;
    }

    return status;
}

static EasyLink_Status disableRx(void)
{
    EasyLink_Status status;
    if(bOngoingRx)
    {
        /* Abort ongoing receptions */
        status = EasyLink_abort();
        bOngoingRx = false;
    }

    return status;
}

static void echoRxDoneCb(EasyLink_RxPacket * rxPacket, EasyLink_Status status)
{
	if (status == EasyLink_Status_Success)
	{
		// handle received packet
	}
	
	/* only re-enable Rx if it was not aborted */
    if (status != EasyLink_Status_Aborted)
    {
        status = enableRx();
    }
}


static void echoTxDoneCb(EasyLink_Status status)
{
    /* Transmission successfully done */
    if (status == EasyLink_Status_Success)
    {
        // callbacks etc.
    }

    /* Since transmission is done, we can re-enter reception */
    status = enableRx();
}


static void sendMacPdu(void)
{
	EasyLink_TxPacket txPacket = {{0}, 0, 0, {0}};
	
	/* Fill some dummy data for testing */
	txPacket.dstAddr[0] = 0xff;
    txPacket.len = 3;
    txPacket.payload[0] = 0x01;
    txPacket.payload[1] = 0x02;
    txPacket.payload[2] = 0x03;
	
	/* disable Rx prior transmission */
    stat = disableRx();

	/* Transmit the PDU */
	// returns EasyLink_Status_BusyError
    stat = EasyLink_transmitAsync(&txPacket, echoTxDoneCb);
}


static void timerInit(void) {
    /*
     * Setting up the timer in continuous callback mode that calls the callback
     * function every 1,000,000 microseconds, or 1 second.
     */
    Timer_init();
    Timer_Params_init(&params);
    params.period = 1000000;
    params.periodUnits = Timer_PERIOD_US;
    params.timerMode = Timer_CONTINUOUS_CALLBACK;
    params.timerCallback = timerCallback;

    timer0 = Timer_open(CONFIG_TIMER_0, &params);

    if (timer0 == NULL) {
        /* Failed to initialized timer */
        while (1) {}
    }
}


static void startTimer(void)
{
    if (Timer_start(timer0) == Timer_STATUS_ERROR) {
        /* Failed to start timer */
        while (1) {}
    }
}

Thank you in advance

Greetings,

Alex