2009-09-07 11:51 PM
How should i create SVC calls from C?
2011-05-17 04:22 AM
In my hobby kernel, I have so far defined a few system calls. Currently I call them by doing inline assembly calls from a C program (I use gcc) or directly using the SVC instruction from an assembly program.
I am looking for a nice and compact way to call systems calls from C, i.e. a call like: buffer = rtos_alloc(42); should end up something like this after compilation: mov r12, 1 # 1 = syscall id for alloc mov r0, 42 svc ... The return value from rtos_alloc is located in r0 which can then be assigned to ''buffer''. I have tried a number of tricks using macros like: #define rtos_syscall_1(CALL_ID, RET_TYPE, NAME, TYPE0, NAME0) __attribute__ ((always_inline)) static inline RET_TYPE NAME(TYPE0 NAME0) { asm volatile(''mov r12, ''stringify(CALL_ID)''\n\t'' ''mov r0, %0\n\t'' ''svc\n\t'':: ''r'' (NAME0)); } to define inline assembly functions, but I can't get it to work properly. Are there any better ways to do this?2011-05-17 04:22 AM
Go for clarity, not compactness.
Each function i.e. timer wait, wait for event, allocate etc should have its own subroutine. Consider this (using IAR asm syntax) . . . char* rtos_alloc(int arg) { // note: arg already in r0 asm (mov r12,#1); // allocate opcode asm (svc 0); // kernel returns address in r0 // ignore “no return value warning� (or turn it off) } This may take an extra stack level and a few extra lines of code. The compiler will push lr before calling rtos_alloc (unless it has already saved lr in the calling module.) You always have the bl rtos_alloc and the bx lr overhead. ‘Tiz a small price to pay for clarity. It’s more work in your svc handler but you could use the svc code to say which function you are calling. (But don’t inline a function that assumes r0 is set on entry. IAR noticed that arg was not used and optimized out loading r0.)2011-05-17 04:22 AM
Hi!
Thanks for your answer, I agree with you. Clarity is very important. Without considering the options, I was initially aiming for a compact inlined solution which, as you mention, might save a couple of instructions but increases complexity. GCC in this case pushes lr in the calling function anyway, so that wont give any extra cost.