/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
/* Size of the source and destination buffers in 32-bit words.
Allowable values = 128, 256, 512, or 1024 */
#define SIZE_BUFFER (512)
/* Source and destination buffers */
uint32_t adc_buf[SIZE_BUFFER];
/* DMA completion flag */
static volatile bool dmaDone;
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
/*****************************************************************************
* Public functions
****************************************************************************/
/**
* @briefDMA Interrupt Handler
* @returnNone
*/
void DMA_IRQHandler(void)
{
/* Error interrupt on channel 0? */
if ((Chip_DMA_GetIntStatus(LPC_DMA) & DMA_INTSTAT_ACTIVEERRINT) != 0) {
/* This shouldn't happen for this simple DMA example, so set the LED
to indicate an error occurred. This is the correct method to clear
an abort. */
Chip_DMA_DisableChannel(LPC_DMA, DMA_CH0);
while ((Chip_DMA_GetBusyChannels(LPC_DMA) & (1 << DMA_CH0)) != 0) {}
Chip_DMA_AbortChannel(LPC_DMA, DMA_CH0);
Chip_DMA_ClearErrorIntChannel(LPC_DMA, DMA_CH0);
Chip_DMA_EnableChannel(LPC_DMA, DMA_CH0);
Board_LED_Set(0, true);
}
/* Clear DMA interrupt for the channel */
Chip_DMA_ClearActiveIntAChannel(LPC_DMA, DMA_CH0);
dmaDone = true;
}
void DMA_init( void ) {
DMA_CHDESC_T dmaDesc;
/* DMA initialization - enable DMA clocking and reset DMA if needed */
Chip_DMA_Init(LPC_DMA);
/* Enable DMA controller and use driver provided DMA table for current descriptors */
Chip_DMA_Enable(LPC_DMA);
Chip_DMA_SetSRAMBase(LPC_DMA, DMA_ADDR(Chip_DMA_Table));
/* Setup channel 0 for the following configuration:
- High channel priority
- Interrupt A fires on descriptor completion
- trigger on ACD1 seq A completion
- burst size is 1 */
Chip_DMA_EnableChannel(LPC_DMA, DMA_CH0);
Chip_DMA_EnableIntChannel(LPC_DMA, DMA_CH0);
Chip_INMUX_SetDMATrigger(DMA_CH0, DMATRIG_ADC1_SEQA_IRQ);
Chip_DMA_SetupChannelConfig(LPC_DMA, DMA_CH0,
(DMA_CFG_PERIPHREQEN | DMA_CFG_HWTRIGEN | DMA_CFG_TRIGTYPE_EDGE |
DMA_CFG_TRIGPOL_HIGH | DMA_CFG_BURSTPOWER_1 | DMA_CFG_CHPRIORITY(0)));
/* DMA descriptor for peripheral to memory operation - note that addresses must
be the END address for src and destination, not the starting address.
DMA operations moves from end to start. */
dmaDesc.source = DMA_ADDR(&(LPC_ADC1->DR[ADC1_IBUS_CH]));
dmaDesc.dest = DMA_ADDR(&adc_buf[SIZE_BUFFER - 1]) + 3;
dmaDesc.next = DMA_ADDR(0);
/* Setup transfer descriptor and validate it */
Chip_DMA_SetupTranChannel(LPC_DMA, DMA_CH0, &dmaDesc);
Chip_DMA_SetValidChannel(LPC_DMA, DMA_CH0);
NVIC_EnableIRQ(DMA_IRQn);// Enable DMA interrupt
/* Setup data transfer and software trigger in same call */
Chip_DMA_SetupChannelTransfer(LPC_DMA, DMA_CH0,
(DMA_XFERCFG_CFGVALID | DMA_XFERCFG_SETINTA |
DMA_XFERCFG_WIDTH_32 | DMA_XFERCFG_SRCINC_0 | DMA_XFERCFG_DSTINC_1 |
DMA_XFERCFG_XFERCOUNT(SIZE_BUFFER)));
dmaDone = false;
}
|
/**
* Init ADC1 to perform periodical reads on channels 0 and 1, whith threshold detection
*/
void ADC1_init( void )
{
/* --- ADC Init --- */
/* Setup ADC for 12-bit mode and normal power */
Chip_ADC_Init(ADC, 0);
/* Setup for maximum ADC clock rate */
Chip_ADC_SetClockRate(ADC, ADC_MAX_SAMPLE_RATE);
/* For ADC1, sequencer A will be used with threshold events.
It will run continuously in burst mode and will monitor the CH0 & CH1 input. */
Chip_ADC_SetupSequencer(ADC, ADC_SEQA_IDX,(ADC_SEQ_CTRL_CHANSEL(ADC1_VBUS_CH) |
ADC_SEQ_CTRL_CHANSEL(ADC1_IBUS_CH) |
ADC_SEQ_CTRL_BURST |
ADC_SEQ_CTRL_MODE_EOS));
/* Need to do a calibration after initialization and trim */
Chip_ADC_StartCalibration(ADC);
while (!(Chip_ADC_IsCalibrationDone(ADC))) {}
/* ACD clock must be set after calibration !! (bug in lib) */
Chip_ADC_SetClockRate(ADC, ADC_MAX_SAMPLE_RATE);
/* setup thresholds so that they are never crossed.
* They will be set by application, through ADC1_set_thr(...)
*/
// ch 0
Chip_ADC_SelectTH0Channels(ADC, ADC_SEQ_CTRL_CHANSEL(ADC1_VBUS_CH));
Chip_ADC_SetThrLowValue(ADC, 0, 0x000);
Chip_ADC_SetThrHighValue(ADC, 0, 0xFFF);
// ch 1
Chip_ADC_SelectTH1Channels(ADC, ADC_SEQ_CTRL_CHANSEL(ADC1_IBUS_CH));
Chip_ADC_SetThrLowValue(ADC, 1, 0x000);
Chip_ADC_SetThrHighValue(ADC, 1, 0xFFF);
/* Clear all pending interrupts */
Chip_ADC_ClearFlags(ADC, Chip_ADC_GetFlags(ADC));
/* Enable sequence A completion and threshold crossing interrupts for ADC1_0 and ADC 1_1 */
Chip_ADC_EnableInt(ADC, ADC_INTEN_CMP_ENABLE(ADC_INTEN_CMP_CROSSTH, ADC1_VBUS_CH) |
ADC_INTEN_CMP_ENABLE(ADC_INTEN_CMP_CROSSTH, ADC1_IBUS_CH) |
ADC_INTEN_SEQA_ENABLE);
Chip_ADC_SetThresholdInt(ADC, ADC1_VBUS_CH, ADC_INTEN_THCMP_CROSSING);
Chip_ADC_SetThresholdInt(ADC, ADC1_IBUS_CH, ADC_INTEN_THCMP_CROSSING);
// DO NOT ACTIVATE NVIC (for dma operation)
//_NVIC_ClearEnableIRQ(ADC1_SEQA_IRQn);
/* Enable sequencers */
Chip_ADC_EnableSequencer(ADC, ADC_SEQA_IDX);
}
/**
* ADC Mux PIN enable
*/
void ADC1_init_PinMux( void )
{
/* Disables pullups/pulldowns and disable digital mode */
Chip_IOCON_PinMuxSet(LPC_IOCON, 0, 9, (IOCON_MODE_INACT | IOCON_ADMODE_EN));
Chip_IOCON_PinMuxSet(LPC_IOCON, 0, 32+1, (IOCON_MODE_INACT | IOCON_ADMODE_EN));
/* Assign ADC1_1 to PIO0_9 via SWM (fixed pin) */
Chip_SWM_EnableFixedPin(SWM_FIXED_ADC1_0);/*!< ADC0_0 fixed pin enable/disable on pin P1_1 */
Chip_SWM_EnableFixedPin(SWM_FIXED_ADC1_1);/*!< ADC0_1 fixed pin enable/disable on pin P0_9 */
}
|
Hi Tom,
Did you have success in the meantime?
I have a rather similar use case and still cannot find any examples / application notes on this topic :-(
Regards, Martin