1
votes

I want to write a bare metal hello-world for ARM. the message should be outputted at the uart. The device tree file says about the uart:

            uart@09000 {
            compatible = "arm,pl011", "arm,primecell";
            reg = <0x9000 0x1000>;
            interrupts = <0x5>;
        };

Here is my hello world program.

// vexpress.js:651
const int    DR    = 0x00;
const int    FR    = 0x18;
const int    IBRD  = 0x24;
const int    FBRD  = 0x28;
const int    LCR_H = 0x2c;
const int    CR    = 0x30;
const int    IFLS  = 0x34;
const int    IMSC  = 0x38;
const int    MIS   = 0x40;
const int    ICR   = 0x44;
unsigned int *uart;

void
putc(char c)
{
    // wait for UART to become ready to transmit
    // vexpress.js:707
    while ((uart[FR] & (1 << 7)));
    uart[DR]= c;
    while ((uart[FR] & (1 << 7)));
}

void
puts(char *s) {    
    while(*s)
        putc(*(s++));    
}

int
main()
{
    char s[] = { 'H', 'a', 'l', 'l', 'o' , 0};
    int i;
    // vexpress.js:1455
    uart = (unsigned int*)0x10009000;


    // 1
    putc('H');
    putc('a');
    putc('l');
    putc('l');
    putc('o');
    putc(' ');
    putc('W');
    putc('e');
    putc('l');
    putc('t');
    putc('\n');
    putc('\r');

    // 2
    puts(s);

    // 3
    for(i=97;i<123;i++){
        putc((char)i);
    }

    // 4
    puts("Hello World\n\r");
    while(1);
}

So, this program uses several ways out output stuff to the uart. Section 1 (with all the calls to putc does work. But putc seems not to like being called in a loop. Neither 2 nor 3 nor 4 do work. The first charter does work, oddly '\0' are sent thereafter, and i have no clue why. The output is

Hallo Welt                                                                      
a\0\0\0\0.........                                                               

I use arm-js because that is the only arm emulator that was either complete enough (mmu, can run linux) and is simple enough to single step (no jit or alike).

Also, is there a way to integrate a uart driver that does read information for a device tree file at build time? Is there a kernel that allow me to use that part stand alone easily?

/edit

The cpu is a ARMv5 cortex-a9 vexpress processor. I'm not sure what other information are of interest, so
this is the device tree file and this is the assembler code

1
You can't just say ARM cpu , pls be specific about the exact microcontroller used along with the tool chain and development board/platform.manufacturer used - Barath Ravikumar
I hope now all the missing details are added. - user2279596
Also, you might take a look at the processor data sheet. The address could be 0x90001000; device tree is probably big endian due to PowerPC heritage, but I would trust a data sheet for the UART's physical address. - artless noise
> The cpu is a ARMv5 cortex-a9 vexpress processor I thought Cortex-A9 is ARMv7a processor (and, also, MP-Core in most cases). Moreover, if we are baremetal, wouldn't it be mandatory to initialize UART first ? (activate clock, set baudrate, data size, flow control, and so on...) Or is it done by the ROM code of your processor ? (I don't know vexpress) - Jacen

1 Answers

3
votes
uart = (unsigned int*)0x10009000;

while ((uart[FR] & (1 << 7)));

so you are taking 0x10009000 then taking a variable FR which is initialized to 0x18 and using that as an offset. uart is defined as an int so 32 bits so take 32 bits or 4 bytes times 0x18 = 0x60. so you are reading the memory location 0x10009060, which I doubt is what you were wanting to do. using pointers like this is not a good way to do this anyway. (you also failed to declare uart as volatile). DR would be the only one that would work as 0*4 = 0 and you would get address 0x10009000.

These updates highlight some of the issues,

const int FR = 6;
unsigned int volatile *uart;