Search code examples
carmqemu

qemu-arm with Cortex-M4 on Linux


I am using qemu-arm and the ARM Workbench IDE to run/profile an ARM binary which was built with armcc/armlink (an .axf-File, program written in C). This works fine with Cortex-A9 and ARM926/ARM5TE. However, whatever I tried, it doesnt work when the binary is built for Cortex-M4. Both the simulator and qemu-arm hang when M4 is selected as CPU.

I know that this processor requires some additional startup code, but I could find any comprehensive tutorial on how to get it running. Does anyone know how to do this? I have a quite big project with one main function, but it would already help if a "hello world" or some simple program which takes arguments would run.

Here is the command line I am using with Cortex-A9:

qemu-system-arm -machine versatileab -cpu cortex-a9 -nographic -monitor null -semihosting -append 'some program arguments' -kernel program.axf

Solution

  • I do not know how to do it with the versatilepb, it did not "just work", but this does work:

    flash.s

    .thumb
    .thumb_func
    .global _start
    _start:
    stacktop: .word 0x20001000
    .word reset
    .word hang
    
    .thumb_func
    reset:
        bl notmain
        b hang
    
    .thumb_func
    hang:   b .
    
    .thumb_func
    .globl PUT32
    PUT32:
        str r1,[r0]
        bx lr
    

    notmain.c

    void PUT32 ( unsigned int, unsigned int );
    #define UART0BASE 0x4000C000
    int notmain ( void )
    {
        unsigned int rx;
        for(rx=0;rx<8;rx++)
        {
            PUT32(UART0BASE+0x00,0x30+(rx&7));
        }
        return(0);
    }
    

    flash.ld

    ENTRY(_start)
    
    MEMORY
    {
        rom : ORIGIN = 0x00000000, LENGTH = 0x1000
        ram : ORIGIN = 0x20000000, LENGTH = 0x1000
    }
    
    SECTIONS
    {
        .text : { *(.text*) } > rom
        .rodata : { *(.rodata*) } > rom
        .bss : { *(.bss*) } > ram
    }
    

    (I am told the entry point being a thumb function address is critical YMMV)

    arm-none-eabi-as --warn --fatal-warnings -mcpu=cortex-m3 flash.s -o flash.o
    arm-none-eabi-gcc -Wall -O2 -ffreestanding -mcpu=cortex-m3 -mthumb -c notmain.c -o notmain.o
    arm-none-eabi-ld -nostdlib -nostartfiles -T flash.ld flash.o notmain.o -o notmain.elf
    arm-none-eabi-objdump -D notmain.elf > notmain.list
    arm-none-eabi-objcopy -O binary notmain.elf notmain.bin
    

    check the vector table, etc.

    00000000 <_start>:
       0:   20001000
       4:   0000000d
       8:   00000013
    
    0000000c <reset>:
       c:   f000 f804   bl  18 <notmain>
      10:   e7ff        b.n 12 <hang>
    
    00000012 <hang>:
      12:   e7fe        b.n 12 <hang>
    

    Looks good.

    And run it

    qemu-system-arm -M lm3s811evb -m 8K -nographic -kernel notmain.bin
    01234567
    

    Then ctrl-a then x to exit

    QEMU: Terminated
    

    -cpu cortex-m4 works as well as one would expect. Would have to try to find things different between the m3 and m4 that might show up in a sim like this and go from there.

    After Luminary Micro (acquired by ti a while ago now) I do not think anyone else put the effort in for a machine. But as already discussed in at least one question at this site, you can run the cores (an exercise for the reader).

    For versatilepb

    int notmain ( void )
    {
        unsigned int ra;
    
        for(ra=0;;ra++)
        {
            ra&=7;
            PUT32(0x101f1000,0x30+ra);
        }
    
        return(0);
    }
    
    qemu-system-arm -machine versatileab -cpu cortex-m4 -nographic -monitor null -kernel notmain.elf
    qemu-system-arm: This board cannot be used with Cortex-M CPUs