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.

Sensor Controller Multi-buffer problem



I am having an issue with fwSwitchOutputBuffer.   I have a two buffer setup.   I'm running this inside an "infinite loop" in the sensor controller.

I used the "Quick" alert to notify the ARM (after collecting a buffer full of samples as shown here (A buffer and B buffer are from two sensors; both in a single buffer to be exchanged):

At initialization, I set values to pointers being stored in the state structure:

state.Aptr = #output.ABuffer;

state.Bptr = #output.BBuffer;

At the top of the loop, I wait for an edge on an external control signal that indicates that data is available from an SPI peripheral and then access the data.

I then grab pointers to two buffers in my output structure:

Aptr = state.Aptr;

Bptr = state.Bptr;

and store the data using the pointers.

I then write the updated pointer values back to their state variable equivalents.

After storing the data, I check to see if I have filled the buffer.   If so, I do an exchange and send a notification to the ARM.   Since I stay in a loop, I use the QuickAlert  function (since the automated alert from the fwSwitchOutputBuffer() will not be issued because the task continues).

if(state.bufCnt >= cfg.numSamples) {

    fwSwitchOutputBuffer();

    state.Aptr = #output.ABuffer;

    state.Bptr = #output.BBuffer;

    state.bufCnt = 0;

    fwGenQuickAlertInterrupt();

}

After the exchange, I re-initialize the buffer pointers.   Here I expect the pointers to reflect the "exchanged" buffer addresses.

Then the SensorController code loops around to wait for more "edges" and collects more data.

On the ARM side:

void scTaskAlertCallback(void) {
      // Called when a buffer is ready from the Sensor Controller

      // Clear the ALERT interrupt source
      scifClearAlertIntSource();

      if(scifGetTaskIoStructAvailCount(SCIF_TASK_ID,SCIF_STRUCT_OUTPUT) == 1) {
         SCIF_OUTPUT_T *ptrOutput = scifGetTaskStruct(SCIF_TASK_ID, SCIF_STRUCT_OUTPUT);

         memcpy(RawAData,&(ptrOutput->ABuffer),sizeof(RawAData));
         memcpy(RawBData,&(ptrOutput->BBuffer),sizeof(RawBData));

         scifHandoffTaskStruct(SCIF_TASK_ID, SCIF_STRUCT_OUTPUT);
      }

      // Acknowledge the alert event
      scifAckAlertEvents();

      // Set a flag so task knows why it is being wakened.
      DataReceived = true;

      Semaphore_post(localSem);
}

My application runs but, but every other data buffer has all zeros.     

I looked at the assembly code generated by SensorController.   I don't think the statements (after the buffer exchange):

    state.Aptr = #output.ABuffer;

    state.Bptr = #output.BBuffer;

take into consideration that the A/B Buffers are in a multi-buffer structure.   They always get initialized (I think) to buffer zero.

The other code does what it is supposed to do, so when the ARM grabs the data and looks at buffer one, it sees zeros because the Sensor Controller is always using buffer zero!

Is there a work around for this?  Or is there a different syntax to indicate that one wants the value of the "swapped/updated" buffer?

BTW, I originally had "local" variables for the buffer pointers, but found that the compiler didn't realized that the code looped back, so was "re-using" registers that held the pointers, hence the need to copy them into "state" memory.

Thanks!

Ed

  • I have asked the developer to take a look. Also check out my answer in your other thread.
  • More info. I think I have verified what is happening.

    I defined a double buffer arrangement. Each output buffer has two arrays that the sensor fills. When the buffer is filled, the following statements are used to swap the buffers:

    fwSwitchOutputBuffer();
    fwGenQuickAlertInterrupt();
    fwDelayUs(10,FW_DELAY_RANGE_10_US);
    state.bufCnt = 0;
    state.Aptr = #output.ABuffer;
    state.Bptr = #output.BBuffer;

    This didn't work.

    The documentation states that pointers are no longer valid after a fwSwitchOutputBuffer() call, so they have to be reinitialized to the new buffer (the swapped buffer) addresses. When things didn't work properly, I added the delay to see if it helped (it didn't). I also use the fwGenQuickAlertInterrupt() call since this is in an infinite loop and therefore the task doesn't finish and therefore the "normal" alert doesn't fire.

    I looked at the assembly code that the compiler produced for the pointer statements (state.Aptr = #output.Abuffer, etc.) and it doesn't look correct. It always gets "version 0" of the output buffer. No provision is made for the double buffer arrangement.

    So I created a .prd file to produce the assembly that works for me. The new code looks like this:

    fwSwitchOutputBuffer();
    fwGenQuickAlertInterrupt();
    fwDelayUs(10,FW_DELAY_RANGE_10_US);
    fwUpdateMyPointers();
    state.bufCnt = 0;

    The function "fwUpdateMyPointers()" produces the assembly:

    ;? fwUpdateMyPointers();
    039a ---- 0907 ld R0, [#readAfechip/outputScePtr]
    039b ---- 0dbc st R0, [#readAfechip/state/Aptr]
    039c ---- 882d add R0, #45
    039d ---- 0dbd st R0, [#readAfechip/state/Bptr]

    It looks like the SensorController correctly maintains the "outputScePtr" which seems to be a "word" pointer to the active output buffer.
    My two output arrays sit back-to-back in the output structure, so the Aptr gets the value stored in "outputScePtr" while the Bptr gets this value offset by "45" (which is the length of the array).

    Note that I couldn't figure out how to declare a "state" variable as a pointer. Using *(state.Aptr++) generates a syntax error. Just using a "local" variable (ie. U16* aa) *(aa++) doesn't work because the compiler doesn't maintain the register values properly around the loop. So I declared a local variable for each array (U16* aa and U16* bb) and assign them from the state variables (state.Aptr and state.Bptr) at the top of the loop, use them, then store them back to the state variables (state.Aptr and state.Bptr) at the end of the loop.

    In any case this now works for me...
  • Hello Ed,
    Thanks for digging this one out. It is indeed a bug and this will be fixed in the upcoming release (version 1.2.0).