what's different - Interrupts & Context

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

Write Lads, leading on from my thread about calling a function from within cstartup.s, I would like to hear your input about making a context switch at the end of handling interrupts.

 

I'm making a context switch "bl xapi_system_gateway", when I make it the timer stops firing, but if I make the test that is performed by "xapi_system_gateway" outside the interrupt it works.

 

Have a wee look at the code.  The Interrupt has finished and all is left to do is return to the function.

 

//------------------------------------------------------------------------------
/// Handles incoming interrupt requests by branching to the corresponding
/// handler, as defined in the AIC. Supports interrupt nesting.
//------------------------------------------------------------------------------
irqHandler:
	/* Save interrupt context on the stack to allow nesting */

	sub     lr, lr, #4
	stmfd   sp!, {lr}
	mrs     lr, SPSR
	stmfd   sp!, {r0, lr}

	/* Write in the IVR to support Protect Mode */

	ldr     lr, =AIC
	ldr     r0, [r14, #AIC_IVR]
	str     lr, [r14, #AIC_IVR]
	/* Dummy read to force AIC_IVR write completion */
	ldr     lr, [r14, #AIC_SMR]

	/* Branch to interrupt handler in Supervisor mode */

	msr     CPSR_c, #ARM_MODE_SVC
	stmfd   sp!, {r1-r3, r4, r12, lr}

	/* Check for 8-byte alignment and save lr plus a */
	/* word to indicate the stack adjustment used (0 or 4) */

	and     r1, sp, #4
	sub     sp, sp, r1
	stmfd   sp!, {r1, lr}

	blx     r0

	ldmia   sp!, {r1, lr}
	add     sp, sp, r1

	ldmia   sp!, {r1-r3, r4, r12, lr}
	msr     CPSR_c, #ARM_MODE_IRQ | I_BIT | F_BIT

	/* Acknowledge interrupt */

	ldr     lr, =AIC
	str     lr, [r14, #AIC_EOICR]


	/* Restore interrupt context and branch back to calling code */

	ldmia   sp!, {r0, lr}
	msr     SPSR_cxsf, lr

	bl		xapi_system_gateway
	ldmia   sp!, {pc}^

 

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

Just to clarify, making the context before the end

 

bl xapi_system_gateway
ldmia   sp!, {pc}^

 

makes the timer stop, but if I make it after in main it works.

Last Edited: Tue. Sep 4, 2018 - 04:33 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My guess is the interrupts get disabled when you change context. Use the debugger to look at the processor state before and after the context change.

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

"My guess is the interrupts get disabled when you change context. Use the debugger to look at the processor state before and after the context change"


I thought that, not even sure yet how to enable disable interrupts, the ARM is a learning experience for me and the MPU is way-way more complicated than say a MCU.

 

 

Anyway, I've been unable to get it working as of yet.  I'll update yous tomorrow.

Slán

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

Forgot to mention, I look to see if any further instructions where carried out after the instruction  "ldmia   sp!, {pc}^"

It appears clean:

 

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

 

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

I’m not very experienced with the low level details of the various arm architectures. I dare say you need to be careful with user vs system modes when you restore the processor state. I’d suggest you have a look at how freertos does it as they have a port for the sama5. Or read in depth the arm documentation.......

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

Thanks Kartman, like you I'm not so understanding of low level stuff but I get the just of it.

 

 

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

Right lads, £50 up for grabs to the person who solves my issue of performing a context switch at the end of "irqHandler".

The system successfully performs the context switch but the timer that caused the context switch stops responding.  I've attached the entire project for the user to look at but basically a call to "xapi_system_gateway" causes the context switch.  I've also included a link to the bare metal software pack.

 

Any further information required as and when you need it I will gladly answer.  As I said, it could take minutes or weeks so lets go guys, £50 is up for grabs.

 

Just to add, this is not a work related issue, it's for academia.

 

 

 

Software Package:

https://github.com/atmelcorp/atmel-software-package

 

I'm sure more information will be required so just ask here and I'll get back you as soon as possible.

 

Wm.

Attachment(s): 

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

Guys, I know a lot of you compiling the code is pointless without the hardware so feel free to through out suggestions.  I'll test them and if one works then you claim the £50.

 

Wm.

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

Lads, I'll be away till tomorrow to say 7pm, what can I say... I'm Irish and I'm thirsty - so it's beer time with my lovely brothers.

 

Slán

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

So hungover and no one has made a suggestion to my problem.

Think I'll go to bed.

 

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

The rfeia instruction might be of interest. It seems to handle the CPSR correctly.

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

What about looking at this in a different way!  How about manipulate the stack to call "xapi_system_gateway" after finishing the interrupt???

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

Okay lads, If I get this setup working it might answer my problems!

I'm calling "xapi_system_gateway" at the end of the interrupt:

 

	/* Restore interrupt context and branch back to calling code */

	//ldmia   sp!, {r0, lr}
	//msr     SPSR_cxsf, lr

	/* Test for Pre-emption */
	ldr     pc, =xapi_system_gateway

	//ldmia   sp!, {pc}^

and in "xapi_system_gateway" I'm finishing the interrupt as per stipulated in "cstartup.s"

// Enter Application api_program Interface Mode
__attribute__((naked))void xapi_system_gateway(void){

	asm volatile("ldmia   sp!, {r0, lr}\n\t"
				 "msr     SPSR_cxsf, lr");

	asm volatile ("ldmia   sp!, {pc}");
}

However the interrupt fails, I'm thinking it could have something to do with the mode the cpu is in.

 

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

Like most here I have only rudimentary knowledge of ARM internals but as I see it when you perform a context switch you'll need to:

 

  1. Restore the CPU mode to User Mode
  2. Switch back the current interrupt priority to a lower level so that your interrupt can re-trigger.

 

 

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

Hi N.winterbottom, I'll have a look at that.

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

I found it, I'll let yous know when I test it.