I'm building a project using the DAC on the SAM L21. I thought I could use the DAC's EMPTY0 event to feed new samples into DATABUF0, but it's not working the way I would expect.
The datasheet is light on how EMPTY0 works, but I've figured out the following through meticulous trial and error:
- The first write to DATA0 or DATABUF0 always triggers EMPTY0. It triggers very quickly; and in the latter case, well before a START0 input event occurs (i.e. before a conversion is started).
- If you write to DATABUF0 and don't touch it again until after the next START0, behavior is as expected and the DAC output updates on the START0 event. Writing to DATABUF0 after the START0 event occurs triggers another immediate EMPTY0.
- However, if you attempt to write to DATABUF0 a second time before the next START0 (as would happen if you're loading new data each EMPTY0), you get the following behavior:
- SYNCBUSY.DATABUF0 stays high until the next START0
- EMPTY0 doesn't fire until the next START0
- DAC output (usually) doesn't get updated when the next START0 event fires (may have seen some exceptions to this in async mode but it didn't seem consistent)
- If a second START0 event fires before DATABUF0 is written again, an event overrun occurs
In all, this seems to make EMPTY0 useless for triggering writes to DATABUF0. It's firing too soon after the previous value is written.
I had expected the sequence to be more like this:
- START0 moves value from DATABUF0 to DATA0 (starting a conversion)
- DATABUF0 is now "empty", firing EMPTY0
In fairness, the datasheet says:
Data Buffer 0 Empty (EMPTY0): The request is set when data is transferred from DATABUF0 or DATA0 to the internal data buffer of DAC0.
I couldn't find any more information or a diagram referencing this "internal data buffer".
Eventually I want to use SleepWalking to feed the DAC directly from low power memory without CPU intervention. But I'm trying to build this project up one piece at a time, and for now I just want to develop a thorough understanding of the behavior of the peripheral and how it interacts with events. I'm triggering the events via the a TC4 generator (in some test cases) or via the CPU through a SWEVT (in recent, more methodical test cases). I do note the datasheet says (under DMA section where the Empty events are discussed):
If the CPU accesses the registers which are source of DMA request set/clear condition, the DMA request can be lost or the DMA transfer can be corrupted, if enabled.
Do you think I would see different behavior than above if it were DMA requests instead of the timer or SWEVT directly triggering things?
Is there anyone out there who's had better luck with EMPTY0 and is willing to share some non-ASF sample code?
From what I can tell, it seems I'll need to trigger loads of new bytes from EOC0 instead of EMPTY0 (which is a bit annoying as it means I don't get as large a head-start before the next sample is due).