Switched to DMA
84% load with 1Msps no DMA 2.4% load with 2Msps with DMA
This commit is contained in:
parent
bd79be6eac
commit
15a478c9aa
4 changed files with 103 additions and 19 deletions
8
main.c
8
main.c
|
@ -188,7 +188,7 @@ void capture_waveform(UArg arg1, UArg arg2)
|
|||
int32_t i;
|
||||
|
||||
if (options.fft) {
|
||||
adc_current_index = gADCBufferIndex;
|
||||
adc_current_index = getADCBufferIndex();
|
||||
int32_t j = 0;
|
||||
for(i=adc_current_index-FFT_BUF_LEN; i<adc_current_index; i++) {
|
||||
adc_buffer_fft_sample[j++] = gADCBuffer[ADC_BUFFER_WRAP(adc_current_index + i)];
|
||||
|
@ -199,7 +199,7 @@ void capture_waveform(UArg arg1, UArg arg2)
|
|||
|
||||
int trigger;
|
||||
if (trigger_mode == 2) {
|
||||
trigger = gADCBufferIndex - (WIDTH / 2); // show latest if trigger disabled
|
||||
trigger = getADCBufferIndex() - (WIDTH / 2); // show latest if trigger disabled
|
||||
} else {
|
||||
trigger = Trigger(trigger_mode);
|
||||
}
|
||||
|
@ -367,7 +367,7 @@ void display_waveform(UArg arg1, UArg arg2)
|
|||
|
||||
int Trigger(bool rising) // search for edge trigger
|
||||
{
|
||||
int x = gADCBufferIndex - (WIDTH / 2); // half screen width
|
||||
int x = getADCBufferIndex() - (WIDTH / 2); // half screen width
|
||||
int x_stop = x - ADC_BUFFER_SIZE/2;
|
||||
for (; x > x_stop; x--) {
|
||||
if (rising) {
|
||||
|
@ -383,6 +383,6 @@ int Trigger(bool rising) // search for edge trigger
|
|||
}
|
||||
}
|
||||
if (x == x_stop) // for loop ran to the end
|
||||
x = gADCBufferIndex - (WIDTH / 2); // reset x back to how it was initialized
|
||||
x = getADCBufferIndex() - (WIDTH / 2); // reset x back to how it was initialized
|
||||
return x;
|
||||
}
|
||||
|
|
6
rtos.cfg
6
rtos.cfg
|
@ -36,6 +36,7 @@
|
|||
var Clock = xdc.useModule('ti.sysbios.knl.Clock');
|
||||
var Mailbox = xdc.useModule('ti.sysbios.knl.Mailbox');
|
||||
var TimestampProvider = xdc.useModule('ti.sysbios.family.arm.lm4.TimestampProvider');
|
||||
var GateHwi = xdc.useModule('ti.sysbios.gates.GateHwi');
|
||||
/*
|
||||
* Default value is family dependent. For example, Linux systems often only
|
||||
* support a minimum period of 10000 us and multiples of 10000 us.
|
||||
|
@ -538,7 +539,7 @@ Clock.timerId = 0;
|
|||
TimestampProvider.useClockTimer = true;
|
||||
var m3Hwi0Params = new m3Hwi.Params();
|
||||
m3Hwi0Params.instance.name = "m3Hwi0";
|
||||
m3Hwi0Params.priority = 0;
|
||||
m3Hwi0Params.priority = 64;
|
||||
Program.global.m3Hwi0 = m3Hwi.create(62, "&ADC_ISR", m3Hwi0Params);
|
||||
var task1Params = new Task.Params();
|
||||
task1Params.instance.name = "waveform";
|
||||
|
@ -593,3 +594,6 @@ var semaphore4Params = new Semaphore.Params();
|
|||
semaphore4Params.instance.name = "options_sem";
|
||||
semaphore4Params.mode = Semaphore.Mode_BINARY;
|
||||
Program.global.options_sem = Semaphore.create(1, semaphore4Params);
|
||||
var gateHwi0Params = new GateHwi.Params();
|
||||
gateHwi0Params.instance.name = "gateHwiDMA";
|
||||
Program.global.gateHwi0 = GateHwi.create(gateHwi0Params);
|
||||
|
|
106
sampling.c
106
sampling.c
|
@ -7,37 +7,111 @@
|
|||
#include "driverlib/sysctl.h"
|
||||
#include "driverlib/interrupt.h"
|
||||
#include "driverlib/timer.h"
|
||||
#include "driverlib/udma.h"
|
||||
#include "sysctl_pll.h"
|
||||
#include "inc/hw_types.h"
|
||||
#include "inc/hw_memmap.h"
|
||||
#include <math.h>
|
||||
#include "buttons.h"
|
||||
#include "sampling.h"
|
||||
#include <xdc/std.h>
|
||||
#include <xdc/runtime/System.h>
|
||||
#include <xdc/cfg/global.h>
|
||||
#include <ti/sysbios/gates/GateHwi.h>
|
||||
|
||||
|
||||
#define DMA
|
||||
|
||||
#ifdef DMA
|
||||
#pragma DATA_ALIGN(gDMAControlTable, 1024)
|
||||
tDMAControlTable gDMAControlTable[64]; // uDMA control table
|
||||
#endif
|
||||
|
||||
extern uint32_t gSystemClock; // [Hz] system clock frequency
|
||||
|
||||
// latest sample index
|
||||
void ADC_ISR(void)
|
||||
// is DMA occurring in the primary channel?
|
||||
volatile bool gDMAPrimary = true;
|
||||
void ADC_ISR(void) // DMA
|
||||
{
|
||||
// clear ADC1 sequence0 interrupt flag in the ADCISC register
|
||||
//HWREGBITW(ADC1_ISC_R, 1) = 1;
|
||||
ADC1_ISC_R |= 1;
|
||||
|
||||
// check for ADC FIFO overflow
|
||||
if(ADC1_OSTAT_R & ADC_OSTAT_OV0) {
|
||||
gADCErrors++; // count errors
|
||||
ADC1_OSTAT_R = ADC_OSTAT_OV0; // clear overflow condition
|
||||
ADCIntClearEx(ADC1_BASE, ADC_INT_DMA_SS0); // clear the ADC1 sequence 0 DMA interrupt flag
|
||||
// Check the primary DMA channel for end of transfer, and
|
||||
// restart if needed.
|
||||
if (uDMAChannelModeGet(UDMA_SEC_CHANNEL_ADC10 | UDMA_PRI_SELECT) ==
|
||||
UDMA_MODE_STOP) {
|
||||
// restart the primary channel (same as setup)
|
||||
uDMAChannelTransferSet(UDMA_SEC_CHANNEL_ADC10 | UDMA_PRI_SELECT,
|
||||
UDMA_MODE_PINGPONG, (void*)&ADC1_SSFIFO0_R,
|
||||
(void*)&gADCBuffer[0], ADC_BUFFER_SIZE/2);
|
||||
// DMA is currently occurring in the alternate buffer
|
||||
gDMAPrimary = false;
|
||||
}
|
||||
// Check the alternate DMA channel for end of transfer, and
|
||||
// restart if needed.
|
||||
// Also set the gDMAPrimary global.
|
||||
if (uDMAChannelModeGet(UDMA_SEC_CHANNEL_ADC10 | UDMA_ALT_SELECT) ==
|
||||
UDMA_MODE_STOP) {
|
||||
// restart the primary channel (same as setup)
|
||||
uDMAChannelTransferSet(UDMA_SEC_CHANNEL_ADC10 | UDMA_ALT_SELECT,
|
||||
UDMA_MODE_PINGPONG, (void*)&ADC1_SSFIFO0_R,
|
||||
(void*)&gADCBuffer[ADC_BUFFER_SIZE/2],
|
||||
ADC_BUFFER_SIZE/2);
|
||||
// DMA is currently occurring in the primary buffer
|
||||
gDMAPrimary = true;
|
||||
}
|
||||
// The DMA channel may be disabled if the CPU is paused by the debugger
|
||||
if (!uDMAChannelIsEnabled(UDMA_SEC_CHANNEL_ADC10)) {
|
||||
// re-enable the DMA channel
|
||||
uDMAChannelEnable(UDMA_SEC_CHANNEL_ADC10);
|
||||
}
|
||||
gADCBufferIndex = ADC_BUFFER_WRAP(gADCBufferIndex + 1);
|
||||
// read sample from the ADC1 sequence 0 FIFO
|
||||
gADCBuffer[gADCBufferIndex] = (ADC1_SSFIFO0_R & ADC_SSFIFO0_DATA_M);
|
||||
}
|
||||
|
||||
int32_t getADCBufferIndex(void)
|
||||
{
|
||||
int32_t index;
|
||||
uint32_t key = GateHwi_enter(gateHwi0);
|
||||
if (gDMAPrimary) { // DMA is currently in the primary channel
|
||||
index = ADC_BUFFER_SIZE/2 - 1 -
|
||||
uDMAChannelSizeGet(UDMA_SEC_CHANNEL_ADC10 |
|
||||
UDMA_PRI_SELECT);
|
||||
} else { // DMA is currently in the alternate channel
|
||||
index = ADC_BUFFER_SIZE - 1 -
|
||||
uDMAChannelSizeGet(UDMA_SEC_CHANNEL_ADC10 |
|
||||
UDMA_ALT_SELECT);
|
||||
}
|
||||
GateHwi_leave(gateHwi0, key);
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
void start_sampler() {
|
||||
gADCBufferIndex = ADC_BUFFER_SIZE - 1;
|
||||
gADCErrors = 0;
|
||||
|
||||
// init DMA
|
||||
SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
|
||||
uDMAEnable();
|
||||
uDMAControlBaseSet(gDMAControlTable);
|
||||
// assign DMA channel 24 to ADC1 sequence 0
|
||||
uDMAChannelAssign(UDMA_CH24_ADC1_0);
|
||||
uDMAChannelAttributeDisable(UDMA_SEC_CHANNEL_ADC10, UDMA_ATTR_ALL);
|
||||
// primary DMA channel = first half of the ADC buffer
|
||||
uDMAChannelControlSet(UDMA_SEC_CHANNEL_ADC10 | UDMA_PRI_SELECT,
|
||||
UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 |
|
||||
UDMA_ARB_4);
|
||||
uDMAChannelTransferSet(UDMA_SEC_CHANNEL_ADC10 | UDMA_PRI_SELECT,
|
||||
UDMA_MODE_PINGPONG, (void*)&ADC1_SSFIFO0_R,
|
||||
(void*)&gADCBuffer[0], ADC_BUFFER_SIZE/2);
|
||||
// alternate DMA channel = second half of the ADC buffer
|
||||
uDMAChannelControlSet(UDMA_SEC_CHANNEL_ADC10 | UDMA_ALT_SELECT,
|
||||
UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 |
|
||||
UDMA_ARB_4);
|
||||
uDMAChannelTransferSet(UDMA_SEC_CHANNEL_ADC10 | UDMA_ALT_SELECT,
|
||||
UDMA_MODE_PINGPONG, (void*)&ADC1_SSFIFO0_R,
|
||||
(void*)&gADCBuffer[ADC_BUFFER_SIZE/2],
|
||||
ADC_BUFFER_SIZE/2);
|
||||
uDMAChannelEnable(UDMA_SEC_CHANNEL_ADC10);
|
||||
|
||||
|
||||
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
|
||||
GPIOPinTypeADC(GPIO_PORTE_BASE,
|
||||
GPIO_PIN_0); // GPIO setup for analog input AIN3
|
||||
|
@ -64,8 +138,12 @@ void start_sampler() {
|
|||
ADCSequenceStepConfigure(ADC1_BASE, 0, 0, ADC_CTL_CH3 | ADC_CTL_END | ADC_CTL_IE);
|
||||
// enable the sequence. it is now sampling
|
||||
ADCSequenceEnable(ADC1_BASE, 0);
|
||||
|
||||
// enable sequence 0 interrupt in the ADC1 peripheral
|
||||
ADCIntEnable(ADC1_BASE, 0); // INT_ADC1SS0
|
||||
//ADCIntEnable(ADC1_BASE, 0); // INT_ADC1SS0
|
||||
|
||||
ADCSequenceDMAEnable(ADC1_BASE, 0); // enable DMA for ADC1 sequence 0
|
||||
ADCIntEnableEx(ADC1_BASE, ADC_INT_DMA_SS0); // enable ADC1 sequence 0 DMA interrupt
|
||||
}
|
||||
|
||||
void set_frequency(uint64_t microseconds) {
|
||||
|
|
|
@ -17,4 +17,6 @@ void start_sampler(void);
|
|||
|
||||
void set_frequency(uint64_t microseconds);
|
||||
|
||||
int32_t getADCBufferIndex(void);
|
||||
|
||||
#endif /* SAMPLING_H_ */
|
||||
|
|
Loading…
Reference in a new issue