UC3C ADCIF PDCA PEVC

Go To Last Post
5 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi! My goal was to "trig" start of ADCIF sequencer 0 with exteral pin by PEVC function. Let the ADCIF SEQ0 run at ful speed and save a number of sampels with PDAC function from two ADCIN channels. The setup that I have done works almost as I want. The 10 sampels is collected and the PDAC interrupt works but I have to schift level on the external pin 10 times to get my 10 samples and the PDAC interrupt. Anyone! can I achive the function that I want or do I need to configurate ADCIF, PDAC or PEVC in an other way? "Free Running Mode" on ADCIF SEQ0 do not help either.

// Size of the string to transfer from ADCIF to memory through the PDCA
#define STRING_TRANSFER_SIZE	10	// Number of samples for one ADCIF channel
#define ADCIF_CH_IN_USE			2	// ADCIN0 and ADCIN1 is used
#define PDCA_CHANNEL_ADCIF      0

// Address of PEVC module
volatile avr32_pevc_t* ppevc = &AVR32_PEVC;
// PDCA channel
volatile avr32_pdca_channel_t *pdca_channel;
static volatile U32 u32PdcaIsr;

// String to transfer ADCIF SEQ0 to memory through the PDCA.
static volatile uint16_t aDataTransfered[ADCIF_CH_IN_USE*STRING_TRANSFER_SIZE];

// ********* PDCA Interrupts handler ***********************************************
ISR(pdca_int_handler, AVR32_PEVC_IRQ_GROUP0, 0)
{
	if (DBG_MODE_RS232){print_dbg("PDCA int handler!\r\n");}
	u32PdcaIsr = pdca_channel->isr;
	if( u32PdcaIsr & (1<<AVR32_PDCA_ISR0_TRC_OFFSET) )
	{
		// Count the number of Transfer Complete interrupts.
		pdca_reload_channel(PDCA_CHANNEL_ADCIF, (void *)aDataTransfered, sizeof( aDataTransfered ));
		print_dbg("\r\n");
	}
}

// ********** PEVC overrun and trigger Interrupt handler ***************************
ISR(pevc_int_handler, AVR32_PEVC_IRQ_GROUP, 0)
{
	if (DBG_MODE_RS232){print_dbg("PEVC int handler!\r\n");}
int32_t i=0;
	for(i=0;i<PEVC_NUMBER_OF_EVENT_USERS;i++) {
		if(true == pevc_channel_is_trigger_interrupt_raised(ppevc, i)) {
		// An overrun on the channel Id=i occurred.
		// Clear the interrupt
		pevc_channel_clear_trigger_interrupt(ppevc, i);
//		if (DBG_MODE_RS232){print_dbg("PEVC clear interrupt\r\n");}
		gpio_tgl_gpio_pin(AVR32_PIN_PA08);	// PA08, pin 11
		}
		if(true == pevc_channel_is_overrun_interrupt_raised(ppevc, i)) {
			// An overrun on the channel Id=i occurred.
			// Clear the interrupt
			pevc_channel_clear_overrun_interrupt(ppevc, i);
//			if (DBG_MODE_RS232){print_dbg("PEVC clear overrun\r\n");}
			gpio_tgl_gpio_pin(AVR32_PIN_PA09);	// PA09, pin 12
		}
	}
}

// ********* brief Init PEVC *******************************************************
void init_pevc_PAD_2(void)
{
	// Use external pin 9 (PA06) to trig start of ADCIF and SEQ0
	// PEVC Event Shaper options.
	static const pevc_evs_opt_t PEVC_EVS_OPTIONS =
	{
		.igfdr = 0x0A,            // Set the IGF clock to be clk_slow*2pow11
		.igf = PEVC_EVS_IGF_OFF,  // Input Glitch Filter off
		.evf = PEVC_EVS_EVF_ON,   // Enable Event on falling edge, Low when SW pressed
		.evr = PEVC_EVS_EVR_OFF   // No Event on rising edge
	};

	// Need to Setup GPIO ash PEVC PAD EVT
	static const gpio_map_t PEVC_GPIO_MAP =
	{
		{AVR32_PEVC_PAD_EVT_2_1_PIN , AVR32_PEVC_PAD_EVT_2_1_FUNCTION}	// PA06, pin 9
	};

	// Assign GPIO pins
	gpio_enable_module(PEVC_GPIO_MAP,
		sizeof(PEVC_GPIO_MAP) / sizeof(PEVC_GPIO_MAP[0]));

	// Register PEVC interrupts
	irqflags_t flags = cpu_irq_save();
	irq_register_handler(pevc_int_handler, AVR32_PEVC_TRIGGER_IRQ, 0);
	irq_register_handler(pevc_int_handler, AVR32_PEVC_OVERRUN_IRQ, 0);
	cpu_irq_restore(flags);

  // Assign PEVC PAD 2 to ADCIF and SEQ0
	if(FAIL == pevc_channel_configure(ppevc, AVR32_PEVC_ID_USER_ADCIFA_0,
			AVR32_PEVC_ID_GEN_PAD_2, &PEVC_EVS_OPTIONS))
	{
	  print_dbg("PEVC channel config failed!!!\r\n");
	  while(1);
	}

	// Enable the PEVC trigger interrupt.
	pevc_channels_enable_trigger_interrupt(ppevc, 1<<AVR32_PEVC_ID_USER_ADCIFA_0);
	pevc_channels_enable_overrun_interrupt(ppevc, 1<<AVR32_PEVC_ID_USER_ADCIFA_0);

	// Enable the PEVC channel "PDCA CHANNEL 0/1 ONE-ITEM-TRANSFER"
	pevc_channels_enable(ppevc, 1<<AVR32_PEVC_ID_USER_ADCIFA_0);
}

void init_pdca_adcif(void)
{
	// PDCA channel 0/1 options
	static const pdca_channel_options_t PDCA_CH_OPTIONS =
	{
		.addr = (void *)aDataTransfered,          // memory address
		.pid = AVR32_PDCA_PID_ADCIFA_CH0_RX,      // select peripheral, ADCIF
		.size = (sizeof(aDataTransfered)/sizeof(uint16_t)),    // transfer counter, number of samples
		.r_addr = 0,						      // No reload address
		.r_size = 0,					          // No reload counter
		.transfer_size = PDCA_TRANSFER_SIZE_HALF_WORD, // 16-bit transfer
		.etrig = false                            // No event trigger
	};
	// register Register interrupts
	irqflags_t flags = cpu_irq_save();
	irq_register_handler(pdca_int_handler, AVR32_PDCA_IRQ_0, 0);
	cpu_irq_restore(flags);

	// PDCA Init.
	// Init PDCA channel with the pdca_options.
	pdca_init_channel(PDCA_CHANNEL_ADCIF, &PDCA_CH_OPTIONS);
	pdca_channel = pdca_get_handler(PDCA_CHANNEL_ADCIF); // For use in the pdca interrupt handler.

	// Enable pdca transfer error interrupt & transfer complete interrupt.
	pdca_enable_interrupt_transfer_error(PDCA_CHANNEL_ADCIF);
	pdca_enable_interrupt_transfer_complete(PDCA_CHANNEL_ADCIF);
	
	// Enable the PDCA.
	pdca_enable(PDCA_CHANNEL_ADCIF);
}

// **********************************************************************************
//	For ADC converter setup for sequencer 0
adcifa_opt_t adc_config_t;
adcifa_sequencer_opt_t adcifa_sequence_opt;
adcifa_sequencer_conversion_opt_t adcifa_sequence_conversion_opt[ADCIFA_NUMBER_OF_SEQUENCE];
volatile avr32_adcifa_t *adcifa = &AVR32_ADCIFA; // ADCIFA IP registers address
int16_t adc_values[ADCIFA_NUMBER_OF_SEQUENCE];	// For "print_dbg" function

// Assign and enable GPIO pins to the ADC function.
gpio_enable_module(ADCIFA_GPIO_MAP, sizeof(ADCIFA_GPIO_MAP) / sizeof(ADCIFA_GPIO_MAP[0]));

// Configure the ADC for the application
adc_config_t.frequency                = 1500000;	// ADC frequency (Hz)
adc_config_t.reference_source         = ADCIFA_REF06VDD;	// Reference Source, Internal 0.6*VDDANA ref
adc_config_t.sample_and_hold_disable  = false;		// Disable Sample and Hold Time
adc_config_t.single_sequencer_mode    = false;		// Single Sequencer Mode,
adc_config_t.free_running_mode_enable = false;		// Free Running Mode
adc_config_t.sleep_mode_enable        = false;		// Sleep Mode
adc_config_t.mux_settle_more_time     = false;		// Wat is this???

// Get ADCIFA Factory Configuration
adcifa_get_calibration_data(&AVR32_ADCIFA, &adc_config_t);
// Calibrate offset first, CPU clock must be running
adcifa_calibrate_offset(&AVR32_ADCIFA, &adc_config_t, FPBB_HZ); // PB clock 32MHz
// Configure ADCIFA core, CPU clock must be running
adcifa_configure(&AVR32_ADCIFA, &adc_config_t, FPBB_HZ);	// PB clock 32MHz

// ADCIFA sequencer 0 configuration structure
adcifa_sequence_opt.convnb              = ADCIFA_NUMBER_OF_SEQUENCE;	// Number of sequence, two ADCIN channels
adcifa_sequence_opt.resolution          = ADCIFA_SRES_12B;				// Resolution selection
adcifa_sequence_opt.trigger_selection   = ADCIFA_TRGSEL_EVT;			// Trigger selection, event
adcifa_sequence_opt.start_of_conversion = ADCIFA_SOCB_ALLSEQ;			// Conversion Management
adcifa_sequence_opt.sh_mode             = ADCIFA_SH_MODE_OVERSAMP;		// Oversampling Management
adcifa_sequence_opt.half_word_adjustment= ADCIFA_HWLA_NOADJ;			// Half word Adjustment
adcifa_sequence_opt.software_acknowledge= ADCIFA_SA_NO_EOS_SOFTACK;		// Software Acknowledge

// ADCIFA conversions for sequencer 0
// ADCIN0
adcifa_sequence_conversion_opt[0].channel_p = ADC_AIN0_RECEIVER_INP;	// Positive Channel
adcifa_sequence_conversion_opt[0].channel_n = ADC_AIN0_RECEIVER_INN;	// Negative Channel
adcifa_sequence_conversion_opt[0].gain      = ADCIFA_SHG_1;				// Gain of the conversion
// ADCIN1
adcifa_sequence_conversion_opt[1].channel_p = ADC_AIN1_RECEIVER_INP;	// Positive Channel
adcifa_sequence_conversion_opt[1].channel_n = ADC_AIN1_RECEIVER_INN;	// Negative Channel
adcifa_sequence_conversion_opt[1].gain      = ADCIFA_SHG_1;				// Gain of the conversion

// Configure ADCIFA sequencer 0 SEQ0
adcifa_configure_sequencer(&AVR32_ADCIFA, 0, &adcifa_sequence_opt, adcifa_sequence_conversion_opt);
// Start ADCIFA sequencer 0 SEQ0 for ADC starting ADC conversion
adcifa_start_sequencer(&AVR32_ADCIFA, 0);
// **********************************************************************************

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

First I'm not a UC3 user and there are not many here, but your OP above sounds like an X/Y problem.

Instead of asking for a solution to your issue, better to describe the big picture of what your trying to do, perhaps a freak will have a ready made solution.

 

Jim

 

 

(Possum Lodge oath) Quando omni flunkus, moritati.

"I thought growing old would take longer"

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Option 1 :
Put 10 identical channels into the sequencer queue.
Unfortunately, in non-cascaded mode each sequencer queue is only 8 deep. :(


Option 2 :
In the PDC interrupt after the first conversion, change the trigger source from 'event-controller' to 'software',
then do a software trigger on the ADC to start the next conversion.
After the tenth conversion change the trigger source back to the 'event controller'.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So Jim have you been eating barbed wire for breakfast ;o)

 

1: I need more ADC samples so to run the SEQ0 one time ain't enough. Combining SEQ0 and SEQ1 will give 16 deep.

 

2: The pdac interrupt do not comes until all ten SEQ0 is done so I cant change trigger source in that interrupt.

 

As  mikech recommended:

I implemented an AVR32_ADCIFA_SEQUENCER0_IRQ interrupt where I changes trigger source to Software and back to Event and it seems to work. I do not know if this is te correct solution but I will now test it.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This works fine and with good sampling rate if I run the SEQ0 one time, same ADCIN channel eight times. Restarting SEQ0 and run one more time takes to long time.

And this is important to get the right size!

pdca_reload_channel(PDCA_CHANNEL_ADCIF, (void *)aDataTransfered, (sizeof(aDataTransfered)/sizeof(uint16_t)));