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

58
Embedded Systems Programming Pattern

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

Page 1: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

Embedded Systems

Programming Pattern

Page 2: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

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

Page 3: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

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

Page 4: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

Startup method(Run from ROM)

First instruction executed is in

address 0Jump to

initialization codes

Jump to entry of C code——main()

ROM

Page 5: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

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

Page 6: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

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

Page 7: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

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

Page 8: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

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

Page 9: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

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

Page 10: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

Memory Management

• Static allocation

• User defined management methods

Page 11: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

Static memory allocation

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

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

Page 12: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

Dynamically allocate memory

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

• Write simple memory management code

Page 13: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

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

Page 14: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

Support different

block size

Free NodeList 1

Block

Block

Block

Block

Block

Free NodeList 2

Block

Block…

Page 15: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

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

Page 16: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

Implementation of Malloc function

初始状态

validsize

Page 17: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

Initial stateAllocated a block

Page 18: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

Initial state Allocated a block

Allocated another

Page 19: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

Return one block

Initial state Allocated a block

Allocated another

Page 20: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

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

Page 21: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

Data exchange between device driver and Application program

INT signal

Interrupt

Applications

Page 22: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

Data exchange methods

• Shared buffer

• Ring buffer

• Link list

Page 23: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

Data exchange between device driver and Application program

INT signal

ISR

Application

Shared Buffer

Page 24: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

Data exchange by shared buffer

Data

Data length

INT signal

ISR

Application

Page 25: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

Data exchange between device driver and Application program

INT signalISR

Application

Ring Buffer

Page 26: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

Data exchange between device driver and Application program

INT signalISR

Application

Ring Buffer

Page 27: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

Data exchange between device driver and Application program

length of data block

data block

read pointer

write pointer

Page 28: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

Data exchange between device driver and Application program

INT SignalISR

Application

Linked List

Page 29: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

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

Page 30: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

Requirement to the embedded program

• Periodical

• Multi-task

• Real-time response

Page 31: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

Example: Embedded data recorder

Tasks• Sample analog in fixed (high)

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

time

tasks

Page 32: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

Cyclic Execution

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

measure(); control_output(); } }

Page 33: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

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(); } }

Page 34: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

Adjust sample rate

int meaure_data(){ static last_sample_time;

while (get_time () % sample_period) ;

return read_data();}

// Ensure sample at time grid

Page 35: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

INT controlled analog signal sampling

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

control_output(); } } timer_ISR()

{ measure();}

Page 36: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

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

Page 37: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

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();}

Page 38: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

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);}

Page 39: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

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

Page 40: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

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

Page 41: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

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;}

Page 42: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

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

Page 43: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

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

Page 44: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

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

Page 45: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

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

Page 46: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

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

Page 47: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

Device Driver

Function

• Initialize device

• Data receive and transmit

• Device driver without ISR– may lost data

• Device driver with ISR– Need data receiving buffer

Page 48: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

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;}

Page 49: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

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;

}

Page 50: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

Device Driver with ISR ( Rec

eive data)Rx

ControllerHardware FIFO

CPU

IRQ

ISR

ApplciationBuffer

API

Device Driver

Page 51: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

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();}

Page 52: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

Device Driver with ISR ( Sen

ding data)

Tx Controler

Hardware FIFO

CPU

IRQ

ISR

Application

Buffer API

Device Driver

Page 53: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

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()); }

Page 54: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

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;}

Page 55: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

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

Page 56: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

ISR design requirement

• Return——No return value

• Speed——as fast as possible

• Can we reenter ISR (allow INT nest?)

Page 57: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

Data Tx/Rx by timer

ISR

Tx Controller

FIFO

CPU

ISR

Application

Buffer API

Device Driver

Page 58: Embedded Systems Programming Pattern. Generation of Code in Embedded System main() { while (1) { … } main() { while (1) { … } xxx.c , xxx.h main() { while.

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