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.

RTOS/CC2640R2F: TI's methodology of using the RF circular queue when running in propriety radio mode

Part Number: CC2640R2F


Tool/software: TI-RTOS

Hi

I have an issue when using the CC2640R2F in propriety mode. I define a circular buffer (using a fixed version of TI's RFQueue code) using the rfc_dataEntryGeneral_t structure (DATA_ENTRY_TYPE_GEN), and when ever a "RF_EventRxEntryDone" callback is made, I read the next entry in the linked list.

Very occasionally, I get a callback with the error condition 0x3841, which means the buffer/queue is full. When checked with the debugger, it is indeed full, yet there has been no "RF_EventRxEntryDone" callback immediately prior.

Can TI clarify the mechanism used by the radio, to populate entries in the RX buffer; for example :

1. Does the radio simply find any empty slot in the circular buffer, and populate it. If it can not find one, it throws the error described above?

2. Does the radio keep track of its own head/tail pointers and only populates the entry at 'head', and if it is not free, it throws the error described above?

3. Does the radio use some other mechanism to populate the buffer....?

Kind regards

Gary Partis

  • Hi Gary,

    Have you subscribed to the RF_EventRxEntryDone event when scheduling the RX command?
  • Hi Edvard

    Yes - I get thousands of packets successfully, then it eventually fails (random period of time) with error 0x3841.

    If I knew how the radio engine populates the buffer, I feel I may program defensively to depopulate the buffer...

    Kind regards

    Gary
  • When you process the RX queue, do you check all of the entries or do you stop after the first entry which is done? And how many RX buffers is in your RX queue?

    Also, what kind of traffic is on the air, e.g. very busy traffic or not much at all?
  • Hi Edvard

    I stop at the first non-complete entry; then on the next callback continue where I left off, again until the first non-complete entry. I currently have an 8 entry buffer; but only expect 4 packets in quick succession (one packet every 500us). Then a gap of 18ms.

    Judging by the question you posed, ought I check _all_ entries for completed data; instead of treating it as a FIFO...?


    Kind regards

    Gary
  • Ok, sounds good to me. You shouldn't need to check all entries. Would it be possible for you to show me how you initialize and handle your RX queue?
  • Hi Edvard

    The buffer structure is created in a fashion similar to the RFQueue.c file supplied by TI. The main guts are :
        for ( i = 0; i < numEntries; i++ )
        {
     
            /* get current and next entry, address */
            rfc_dataEntry_t *entry  = (rfc_dataEntry_t *)(&buffer[ i * record_size ]);
            rfc_dataEntry_t *next   = (rfc_dataEntry_t *)(&buffer[ ( ( i + 1 ) % numEntries ) * record_size ]);
     
            /* populate with default information */
            entry->status           = DATA_ENTRY_PENDING;   /* pending - starting state         */
            entry->config.type      = DATA_ENTRY_TYPE_GEN;  /* general Data Entry               */
            entry->config.lenSz     = 0;                    /* no length indicator byte in data */
            entry->length           = length;               /* total length of data field       */
            entry->pNextEntry       = (uint8_t *)next;      /* pointer to next record           */
        }
     
        /* create queue and configure for circular buffer */
        dataQueue->pCurrEntry = buffer;
        dataQueue->pLastEntry = NULL;
     
        /* set read pointer to first entry */
        readEntry = (rfc_dataEntryGeneral_t *)dataQueue->pCurrEntry;
     
    Memory has been extensively checked for pointer errors, alignment, content, etc etc; and essentially the buffer structure is perfect. Other calls such as RFQueue_getDataEntry and RFQueue_nextEntry are left unchanged (returning head queue, and resetting inuse flag then moving to next entry; respectfully).
    The depopulating code is thus:
     
    static void RxCallBack( RF_Handle rfHandleParam, RF_CmdHandle cmdHandleParam, RF_EventMask eventMask )
    {
        if( eventMask & RF_EventRxEntryDone )
        {
            /* loop until fifo has nothing else to offer us */
            while ( ( RFQueue_getDataEntry()->status == DATA_ENTRY_FINISHED ) || ( RFQueue_getDataEntry()->status == DATA_ENTRY_UNFINISHED ) )
            {
     
                /* is this packet something we can work with */
                if ( RFQueue_getDataEntry()->status == DATA_ENTRY_FINISHED )
                {
     
                    /* get packet information */
                    rfc_dataEntryGeneral_t *currentDataEntry = RFQueue_getDataEntry();
     
                    /* process here very quickly (ie < 30us) */
                }
     
                /* move to next buffer entry */
                RFQueue_nextEntry();
            }
        }
        else if( eventMask & RF_EventCmdAborted )
        {
            /* probably a RF_cancelCmd call */
        }
        else
        {
            /* something may have gone horribly wrong */
        }
    }
     
    So:

    1.       Does the radio code populate the buffer also as a FIFO-type structure?

    2.       Does the radio code guarantee to issue a call back for every packet placed into buffer?

     
    Kind regards
     
  • It's hard to say what would cause the buffer overflow. Would it be possible to subscribe to the RF_EventRxBufFull event and set a breakpoint when the event occurs. When you hit the breakpoint, could you then inspect the RX buffers and see what the current status is?
  • Hi Edvard

    I have added some logging code (logging to flash) for when "bad" events occur. As these happens so randomly/infrequently, a number of devices are tested unison to hopefully shorten any test cycle. Running a single device connected to a PC with break points is impracticable.

    I shall report back as soon as something goes wrong.

    But for clarification, could you please answer my two earlier questions :

    1.       Does the radio code populate the buffer also as a FIFO-type structure?
    2.       Does the radio code guarantee to issue a call back for every packet placed into buffer?

    Kind regards

  • 1) Yes.
    2) The radio core will generate one interrupt when an RX entry is done. However, if more RX entries become done while the interrupt is active, no more interrupts will be generated. This means the generated interrupt triggers one callback with the event RF_EventRxEntryDone, which means one or more RX entries are done. That means a single RF_EventRxEntryDone event indicates one or more RX entries are done.