ARM System Calls: Difference between revisions
[unchecked revision] | [unchecked revision] |
No edit summary |
m Bot: Replace deprecated source tag with syntaxhighlight |
||
Line 6: | Line 6: | ||
<pre>mov pc, lr</pre> |
<pre>mov pc, lr</pre> |
||
Most of the time you won't need to worry about returning from the interrupt, as GCC, set up to cross compile for ARM, lets you code the interrupt handlers in C: |
Most of the time you won't need to worry about returning from the interrupt, as GCC, set up to cross compile for ARM, lets you code the interrupt handlers in C: |
||
< |
<syntaxhighlight lang="c">void swi_handler () __attribute__((interrupt));</syntaxhighlight> |
||
==Creating System Calls== |
==Creating System Calls== |
||
Line 31: | Line 31: | ||
</pre> |
</pre> |
||
We can code the interrupt handler like this: |
We can code the interrupt handler like this: |
||
< |
<syntaxhighlight lang="c"> |
||
void __attribute__ ((interrupt ("SWI"))) swi_handler (void) {} |
void __attribute__ ((interrupt ("SWI"))) swi_handler (void) {} |
||
</syntaxhighlight> |
|||
</source> |
|||
Parameters to functions on ARM, are passed in registers r0-r3, if follow the same convention for system calls, then our interrupt handler can take parameters: |
Parameters to functions on ARM, are passed in registers r0-r3, if follow the same convention for system calls, then our interrupt handler can take parameters: |
||
< |
<syntaxhighlight lang="c"> |
||
void __attribute__ ((interrupt ("SWI"))) swi_handler (int r0, int r1, int r2, int r3) {} |
void __attribute__ ((interrupt ("SWI"))) swi_handler (int r0, int r1, int r2, int r3) {} |
||
</syntaxhighlight> |
|||
</source> |
|||
You've probably noticed that <span style="font-family:monospace">swi</span> takes an integer argument. To get this argument in C, we have to do this: |
You've probably noticed that <span style="font-family:monospace">swi</span> takes an integer argument. To get this argument in C, we have to do this: |
||
< |
<syntaxhighlight lang="c"> |
||
uint8_t int_vector = 0; |
uint8_t int_vector = 0; |
||
asm volatile ("ldrb %0, [lr, #-2]" : "=r" (int_vector)); |
asm volatile ("ldrb %0, [lr, #-2]" : "=r" (int_vector)); |
||
</syntaxhighlight> |
|||
</source> |
|||
This loads the high 8 bits (16-23) of the argument into <span style="font-family:monospace">int_vector</span>, as loading the full 24-bits won't work using Thumb. |
This loads the high 8 bits (16-23) of the argument into <span style="font-family:monospace">int_vector</span>, as loading the full 24-bits won't work using Thumb. |
||
Latest revision as of 04:11, 9 June 2024
System Calls
swi 0x420000
This is how you call the system on ARM. The instruction swi jumps to a predefined address, which in turn jumps to the system call handler. The system call handler executes the specific function and return to the user code with:
mov pc, lr
Most of the time you won't need to worry about returning from the interrupt, as GCC, set up to cross compile for ARM, lets you code the interrupt handlers in C:
void swi_handler () __attribute__((interrupt));
Creating System Calls
interrupt_vector_table: b . @ Reset Handler b . @ Undefined b . @ SWI Handler b . @ Prefetch Abort b . @ Data Abort b . @ IRQ b . @ FIQ
This is the ARM equivalent to the IDT, on the x86, and it is stored by default at address 0. The only entry, we need to worry about is the SWI Handler. To install our own SWI handler, we replace the b . instruction with a branch to our handler:
interrupt_vector_table: b . @ Reset Handler b . @ Undefined b swi_handler @ Our new SWI Handler b . @ Prefetch Abort b . @ Data Abort b . @ IRQ b . @ FIQ
We can code the interrupt handler like this:
void __attribute__ ((interrupt ("SWI"))) swi_handler (void) {}
Parameters to functions on ARM, are passed in registers r0-r3, if follow the same convention for system calls, then our interrupt handler can take parameters:
void __attribute__ ((interrupt ("SWI"))) swi_handler (int r0, int r1, int r2, int r3) {}
You've probably noticed that swi takes an integer argument. To get this argument in C, we have to do this:
uint8_t int_vector = 0;
asm volatile ("ldrb %0, [lr, #-2]" : "=r" (int_vector));
This loads the high 8 bits (16-23) of the argument into int_vector, as loading the full 24-bits won't work using Thumb.