Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { …...

Post on 14-Jan-2016

216 views 2 download

Tags:

Transcript of Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { …...

Embedded Systems

Programming Pattern

Generation of Code in Embedded Systemmain()

{ while (1) { … … … }}

main(){ while (1) { … … … }}

xxx.c , xxx.h

main(){ while (1) { … … … }}

main(){ while (1) { … … … }}

main(){ while (1) { … … … }}

main(){ while (1) { … … … }}

main(){ while (1) {

}}

main(){ while (1) {

}}

xxx.s

Iniitial codes

xxx.lds

memory address

Compilegcc –c xxx.s –o xxx.o

xxx.oxxx.oxxx.oxxx.o

// never return

Compile

xxx.oxxx.oxxx.oxxx.o

gcc –c xxx.c –o xxx.o

Linkld –T xxx.lds xxx.o xxx.o –o xxx.elf

xxx.elf

Generate ROM ImageObjcopy –O ihex xxx.elf xxx.hex

FlashROM

programmer

Memory Image of Embedded Processor

Interrupt VectorsInterrupt Vectors

ISRISR

Executive binaryExecutive binary

Variable data area

Variable data area

xxx.lds

memory address is given by

xxx.ldsROM

RAM

FlashROM

RAM

CPU

Startup method(Run from ROM)

First instruction executed is in

address 0Jump to

initialization codes

Jump to entry of C code——main()

ROM

First instruction executed is in

address 0

Function of Initiation Codes

•Set SP registers ( Stack)•Copy ROM data to RAM•Jump main()

Startup method(Run from ROM)

ROM

RAM

Startup method(run from ROM)

ROM

sp

RAM

RAM allocation

•SP pointer to stack space•Ensure stack pointer won’t invade heap area•use LDS file to define RAM allocation scheme

堆栈空间

数据空间

First instruction executed is in

address 0

Startup method(Run from RAM)

1. Copy itself and ROM data to RAM

2. Jump to entry point in RAMROM

RAM

First instruction executed is in

address 0

Startup method(Load Executable image to RAM and

execute)

1. Copy external data into RAM

2. Jump to the entry of executable binary

ROM

RAM

External Storage ( SD Card 、 USB

Disk 、 Network IF)

External Storage ( SD Card 、 USB

Disk 、 Network IF)

First instruction executed is in

address 0

Why run from RAM• Faster• Dynamically load executable codes• multi-task/thread/process

Run from ROM• need less RAM space• reliable

• low cost simple, high reliable. low cost simple, high reliable. control oriented code often control oriented code often run from ROMrun from ROM

• program with complex GUI program with complex GUI and complex application and complex application often run from RAMoften run from RAM

Memory Management

• Static allocation

• User defined management methods

Static memory allocation

• pre-defined global variables•Static variable within a function

u8 buffer[8192]; // a 8KByte Buffer Spacevoid func(){ static u8 str[128]; …}

Dynamically allocate memory

• Using malloc/free (require C run-time library support)

• Write simple memory management code

Manage memory in fixed block

size

Free NodeList

Block

Block

Block

Block

Block

User Data List 1

Block

Block

Block

User Data List 2

Block

Block

Support different

block size

Free NodeList 1

Block

Block

Block

Block

Block

Free NodeList 2

Block

Block…

Memory management function

• format()

Construct link list for all memory block

• get_mem_block()

Obtain an idle memory block from the line

• free_mem_block()

release a memory block ,return it to the memory link list

Implementation of Malloc function

初始状态

validsize

Initial stateAllocated a block

Initial state Allocated a block

Allocated another

Return one block

Initial state Allocated a block

Allocated another

Flowchart of malloc function

Find the memory block large enough for allocation

Find the memory block large enough for allocation

found?found?

fragment combinationfragment combination

find memory block large enough for allocation

find memory block large enough for allocation

found?found?

return memory pointer

return error

yes

No

No yes

Data exchange between device driver and Application program

INT signal

Interrupt

Applications

Data exchange methods

• Shared buffer

• Ring buffer

• Link list

Data exchange between device driver and Application program

INT signal

ISR

Application

Shared Buffer

Data exchange by shared buffer

Data

Data length

INT signal

ISR

Application

Data exchange between device driver and Application program

INT signalISR

Application

Ring Buffer

Data exchange between device driver and Application program

INT signalISR

Application

Ring Buffer

Data exchange between device driver and Application program

length of data block

data block

read pointer

write pointer

Data exchange between device driver and Application program

INT SignalISR

Application

Linked List

Data exchange between device

driver and Application program

data

pointer

data

pointer

data

pointer

remove from the linked

list

add to the linked list

pointer

Requirement to the embedded program

• Periodical

• Multi-task

• Real-time response

Example: Embedded data recorder

Tasks• Sample analog in fixed (high)

frequency• Output Control Signal• Accept User inputs• Update display

time

tasks

Cyclic Execution

void main(){ while (1) { measure(); check_user_input(); measure(); control_output(); measure(); display_and_store();

measure(); control_output(); } }

Cyclic Execution

• Frequency of each task (function) is fixed

• difficult to adjust period• Response time is given

by the slowest task(function)

void main(){ while (1) { measure(); check_user_input(); measure(); control_output(); measure(); display_and_store();

measure(); control_output(); } }

Adjust sample rate

int meaure_data(){ static last_sample_time;

while (get_time () % sample_period) ;

return read_data();}

// Ensure sample at time grid

INT controlled analog signal sampling

void main(){ while (1) { check_user_input(); control_output(); display_and_store();

control_output(); } } timer_ISR()

{ measure();}

Mix mode• Realtime operation is implemented by ISR

• un-realtime operation is implemented in main loop

Example : Measure and analysis instrument with GUI

GUI

measurementSample clock INT

Shared Memory

split slow operation for

realtime execution

slow_operation(){ static current_phase = SPHASE_1;

switch (current_phase){case PHASE_1:

operation_1();

current_phase = PHASE_2;

break;case PHASE_2:

operation_2(); current_phase = PHASE_3;

break;case PHASE_3:

operation_3(); current_phase = PHASE_1;

break;}return;

}

PHASE_1 PHASE_2

PHASE_3

slow_operation(){ operation_1(); operation_2(); operation_3();}

Structure of event driven program

ISR(Detect user inputs)

ISR(Measure)

ISR(Update display)

INT of high frequency timer

Button INT

INT of low frequency timer

// main loopvoid main{while(1);}

Event listmain( ){ while (1) { if (there is pending event in list) { Get_event(); Process_event(); }

}} ISR_1()

{ Add_event_to_list(); }

ISR_2(){ Add_event_to_list(); }

ISR_3(){ Add_event_to_list(); }

Event List

Event list with prioritymain( ){ while (1) { if (there is pending event in lists) { Get_event(); Process_event(); }

}} ISR_1()

{ Add_event_to_list(); }

ISR_2(){ Add_event_to_list(); }

ISR_3(){ Add_event_to_list(); }

Event Lists

high priority

( get event from no-empty list with highest priority)

low priority

Event list with time information

main( ){ while (1) { if (first clock time out)

{ Execute event list

on 1st clock; take off 1st clock;

}}

}

Time_ISR (){ update 1st clock;}

Programming requirement of ISR

• Fast and high efficiency

• If not fast enough?

Consider put data processing into mainloop, while ISR focus on data receive and send

ISR and data processingmain()

{

while (1)

if (Buffer is full)

{

Data processing; Clear buffer full flag;

}

}

ISR()

{

if (Buffer is empty)

{

Fill Buffer with data;

Set buffer full flag;

}

}

data

data length (flag)

Buffer

Structure of event driven program(polling mode)

While (1){

switch (Read_IO_Event()){case EVEN_A:

Event_A_Handler( );break;

case EVEN_B:Event_B_Handler( );break;

case EVEN_C:Event_C_Handler( );break;

}}

SystemIOAIOBIOC Event_A_Handler()

{ … }

Event_B_Handler(){ … }

Event_C_Handler(){ … }

IO priority is determined by Read_IO_Event function

FSM programming

State 0Output 0

State 1Output 1

State 2Output 2

State 3Output 3

State 4Output 4

State 5Output 5

Input A

Input A

Input A

Input BInput C

Input B

Input C

Input C

Input A

Input AInput B

Input C

Input B

while (TRUE){ Input = Get_IO_Data();

Switch (State){case STATE_A: State = Data_Processing_for_State_A( Input );

break;case STATE_B: State = Data_Processing_for_State_B( Input );

break; case STATE_C: State = Data_Processing_for_State_C( Input ); break;}

}

DataProc.

output Input

FSM programming

Device Driver

Function

• Initialize device

• Data receive and transmit

• Device driver without ISR– may lost data

• Device driver with ISR– Need data receiving buffer

Device Driver without ISR ( Pool Mode)

Char get_data_block_mode() { while (*IO_port_status==EMPTY); return *IO_port;}

char get_data_non_block_mode() { if (*IO_port_status==EMPTY)

return INVALID_DATA; else

return *IO_port;}

Device Driver without ISR ( Pool Mode)

void send_data_block_mode(data) { while (*IO_port_status==BUSY); *IO_port=data;}

int send_data_non_block_mode(data) { if (*IO_port_status==BUSY)

return FALSE;*IO_port=data;return TRUE;

}

Device Driver with ISR ( Rec

eive data)Rx

ControllerHardware FIFO

CPU

IRQ

ISR

ApplciationBuffer

API

Device Driver

Device Driver with ISR ( Receive data)

• ISR(){ data=IO_port_read(); put_to_buffer(data);}

• read_data(){ if (buffer_empty) return INVALID_DATA; return get_from_buffer();}

Device Driver with ISR ( Sen

ding data)

Tx Controler

Hardware FIFO

CPU

IRQ

ISR

Application

Buffer API

Device Driver

Device Driver with ISR ( Send data)• ISR()

{ if (buffer_empty()) return; data=get_from_buffer(); IO_port_send(data);}

• write_data(){ if (buffer_full()) return FALSE; return put_to_buffer(data);}

• Flush_transmitter_buffer(){ while(!buffer_empty()); }

Start transmitting of 1st data

• Data transmitting is continued by ISR triggled by previous “data sent” INT

• The first data transmission should be manually started

• write_data(data){ if (buffer_full()) return FALSE; fill_data(); if (device_idle()) transmit_first_data(data); return;}

FIFO Half Full/Empty

ISR_FIFO_Half_Empty(){ feed data to Tx FIFO; }

ISR_FIFO_Half_Empty(){ fetch data from Rx FIFO; }

Tx FIFO Rx FIFO

ISR design requirement

• Return——No return value

• Speed——as fast as possible

• Can we reenter ISR (allow INT nest?)

Data Tx/Rx by timer

ISR

Tx Controller

FIFO

CPU

ISR

Application

Buffer API

Device Driver

Methods to increase efficiency of ISR

• Batch data transfer——DMA

• Simple memory management scheme

• Implement least work, leave remaining's to the mainloop

• Allow INT nest for higher priority INT