minimal baremeta example



  • no rtos
    no other driver
    no complex build process

    just a uart and hello world.



  • @latyas fail to compile, sorry I 'm a newbie for embed system.


  • Staff

    @pynix This may help?

    1. no rtos
    2. no other driver
    3. no complex build process

    A real bare-metal example 🙂

    main.S

    #define SYSCTL_BASE            (0x50440000)
    #define SYSCTL_OFFSET_FREQ     (4*1)
    #define SYSCTL_OFFSET_PLL0     (4*2)
    #define SYSCTL_OFFSET_PLL_LOCK (4*6)
    #define SYSCTL_OFFSET_CLK_SEL  (4*8)
    #define UART_BASE              (0x38000000)
    #define UART_OFFSET_TXDATA     (4*0)
    #define UART_OFFSET_RXDATA     (4*1)
    #define UART_OFFSET_TXCTRL     (4*2)
    #define UART_OFFSET_RXCTRL     (4*3)
    #define UART_OFFSET_IE         (4*4)
    #define UART_OFFSET_IP         (4*5)
    #define UART_OFFSET_DIV        (4*6)
    #define UART_BAUD              (115200)
    #define MSTATUS_FS             (0x00006000)
    
    .section .text.start, "ax", @progbits
    .globl _start
    _start:
      j 1f
      .word 0xdeadbeef
    1:
      ## Clear mideleg and medeleg registers
      csrw mideleg, 0
      csrw medeleg, 0
      csrw mtvec, x0
      csrr t0, mhartid
      bgtz t0, _start
    
      # enable hard float
      li t0, MSTATUS_FS
      csrs mstatus, t0
    
    .clk_sel_init:
      li    t0, SYSCTL_BASE
      li    t1, 0x0000e248
      sw    t1, SYSCTL_OFFSET_CLK_SEL(t0)
    
    .pll:
      # disabled PLL0 output
      lw    t1, SYSCTL_OFFSET_PLL0(t0)
      li    t2, 0xfdffffff
      and    t1, t1, t2
      sw    t1, SYSCTL_OFFSET_PLL0(t0)
    
      # Turn off pll0
      lw    t1, SYSCTL_OFFSET_PLL0(t0)
      li    t2, 0xffdfffff
      and    t1, t1, t2
      sw    t1, SYSCTL_OFFSET_PLL0(t0)
      # Set PLL to 793M MHz
      li    t1, 0x004f07c0
      sw    t1, SYSCTL_OFFSET_PLL0(t0)
      # Power on PLL0
      li    t1, 0x006f07c0
      sw    t1, SYSCTL_OFFSET_PLL0(t0)
      # Reset PLL0
      li    t1, 0x007f07c0
      sw    t1, SYSCTL_OFFSET_PLL0(t0)
      # Release reset
      li    t1, 0x006f07c0
      sw    t1, SYSCTL_OFFSET_PLL0(t0)
    .pll_lock:
      # Get lock status
      lw    t1, SYSCTL_OFFSET_PLL_LOCK(t0)
      li    t2, 0x03
      and   t1, t1, t2
      beq   t1, t2, .pll_enable
      # Clean PLL lock status
      li    t1, 0x04
      sw    t1, SYSCTL_OFFSET_PLL_LOCK(t0)
      j .pll_lock
    .pll_enable:
      # Enable PLL output
        lw    t1, SYSCTL_OFFSET_PLL0(t0)
        li    t2, 0x02000000
        or    t1, t1, t2
        sw    t1, SYSCTL_OFFSET_PLL0(t0)
    .clk_sel:
      # ACLK(CPU) USE PLL0
      li    t1, 0x0000e249
      sw    t1, SYSCTL_OFFSET_CLK_SEL(t0)
    
    .uart:
      ## Get base freq from sysctl
      li    t0, SYSCTL_BASE
      lw    t2, SYSCTL_OFFSET_FREQ(t0)
      ## Get UART div = freq / UART_BAUD - 1;
      li    t1, UART_BAUD
      divuw t0, t2, t1
      addiw t0, t0, -1
      ## Set UART base address
      li    t1, UART_BASE
      ## Set UART div
      sw    t0, UART_OFFSET_DIV(t1)
      ## Set UART txctrl
      li    t0, 1
      sw    t0, UART_OFFSET_TXCTRL(t1)
    
      la    t2, .message
    
    .print:
      # Print hello world to UART
      lbu   t0, 0(t2)
      andi  t0, t0, 0xff
      sw    t0, UART_OFFSET_TXDATA(t1)
      addi  t2, t2, 1
      beqz  t0, .loop
      j     .print
    .loop:
      j     .loop
    
    .message:
      .string "Hello world!\r\n"
      .word   0
    

    tiny.ld

    SECTIONS
    {
        RAM_BASE = 0x80000000;
    
        . = RAM_BASE;
        .text.start :
        {
          KEEP( *(.text.start) )
        }
    }