DOC

EmbeddedSW_MP+WLZ

By Melissa Thompson,2014-05-11 16:25
10 views 0
EmbeddedSW_MP+WLZ

Embedded Software for Mobile Phone By Wanglingzhi

Mobile Phone "Playground"

    1.) What we have and what we don't...

     We typically don't have

     enough memory (it's expensive)

     enough MIPS (it's expensive, uses too much power)

     enough energy (battery operation)

     good tools (they just don't exist…)

We have

     huge volumes and too high FFR's (Field Failure Rate)

     threat to lose our leading position every day

     chronic competition against time

2.) Flash memories

     Increase the size of memory = increase cost (2000Y)

     FLASH 16M -> 32M +3.5 USD

     UPP-RAM 2M -> 4M +1.5 USD Memories are the most expensive parts in total cost. If we take top 20 most expensive

    components memories are covering 25% of the costs.

     A good reason to write as optimal code as possible?

3.) FFR

     FFR = Field Failure Rate

     Cost per returned phone in US is about $XX. This means that cost for SW upgrade is $XX. During

    warranty period there can be several new SW releases…

     How about YOU taking a challenge to reduce SW FFR by 1% / product. What kind of bonus could

    you ask from your boss if you succeed :)

Interface to HW

     Unfortunately we still need some HW to run SW... :)

SW interface to HW is more or less SW interface to our ASIC registers that are memory mapped.

    We have several ASICs and each of them contain hundreds of registers. Fortunately there is also a

    lot that is common and portable.

When coding some HW interface functionality

verify that ASIC specs you are using are up to date

     read and understand those specs

     notice that also specs may have bugs...

     then go ahead and design, implement, test…

     and find them bugs… in ASIC (hopefully not; long and expensive bug fixing circle), in

    ASIC specs or in your code

     maybe there is no bugs... if everyone has done everything correctly from the beginning…

    1.) Latency

     means time from your controlling command to actual validity of command in HW there is always some latency!

     typically latency is so short that it causes no problems

     when it causes problems, then problems are typically tricky to find and avoid causes wasting of processor power - sometimes you need to poll until given command is

    valid in HW.

     sometimes there is not even a status flag to be polled, you just have to know how long you

    need to wait...

    

OS controlled statemachines (=tasks)

     Idle again...

     State message, machine event B

    External

     stimulus State

     machine C

     State

     machine

     D

     Stimulus State handlinmachine Idle, saving power g i.e running E

     Activation of each state machines i.e. tasks is taken care by operating

    system

In scheduling (done by OS) active tasks are run in their priority order

     If there is no active tasks then idle task is run

     Idle task typically drives HW and SW to power saving mode

     External input (interrupt) wakes system from power save state

'Clever' Codes?

What does following code do?? Is this code easy to maintain?

     register n = (count + 7) / 8; „Clever‟ code may work OK and may

    generate small object but is quite /* count > 0 assumed */

    impossible to debug and maintain.

    Compiler may also fail with exotic code switch (count % 8)

    structures.

     Actually simple code is clever. It's easy to

    maintain, re-use and modify when needed.

     {

     case 0: do { *to = *from++;

     case 7: *to = *from++;

     case 6: *to = *from++;

     case 5: *to = *from++;

     case 4: *to = *from++;

     case 3: *to = *from++;

     case 2: *to = *from++;

     case 1: *to = *from++;

     } while (--n > 0);

     }

Maintainable code

     Write maintainable code:

     simple, easy to understand

     easy to reuse/modify

     well structured, well documented

     portable

     no C tricks!

     let compiler do the optimization

     optimize on structural and design level, not line by line in implementation Don‟t forget to make also the unit test environment maintainable!

Portable code

Write portable code:

     don't use bitfields: size and order of bits varies

     don‟t rely on alignment (explained later) of variables: may be 8, 16 or 32 bits

     make endianess (explained later) independent code

     structures may have "holes" e.g. byte padding (explained later) inside or after structure due

    to structure alignment

     sizeof may return different value for structures on different processors due to holes and fill

    bytes added

     sizeof -however always gives the correct size of a structure on any processor Reference Ttd00typ.h for common type declaration:

#define BYTE unsigned char

    #define WORD16 unsigned short

    #define WORD32 unsigned long

    #define INT short int #define LONGINT long #define BOOL BYTE #define WORD WORD16 #define LONGWORD WORD32 #define U8 BYTE #define u8 U8 #define U16 WORD16 #define u16 U16 #define U32 WORD32 #define u32 U32 #define S8 char #define s8 S8 #define S16 INT #define s16 S16 #define S32 LONGINT #define s32 S32 #define t_Return BYTE

    #define CONST const Variable types

Following types should be used: Statically located in RAM, visible Int must not be used because its size is compiler dependent! globally to all linked objects. Be sure that name is unique and follow naming Variable locating in module conventions.

     Statically located in RAM, visible only inside this compilation module i.e. U8 call_status; inside the C file you are compiling. static U8 xbus_status; If your C function is not needed outside your compilation module (i.e. it is not LOCAL void xbus_send_msg(BYTE * global) add keyword "LOCAL" msg) (definition to static) it saves code. { static U16 send_counter; U8 tmp_counter; . Statically located in RAM, visible only . inside this function. Value is kept when . exiting and re-entering function } Located into stack (RAM), visible only

    inside this function. Value is unknown

    when entering and after exiting

    function

According to ANSI C all uninitialized statically located variables are cleared (filled with 0) in

    startup

     When entering the function you never know the contents of stack variables

Const

     Const means two things:

     read only, contents can not be changed.

     placed in ROM area instead of RAM.

Usage of const with pointers:

     BYTE* pntr; /* read-write pointer to read-write byte variable or array */

     const BYTE * pntr; /* read-write pointer to read-only byte variable or array */

     BYTE * const pntr; /* read-only pointer to read-write byte variable or array */

     const BYTE * const pntr; /* read-only pointer to read-only variable or array */

=>Use "const" to save RAM whenever you have initialized truly constant variable, array or

    structure.

Static & Const

Use always static with const table inside a function body

     u32* pow10( u8 exponent )

     {

     static const u32 powers_of_ten[ ] =

     {

     1, 10, 100, 10000, 100000

     };

     return( powers_of_ten[ exponent ] );

     }

     Why?

     without „static‟, contents of table is copied from ROM to stack whenever the function is

    called instead of keeping table only in ROM.

Alignment

Microprocessors operate with different “natural” sizes of data items. The terminology used to

    describe these items is not standardized.

     The common types are

     8-bit values (byte, octet)

     16-bit values (word, short, halfword)

     32-bit values (word, long)

     The interface between the microprocessor and the memory is designed differently from processor to

    processor. This puts restrictions of the positioning of the data items on some processors. H8: 8-bit values on any address. 16-bit values on even addresses. 32-bit values on even addresses. ARM:8-bit values on any address. 16-bit values on even addresses. 32-bit values on addresses

    divisible by 4.

Alignment of 16-bit entities

16-bit entities must be located on even addresses.

     0 1 2 3

     0 1 2 3

     BUS ERROR!

     0 1 2 3

One way of causing a bus error is to initialize pointer in a wrong way

     Other example is abusing of cast operation. By casting a character i.e. byte pointer to a word or dword

    pointer and trying to read/write with that. Pointer can point to an odd memory location and cause a bus

    error

Alignment and 32-bit entities

How to avoid alignment problems for 32-bit entities. Declare messages to 32-bit items start on

    addresses divisible by 4.

     3 0 1 2 4 5 6 7

     0 1 2 3 4 5 6 7

    BUS

     ERROR!

     0 1 2 3 4 5 6 7

     BUS ERROR!

    0 1 2 3 4 5 6 7

     BUS

     ERROR!

     0 1 2 3 4 5 6 7

Alignment summary

     In your module and/or function first declare possible structures, then pointers, then words (16-bit

    elements) and bytes last.

     Why?

     you will minimize wasting of memory caused by padding The very same rule also applies when specifying the contents of a structure

{word xx;

    byte yy; //Padding word zz;

    byte ww}; //Possible Padding.

{word xx;

    word zz;

    byte yy;

    byte ww}; //No Padding.

    SO WHY:

    typedef const struct mcc_s {

     u8 v_ctrl_code;

     u8 v_attrib1;

     u8 v_attrib2;

     MC_PCC_FILL_STRUCT1

     u16 v_attrib3;

     u16 v_attrib4;

     const struct mcc_s *p_link;

     u16 v_attrib5;

     MC_PCC_FILL_STRUCT2

    } t_mcc;

     If you are specifying mobi-msg messages be extra careful with this. Notice the type of message

    element (i.e. word, pointer, structure…) you are specifying and it's restrictions to begin address. To

    increase the challenge: there can also be a different type of processor in the message receiving end...

     MC_PCC_HEADER( PROCESS_MMI, PROCESS_HSC, MOBI_LCD_CURSOR_REQ,

    MC_RTK_PROCESS_OPERATION( PROCESS_HSC, F_LCD_CURSOR_REQ ) )

     MC_PCC_BEGIN_STRUC( t_LcdCursor )

     MC_PCC_FIELD( u32, v_AreaId )

     MC_PCC_FIELD( u32, v_Type )

     MC_PCC_FIELD( u32, v_Position )

     MC_PCC_END_STRUC( t_LcdCursor )

    ?MC_PCC_BEGIN_API_STRUC( t_MsgHeader, StrucName)

     To summarize:

     ARM requires 32-bit on 4-byte boundaries

Report this document

For any questions or suggestions please email
cust-service@docsford.com