but
Posts: 6
Joined: Sat May 31, 2014 8:19 am

exception vector handling problem

Sat May 31, 2014 9:11 am

hello, i've been trying to handle an exception on my raspberry, and can't figure out what the problem is. instead of jump to my blink() function (which is just simple led blinking) execution just hangs somewhere. here is my code:
vector.S

Code: Select all

#include "exception.h"
.global reset
.global _undefine_instruction
.global _svc_smc_call
.global _prefetch_abort
.global _data_abort
.global _not_used
.global _irq
.global _fiq
.global _start
.global temp_label

.section .vectors
.align 5
_start:
b _reset				@0x0
b _undefine_instruction @0x4
b _svc_smc_call			@0x8
b _prefetch_abort		@0xc
b _data_abort			@0x10
b _not_used				@0x14
b _irq					@0x18
b _fiq					@0x1с
reset:
	b _reset @hello_world
_undefine_instruction:
	b undefine_instruction
_svc_smc_call:
	b svc_smc_call
_prefetch_abort:
	b prefetch_abort
_data_abort:
	b data_abort
_not_used:
	b .
_irq:
	b .
_fiq:
	b .


boot.S

Code: Select all

.equ Mode_USR       ,       0x10
.equ Mode_FIQ       ,       0x11
.equ Mode_IRQ       ,       0x12
.equ Mode_SVC       ,       0x13
.equ Mode_MON       ,       0x16
.equ Mode_ABT       ,       0x17
.equ Mode_UNDEF     ,       0x1B
.equ Mode_SYS       ,       0x1F

.equ I_Bit          ,       0x80              @ when I bit is set, IRQ is disabled
.equ F_Bit          ,       0x40              @ when F bit is set, FIQ is disabled

/*							descriptors for Sections						*/
.equ L1_COHERENT     ,    0x00015c06          @ Template descriptor for coherent memory (and L2 cache enabled)
@.equ L1_COHERENT     ,    0x00014c02          @ Template descriptor for coherent memory (and L2 cache enabled)

.equ L1_NONCOHERENT  ,    0x00000c1e          @ Template descriptor for non-coherent memory
.equ L1_DEVICE       ,    0x00000c06          @ Template descriptor for device memory
.equ temp , 0

.global _reset

tlbs_l1_base:
.word 0x8000

.section ".text"
.type   _reset, %function
	_reset:
	.fnstart
	.cantunwind

	b main

	.fnend
.size   _reset, . - _reset
exception.c

Code: Select all

#include <common.h>
#include "reg_debug.h"
#include "checker.h"

void svc_smc_call(){
	blink();
};

void undefine_instruction(){
	blink();
};

void prefetch_abort(){
	blink();
};

void data_abort(){
	blink();
};


main.c

Code: Select all


#include <common.h>
#include <exports.h>
#include "reg_debug.h"
#include "v6.h"
#include "addition.h"

int main() {
	printf("\nhello\n");
	asm volatile ("mvn r1, #0");

	enableAbortException();
	setVBAR(0x18000);
	disableHighVecs();

	unsigned int reg_value;
	asm volatile ("mov %0, r1" : "=r" (reg_value) );
	PRN_REG(reg_value, "reg_val")
	asm volatile ("mov %0, r8" : "=r" (reg_value) );
	PRN_REG(reg_value, "reg_val")

	printf("\ntry to generate exception...\n");
	asm volatile ("ldr r0, [r1]");

	asm volatile ("mov %0,r0" : "=r" (reg_value) );
	PRN_REG(reg_value, "reg_val")

	for(;;) {}
	return 0;
}
v6.S

Code: Select all

  .global enableAbortException
  .global enableAbortExceptionSize
  	.type enableAbortException, %function
enableAbortException:
	.fnstart
	.cantunwind
	CPSIE   a
  	BX      lr
  	.fnend
	.size   enableAbortException, . - enableAbortException

	.global disableHighVecs
    .global disableHighVecsSize
  @ void invalidateCaches(void);
	.type disableHighVecs, %function
disableHighVecs:
	.fnstart
	.cantunwind
	MRC     p15, 0, r0, c1, c0, 0 @ Read Control Register
	BIC     r0, r0, #(1 << 13)    @ Set the V bit (bit 13)
	MCR     p15, 0, r0, c1, c0, 0 @ Write Control Register
	BX      lr
  	.fnend
	.size   disableHighVecs, . - disableHighVecs
checker.c

Code: Select all

#define GPFSEL1 0x20200004
#define GPSET0 0x2020001C
#define GPCLR0 0x20200028

void blink() {
	  unsigned int ra;
	    ra=GET32(GPFSEL1);
	    ra&=~(7<<18);
	    ra|=1<<18;
	    PUT32(GPFSEL1,ra);

	    while(1)
	    {
	        PUT32(GPSET0,1<<16);
	        for(ra=0;ra<0x100000;ra++) _dummy(ra);
	        PUT32(GPCLR0,1<<16);
	        for(ra=0;ra<0x100000;ra++) _dummy(ra);
	    }
}
addition.S

Code: Select all

.global PUT32
PUT32:
str r1, [r0]
bx lr

.global GET32
GET32:
ldr r0, [r0]
bx lr

.global _dummy
_dummy:
nop
bx lr
reg_debug.c

Code: Select all

#include <common.h>
/*#include <exports.h>*/

#include "reg_debug.h"

void prnSCR(){
    int ret;
    asm("mrc p15, 0, %0, c1, c1, 0" : "=r" (ret) );
#ifdef DEBUG
    PRN_REG(ret, "SCR")
#endif

}

void prnSCTLR(){
    int ret;
    asm("mrc p15, 0, %0, c1, c0, 0" : "=r" (ret) );
#ifdef DEBUG
    PRN_REG(ret, "SCTLR")
#endif

}

void prnCPSR(){
    int ret;
    asm("mrs %0, CPSR" : "=r" (ret));
#ifdef DEBUG
    PRN_REG(ret, "CPSR")
#endif

}

void prnCPACR(){
    int ret;
    asm("mrc p15, 0, %0, c1, c0, 2" : "=r" (ret) );
#ifdef DEBUG
    PRN_REG(ret, "CPACR")
#endif
}

void prnACTLR(){
    int ret;
    asm("mrc p15, 0, %0, c1, c0, 1" : "=r" (ret) );
#ifdef DEBUG
    PRN_REG(ret, "ACTLR")
#endif

}

void prnVBAR(){
    int ret;
    asm("MRC p15,0,%0,c12,c0,0" : "=r" (ret) );
#ifdef DEBUG
    PRN_REG(ret, "VBAR")
#endif
}


void prnCLIDR(){
	int ret;
	asm("MRC p15,1,%0,c0,c0,1" : "=r" (ret) );
#ifdef DEBUG
    PRN_REG(ret, "CLIDR")
#endif
}

unsigned int getSCR(){
	unsigned int ret;
    asm("mrc p15, 0, %0, c1, c1, 0" : "=r" (ret) );
#ifdef DEBUG
    PRN_REG(ret, "SCR")
#endif
    return ret;

}

unsigned int getSCTLR(){
	unsigned int ret;
    asm("mrc p15, 0, %0, c1, c0, 0" : "=r" (ret) );
#ifdef DEBUG
    PRN_REG(ret, "SCTLR")
#endif
    return ret;

}

unsigned int getCPSR(){
	unsigned int ret;
    asm("mrs %0, CPSR" : "=r" (ret));
#ifdef DEBUG
    PRN_REG(ret, "CPSR")
#endif
    return ret;

}

unsigned int getCPACR(){
	unsigned int ret;
    asm("mrc p15, 0, %0, c1, c0, 2" : "=r" (ret) );
#ifdef DEBUG
    PRN_REG(ret, "CPACR")
#endif
    return ret;

}

unsigned int getACTLR(){
	unsigned int ret;
    asm("mrc p15, 0, %0, c1, c0, 1" : "=r" (ret) );
#ifdef DEBUG
    PRN_REG(ret, "ACTLR")
#endif
    return ret;

}

unsigned int getVBAR(){
	unsigned int ret;
    asm("MRC p15,0,%0,c12,c0,0" : "=r" (ret) );
#ifdef DEBUG
    PRN_REG(ret, "VBAR")
#endif
    return ret;
}

///////////////// Register Set Functions //////////////////
void setVBAR(unsigned int var){
    asm("MCR p15,0,%0,c12,c0,0" : :"r" (var) );
}


sorry for bulky code samples. to generate an interrupt i'm trying to read from 0xffffffff in main.c. but, as i said above, instead of blinking led i'm get nothing but black screen which is confusing me. i'll be appreciate for any guess.

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

Re: exception vector handling problem

Mon Jun 02, 2014 11:47 am

It's not clear to me where you expect your exception vectors to be and how they get there. I guess this is done in your linker script...?
The approach I take which has been suggested elsewhere in this forum is to have the vectors defined along with your main entry point and move them to low memory on startup. I also use ldr pc instructions not b instructions, to allow the routines to be anywhere in memory.

Code: Select all

_reset:
    ldr r0, =_exception_handlers
    mov r1, #0x0000
    ldmia r0!,{r2,r3,r4,r5,r6,r7,r8,r9}
    stmia r1!,{r2,r3,r4,r5,r6,r7,r8,r9}
    ldmia r0!,{r2,r3,r4,r5,r6,r7,r8,r9}
    stmia r1!,{r2,r3,r4,r5,r6,r7,r8,r9}

    mov sp, #0x8000
    b main

# Exception handler table - needs to be copied to address 0.
_exception_handlers:
    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

# Addresses of exception routines in the Kernel (defined in exception.c)

_reset_vector:     .word excReset
_undefined_vector: .word excUndefinedInstruction
_swi_vector:       .word excSoftwareInterrupt
_prefetch_vector:  .word excPrefetchAbort
_data_vector:      .word excDataAccess
_reserved_vector:  .word excUnhandledException
_irq_vector:       .word excInterrupt
_fiq_vector:       .word excFastInterrupt

dwelch67
Posts: 965
Joined: Sat May 26, 2012 5:32 pm

Re: exception vector handling problem

Mon Jun 02, 2014 6:16 pm

we would need to see your linker script or linking information, as well as how you load this (config.txt or whatever it is on the sd card). If you are not actually forcing this code to be at address 0x0000000 in arm address space then the handlers will not work (but it may reset just fine into your program).

David

but
Posts: 6
Joined: Sat May 31, 2014 8:19 am

Re: exception vector handling problem

Mon Jun 02, 2014 8:42 pm

thank you for your responses. i fixed my linker script to re-base vectors table to 0, but it doesn't help either :( . here is my linker script:

Code: Select all

ENTRY(vectors)
/*
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-little", "elf32-big", "srec", "symbolsrec", "verilog", "tekhex", "binary", "ihex
)
*/
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-little")
OUTPUT_ARCH(arm)
SECTIONS
{
	
	.text       :
	{
			
		text_start = .;
		
		*(.vectors)

		*(.text*)
	
		. = ALIGN(4);
		. += 0x10000;
	}

	. = ALIGN(4);
	.rodata  : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }

	. = ALIGN(4);
	.data  : { *(.data*) }

	.sdata  : { *(.sdata*) }

	. = ALIGN(4);
	__bss_start = .;
	.sbss (NOLOAD) : { *(.sbss*) }
	.bss (NOLOAD)  : { *(.bss*) . = ALIGN(4); }

	_end = .;

	. = ALIGN(8);
	heap_low = .; /* for _sbrk */
 	. = . + 0x00002000; 
	
	heap_top = .; /* for _sbrk */

	/*CPU stack*/
	. = . + 0x01000; 
	appstack_top = .; /* for startup.s */

	/* IRQs stack*/
	. = . + 0x0100;
	irqstack_top = .;
}

i load my binary file with help of u-boot command line:
( loady 0x0
go 0x0 ). program sample built with u-boot as standalone project (just because i'm to lazy to write own printf )
here is beginning of the main disasm:

Code: Select all

Disassembly of section .text:

00000000 <_start>:
       0:	ea00005e 	b	180 <_reset>
       4:	ea000006 	b	24 <_undefine_instruction>
       8:	ea000006 	b	28 <_svc_smc_call>
       c:	ea000006 	b	2c <_prefetch_abort>
      10:	ea000006 	b	30 <_data_abort>
      14:	ea000006 	b	34 <_not_used>
      18:	ea000006 	b	38 <_irq>
      1c:	ea000006 	b	3c <_fiq>

00000020 <reset>:
      20:	ea000056 	b	180 <_reset>

00000024 <_undefine_instruction>:
      24:	ea00024d 	b	960 <undefine_instruction>

00000028 <_svc_smc_call>:
      28:	ea00024b 	b	95c <svc_smc_call>

0000002c <_prefetch_abort>:
      2c:	ea00024c 	b	964 <prefetch_abort>

00000030 <_data_abort>:
      30:	ea00024c 	b	968 <data_abort>

00000034 <_not_used>:
      34:	eafffffe 	b	34 <_not_used>

00000038 <_irq>:
      38:	eafffffe 	b	38 <_irq>

0000003c <_fiq>:
      3c:	eafffffe 	b	3c <_fiq>

00000040 <temp_label>:
      40:	ffffffff 			; <UNDEFINED> instruction: 0xffffffff
	...

00000060 <main>:
      60:	e92d4010 	push	{r4, lr}
      64:	e59f00f8 	ldr	r0, [pc, #248]	; 164 <I_Bit+0xe4>
      68:	eb000082 	bl	278 <printf>
      6c:	e3e01000 	mvn	r1, #0
      70:	eb000070 	bl	238 <enableAbortException>
      74:	eb000071 	bl	240 <disableHighVecs>
      78:	e1a04001 	mov	r4, r1
seems like must be fine
p.s. to dwelch67: nice to meet You. Your samples extreme useful for me :)

dwelch67
Posts: 965
Joined: Sat May 26, 2012 5:32 pm

Re: exception vector handling problem

Mon Jun 02, 2014 8:49 pm

Hello, you're welcome...

Assuming uboot is doing what you/we think it is doing then yes that should have worked. And your branching should hop it to the handler. Perhaps you are not really getting or causing an exception. I think with the armv6 the alignment is allowed by default, maybe not, but you can go change it (I think it is in the same register as the L1 cache enable). And then anything unaligned may cause a fault.

You can also try running into an undefined instruction and hit that handler instead if you are just trying to hit one of the handlers.

do_undefined:
.word 0xFFFFFFFF
bx lr (should not get here)

I believe all ones is an undefined instruction...

Or try an interrupt, I have one in one of my blinker examples.

David

but
Posts: 6
Joined: Sat May 31, 2014 8:19 am

Re: exception vector handling problem

Mon Jun 02, 2014 9:08 pm

thanks, i'll try. actually my real goal is to try TrustZone possibilities, but i could not get to monitor mode, so try to generate plain exception first. by the way, have You ever try TrustZone? it should be maintained on RPI...

dwelch67
Posts: 965
Joined: Sat May 26, 2012 5:32 pm

Re: exception vector handling problem

Mon Jun 02, 2014 10:10 pm

No I have not, with as many people that have asked maybe I should...someday...

David

but
Posts: 6
Joined: Sat May 31, 2014 8:19 am

Re: exception vector handling problem

Tue Jun 03, 2014 8:02 pm

dwelch67 wrote:Hello, you're welcome...

Assuming uboot is doing what you/we think it is doing then yes that should have worked. And your branching should hop it to the handler. Perhaps you are not really getting or causing an exception. I think with the armv6 the alignment is allowed by default, maybe not, but you can go change it (I think it is in the same register as the L1 cache enable). And then anything unaligned may cause a fault.

You can also try running into an undefined instruction and hit that handler instead if you are just trying to hit one of the handlers.

do_undefined:
.word 0xFFFFFFFF
bx lr (should not get here)

I believe all ones is an undefined instruction...

Or try an interrupt, I have one in one of my blinker examples.

David
well, i try what you advised to me (asm volatile("ldr pc, =0xfffffff1"); ) but instead of getting to undefined instruction its jump to reset again and again... strange

dwelch67
Posts: 965
Joined: Sat May 26, 2012 5:32 pm

Re: exception vector handling problem

Wed Jun 04, 2014 2:46 am

but wrote:
well, i try what you advised to me (asm volatile("ldr pc, =0xfffffff1"); ) but instead of getting to undefined instruction its jump to reset again and again... strange
Hmm, I was thinking asm volatile(".word 0xFFFFFFFF");

but
Posts: 6
Joined: Sat May 31, 2014 8:19 am

Re: exception vector handling problem

Wed Jun 04, 2014 7:52 pm

dwelch67 wrote:
but wrote:
well, i try what you advised to me (asm volatile("ldr pc, =0xfffffff1"); ) but instead of getting to undefined instruction its jump to reset again and again... strange
Hmm, I was thinking asm volatile(".word 0xFFFFFFFF");
sorry, i might have not understood you right. you're mean that i have to put asm volatile(".word 0xFFFFFFFF"); right in main execution? if yes - is it not the same as( asm volatile("ldr pc, =0xffffffff"); )
sorry for bothering you

dwelch67
Posts: 965
Joined: Sat May 26, 2012 5:32 pm

Re: exception vector handling problem

Thu Jun 05, 2014 12:54 am

what i was saying is execute the instruction 0xFFFFFFFF which I am pretty sure is an undefined instruction and should trip the exception and hit the handler. Doing this or an interrupt is perhaps a better way to insure an exception than trying to get a prefetch or data abort with an address. so if you prefer to inline then yes asm(.word 0xFFFFFFFF) or whatever the syntax is right in the code.

dwelch67
Posts: 965
Joined: Sat May 26, 2012 5:32 pm

Re: exception vector handling problem

Thu Jun 05, 2014 1:02 am

at least one of my examples demonstrates an interrupt using a timer, so you can try that as well, I think the undefined instruction...hmmm. or using the swi/svc instruction takes any question out of though. the swi/svc or an undefined instruction should "just work" with minimal overhead. unaligned accesses, reaching out into unknown address spaces, who knows if that will work.

Another approach is simply go with one of my simple linker scripts and the copy thing that was mentioned above (also from one of my examples) as the front end to the code you are using.

Basically divide the problem in half. Is the problem that you are not actually triggering the event you think you are triggering. Is it that the event handler instructions are not in the right place. Is it that the handler instructions are in the right place but not actually calling the handler for some reason and/or then handler has an issue and is not indicating to you that it was called...by changing the type of exception to something very simple, yes, you are changing more than one thing at a time, but there is low overhead to an swi/svc or undefined instruction, pretty high chance that you dont have a bug trying to cause that exception. pretty high chance that the exception you think you are triggering...you are triggering. Basically try to move the problem to one side or the other of a line, things you are pretty or very sure it is not and things that you are not sure yet. Keep dividing the problem until you find it.

was just a suggestion...

dwelch67
Posts: 965
Joined: Sat May 26, 2012 5:32 pm

Re: exception vector handling problem

Thu Jun 05, 2014 1:04 am

you mentioned uboot I think, it may be doing something undesireable. You could try simply putting your program as kernel.img and modifying config.txt to load at zero, and eliminate uboot as a problem or not.

but
Posts: 6
Joined: Sat May 31, 2014 8:19 am

Re: exception vector handling problem

Sat Jun 07, 2014 4:35 pm

dwelch67 wrote:you mentioned uboot I think, it may be doing something undesireable. You could try simply putting your program as kernel.img and modifying config.txt to load at zero, and eliminate uboot as a problem or not.
well, svc #0 works fine, don't know how he swallowed 0xffffffff instruction.. kind of strange.. any way thanks a lot, now have to investigate why after smc #0 execution doesn't jump to appropriate handler

Return to “Bare metal, Assembly language”