Symbian
 Developer Library

DEVELOPER LIBRARY

[Index] [Glossary] [Previous] [Next]



The native build targets

Symbian OS natively runs on ARM processors. It supports three form of ARM executable code, termed Application Binary Interfaces (ABIs), called ARM4, ARMI, and THUMB.

The BX instruction deals with changing from ARM mode into THUMB mode. The "using BX" comment indicates that the ABI in question (ARMI and THUMB) is compiled so that it is capable of interworking with code in either mode of the ARMv4T instruction set, and will switch automatically to the right mode when calling a function or returning back to the caller.

Operating system code for ROMs may be compiled with any of the ABIs. Projects built for ARMI will work with code built in any of the three ABIs, and ARMI is therefore the recommended choice for ISVs and third parties.

Code for native targets can be built from the command line, and from the CodeWarrior IDE. In either case, the Cygnus GCC toolchain installed as part of the development kit is invoked.

The remainder of this topic notes some distinctive issues when coding and running on native targets.


Machine word alignment

ARM uses a 32-bit RISC architecture with minimal extra silicon for unnecessary control purposes. This is the main reason why the chip is so cheap, and uses so little power, which in turn is why it is so popular for battery-powered consumer devices.

One consequence of this is that 32-bit quantities must be aligned to a 32-bit machine word boundary — in other words, their address must be a multiple of four. So, for instance, the following code

TInt* p; // pointer to integers
...
TInt i=*p; // get from a pointer

will only work if p is a multiple of four at the time it is used. If p is not a multiple of four, an access violation will result.

For normal purposes, this restriction is transparent to the programmer, because struct and class members are aligned appropriately by the compiler and heap allocator. For example, in

struct S
    {
    TText8 iText; // offset 0, 1 byte
    TText8 iText2; // offset 1, 1 byte
    TInt32 iInteger; // offset 4, 4 bytes
    };

the second byte quantity is aligned at offset 1, which is ok for bytes. But the compiler generates two pad bytes in order to align the integer at offset 4. Therefore, sizeof(S) is 8, not 6 as might be expected. The compiler ensures that all quantities are aligned, whether in structs or C arrays.

You must be aware of the alignment restriction, however, if you are implementing a packed structure of some kind. For instance, the code

TText8 array[200];
for (TInt i=0; i<=196; i++)
    {
    TInt* p=(TInt*) array[i]; // needs a cast
    TInt n=*p; // four bytes from the array makes one integer?
    }

will work under WINS and will compile with gcc. But it will generate an access violation the second time through the loop, because p will be one greater than a multiple of four.

To bypass this problem, you should do something like

TText8 array[200];
for (TInt i=0; i<196; i++)
    {
    TAny* p=array[i]; // really a TAny*, so no cast needed!
    TInt n;
    Mem::Copy(&n, p, sizeof(TInt)); // copy byte by byte
    }

In a way, C++’s type system supports the programmer here. The packed structure can only be implemented by using casting. When you do a cast, you must always think about what might be the potentially dangerous consequences. In the ARM environment, machine word alignment is a potentially dangerous consequence that you must always bear in mind. On the other hand, when you are not using casts, the compiler will do all that is necessary to ensure machine word alignment, without programmer intervention.

[Top]


Timer

On emulator targets, standard timer resolution is 1/10th second. Under ARM, it is 1/64th second. Under both platforms, an After() timer request is effectively rounded upwards to the machine’s timer resolution. Also, there is a minimum wait of one tick.

Therefore, animation as used for games and other special effects must be carefully controlled for each platform.

The differences in standard timer resolution do not matter so much for communications and other time-out purposes, where a coarser grain is often acceptable. On the other hand, some protocols are much more demanding, in which case a higher-resolution time service must be used.