DMA eases CPU's workload for waveform generation
To generate analog voltages and waveforms, embedded systems often require one or more embedded or external DACs. To produce an analog voltage, the CPU must write the desired output value to the DAC at the appropriate time, a task that a timer-generated interrupt applied to the CPU usually initiates. In applications in which the DAC generates a periodic waveform, the CPU reads the next value from the table, sends it to the DAC, increments a table pointer, and checks for table boundaries to determine when to reset the table pointer.
Writing the periodic values to the DAC to maintain the output waveform requires CPU overhead, which varies depending on the data table's length, the output waveform's frequency, and the CPU's operating frequency. For example, using 32 data points per period to generate a 1-kHz sine wave requires the CPU to service 32,000 interrupts/sec. If the application requires a second analog output waveform, the CPU's loading increases, and updating both DACs within the required interrupt-service time may be impossible.
To calculate CPU loading, you need to know the length and the context-switching overhead of the ISR (interrupt-service routine). For the MSP430 processor, the ISR's overhead consumes 11 cycles, but the ISR's length depends upon how it is written. The assembly code in Listing 1, uses the fewest cycles to implement periodic waveform generation using one or two DACs. For a typical 1-MHz MSP430 CPU-instruction rate, serving 32,000 interrupts/sec leaves 1 million/32,000=31.25 CPU-instruction cycles between interrupts. An ISR requiring 18 cycles—that is, 18/31.25=57.6—represents a 57.6% CPU load. Supporting two DACs requires 23 cycles—that is, 23/31.25=73.6—and imposes a 73.6% CPU load. Increasing the MSP430's clock rate to its maximum 8 MHz reduces the CPU loading to 7.2 and 9.2%, respectively.
The required CPU load imposes limits not only on other tasks that the application may demand, but also on the waveform's maximum frequency. For example, a CPU operating at 100% CPU loading and an instruction rate of 1 MHz can generate a single waveform with a maximum frequency of approximately 1.73 kHz or two waveforms with a maximum frequency of approximately 1.35 kHz each. Raising the instruction rate to 8 MHz increases the respective maximum frequencies to approximately 13.9 and 10.9 kHz.
However, the MSP430F15x/16x family of devices includes a multichannel-DMA controller that can move data from one location to another without CPU intervention (Figure 1). In a waveform-generation application, the DMA controller moves data from the data table to the two DACs, significantly reducing the necessary CPU overhead to produce the waveforms. You can configure each of the DMA controller's three separate and independent channels to move a value from any address to any other address. In this example, one data table contains values for both the sine and the cosine waves, and two of the DMA channels simply access different parts of the table to form the sine and the cosine outputs. In addition, each DMA channel can independently increment its source or destination address. For this application, each DMA channel increments its source address, but the destination addresses of the respective DAC data registers always remain the same.
You can reconfigure each controller's preset number of DMA transfers. When either DMA channel has transferred its programmed number of data values, it begins the next data transfer from its originally programmed source address. In effect, each DMA channel treats its portion of the data table as a circular buffer to generate a periodic waveform. Although DMA transfers do not involve the CPU, each transfer does consume two CPU clock cycles, which delays CPU code execution and thus introduces overhead. For the single-waveform example, using DMA transfers consumes two clock cycles for each DAC update instead of the 18 cycles necessary when using only the CPU. Thus, for a CPU clock rate of 1 MHz, using DMA reduces the effective CPU loading from 57.6% to 6.4% and increases the possible maximum output frequency from approximately 1.73 kHz to approximately 15.6 kHz. For an 8-MHz clock rate, using DMA reduces single-waveform CPU loading from 7.2% to 0.8%.
Generating two waveforms requires two DMA transfers or four clock cycles. For the two-waveform example, DMA reduces loading from 73.6% to 12.8% for a 1-MHz instruction rate, and from 9.2% to 1.6% for an 8-MHz rate. For the 1-MHz instruction rate, using DMA increases the possible maximum frequency for two waveforms from approximately 1.35 kHz to approximately 7.8 kHz.
After initialization, each DMA controller simply performs its duties with no further intervention other than receiving a trigger to move the data value. In this example, each DAC's interrupt flag serves as a trigger for its respective DMA channel. When you use dual DACs, you can load each DAC with the next value of waveshape data before it's required and then simultaneously trigger both DACs using a timer to avoid introducing delays that manifest themselves as output harmonic distortion. Listing 2, contains software that generates sine and cosine waves and illustrates the DMA channels' independent operation apart from the CPU. Note that, after initialization of DMA channels and other device-specific peripherals, no further CPU activity occurs.
Figure 2 shows a partial schematic of the DACs' outputs. Depending on the application, you may need to add optional resistance-capacitance lowpass filters at the DACs' outputs. Select values for the resistor and capacitor in each filter to produce a pole in the filter response at the desired output frequencies. Note that the oscilloscope photo in Figure 3 was taken with filters removed to show the DAC outputs' unfiltered waveforms.