Q: How do I start writing an AFE squence ?
A: Advise to use the example sequences in the Software Development Kit as a reference, e.g. ImpedanceMeasurement_2wire.c
Then use the ADuCM350 ASH (AFE Sequence Helper) Tool to modify the sequence.
Link to ADuCM350 ASH: ADuCM350 ASH Tool (v1.0).
Q: Details on how to program the sequencer ?
Q: How deep / how many steps are available in Sequencer ?
A: Used correctly there is no limit to the sequncer depth ? If you feel adventurous you can feed it in commands from external memory.
Q: How are sequences for the AFE sequencer represented in software?
A: The afe_sequences.h file in the Software Development Kit (SDK) contains a number of example sequences. Each sequence is represented by an array of unsigned, 32-bit numbers in hexadecimal format. Each array consists of 2 pieces; the Safety Word and the sequence itself.
The first element (element ) of any example sequence array is the Safety Word. This is NOT part of the sequence itself. It is used to check the integrity of the sequence that has been executed. The upper half-word (bits[31:16]) contains the command count. This indicates how many commands the sequence comprises of. Note that this does NOT include the Safety Word. Each time the sequencer executes a sequence, the value in the AFE_SEQ_COUNT register is incremented by 1. When the sequence has finished executing, this value should match the command count element of the Safety Word.
The lowest byte (bits[7:0]) contains the CRC of the sequence. The CRC algorithm used is CRC-8, using the polynomial x8 + x2 + x + 1, with a seed of 1. There is a function in afe.c called crc8 which performs the calculation and mirrors the ADuCM350 hardware exactly. There is also an appendix in AN-1293 with instructions on how to use a Python CRC calculator (which is available online). Note that the CRC calculation should NOT include the Safety Word. The sequencer performs a CRC calculation on the sequences that it executes and returns the result to the AFE_SEQ_CRC register. This value should match the CRC element of the Safety Word.
Q: How are sequences triggered by the software?
A: The AFE driver (afe.c) in the SDK contains a function called adi_AFE_RunSequence which illustrates how a sequence can be triggered in software. It should be noted that this function is not optimised for performance and may not be suited to all applications, in particular where the core is required to perform other tasks while the sequencer is running. adi_AFE_RunSequence is a function which does a number of things, but remember that all of these tasks are executed on the core, the sequencer is a separate piece of hardware. First it initializes the sequencer (adi_AFE_SeqInit), pointing to the sequence to be run (txbuffer), where to put the results (rxbuffer) and how big the set of results will be (size). Some error checking is performed, some flags are set to keep track of what is happening and then the sequencer is started (adi_AFE_SeqStart). At this point, the core kicks the sequencer into action and then goes into CORE_SLEEP mode. When both the Rx DMA Done and Sequence Finished interrupts have fired, the core wakes from CORE_SLEEP mode, does some error checking and disables the FIFO and the DMA (adi_AFE_SeqStop). The very last thing the function does before returning is it checks that the CRC and command count elements of the safety word of the sequence array are equal to the CRC and command count values returned by the sequencer (adi_AFE_SeqCheck).
Q: How do I determine if I have a CRC error? Is there a flag or error code that I can look at?
A: If you are using the adi_AFE_RunSequence function, look at the return code. If it returns ADI_AFE_ERR_SEQ_CHECK, this indicates a CRC error (i.e. a mismatch between the CRC value in the safety word and the value returned by the sequencer to the AFE_SEQ_CRC register) or a command count error (i.e. a mismatch between the command count value in the safety word and the final value in the AFE_SEQ_COUNT register after the sequence has finished). If you step through the function (you will need to set multiple breakpoints to ensure that you “run” through the piece of code where the sequence is executing, remember, the sequence executes in a separate piece of hardware to the core) you will notice that the last function, adi_AFE_SeqCheck, will return this error. Also remember that if you are setting breakpoints within the adi_AFE_RunSequence function, this is called many times for the power up and calibration steps, before the code ever gets to the actual measurement!
Q: I keep getting Command FIFO Underflow interrupts (INT_CMD_FIFO_UDF) when I run my sequence, but I can't see any reason for it.
A: The Command FIFO is 8 commands deep. The sequencer will execute 1 MMR write command in a single clock cycle. Once the Command FIFO is no longer full, it will trigger to the DMA that more commands are needed. If the command FIFO is filled with 8 MMR write commands (i.e. if the sequence has 8 consecutive MMR write commands), then these commands will be executed by the sequencer in 8 clock cycles. As soon as the FIFO starts to empty, the DMA gets a request to add more commands. But the DMA cannot fullfill this request in 8 clock cycles, so the sequencer finds an empty Command FIFO and generates an underflow interrupt (INT_CMD_FIFO_UDF). To resolve this, we can delay the sequencer a little to allow the DMA controller to catch up. After (every) 7 consecutive MMR write commands in a sequence, add a short wait (100us should be sufficient). This should resolve the problem. Don't forget to update the command count!!
Handlers for these interrupts will be provided in the next revision of the SDK (v2.3.X), which is due for release soon. In the meantime, I have added an FAQ which contains code snippets which should help you.
How to create handler for AFE_ANALOG_CAPTURE_INT or AFE_ANALOG_GEN_INT?
Is there Callback function for this group similar to adi_AFE_RegisterCallbackOnReceiveDMA?