SenorMeltyface
Posts: 1
Joined: Tue Mar 24, 2015 2:05 am

Loading Code Into a Memory Address?

Tue Mar 24, 2015 2:13 am

I'm writing in assembly, and I want to write a branch instruction to 0x00000018 (the IRQ vector's address) so that it will jump to my own code (using a label), with which I can handle the interrupt, which will be a falling edge GPIO interrupt. How would I go about this, specifically the loading of my own code into 0x00000018? I've been looking around for a while and can't seem to find anything applicable on the subject.

rst
Posts: 450
Joined: Sat Apr 20, 2013 6:42 pm
Location: Germany

Re: Loading Code Into a Memory Address?

Tue Mar 24, 2015 10:38 am

I use the same method to set the exception handlers but in C. The following code may do it in assembler (untested):

Code: Select all

	ldr	r2, =irqhandler-0x18  /* calculate distance */
	asr	r2, r2, #2
	sub	r2, r2, #2
	orr	r2, r2, #0xea000000   /* OP code branch instruction */
	mov	r3, #0x18
	str	r2, [r3]              /* store it into exception table */
	...

irqhandler:
	...

hldswrth
Posts: 108
Joined: Mon Sep 10, 2012 4:14 pm

Re: Loading Code Into a Memory Address?

Wed Mar 25, 2015 12:51 am

People typically have a set of PC loading instructions with an address table, and then copy that whole lot over the low addresses for the fault vectors. Something like:

Code: Select all

# these instructions are copied over the fault vectors at their expected location.
   ldr pc,_reset_vector
   ldr pc,_undefined_vector
   ldr pc,_swi_vector
   ldr pc,_prefetch_vector
   ldr pc,_data_vector
   ldr pc,_reserved_vector
   ldr pc,_irq_vector
   ldr pc,_fiq_vector
_reset_vector:     .word reset_routine_address
_undefined_vector: .word undef_routine_address
_swi_vector:       .word swi_routine_address
_prefetch_vector:  .word preabort_routine_address
_data_vector:      .word dataabort_routine_address
_reserved_vector:  .word unhandled_routine_address
_irq_vector:       .word irq_routine_address
_fiq_vector:       .word fiq_routine_address
If the routine addresses immediately follow the vectors, the vectors end up all being the same instruction:

Code: Select all

e59ff018    ldr pc, [pc,#24]

mrvn
Posts: 58
Joined: Wed Jan 09, 2013 6:50 pm

Re: Loading Code Into a Memory Address?

Sun Apr 19, 2015 9:53 am

The ARM cpu in the RPi also supports setting a exception vector base address in the VBAR register. This avoids the need to copy the exception vector to either its low or high address completly. In C the code looks like this:

Code: Select all

extern uint32_t exception_vector[];

void set_vbar(uint32_t *base) {
    asm volatile ("mcr p15, 0, %[base], c12, c0, 0"
                  :: [base] "r" (base));
}

void exceptions_init(void) {
    set_vbar(exception_vector);
}
And your excepion vector would be in an assembly file like this:

Code: Select all

.section ".text"
.balign 32
.global exception_vector
.type exception_vector, STT_FUNC
exception_vector:
        b       stub_reset
        b       stub_undef
        b       stub_svc
        b       stub_prefetch_abort
        b       stub_data_abort
        b       stub_hypervisor_trap
        b       stub_irq
        b       stub_fiq
I use simple branches since I just call stubs in the same assembly file that save/restore registers and then call my C code. You can use ldr instructions instead like in the previous example. What you put into the exception vector doesn't realy matter but it is important that the vector is 32 byte aligned. The ARM requires this.

Return to “Bare metal, Assembly language”