Debugging state machine timing discontinuity

I agree that busy waiting is incorrect, and I will resolve this. I wanted to double check the logic here though - the reason I am testing TXBUFE is due to this language in the data sheet:

The following list gives an overview of how status register flags behave depending on the counters’ values:
 ENDRX flag is set when the PERIPH_RCR register reaches zero.
 RXBUFF flag is set when both PERIPH_RCR and PERIPH_RNCR reach zero.
 ENDTX flag is set when the PERIPH_TCR register reaches zero.
 TXBUFE flag is set when both PERIPH_TCR and PERIPH_TNCR reach zero
These status flags are described in the Peripheral Status Register.
Each peripheral connected to the PDC sends out receive ready and transmit ready flags and the PDC sends back flags to the peripheral. All these flags are only visible in the Peripheral Status Register.

I took this to mean that status flags can only be accessed through the peripheral's status register - not the DMA controller register. The only flags in the DMA controller's status register (PTSR) are whether the transfer and receive channels are enabled - I don't think those flags change when transfers end:

The PDC has dedicated status registers which indicate if the transfer is enabled or disabled for each channel. The status for each channel is located in the associated peripheral status register. Transfers can be enabled and/or disabled by setting TXTEN/TXTDIS and RXTEN/RXTDIS in the peripheral’s Transfer Control Register.
At the end of a transfer, the PDC channel sends status flags to its associated peripheral. These flags are visible in the peripheral status register (ENDRX, ENDTX, RXBUFF, and TXBUFE). Refer to Section 26.4.3 and to the associated peripheral user interface.

Thank you all for the help and the time you took out of your days to respond to this thread!! I have resolved the issue. I will paste my report of the solution, for anybody who is interested:

I have fixed the timing discontinuity in the state machine - the thing where every 404 cycles, there would be 13 cycles that were not at 22 ms. Below is the detailed description of what the issue was and how I fixed it, for future reference + to maybe explain why this took me so long to fix, haha.

The description of the issue:

The internal timer begins running prior to the first sweep. On this board, this resulted in the first "ready for next cycle" variable getting set to true prior to the conclusion of the first cycle. Here is a picture of the oscilloscope at the beginning of the state machine:

Blue is the DAC sweep, green goes high when the "ready for next cycle" variable gets set to true, and yellow goes high when the "wait for next cycle" state begins. Purple is the SPI CS pin with the EEPROM, which is the last state before "wait for next cycle." As you can see, for the first 13 cycles, the variable was getting set to true prior to the SPI transaction with the EEPROM.

For those first 13 cycles, the state machine goes directly into the next cycle at the conclusion, rather than waiting until 22.2 ms, because it thinks it has already been 22.2 ms since the variable has been set to true. After 13 cycles, it waits and each cycle is 22.2 ms.

At that point, it took 13 cycles for the timer to "get in sync" with the state machine - for the "ready for next cycle" variable to get set after the conclusion of the cycle. That's why when it would get out of sync, it would get out of sync for exactly 13 cycles every time.

So, I added some code that resets the internal timer at the beginning of the first sweep:

if (isFirst){

    isFirst = false;

    timer = micros();

    newCycle = false;

}

This code resolved the timing jumps. Here is what the beginning of the state machine looks like now:

As you can see now, green goes high before yellow goes high during the very first cycle, which is how it looks in normal operation.

Note that the EEPROM transaction occurs every other cycle because we only send a read command after ten seconds have passed (when we start sending buffered data) and it only writes every other cycle.

EDIT: I have no clue why removing my UART communications got rid of the timing discontinuity before. It may have been entirely incidental, as the discontinuity did not always happen, as I mentioned in an earlier post. I apologize for probably misleading some of you!

1 Like

Thanks for the detailed explanation and kudos for your debugging efforts !

NP.

Do you have a theory, or did I miss something, about why it would sometimes not start up in such a way as to show the problem?

Is that fix done once per restart? Could it be the last thing in setup() and unconditional?

a7