1
votes

I'm trying to make my own code from the scratch for an interrupt program. I'm using zynq7000 which consists of two ARM cortex A9 processors.

I load the program written in C using SDK alongwith the the FSBL and bit file generated in PlanAhead, into the Flash Memory. When my program starts running the processor enters the user mode. In user mode IRQ and FIQ are disabled. I'm trying to enter the supervisor mode using the SWI instruction to enable the IRQ and FIQ interrupts. When I debug, it shows that it encounters the SIGTRAP when I call the SWI instruction.

So, how can I make my own code in C, which can enable the interrupts and run my ISR, even after the processor has booted(FSBL) and started?

Thanks

1
To use SWI you need to provide an SWI handler, in that handler you do whatever it is you want to do. C as a language does not have knowledge of the ARM instructions required to enable/disable interrupts so some assembly is required. All of this might be done for you in a compiler specific way but that of course makes your code extremely unportable.old_timer
I had made my own SWI handler according to the syntax provided for it by armgcc, but it never enters the handler. Also I found the SWI handler in the arm_vectors.S (I guess its the startup file), where it uses a "BL" command for it jump to the handler. I tried to change it to jump to my handler but it never does. Any ideas as to what the value passed to the SWI instruction means might be helpful?sbh
the value passed in the swi instruction is encoded in the instruction, see the arm manuals. Also as the arm manuals tell you, you can use the link register to know what instruction called the swi, you then have to read the instruction then extract the value passed. the values only have any value to the handler, if you use some stock arm rom monitor or arm linux or whatever operating systems handler then they have a list of what the numbers mean.old_timer

1 Answers

0
votes

vectors.s

.globl _start
_start:
    ldr pc,_reset_handler
    ldr pc,_undefined_handler
    ldr pc,_swi_handler
    b hang
    b hang
    b hang
    b hang
    b hang

_reset_handler:     .word reset
_undefined_handler: .word hang
_swi_handler:       .word swi

reset:
    mov sp,#0xD6000000
    add sp,sp,#0xC000

    bl notmain
hang: b hang

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

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

swi:
    ldr r0,[lr,#-4]
    mov r1,#0x00FFFFFF
    and r0,r0,r1
    movs pc,lr

.globl switest
switest:
    stmdb r13!,{lr}
    swi #0x23
    ldmia r13!,{lr}
    bx lr

linker script

MEMORY
{
    ram : ORIGIN = 0x00000000, LENGTH = 0x4000
}
SECTIONS
{
    .text : { *(.text*) } > ram
}

notmain.c

extern void uart_init ( void );
extern void uart_putc ( unsigned char );
extern unsigned int switest ( void );
void hexstrings ( unsigned int d )
{
    unsigned int rb;
    unsigned int rc;

    rb=32;
    while(1)
    {
        rb-=4;
        rc=(d>>rb)&0xF;
        if(rc>9) rc+=0x37; else rc+=0x30;
        uart_putc(rc);
        if(rb==0) break;
    }
    uart_putc(0x20);
}
void hexstring ( unsigned int d )
{
    hexstrings(d);
    uart_putc(0x0D);
    uart_putc(0x0A);
}
int notmain ( void )
{
    uart_init();
    hexstring(0x12345678);
    hexstring(switest());
    return(0);
}

The above are relevant parts from a minimal swi working example. Note that this only works for svc/swi instructions in arm mode not thumb nor thumb2, if you want to make a generic works in all modes, I recommend you dont bother with the svc immediate and instead pass something in a register.

This example does not enable interrupts it just shows how to make an svc/swi call and how to implement the exception handler. This knowledge has been well documented in the arm architectural reference manuals for many many years now.