200 likes | 482 Views
C Programming in Embedded Systems. Computer Science & Engineering Department Arizona State University Tempe, AZ 85287 Dr. Yann-Hang Lee yhlee@asu.edu (480) 727-7507. C Programming in Embedded Systems. Assembly language dependent of processor architecture
E N D
C Programming in Embedded Systems Computer Science & Engineering DepartmentArizona State University Tempe, AZ 85287 Dr. Yann-Hang Leeyhlee@asu.edu(480) 727-7507
C Programming in Embedded Systems • Assembly language • dependent of processor architecture • cache control, registers, program status, interrupt • High-level language • memory model • independent of processor architecture (partially true) • Advantages and disadvantages • performance • code size • software development and life cycle
Manage IO Operations Using C • Access memory-mapped IO – pointers • Example #define REG_READ (a, val) ((val) = *(volatile unsigned char *)(a)) #define REG_WRITE (a, val) (*(volatile unsigned char *)(a) = (val)) #define UART_USR0 0x4000_0204 #define UART_CR 0x4000_0208 #define UART_RX_EN 1 #define UART_TX_EN (1<<2) char CR_word=0; CR_word |= UART_RX_EN | UART_TX_EN; REG_WRITE (UART_CR, CR_word);
Platform.h for MXL #ifndef __MCF5213_UART_H__ #define __MCF5213_UART_H__ /* Register read/write macros */ #define MCF_UART0_UMR (*(vuint8 *)(&__IPSBAR[0x000200])) #define MCF_UART0_USR (*(vuint8 *)(&__IPSBAR[0x000204])) #define MCF_UART0_UCSR (*(vuint8 *)(&__IPSBAR[0x000204])) #define MCF_UART0_UCR (*(vuint8 *)(&__IPSBAR[0x000208])) According to Linux C/C++ coding style: “_” Variable not intended to be exposed externally to the user. Internal workings only. Most often used by compiler and library authors. Sometimes used (not preferred) as a suffix to represent a class member variable. “__” Marks an use as extension to ANSI C++. Often not compiler independent. Usually reserved for use by compiler writers.
Bit Manipulation • Boolean operation • operate on 1 (true) and 0 (false) • (2 || !6 ) && 7 ?? • Bitwise operation • operate on individual bit positions within the operands • (2 | ~6 ) & 7 = (0x0002 OR 0xFFF1) AND 0x0007 if (bits & 0x0040)if (bits & (1 <<6)) bits |= (1 <<7) bits &= ~(1<<7) long integer: bits &= ~(1L << 7)
mwasmcf mwldmcf mwccmcf Interface C and Assembly Language • Why combine C and assembly language • performance • C doesn’t handle most architecture features, such as registers, program status, etc. • Develop C and assembly programs and then link them together • at source level – in-line assembly code in C program • at object level – procedure call
Calling Convention • GCC calling convention • arguments passed in registers and in stack • registers saved by caller and callee (including frame pointer and returning PC) • frame pointer points just below the last argument passed on the stack (the bottom of the frame) • stack pointer points to the first word after the frame stack pointer dynamic area local variables saved registers (by callee) argument x frame pointer argument y saved registers (by caller)
Coldfire Calling Convention • Passes all parameters on the stack in reverse order. • Push the last argument first • Compact — Passes on even sized boundary for parameters smaller than int (2 for short and char). • Standard — Like compact, but always padded to 4 bytes. • Register — Passes in scratch registers D0 — D2 for integers, A0— A1 for pointers. • Returning • returns an integer value in register D0. • returns a pointer value in register A0. • If it returns a value of any other type, • the caller reserves temporary storage area for that type in the caller's stack and passes a pointer to that area as the last argument. • the called function returns its value in the temporary storage area.
Save code pointer (the value of pc) allows the function corresponding to a stack backtrace structure to be located Save frame and stack pointers to locate stack frame Register usage A0-A1, D0-D2 – scratch registers A2 through A5 — for pointers D3 through D7 — for integers and pointers. A6 – frame pointer A7 – stack pointer Caller needs to save D0-D2 and A0-A2 before calling if the values must be preserved Callee needs to save D3-D7 and A3-A5 if they are used in the procedure Register Usage by Coldfire C Compiler
Stack Usage by Coldfire C Compiler • Allocation of local variable in stack • Save frame and stack pointers to locate stack frame • Entry code link a6, #-framesize ; save and set up fp and sp, movem.l ….., -(sp) ; save registers move.l (.., a6), d0 ; retrieve parameters ; link instruction: SP – 4 → SP; Ay → (SP); ; SP → Ay; SP + dn → SP • On function exit move.l …., d0 ; return value movem.l (sp)+,…. ; restore registers unlk a6 ; restore sp and fp ; unlk instruction -- Ax → SP; (SP) → Ax; ; SP + 4 → SP rts
Calling Assembly Routine from C • In C program char *srcstr = "First string - source "; char *dststr = "Second string - destination "; strcopy(dststr,srcstr); • Assembly routine .global strcopy strcopy: move.l (4,sp), a0 ; a0 points to destination string. move.l (8,sp), a1 ; a1 points to source string. next: move.b (a1)+, d0 ; Load byte and update address. move.b d0, (a0)+ ; Store byte and update address bne.b next ; Check for zero terminator. rts ; Return. .end
A feature provided by C compiler to specify that a block of code in your file as assembly language use the “asm” keyword. compiler will do the insertion and knows the variables and the registers Example: function level long int b; struct mystruct { long int a; } ; static asm long f(void) // Legal asm qualifier { move.l struct(mystruct.a)(A0),D0 // Accessing a struct. add.l b,D0 // Using a global variable, put // return value in D0. rts // Return from the function: // result = mystruct.a + b } Inline Assembly Code in C Program
Inline Assembly and Access Control Registers • Statement level long square(short a) { long result=0; asm { move.w a,d0 // fetch function argument ‘a’ mulu.w d0,d0 // multiply move.l d0,result // store in local ‘result’ variable } return result; } • Access local and global variables and inline assembly directives • Write to the special purpose registers _mcf5xxx_wr_sr: move.l 4(SP),D0 move.w D0,SR rts _mcf5xxx_wr_vbr: move.l 4(SP),D0 .long 0x4e7b0801 /* movec d0,VBR */ nop rts
int *sum, array[5]; void sumsq (int *sum, int size, int array[]) { int total=0; int i; for ( i = size-1; i < 0; i--) total= total + array[i]^2; *sum=total; } int main() { sumsq(sum, 5, array); while(1); // Idle } Example sumsq
Example sumsq -- main int *sum, array[5]; ; 19: int main() ; 20: { ; 21: 0x00000000 _main: ; main: 0x00000000 0x4E560000 link a6,#0 0x00000004 0x4FEFFFF4 lea -12(a7),a7 ; ; 22: sumsq(sum, 5, array); ; 23: ; 0x00000008 0x41F900000000 lea _array,a0 0x0000000E 0x2F480008 move.l a0,8(a7) 0x00000012 0x7005 moveq #5,d0 0x00000014 0x2F400004 move.l d0,4(a7) 0x00000018 0x41F900000000 lea _sum,a0 0x0000001E 0x2010 move.l (a0),d0 0x00000020 0x2E80 move.l d0,(a7) 0x00000022 0x4EB900000000 jsr _sumsq
Example sumsq -- main ; ; 24: while(1); // Idle ; 25: ; 0x00000028 0x60FE bra.s *+0 ; 0x00000028 0x0000002A 0x4E71 nop ; 10: ; 11: void sumsq (int *sum, int size, int array[]) ; 12: { ; 0x00000000 _sumsq: ; sumsq: 0x00000000 0x4E560000 link a6,#0 0x00000004 0x4FEFFFF4 lea -12(a7),a7 ; 13: int total=0; ; 14: int i; 0x00000008 0x7000 moveq #0,d0 0x0000000A 0x2D40FFF8 move.l d0,-8(a6)
Example sumsq ; ; 15: for ( i = size-1; i < 0; i--) ; 0x0000000E 0x202E000C move.l 12(a6),d0 0x00000012 0x5380 subq.l #1,d0 0x00000014 0x2D40FFF4 move.l d0,-12(a6) 0x00000018 0x6030 bra.s *+50 ; 0x0000004a ; ; 16: total= total + array[i]^2; ; 0x0000001A 0x202EFFF4 move.l -12(a6),d0 0x0000001E 0x2D40FFFC move.l d0,-4(a6) 0x00000022 0x202EFFFC move.l -4(a6),d0 0x00000026 0x206E0010 movea.l 16(a6),a0 0x0000002A 0x222EFFFC move.l -4(a6),d1 0x0000002E 0x202EFFF8 move.l -8(a6),d0 0x00000032 0xD0B01C00 add.l (a0,d1.l*4),d0 0x00000036 0x0A8000000002 eori.l #0x2,d0 ; '....'
Example sumsq 0x0000003C 0x2D40FFF8 move.l d0,-8(a6) 0x00000040 0x202EFFF4 move.l -12(a6),d0 0x00000044 0x5380 subq.l #1,d0 0x00000046 0x2D40FFF4 move.l d0,-12(a6) 0x0000004A 0x202EFFF4 move.l -12(a6),d0 0x0000004E 0x4A80 tst.l d0 0x00000050 0x6DC8 blt.s *-54 ; 0x0000001a ; ; 17: *sum=total; ; 0x00000052 0x206E0008 movea.l 8(a6),a0 0x00000056 0x202EFFF8 move.l -8(a6),d0 0x0000005A 0x2080 move.l d0,(a0) ; ; 18: } 0x0000005C 0x4E5E unlk a6 0x0000005E 0x4E75 rts