Programming in C for ARM

27

I will start a project in C that will have as a% of a board Colibri T20 processor with NVIDIA Tegra 2 ARM , running a lightweight version of Linux.

I would like to know if, in addition to having to use a processor-compatible cross compiler, I need to be concerned about some other specific ARM architecture.

From what I read, it looks like the processor architecture only matters if I'm programming in Assembly. Am I wrong?

I do not know if it's relevant, but my target is Ubuntu 12.04 (Linux).

    
asked by anonymous 20.12.2013 / 18:54

6 answers

21

You're right. My observation is that there is a misconception among many developers that porting C software to a new architecture is difficult. Unless it refers to the type of programming found in operating systems, this simply is not true.

The kernel makes much of the abstraction of hardware components, so that software can often be compiled into one architecture and another without problem. I can think of some examples, though, when this is not so easy:

  • Whether the software depends on another proprietary software that can not itself be ported. The vast majority of software on Linux uses libraries that are already open source, so usually this is not a problem.
  • Whether the software contains architecture-specific optimizations. An example: The x86 architecture has the MMX and SSE extensions, among others, whose specific use can not be ported directly. While it is a concern, this really is rare because usually the software uses a library that uses these special features. An example would be a library that does video processing. In x86 the library would use this extensions, but in Arm the library would use other extensions that only exist there. The library then takes on the responsibility of porting the implementations to new architectures, the software that uses it does not have to worry about how.
  • Whether the software directly handles specific hardware to a system. It is usually the job of the kernel to do this, but I personally have already found software that requires certain devices to be available on the system, so the software does not do very well. Usually this can be fixed by changing this specific hardware dependency with the use of a library that provides the same functionality across multiple architectures.

In addition to these exceptions of which should be aware, almost all software in C port new architectures on the operating system table without problem because, as Guilherme said in his comment, it is the work of the compiler to adapt the code the right way for each architecture, rarely with the intervention of the programmer.

    
22.12.2013 / 11:40
9

As said, in theory yes, but in practice it is difficult to achieve such portability. Since you are using a large-scale embedded operating system, this facilitates things, but this becomes different when you are using less widespread systems between architectures, or even no operating systems.

As Assembly is one of the lowest level languages, you have great control over the generated code, so it's not uncommon to use Assembly in-line together with C for example.

See this quote from link

  

The problem is exacerbated by the fact that the C Language was not   designed for Harvard architectures, it was designed for Von Neumann   architectures where code and data exist in the same address space.   This means that any compiler is a Harvard architecture processor,   like the AVR, has to use other means to operate with separate address   spaces.

Free translation:

  

The problem is evident from the fact that the C language was not   designed for Harvard architecture, it was designed for architectures   of Von Neumann in which code and data exist in the same address space.   This means that any compiler for Harvard architectures, such as   AVR, need to use other means to operate with address spaces   separated.

In this case we use extensions to standard C to store literals in program memory, which in theory is not common in Harvard architectures.

  

From what I read, it looks like the processor architecture only matters if I   you are programming in Assembly. Am I wrong?

Even in Assembly it is possible to have an abstraction layer. Ex: Calling software interrupts implemented by the operating system, so that it abstracts.

Note: This answer does not consider using Linux as OS, but rather more portability.

>     
24.12.2013 / 13:22
7

Not necessarily agreeing or disagreeing with colleagues, I'd rather go by another line: it depends.

Depends on the type of application you want to do. Essentially, as already mentioned, the compiler must translate from the C language to the target target instruction set, regardless of the architecture used. If you use compilers that support the ANSI C pattern (as gcc ), the language C itself and the POSIX functions can be written perhaps, without any difference between the platforms.

But in addition to the set of instructions, there are other differences between desktop x86 (which I'm assuming you have experience) and a ARM architecture. I will also assume that in both cases you use Linux:

  • Embedded hardware : The hardware available for processing is more limited: you have less primary memory and less "processing power."

  • Energy Consumption : Depending on the product you are going to do, you should excel at meeting some power consumption requirement.

  • Peripherals : Basic peripherals, such as USB, should be used in the same way on both platforms, since it is the function of the OS and modules to deal with them and provide APIs for the programmer. But you may need to access some other peripheral on a low-level access (such as using an SPI or I2C protocol - which is very common in an embedded system), and this should be different on an ARM platform than an x86 platform.

  • Graphics Acceleration : A very different feature of an ARM system for a traditional PC is graphic acceleration. Generally on ARM systems only OpenGLES (Embedded System ES) is available. OpenGLES is different from traditional OpenGL. Writing an application that uses graphical acceleration for ARM is certainly different than writing one for an x86 PC.

  • APIs, libraries, and other software : You should be aware of and do a survey of the external libraries and software and APIs you will use, they work correctly on the device you are going to use.

In general, in my experience, these are the characteristics that most differentiate systems. The difference, in my opinion, goes beyond the set of instructions of the processors: although the software abstractions try to hide the architecture of the system and leave everything "transparent" to the programmer via the same APIs, the "ecosystem" that involves ARM is different from x86. I never needed to care about the instruction set itself. If you do not need to make an ultra-optimized application for this platform, you should not have to care about the instruction set either.

UPDATE:

@AlexandreMarcondes recalled in the comments on endianess different from both platforms. In his words:

  

It also has the issue of memory access (little endian and big endian), also called endianess. This is the order that the platform (processor) stores numbers larger than 1 byte, whether or not there is order inversion

Knowing endianess is really important for C programming especially if the programmer uses union in its code or if it transmits data to other peripherals or devices over the network.

    
07.01.2014 / 13:03
2

Do not forget the ABI convention. For example, in EABI ARM you do not send swi [syscall number] , but you have to use register n ° 7 to load the desired syscall number, while the registers below it (% with% to r0 ) are used to load the syscall arguments. And finally, you only send r6 . Example of writing an output:

mov r0, #1 @ stdout, 0 p/ stdin e 2 p/ stderr
ldr r1, = [label da string ascii]
ldr r2, = [label do length da string acima]
mov r7, #4 @ syscall p/ write
swi #0 @ chama o software interrupt

You can search more on PDFs found on the ARM website about ARAB EABI and APCS as this .

    
09.01.2014 / 06:42
2

I recently ported the code from a linux-x86-i382 application to linux-armv8, the portability difficulty depends a lot on your application, in the end, ideally using clean interfaces and leaving code that has dependency of separate architecture into a folder or a file.

In general, the parts of code that are most likely to present errors are parts of IO (files and network), encryption, and checksum, has, etc. The main points that usually cause problems are:

  • Integer size: If you intend to port your code to different platforms, never assume size for integers, for example, a package defined by:

    struct packet {
        int a;
        int b;
        int c;
        int b;
    }
    

It will have different sizes in both 64-bit and 32-bit architectures, which will, if this structure is used in a network map, the two computers will not be able to communicate. The solution to this is to use (c ++) or (c) where you can use types that specify the integer size: uint8_t, int16_t, etc.

  • Endianess: If you are going to use multiple-byte types, big endian architectures write the bytes in the reverse order of little endian architectures. You have to treat the two codes differently. In this case, there is no trivial solution. One way is to treat all input bytes as single bytes and retrieve multiple-byte structures later, for example:

    Little Endian:
    uint32_t a = 0x1234567890,big_a = 0;
    for(uint8_t i=0; i<4,i++)
        big_a += ((a>>(24-8*i))&0xff) << (8*i);
    send(big_a);
    
    Big Endian:
    a=receive();
    

It is important to note that, according to RFC1700 , the bytes must be transmitted over the network in a Big Endian fashion. However, if you are implementing your own protocol, either, as long as one of the two sides converts the bytes that you received, you have a IBM article on how to deal with endianess.

    
14.02.2014 / 02:20
1

Depends on the application. If programming is done using APIs that are already available, chances are you will not encounter many problems that have been resolved before. But even with APIs if you have to deal with device drivers it is good to know at least the endianess since in C we have the pointers to break any rule and your platform has many devices to worry about. You also need to know the set of instructions that will be used to inform the ARM compiler, Thumb, Thumb2. Does your ARM have FPU going to enable this?

There are also several toolchains available for ARM. arm-none-eabi (no OS support, bare-metal), arm-linux-eabi (Linux), and so on.

    
11.01.2014 / 03:33