Why execute cpu_irq_save/cpu_irq_restore?

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

Why do some of the ASF drivers do this?

void pdca_reload_channel(uint8_t pdca_ch_number,
    volatile void *addr, uint32_t size)
{
    /* get the correct channel pointer */
    volatile avr32_pdca_channel_t *pdca_channel =
        pdca_get_handler(
        pdca_ch_number);
    
    irqflags_t flags = cpu_irq_save(); <------

    /* set up next memory address */
    pdca_channel->marr = (uint32_t)addr;
    /* set up next memory size */
    pdca_channel->tcrr = size;
    pdca_channel->cr = AVR32_PDCA_ECLR_MASK;
    pdca_channel->isr;
    
    cpu_irq_restore(flags); <------
}

I understand what it's doing, but not why. I don't do this in any of my ISRs and I've never had an issue. Can I remove those calls to save time in the ISR? Those two function calls represent more than 80% of the time spent in the ISR shown above.

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

it may be a way of doing an atomic code block...

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

Presumably an interrupt could come through and use the struct with the first part changed but the last part still the old values. Simply disabling and reenabling interrupts around the code would not be good if there was the possibility that interrupts were already disabled on entry. So the global interrupt enable bit is saved and restored. The fastest way to do that is to save and restore the entire status register. Don't know if cpu_irq_save strips off the particular bit.

No need to do it within an interrupt because the global interrupt enable bit must have been set to get there in the first place, and the hardware clears it on entry and sets it on exit.

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

here's ASF's code for cpu_irq_save().

static inline irqflags_t cpu_irq_save(void)
{
	irqflags_t flags;

	flags = sysreg_read(AVR32_SR);
	cpu_irq_disable();

	return flags;
}

so, indeed, it saves the status register, and only then turns off interrupts. Restoring thus restores to whatever status it was before we changed it.

I am now more interested in the implementation of the cpu_irq_enable/disable(), here it is (let's pretend we're using GNUC):

#  define cpu_irq_enable()                             \
	do {                                           \
		barrier();                             \
		__builtin_csrf(AVR32_SR_GM_OFFSET);    \
	} while (0)
#  define cpu_irq_disable()                            \
	do {                                           \
		__builtin_ssrf(AVR32_SR_GM_OFFSET);    \
		barrier();                             \
	} while (0)

What is the practical point of doing while(0)? It would run once without anything there regardless. I also can't seem to find the implementaion of __builtin_ssrf...

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

http://stackoverflow.com/questio...

tl;dr

Quote:
It's the only construct in C that you can use to #define a multistatement operation, put a semicolon after, and still use within an if statement.

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

interesting, i did not know that before.

here is the answer to the second question:

names beginning with one underscore are reserved for libraries, names beginning with two underscores are reserved for compilers. Thus, __builtin_ssrf is translated by the compiler into some assembly that ORs a register. The compiler already knows this, so the function is never defined in any of the source.