Interrupts & Context switching

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

Hi guys, I'll describe the operation first then show you what I mean.  

 

Before I enter the interrupt the system calls a function to prepare for the interrupt and clear it afterwards.  In this function I update a counter that shows how many interrupts are active.  After the interrupt finishes and returns to the system function if I then need to do a context switch I test that there are no more interrupts active by checking the counter and if the counter is zero I then make a context switch.

 

My question is, what happens if I enter the system function that prepares for the interrupt and before I increment the counter another higher interrupt occurs and cause a context switch despite the fact that another interrupt was preparing to execute?

 

system function  

.

.

.

prepare for interrupt

.

.

increment counter

.

.

.

execute interrupt

.

.

.

.

clear interrupt

.

.

.

context switch?

.

.

.

 

 

This topic has a solution.
Last Edited: Tue. Aug 20, 2019 - 11:57 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This is something that most of us never encounter. We (mostly) have only one interrupt level and no way to "call" a function to "prepare" for an interrupt ahead of the execution of the actual interrupt.

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

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

ka7ehk wrote:

This is something that most of us never encounter. We (mostly) have only one interrupt level and no way to "call" a function to "prepare" for an interrupt ahead of the execution of the actual interrupt.

 

Jim

 

 

I guess I should add this is a ARM SAMA5D44.

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Commonly called a ‘critical section’. The simplest solution is to disable interrupts whilst you do this. Generally you want to avoid this so you need to look for specific instructions that do this atomically. I’ve not explored the ARM architecture deep enough to give you specifics.

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

Kartman wrote:
Commonly called a ‘critical section’. The simplest solution is to disable interrupts whilst you do this. Generally you want to avoid this so you need to look for specific instructions that do this atomically. I’ve not explored the ARM architecture deep enough to give you specifics.

 

It seems to be the only way to go.  Thanks for your input Kartman.

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

okay, this is where the IRQ is first handled.

 

/* Exception vectors
 *******************/
	.section    .vectors, "a", %progbits

resetVector:
/* Reset */
	ldr     pc, =resetHandler
/* Undefined Instruction */
	ldr     pc, =undefined_instruction_irq_handler
/* Software Interrupt */
	ldr     pc, =software_interrupt_irq_handler
/* Prefetch Abort */
	ldr     pc, =prefetch_abort_irq_handler
/* Data Abort */
	ldr     pc, =data_abort_irq_handler
/* Reserved for future use */
	.word   0
/* Interrupt */
	ldr     pc, =irqHandler
/* Fast interrupt */
	ldr     pc, =fiqHandler

How can I disable IRQ's before either of these are called?

/* Interrupt */
	ldr     pc, =irqHandler
/* Fast interrupt */
	ldr     pc, =fiqHandler

 

 

 

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

Not sure what you’re asking here. I’d reading the ARM docs carefully regarding the interrupt handling sequence as there may be special rules to when further interrupts are serviced.

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

How can I disable IRQ's before either of these are called?

/* Interrupt */
	ldr     pc, =irqHandler
/* Fast interrupt */
	ldr     pc, =fiqHandler

Like the AVR, those are just vectors, "called" when the hardware has interrupts to service...

 

; I'm glad ARM's Cortex-M documentation is better...

 

Normally, you'd do

  save_interrupt_status(istat);
  disable_interrupts();
  // critical code that can't be interrupted.
  // ...
  //
  restore_interrupt_status(istat);

Where the disable_interrupts() either modifies a global CPU register that turns off all interrupts, or sets the "current interrupt priority" so high that no other interrupts can occur (zero.)
But i can't make heads or tails of the Cortex A5 documentation on interrupts; There's some functions defined in CMSIS https://arm-software.github.io/CMSIS_5/Core_A/html/group__irq__ctrl__gr.html

but it's not clear to me how exactly they tie into the general interrupt mechanism (it implies that they use the Generic Interrupt Controller, but I don't know how that relates to the CPU itself.)

There are also mask bits in the "CPSR" register: https://arm-software.github.io/CMSIS_5/Core_A/html/group__CMSIS__CPSR.html

So I'd sorta bet on either using IRQ_GetPriorityMask() and IRQ_SetPriorityMask(), or fiddling with CPSR bits using __get_CPSR() and __set_CPSR()  (the latter seems more dangerous, but also more direct...)

 

With the A5, you may also have to pay attention to pipelines and barriers and stuff.   I'd spend some time looking for existing "start_critical_section()" functions (but I didn't see any in my quick searching.)