Free Running Mode possible?

General discussions about V-USB, our firmware-only implementation of a low speed USB device on Atmel's AVR microcontrollers
Post Reply
psc
Rank 1
Rank 1
Posts: 32
Joined: Sat Nov 15, 2008 9:51 pm

Free Running Mode possible?

Post by psc » Fri Dec 05, 2008 9:35 am

hi all,

from the datasheet (in my case atmega16):

Using the ADC Interrupt Flag as a trigger source makes the ADC start a new conversion as soon as the ongoing conversion has finished. The ADC then operates in Free Running mode, constantly sampling and updating the ADC Data Register. The first conversion must be started by writing a logical one to the ADSC bit in ADCSRA. In this mode the ADC will perform successive conversions independently of whether the ADC Interrupt Flag, ADIF is cleared or not.

turning this feature "on" i get this error in linux when connecting my device:
[ 1173.796651] usb 4-1: new low speed USB device using uhci_hcd and address 44
[ 1173.850848] usb 4-1: device descriptor read/64, error -71

is it possible to make it work with obdev-usb?
pat

christian
Objective Development
Objective Development
Posts: 1443
Joined: Thu Nov 09, 2006 11:46 am

Post by christian » Fri Dec 05, 2008 8:21 pm

There's nothing special with AVR-USB and free running mode of the ADC. It looks as if your code crashes, maybe because you enabled an interrupt which has no vector assigned or the vector is called recursively.

If you need an interrupt for the ADC, you must make sure it enables global interrupts within several cycles after interrupt start AND that it does not trigger again after enabling the interrupts.

psc
Rank 1
Rank 1
Posts: 32
Joined: Sat Nov 15, 2008 9:51 pm

Post by psc » Fri Dec 05, 2008 9:23 pm

it's true, i am new to avr so it might be my code :roll:

//sbi(ADCSRA, ADIE); //Enable ADC conversion complete interrupt
working ([ 2732.974342] usb 3-1: configuration #1 chosen from 1 choice)

sbi(ADCSRA, ADIE); //Enable ADC conversion complete interrupt
not working ([ 2720.042034] usb 3-1: device not accepting address 12, error -71)

Code: Select all

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/wdt.h>
#include "usbdrv.h"

#ifndef BV
   #define BV(bit)         (1<<(bit))
#endif
#ifndef cbi
   #define cbi(reg,bit)   reg &= ~(BV(bit))
#endif
#ifndef sbi
   #define sbi(reg,bit)   reg |= (BV(bit))
#endif

#define ADC_PRESCALE_DIV64      0x06   ///< 0x06 -> CPU clk/64
#define ADC_PRESCALE         ADC_PRESCALE_DIV64
#define ADC_PRESCALE_MASK      0x07
#define ADC_MUX_MASK         0x1F

void adcfrm(void)
{
   DDRA    = 0x00; // set all pins to input
   PORTA    = 0x00; // make sure pull-up resistors are turned off
   sbi(ADCSRA, ADEN); //Enable the ADC
   sbi(ADCSRA, ADATE); //Enable free-running mode
   ADCSRA = ((ADCSRA & ~ADC_PRESCALE_MASK) | ADC_PRESCALE_DIV64);
   SFIOR &= 0x1F;
   sbi(ADMUX,REFS0);cbi(ADMUX,REFS1);
   ADMUX = 0; //Initial channel selection
   sbi(ADCSRA, ADIE); //Enable ADC conversion complete interrupt
   sbi(ADCSRA, ADSC); //Start first conversion in Free-running mode
   sei(); //Enable global interrupts
   //Now the conversions are running
}

void initCoreHardware(void)
{
   // --------------------- Init USB
   DDRD = 0xe0;
   PORTD = 0x70;
   usbDeviceConnect();
   wdt_enable(WDTO_1S);
   usbReset();
    usbInit();
   cbi(MCUCR, ISC11);
   sbi(MCUCR, ISC10);
   set_sleep_mode(SLEEP_MODE_PWR_DOWN);
   TCCR1B = 3;
   TCNT1 = 0;
   sbi(TIFR, TOV1);
   sei();
}

int main(void)
{
   initCoreHardware();
   adcfrm();
   while(1) {
      wdt_reset();
      usbPoll();   
   }
   return 0;
}


i found another post in this forum saying that a low priority interrupt:
#define UTIL_INTERRUPT(signame) \
void signame (void) __attribute__ ((interrupt)); \
void signame (void)

UTIL_INTERRUPT(XXX_vect)
{
... interrupt implementation
}

not sure if it would be necessary in my case?

christian
Objective Development
Objective Development
Posts: 1443
Joined: Thu Nov 09, 2006 11:46 am

Post by christian » Fri Dec 05, 2008 9:40 pm

If you enable the interrupt, you must supply an implementation for the vector. Otherwise the reset vector is called.

Where in your code do you read the ADC data? If you don't need the accuracy of an interrupt, you may poll for it instead. Leave ADIE zero and check for ADIF regularly. If it is set, write a "1" to it and read the ADC value.

Post Reply