C_Programming Part 10 ENG. KEROLES SHENOUDA 1
Brainstorming on previous session 2
Storage classes  In C language, each variable has a storage class which decides scope, visibility and lifetime of that variable. The following storage classes are most oftenly used in C programming,  Automatic variables >>> Local, static and global  External variables  Static variables  Register variables 3
Automatic variables  A variable declared inside a function without any storage class specification, is by default an automatic variable. They are created when a function is called and are destroyed automatically when the function exits. Automatic variables can also be called local variables because they are local to a function. By default they are assigned garbage value by the compiler. 4
External or Global variable  A variable that is declared outside any function is a Global variable. Global variables remain available throughout the entire program. One important thing to remember about global variable is that their values can be changed by any function in the program. 5 Here the global variable number is available to all three functions.
extern keyword The extern keyword is used before a variable to inform the compiler that this variable is declared somewhere else. The extern declaration does not allocate storage for variables. 6
Problem when extern is not used 7
Example Using extern in same file 8
Register variable  Register variable inform the compiler to store the variable in register instead of memory. Register variable has faster access than normal variable. Frequently used variables are kept in register. Only few variables can be placed inside register.  NOTE : We can never get the address of such variables.  Syntax : 9
Volatile Type Qualifier 10
Syntax of C's volatile Keyword  declare a variable volatile, include the keyword volatile before or after the data type in the variable definition. For instance both of these declarations will declare foo to be a volatile integer:  volatile int foo;  int volatile foo; 11
volatile  Now, it turns out that pointers to volatile variables are very common, especially with memory-mapped I/O registers. Both of these declarations declare pReg to be a pointer to a volatile unsigned 8-bit integer:  volatile uint8_t * pReg;  uint8_t volatile * pReg; 12 pointer to a volatile unsigned 8-bit integer
volatile  Volatile pointers to non-volatile data are very rare (I think I've used them once), but I'd better go ahead and give you the syntax:  int * volatile p; 13 Volatile pointers to non-volatile data
volatile  for completeness, if you really must have a volatile pointer to a volatile variable, you'd write: int volatile * volatile p; 14 volatile pointer to a volatile variable
Proper Use of C's volatile Keyword  Memory-mapped peripheral registers  Global variables modified by an interrupt service routine  Global variables accessed by multiple tasks within a multi-threaded application 15
Peripheral Registers  Embedded systems contain real hardware, usually with sophisticated peripherals. These peripherals contain registers whose values may change asynchronously to the program flow. As a very simple example, consider an 8-bit status register that is memory mapped at address 0x1234. It is required that you poll the status register until it becomes non-zero. 16
incorrect implementation 17 uint8_t * pReg = (uint8_t *) 0x1234; // Wait for register to become non- //zero while (*pReg == 0) { } // Do something else This will almost certainly fail as soon as you turn compiler optimization on, since the compiler will generate assembly language that looks something like this: mov ptr, #0x1234 mov a, @ptr loop: bz loop assembly
To force the compiler to do what we want, we modify the declaration to: 18 uint8_t volatile * pReg = (uint8_t volatile *) 0x1234; //The assembly language now looks like this: mov ptr, #0x1234 loop: mov a, @ptr bz loop
Interrupt Service Routines 19 int etx_rcvd = FALSE; void main() { ... while (!ext_rcvd) { // Wait } ... } interrupt void rx_isr(void) { ... if (ETX == rx_char) { etx_rcvd = TRUE; } ... } The solution is to declare the variable etx_rcvd to be volatile
Multithreaded Applications 20 int cntr; void task1(void) { cntr = 0; while (cntr == 0) { sleep(1); } ... } void task2(void) { ... cntr++; sleep(10); ... } This code will likely fail once the compiler's optimizer is enabled. Declaring cntr to be volatile is the proper way to solve the problem.
useful references for C and Embedded C 21
22 How To Write Embedded C Code From Scratch without IDE ?
You will need Cross Toolchain MakefileLinker Script Startup.s C Code files 23
C Startup  It is not possible to directly execute C code, when the processor comes out of reset. Since, unlike assembly language, C programs need some basic pre-requisites to be satisfied. This section will describe the pre-requisites and how to meet the pre-requisites.  We will take the example of C program that calculates the sum of an array as an example.  And by the end of this section, we will be able to perform the necessary setup, transfer control to the C code and execute it. 24
25Sum of Array in C
Before transferring control to C code, the following have to be setup correctly.  Stack (r13”SP”)  Global variables Initialized .data Uninitialized .bss  Read-only data .rodata  Then force the PC register to jump on the main functions 26 CPU Memory Peripherals/Modules
Stack  C uses the stack for storing local (auto) variables, passing function arguments, storing return address, etc. So it is essential that the stack be setup correctly, before transferring control to C code.  Stacks are highly flexible in the ARM architecture, since the implementation is completely left to the software. 27
Stack 28  So all that has to be done in the startup code is to point (r13”SP”) register at the highest RAM address, so that the stack can grow downwards (towards lower addresses). For the connex board this can be achieved using the following ARM instruction.
Global Variables  When C code is compiled, the compiler places initialized global variables in the .data section. So just as with the assembly, the .data has to be copied from Flash to RAM.  The C language guarantees that all uninitialized global variables will be initialized to zero. When C programs are compiled, a separate section called .bss is used for uninitialized variables. Since the value of these variables are all zeroes to start with, they do not have to be stored in Flash. Before transferring control to C code, the memory locations corresponding to these variables have to be initialized to zero. 29
Read-only Data  GCC places global variables marked as const in a separate section, called .rodata. The .rodata is also used for storing string constants.  Since contents of .rodata section will not be modified, they can be placed in Flash. The linker script has to modified to accomodate this. 30
31 Section Placement “Very important” Learn in depth
Linker Script for C code 32
The startup code has the following parts 33 1.exception vectors 2.code to copy the .datafrom Flash to RAM 3.code to copy zero out the .bss 4.code to setup the stack pointer 5.branch to main
Startup Assembly 34
Labs 35 HELLO WORLD FOR BARE METAL On VersatilePB platform, that contains an ARM926EJ-S core
Prerequisites  Download: Qemufrom https://qemu.weilnetz.de/w32/  GNU ARM Embedded Toolchain from https://launchpad.net/gcc-arm-embedded  THEN INSTALL THEM 36
37 What is QEMU ? − QEMU (short for "Quick EMUlator") is a free and open-source machine emulator and virtualizer written originally by Fabrice Bellard − Can emulate 80386, 80486, Pentium, Pentium Pro, AMD64 – from x86 architecture − PowerPC, ARM, MIPS, SPARC, SPARC64 − Work on FreeBSD, FreeDOS, Linux, Windows 9x, Windows 2000, Mac OS X, QNX, Android
38 − Available CPUs: − arm1026 − arm1136 − arm1136-r2 − arm1176 − arm11mpcore − arm926 − arm946 − cortex-a15 − cortex-a8 − cortex-a9 − cortex-m3 − pxa250 − pxa255 − pxa260 − pxa261 − pxa262 − pxa270-a0 − pxa270-a1 − pxa270 − pxa270-b0 − pxa270-b1 − pxa270-c0 − pxa270-c5 − sa1100 − sa1110 − ti925t − any List of supported CPUs (ARM) $ qemu-system-arm –cpu ?
39 List of Platforms (ARM) $ qemu-system-arm -machine ?
40 QEMU Project “QEMU does not have a high level design description document - only the source code tells the full story”
ARM system emulated with QEMU  qemu-system-arm is the software that emulates a VersatilePB platform For more information “VersatilePB physical Board’ http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dsi0034a/index.html  http://www.arm.com/products/tools/development-boards/versatile-express  http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0224i/index.html 41
HELLO WORLD FOR BARE METAL 42 tx RX You will need Cross Toolchain Makefile Linker Script .ld C Code files Startup.s Exectuable File Test.bin
Lab: Steps  The QEMU emulator supports the VersatilePB platform, that contains an ARM926EJ-S core and, among  other peripherals, four UART serial ports;  the first serial port in particular (UART0) works as a terminal  when using the -nographic or “-serial stdio” qemu option. The memory map of the VersatilePB board is implemented in QEMU in this board-specific C source;  note the address where the UART0 is mapped: 0x101f1000. 43
44 there is a register (UARTDR) that is used to transmit (when writing in the register) and receive (when reading) bytes; this register is placed at offset 0x0, so you need to read and write at the beginning of the memory allocated for the UART0
Lab: Steps  The QEMU emulator supports the VersatilePB platform, that contains an ARM926EJ-S core and, among  other peripherals, four UART serial ports;  the first serial port in particular (UART0) works as a terminal  when using the -nographic or “-serial stdio” qemu option. The memory map of the VersatilePB board is implemented in QEMU in this board-specific C source;  note the address where the UART0 is mapped: 0x101f1000. 45
To implement the simple “Hello world!” printing, you should write this test.c file: 46 volatile unsigned int * const UART0DR = (unsigned int *)0x101f1000; void print_uart0(const char *s) { while(*s != '0') { /* Loop until end of string */ *UART0DR = (unsigned int)(*s); /* Transmit char */ s++; /* Next char */ } } void c_entry() { print_uart0("Hello world!n"); } • The volatile keyword is necessary to instruct the compiler that the memory pointed by UART0DR can change or has effects independently of the program. • The unsigned int type enforces 32-bits read and write access.
startup.s 47
the linker script test.ld 48 ENTRY(_Reset) SECTIONS { . = 0x10000; .startup . : { startup.o(.text) } .text : { *(.text) } .data : { *(.data) } .bss : { *(.bss COMMON) } . = ALIGN(8); . = . + 0x1000; /* 4kB of stack memory */ stack_top = .; } .startup .text .data .bss Stack_top 0x1000
49Create the binary file Go to GNU Tools ARM Embedded5.4 2016q3bin directory And open the CMD Console
50Create the binary file Then run those commands Generate startup object file $ arm-none-eabi-as -mcpu=arm926ej-s -g startup.s -o startup.o Generate test object file $ arm-none-eabi-gcc -c -mcpu=arm926ej-s -g test.c -o test.o Invoke the linker and pass the linker script $ arm-none-eabi-ld -T test.ld test.o startup.o -o test.elf Generate binary file $ arm-none-eabi-objcopy -O binary test.elf test.bin interview
To make sure the entry point at address 0x10000 Use the readelf Binary utilities 51
52
To see the disassembly Use the odjdump Binary utilities 53
54
To run the program in the emulator 55 Go to qemu directory And open the CMD Console Copy the test.bin on the qemu folder then press this Command $ qemu-system-arm -M versatilepb -m 128M -nographic -kernel test.bin
To Debug the Code  Using gdb, because QEMU implements a gdb connector using a TCP connection. To do so, run the emulator with the correct options as follows $ qemu-system-arm -M versatilepb -m 128M -nographic -s -S -kernel test.bin  This command freezes the system before executing any guest code, and waits for a connection on the TCP port 1234.  From ARM ToolChan terminal, run arm-none-eabi-gdb and enter the commands: 56
57
58
59 GNU Debugger Tutorial
List all preprocessor directives in c programming language. 60
DIFFERENCE BETWEEN C AND EMBEDDED C  Compilers for C (ANSI C) typically generate OS dependent executables. Embedded C requires compilers to create files to be downloaded to the microcontrollers/microprocessors where it needs to run. Embedded compilers give access to all resources which is not provided in compilers for desktop computer applications. 61
DIFFERENCE BETWEEN C AND EMBEDDED C  Embedded systems often have the real-time constraints, which is usually not there with desktop computer applications.  Embedded systems often do not have a console, which is available in case of desktop applications.  So, what basically is different while programming with embedded C is the mindset; for embedded applications, we need to optimally use the resources, make the program code efficient, and satisfy real time constraints, if any. All this is done using the basic constructs, syntaxes, and function libraries of ‘C’. 62
Embedded C Constrains  Memory  Power  Size  Cost  Timing  CPU 63
SW Should be  Portable  Maintainable  Optimized  Reusable  Readable 64
Embedded versus Desktop Programming  Main characteristics of an Embedded programming environment: • Limited ROM. • Limited RAM. • Limited stack space. • Hardware oriented programming. • Critical timing (Interrupt Service Routines, tasks, …). • Many different pointer kinds (far / near / rom / uni / paged / …). • Special keywords and tokens (@, interrupt, tiny, …) 65
Assembly versus C 66
Why Change to C  C is much more flexible than other high-level programming languages: • C is a structured language. • C is a relatively small language. • C has very loose data typing. • C easily supports low-level bit-wise data manipulation. • C is sometimes referred to as a “high-level assembly language”. ► When compared to assembly language programming: • Code written in C can be more reliable. • Code written in C can be more scalable. • Code written in C can be more portable between different platforms. • Code written in C can be easier to maintain. • Code written in C can be more productive 67
How to make Code more Readable 68
1.Commenting 69
2.memory-mapped devices Documenting the source code is helpful not only for your future reference but for those who come after you. For instance, if you're working on an embedded system, you need to have a memory map indicating where all the memory-mapped devices can be found. Listing 8 shows an example of a memory map. 70
Review: The “super loop” software architecture  Problem What is the minimum software environment you need to create an embedded C program?  Solution 71
Review: An introduction to schedulers  Many embedded systems must carry out tasks at particular instants of time. More specifically, we have two kinds of activity to perform: • Periodic tasks, to be performed (say) once every 100 ms, and - less commonly - • One-shot tasks, to be performed once after a delay of (say) 50 ms. 72
Function Reuse 73
Header File 74
Header File  Each .h file should be “stand alone” ▫ It should declare, #define, and typedef anything needed by prototypes and include any .h files it needs to avoid compiler errors  In our example prototypes for CircleArea() and Circumference are placed in circleUtils.h ▫ circleUtils.h included in circleUtils.c ▫ circleUtils.h included in any other .c file that uses CircleArea() 75
Guarding Header Files 76
Guarding Example 77
Separate Compilation  If code is separated into multiple .c files ▫ Must compile each .c file ▫ Combine resulting .o files to create executable 78
Program Organization 79
How to define u8 ,u32,…. 80
Modularity 81
#pragma  The #pragma directive gives special instructions to the compiler. The #pragma directive is especially useful in embedded C programming and can tell the compiler to allocate a certain variable in RAM or EEPROM. It can also tell the compiler to insert a snippet of assembly language code.  The GNU GCC compiler, which is a popular compiler for various embedded architectures such as ARM and AVR, also uses attributes as an alternative syntax to the #pragma directive. 82 #pragma GCC dependency allows you to check the relative dates of the current file and another file. If the other file is more recent than the current file, a warning is issued. This is useful if the current file is derived from the other file, and should be regenerated. The other file is searched for using the normal include search path. Optional trailing text can be used to give more information in the warning message.
83
References 84  https://balau82.wordpress.com/2010/02/28/hello-world-for-bare-metal-arm-using-qemu/  https://balau82.wordpress.com/2012/03/31/compile-linux-kernel-3-2-for-arm-and-emulate- with-qemu/  https://balau82.wordpress.com/2010/02/14/simplest-bare-metal-program-for-arm/  http://infocenter.arm.com/help/topic/com.arm.doc.ddi0183f/DDI0183.pdf  https://balau82.wordpress.com/2010/03/10/u-boot-for-arm-on-qemu/  https://balau82.wordpress.com/2010/08/17/debugging-arm-programs-inside-qemu/  https://balau82.wordpress.com/2010/04/12/booting-linux-with-u-boot-on-qemu-arm/  https://balau82.wordpress.com/2010/03/10/u-boot-for-arm-on-qemu/  https://balau82.wordpress.com/2010/08/17/debugging-arm-programs-inside-qemu/  https://barrgroup.com/Embedded-Systems/How-To/C-Volatile-Keyword

C programming session10

  • 1.
  • 2.
  • 3.
    Storage classes  InC language, each variable has a storage class which decides scope, visibility and lifetime of that variable. The following storage classes are most oftenly used in C programming,  Automatic variables >>> Local, static and global  External variables  Static variables  Register variables 3
  • 4.
    Automatic variables  Avariable declared inside a function without any storage class specification, is by default an automatic variable. They are created when a function is called and are destroyed automatically when the function exits. Automatic variables can also be called local variables because they are local to a function. By default they are assigned garbage value by the compiler. 4
  • 5.
    External or Globalvariable  A variable that is declared outside any function is a Global variable. Global variables remain available throughout the entire program. One important thing to remember about global variable is that their values can be changed by any function in the program. 5 Here the global variable number is available to all three functions.
  • 6.
    extern keyword The externkeyword is used before a variable to inform the compiler that this variable is declared somewhere else. The extern declaration does not allocate storage for variables. 6
  • 7.
    Problem when externis not used 7
  • 8.
    Example Using externin same file 8
  • 9.
    Register variable  Registervariable inform the compiler to store the variable in register instead of memory. Register variable has faster access than normal variable. Frequently used variables are kept in register. Only few variables can be placed inside register.  NOTE : We can never get the address of such variables.  Syntax : 9
  • 10.
  • 11.
    Syntax of C'svolatile Keyword  declare a variable volatile, include the keyword volatile before or after the data type in the variable definition. For instance both of these declarations will declare foo to be a volatile integer:  volatile int foo;  int volatile foo; 11
  • 12.
    volatile  Now, itturns out that pointers to volatile variables are very common, especially with memory-mapped I/O registers. Both of these declarations declare pReg to be a pointer to a volatile unsigned 8-bit integer:  volatile uint8_t * pReg;  uint8_t volatile * pReg; 12 pointer to a volatile unsigned 8-bit integer
  • 13.
    volatile  Volatile pointersto non-volatile data are very rare (I think I've used them once), but I'd better go ahead and give you the syntax:  int * volatile p; 13 Volatile pointers to non-volatile data
  • 14.
    volatile  for completeness,if you really must have a volatile pointer to a volatile variable, you'd write: int volatile * volatile p; 14 volatile pointer to a volatile variable
  • 15.
    Proper Use ofC's volatile Keyword  Memory-mapped peripheral registers  Global variables modified by an interrupt service routine  Global variables accessed by multiple tasks within a multi-threaded application 15
  • 16.
    Peripheral Registers  Embeddedsystems contain real hardware, usually with sophisticated peripherals. These peripherals contain registers whose values may change asynchronously to the program flow. As a very simple example, consider an 8-bit status register that is memory mapped at address 0x1234. It is required that you poll the status register until it becomes non-zero. 16
  • 17.
    incorrect implementation 17 uint8_t* pReg = (uint8_t *) 0x1234; // Wait for register to become non- //zero while (*pReg == 0) { } // Do something else This will almost certainly fail as soon as you turn compiler optimization on, since the compiler will generate assembly language that looks something like this: mov ptr, #0x1234 mov a, @ptr loop: bz loop assembly
  • 18.
    To force thecompiler to do what we want, we modify the declaration to: 18 uint8_t volatile * pReg = (uint8_t volatile *) 0x1234; //The assembly language now looks like this: mov ptr, #0x1234 loop: mov a, @ptr bz loop
  • 19.
    Interrupt Service Routines19 int etx_rcvd = FALSE; void main() { ... while (!ext_rcvd) { // Wait } ... } interrupt void rx_isr(void) { ... if (ETX == rx_char) { etx_rcvd = TRUE; } ... } The solution is to declare the variable etx_rcvd to be volatile
  • 20.
    Multithreaded Applications 20 intcntr; void task1(void) { cntr = 0; while (cntr == 0) { sleep(1); } ... } void task2(void) { ... cntr++; sleep(10); ... } This code will likely fail once the compiler's optimizer is enabled. Declaring cntr to be volatile is the proper way to solve the problem.
  • 21.
    useful references for Cand Embedded C 21
  • 22.
    22 How To Write EmbeddedC Code From Scratch without IDE ?
  • 23.
    You will need CrossToolchain MakefileLinker Script Startup.s C Code files 23
  • 24.
    C Startup  Itis not possible to directly execute C code, when the processor comes out of reset. Since, unlike assembly language, C programs need some basic pre-requisites to be satisfied. This section will describe the pre-requisites and how to meet the pre-requisites.  We will take the example of C program that calculates the sum of an array as an example.  And by the end of this section, we will be able to perform the necessary setup, transfer control to the C code and execute it. 24
  • 25.
  • 26.
    Before transferring controlto C code, the following have to be setup correctly.  Stack (r13”SP”)  Global variables Initialized .data Uninitialized .bss  Read-only data .rodata  Then force the PC register to jump on the main functions 26 CPU Memory Peripherals/Modules
  • 27.
    Stack  C usesthe stack for storing local (auto) variables, passing function arguments, storing return address, etc. So it is essential that the stack be setup correctly, before transferring control to C code.  Stacks are highly flexible in the ARM architecture, since the implementation is completely left to the software. 27
  • 28.
    Stack 28  Soall that has to be done in the startup code is to point (r13”SP”) register at the highest RAM address, so that the stack can grow downwards (towards lower addresses). For the connex board this can be achieved using the following ARM instruction.
  • 29.
    Global Variables  WhenC code is compiled, the compiler places initialized global variables in the .data section. So just as with the assembly, the .data has to be copied from Flash to RAM.  The C language guarantees that all uninitialized global variables will be initialized to zero. When C programs are compiled, a separate section called .bss is used for uninitialized variables. Since the value of these variables are all zeroes to start with, they do not have to be stored in Flash. Before transferring control to C code, the memory locations corresponding to these variables have to be initialized to zero. 29
  • 30.
    Read-only Data  GCCplaces global variables marked as const in a separate section, called .rodata. The .rodata is also used for storing string constants.  Since contents of .rodata section will not be modified, they can be placed in Flash. The linker script has to modified to accomodate this. 30
  • 31.
  • 32.
  • 33.
    The startup codehas the following parts 33 1.exception vectors 2.code to copy the .datafrom Flash to RAM 3.code to copy zero out the .bss 4.code to setup the stack pointer 5.branch to main
  • 34.
  • 35.
    Labs 35 HELLO WORLD FORBARE METAL On VersatilePB platform, that contains an ARM926EJ-S core
  • 36.
    Prerequisites  Download: Qemufrom https://qemu.weilnetz.de/w32/ GNU ARM Embedded Toolchain from https://launchpad.net/gcc-arm-embedded  THEN INSTALL THEM 36
  • 37.
    37 What is QEMU? − QEMU (short for "Quick EMUlator") is a free and open-source machine emulator and virtualizer written originally by Fabrice Bellard − Can emulate 80386, 80486, Pentium, Pentium Pro, AMD64 – from x86 architecture − PowerPC, ARM, MIPS, SPARC, SPARC64 − Work on FreeBSD, FreeDOS, Linux, Windows 9x, Windows 2000, Mac OS X, QNX, Android
  • 38.
    38 − Available CPUs: −arm1026 − arm1136 − arm1136-r2 − arm1176 − arm11mpcore − arm926 − arm946 − cortex-a15 − cortex-a8 − cortex-a9 − cortex-m3 − pxa250 − pxa255 − pxa260 − pxa261 − pxa262 − pxa270-a0 − pxa270-a1 − pxa270 − pxa270-b0 − pxa270-b1 − pxa270-c0 − pxa270-c5 − sa1100 − sa1110 − ti925t − any List of supported CPUs (ARM) $ qemu-system-arm –cpu ?
  • 39.
  • 40.
    40 QEMU Project “QEMU doesnot have a high level design description document - only the source code tells the full story”
  • 41.
    ARM system emulatedwith QEMU  qemu-system-arm is the software that emulates a VersatilePB platform For more information “VersatilePB physical Board’ http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dsi0034a/index.html  http://www.arm.com/products/tools/development-boards/versatile-express  http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0224i/index.html 41
  • 42.
    HELLO WORLD FORBARE METAL 42 tx RX You will need Cross Toolchain Makefile Linker Script .ld C Code files Startup.s Exectuable File Test.bin
  • 43.
    Lab: Steps  TheQEMU emulator supports the VersatilePB platform, that contains an ARM926EJ-S core and, among  other peripherals, four UART serial ports;  the first serial port in particular (UART0) works as a terminal  when using the -nographic or “-serial stdio” qemu option. The memory map of the VersatilePB board is implemented in QEMU in this board-specific C source;  note the address where the UART0 is mapped: 0x101f1000. 43
  • 44.
    44 there is aregister (UARTDR) that is used to transmit (when writing in the register) and receive (when reading) bytes; this register is placed at offset 0x0, so you need to read and write at the beginning of the memory allocated for the UART0
  • 45.
    Lab: Steps  TheQEMU emulator supports the VersatilePB platform, that contains an ARM926EJ-S core and, among  other peripherals, four UART serial ports;  the first serial port in particular (UART0) works as a terminal  when using the -nographic or “-serial stdio” qemu option. The memory map of the VersatilePB board is implemented in QEMU in this board-specific C source;  note the address where the UART0 is mapped: 0x101f1000. 45
  • 46.
    To implement thesimple “Hello world!” printing, you should write this test.c file: 46 volatile unsigned int * const UART0DR = (unsigned int *)0x101f1000; void print_uart0(const char *s) { while(*s != '0') { /* Loop until end of string */ *UART0DR = (unsigned int)(*s); /* Transmit char */ s++; /* Next char */ } } void c_entry() { print_uart0("Hello world!n"); } • The volatile keyword is necessary to instruct the compiler that the memory pointed by UART0DR can change or has effects independently of the program. • The unsigned int type enforces 32-bits read and write access.
  • 47.
  • 48.
    the linker scripttest.ld 48 ENTRY(_Reset) SECTIONS { . = 0x10000; .startup . : { startup.o(.text) } .text : { *(.text) } .data : { *(.data) } .bss : { *(.bss COMMON) } . = ALIGN(8); . = . + 0x1000; /* 4kB of stack memory */ stack_top = .; } .startup .text .data .bss Stack_top 0x1000
  • 49.
    49Create the binaryfile Go to GNU Tools ARM Embedded5.4 2016q3bin directory And open the CMD Console
  • 50.
    50Create the binaryfile Then run those commands Generate startup object file $ arm-none-eabi-as -mcpu=arm926ej-s -g startup.s -o startup.o Generate test object file $ arm-none-eabi-gcc -c -mcpu=arm926ej-s -g test.c -o test.o Invoke the linker and pass the linker script $ arm-none-eabi-ld -T test.ld test.o startup.o -o test.elf Generate binary file $ arm-none-eabi-objcopy -O binary test.elf test.bin interview
  • 51.
    To make surethe entry point at address 0x10000 Use the readelf Binary utilities 51
  • 52.
  • 53.
    To see thedisassembly Use the odjdump Binary utilities 53
  • 54.
  • 55.
    To run theprogram in the emulator 55 Go to qemu directory And open the CMD Console Copy the test.bin on the qemu folder then press this Command $ qemu-system-arm -M versatilepb -m 128M -nographic -kernel test.bin
  • 56.
    To Debug theCode  Using gdb, because QEMU implements a gdb connector using a TCP connection. To do so, run the emulator with the correct options as follows $ qemu-system-arm -M versatilepb -m 128M -nographic -s -S -kernel test.bin  This command freezes the system before executing any guest code, and waits for a connection on the TCP port 1234.  From ARM ToolChan terminal, run arm-none-eabi-gdb and enter the commands: 56
  • 57.
  • 58.
  • 59.
  • 60.
    List all preprocessordirectives in c programming language. 60
  • 61.
    DIFFERENCE BETWEEN CAND EMBEDDED C  Compilers for C (ANSI C) typically generate OS dependent executables. Embedded C requires compilers to create files to be downloaded to the microcontrollers/microprocessors where it needs to run. Embedded compilers give access to all resources which is not provided in compilers for desktop computer applications. 61
  • 62.
    DIFFERENCE BETWEEN CAND EMBEDDED C  Embedded systems often have the real-time constraints, which is usually not there with desktop computer applications.  Embedded systems often do not have a console, which is available in case of desktop applications.  So, what basically is different while programming with embedded C is the mindset; for embedded applications, we need to optimally use the resources, make the program code efficient, and satisfy real time constraints, if any. All this is done using the basic constructs, syntaxes, and function libraries of ‘C’. 62
  • 63.
    Embedded C Constrains Memory  Power  Size  Cost  Timing  CPU 63
  • 64.
    SW Should be Portable  Maintainable  Optimized  Reusable  Readable 64
  • 65.
    Embedded versus Desktop Programming Main characteristics of an Embedded programming environment: • Limited ROM. • Limited RAM. • Limited stack space. • Hardware oriented programming. • Critical timing (Interrupt Service Routines, tasks, …). • Many different pointer kinds (far / near / rom / uni / paged / …). • Special keywords and tokens (@, interrupt, tiny, …) 65
  • 66.
  • 67.
    Why Change toC  C is much more flexible than other high-level programming languages: • C is a structured language. • C is a relatively small language. • C has very loose data typing. • C easily supports low-level bit-wise data manipulation. • C is sometimes referred to as a “high-level assembly language”. ► When compared to assembly language programming: • Code written in C can be more reliable. • Code written in C can be more scalable. • Code written in C can be more portable between different platforms. • Code written in C can be easier to maintain. • Code written in C can be more productive 67
  • 68.
    How to makeCode more Readable 68
  • 69.
  • 70.
    2.memory-mapped devices Documenting thesource code is helpful not only for your future reference but for those who come after you. For instance, if you're working on an embedded system, you need to have a memory map indicating where all the memory-mapped devices can be found. Listing 8 shows an example of a memory map. 70
  • 71.
    Review: The “superloop” software architecture  Problem What is the minimum software environment you need to create an embedded C program?  Solution 71
  • 72.
    Review: An introductionto schedulers  Many embedded systems must carry out tasks at particular instants of time. More specifically, we have two kinds of activity to perform: • Periodic tasks, to be performed (say) once every 100 ms, and - less commonly - • One-shot tasks, to be performed once after a delay of (say) 50 ms. 72
  • 73.
  • 74.
  • 75.
    Header File  Each.h file should be “stand alone” ▫ It should declare, #define, and typedef anything needed by prototypes and include any .h files it needs to avoid compiler errors  In our example prototypes for CircleArea() and Circumference are placed in circleUtils.h ▫ circleUtils.h included in circleUtils.c ▫ circleUtils.h included in any other .c file that uses CircleArea() 75
  • 76.
  • 77.
  • 78.
    Separate Compilation  Ifcode is separated into multiple .c files ▫ Must compile each .c file ▫ Combine resulting .o files to create executable 78
  • 79.
  • 80.
    How to defineu8 ,u32,…. 80
  • 81.
  • 82.
    #pragma  The #pragmadirective gives special instructions to the compiler. The #pragma directive is especially useful in embedded C programming and can tell the compiler to allocate a certain variable in RAM or EEPROM. It can also tell the compiler to insert a snippet of assembly language code.  The GNU GCC compiler, which is a popular compiler for various embedded architectures such as ARM and AVR, also uses attributes as an alternative syntax to the #pragma directive. 82 #pragma GCC dependency allows you to check the relative dates of the current file and another file. If the other file is more recent than the current file, a warning is issued. This is useful if the current file is derived from the other file, and should be regenerated. The other file is searched for using the normal include search path. Optional trailing text can be used to give more information in the warning message.
  • 83.
  • 84.
    References 84  https://balau82.wordpress.com/2010/02/28/hello-world-for-bare-metal-arm-using-qemu/ https://balau82.wordpress.com/2012/03/31/compile-linux-kernel-3-2-for-arm-and-emulate- with-qemu/  https://balau82.wordpress.com/2010/02/14/simplest-bare-metal-program-for-arm/  http://infocenter.arm.com/help/topic/com.arm.doc.ddi0183f/DDI0183.pdf  https://balau82.wordpress.com/2010/03/10/u-boot-for-arm-on-qemu/  https://balau82.wordpress.com/2010/08/17/debugging-arm-programs-inside-qemu/  https://balau82.wordpress.com/2010/04/12/booting-linux-with-u-boot-on-qemu-arm/  https://balau82.wordpress.com/2010/03/10/u-boot-for-arm-on-qemu/  https://balau82.wordpress.com/2010/08/17/debugging-arm-programs-inside-qemu/  https://barrgroup.com/Embedded-Systems/How-To/C-Volatile-Keyword