avr-gcc-list
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [avr-gcc-list] How to handle interrupt vectors ?


From: Luiz C. Bruscato
Subject: Re: [avr-gcc-list] How to handle interrupt vectors ?
Date: Wed, 29 Oct 2008 22:18:49 -0200
User-agent: KMail/1.9.9

/*
The following is an example of a ISR code, take a look the main for(;;)waits  
indefinitely for an interrupt. 
Thanks Joerg for the example.
Luiz C. Bruscato 
* ----------------------------------------------------------------------------
 * "THE BEER-WARE LICENSE" (Revision 42):
 * Joerg Wunsch wrote this file.  As long as you retain this notice you
 * can do whatever you want with this stuff. If we meet some day, and you 
think
 * this stuff is worth it, you can buy me a beer in return.        Joerg 
Wunsch
 
* ----------------------------------------------------------------------------
 *
 * Demo combining C and assembly source files.
 *
 * This demo implements an RC model type PWM decoder.  The incoming
 * PWM signal consists of a pulse sequence with a pulse width of 920
 * microseconds up to 2120 microseconds (1520 microseconds being the
 * neutral point).  Depending on the value of the decoded incoming
 * PWM, an outgoing PWM is controlled between 0 and 100 %.
 *
 * The project is intented to be run on an ATtiny13 that has only one
 * timer channel (timer 0), so both the incoming signal discrimination
 * as well as the outgoing PWM need to run on the same timer.
 *
 * For verification purposes, the same project can also be run on an
 * ATtiny25/45/85, where timer 1 can be used to evaluate the incoming
 * PWM signal, and timer 0 to generate the outgoing PWM.  In that
 * case, no additional assembly code is needed.
 *
 * $Id: asmdemo.c,v 1.1.2.1 2006/08/29 19:48:39 joerg_wunsch Exp $
 */

/*
 * This is the main C source file for the demo.
 */
#include <avr/interrupt.h>
#include <avr/io.h>
#include <avr/sleep.h>

#include "project.h"

volatile uint16_t pwm_incoming;
volatile struct
{
  uint8_t pwm_received: 1;
}
intbits;

void
ioinit(void)
{
  counter_hi = 0;
  flags = 0;

  /*
   * Timer 0 runs as phase-correct PWM at full clock, OC0B connects to
   * the PWM engine.
   */
  TCCR0A = (1 << COM0B1) | (1 << WGM00);
  TCCR0B = (1 << CS00);
  OCR0A = 255;

#if defined(__AVR_ATtiny13__)
  TIMSK0 = (1 << TOIE0) | (1 << OCIE0A);

# define F_CPU 1200000ul
  /* Minimal PWM pulse width is 920 us. */
# define MIN_PWM_VAL ((920ul * F_CPU) / 1000000ul)
  /* Maximal PWM pulse width is 2120 us */
# define MAX_PWM_VAL ((2120ul * F_CPU) / 1000000ul)

#elif defined(__AVR_ATtiny25__) ||\
        defined(__AVR_ATtiny45__) ||\
        defined(__AVR_ATtiny85__)

# define F_CPU 1000000ul
  /*
   * We use a prescaler of 16 here to avoid the 32-bit calculations
   * below.
   */
  /* Minimal PWM pulse width is 920 us. */
# define MIN_PWM_VAL ((920ul * F_CPU) / 16 / 1000000ul)
  /* Maximal PWM pulse width is 2120 us */
# define MAX_PWM_VAL ((2120ul * F_CPU) / 16 / 1000000ul)

#else
# error "Don't know how to run on your MCU_TYPE."
#endif

  PCMSK = (1 << 4);
  GIFR = (1 << PCIF);
  GIMSK = (1 << PCIE);

  DDRB = (1 << PB1);
  PORTB = 0;

  sei();
}

#if defined(__AVR_ATtiny25__) ||\
        defined(__AVR_ATtiny45__) ||\
        defined(__AVR_ATtiny85__)
ISR(PCINT0_vect)
{
  uint8_t tcnt1;

  if (PINB & (1 << 4))
    {
      /* Start timer 1 with a prescaler of 16. */
      TCNT1 = 0;
      TCCR1 = (1 << CS12) | (1 << CS10);
      return;
    }

  /* Stop timer 1, current value is pulse width. */
  tcnt1 = TCNT1;
  TCCR1 = 0;
  GIMSK &= ~(1 << PCIE);

  pwm_incoming = tcnt1;
  intbits.pwm_received = 1;
}
#endif /* ATtinyX5 */

int
main(void)
{

  ioinit();

  for (;;)
    {
      if (intbits.pwm_received)
        {
          intbits.pwm_received = 0;
#if defined(__AVR_ATtiny13__)
          if (pwm_incoming < MIN_PWM_VAL)
            pwm_incoming = MIN_PWM_VAL;
          else if (pwm_incoming > MAX_PWM_VAL)
            pwm_incoming = MAX_PWM_VAL;
          OCR0B = (pwm_incoming - MIN_PWM_VAL) * 255ul / (MAX_PWM_VAL - 
MIN_PWM_VAL);
#else
          OCR0B = (pwm_incoming - MIN_PWM_VAL) * 255u / (MAX_PWM_VAL - 
MIN_PWM_VAL);
#endif
          GIFR = (1 << PCIF);
          GIMSK |= (1 << PCIE);
        }
      sleep_mode();
    }
}

On Wednesday 29 October 2008 04:31:53 pm Joerg Wunsch wrote:
> Charalampos Alexopoulos <address@hidden> wrote:
> > Yes i have seen the code for the ISR and i have no understanding of
> > the mechanism because i don't know what that vector is.
>
> I have already explained you that, and you can take my word that you
> don't stand a chance using the existing gcrt1.S file.  That's not to
> say it could not be done at all, but you'd have to start over from
> scratch, writing your own C run-time startup code in a different way
> than the existing code is done.
>
> You could perhaps seek up some old (maybe about 4 years old)
> suggestion from Marek Michalkiewicz about what changes would be needed
> in order to allow for arbitrarily-named interrupt vectors.  Offhand, I
> can't tell you though whether it has been discussed here on
> avr-gcc-list, or on avr-libc-dev instead.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]