Browse Source

Initial import with uart

master
Mathieu Maret 4 months ago
commit
787b4617ae
  1. 23
      Makefile
  2. 8
      config.txt
  3. 27
      crt0.S
  4. 9
      gpio.h
  5. 6
      hello.c
  6. 13
      mmio.h
  7. 32
      rpi3.ld
  8. 45
      uart.c
  9. 15
      uart.h

23
Makefile

@ -0,0 +1,23 @@
#CROSS=aarch64-none-elf-
CROSS=aarch64-linux-gnu-
CC=$(CROSS)gcc
LD=$(CROSS)ld
CFLAGS=-Wall -Wextra -ffreestanding -march=armv8-a+crc -mcpu=cortex-a53
LDSCRIPT=rpi3.ld
OBJS=crt0.o uart.o hello.o
all:kernel.bin
kernel.elf: $(OBJS) $(LDSCRIPT)
$(LD) -o $@ $(OBJS) -T$(LDSCRIPT) -Map kernel.map
kernel.bin: kernel.elf
$(CROSS)objcopy -O binay -B aarch64 $< $@
clean:
rm -rf $(OBJS) *.bin *.elf *.map
run: kernel.bin
qemu-system-aarch64 -machine raspi3b -kernel $<

8
config.txt

@ -0,0 +1,8 @@
#bootloarder
uart_2ndstage=1
# 64bits
arm_64bit=1
# Kernel name
kernel=kernel.bin

27
crt0.S

@ -0,0 +1,27 @@
.section .text.boot
.global __start
.type __start, %function
__start:
//Use core 0 only
mrs x7, mpidr_el1
and x7, x7, #3
cbz x7, __start_master
0: wfe
b 0b
__start_master:
//Setup stack pointer
ldr x2, = __stack_start
mov sp, x2
//Clear BSS
ldr w0, = __bss_start
ldr w1, = __bss_size
1: cbz x1, 2f
str xzr, [x0], #8
sub x1, x1, #1
cbnz x1, 1b
2:
bl kernelmain
b 0b

9
gpio.h

@ -0,0 +1,9 @@
#pragma once
#include "mmio.h"
// GPIO Function Select 1
#define GPFSEL1 (*(volatile unsigned *)(GP_BASE + 0x04))
// GPIO Pin Pull-up/down Enable
#define GPPUD (*(volatile unsigned *)(GP_BASE + 0x94))
// GPIO Pin Pull-up/down Enable Clock 0
#define GPPUDCLK0 (*(volatile unsigned *)(GP_BASE + 0x98))

6
hello.c

@ -0,0 +1,6 @@
#include "uart.h"
int kernelmain(void) {
init_uart();
return 0;
}

13
mmio.h

@ -0,0 +1,13 @@
#pragma once
// IO mapping
#define IO_BASE 0x3f000000
// Mini-UART mapping
#define MU_BASE (IO_BASE + 0x215000)
// GPIO mapping
#define GP_BASE (IO_BASE + 0x200000)
// videocore mbox system
#define VCORE_MBOX (IO_BASE + 0x0000B880)

32
rpi3.ld

@ -0,0 +1,32 @@
MEMORY
{
/* Load at a classic 64bit addr*/
/* Could be replace by . = 0x8000; before .text*/
RAM (rwx) : ORIGIN = 0x80000, LENGTH = 0x10000000
}
SECTIONS
{
.text : { *(.text .text.*) }
.rodata : { *(.rodata .rodata.*) }
.data : { *(.data .data.*) }
.bss (NOLOAD):
{
__bss_start = ALIGN(16);
*(.bss .bss.*)
__bss_end = ALIGN(16);
}
__end =.;
. = ALIGN(16);
. += 0x1000;
__stack_start = .;
/DISCARD/ :
{
*(.comment) *(.gnu) *(.note*) *(.eh_frame*)
}
}
__bss_size = (__bss_end - __bss_start) >> 3;

45
uart.c

@ -0,0 +1,45 @@
#include <stdint.h>
#include "uart.h"
#include "gpio.h"
//#include "mbox.h"
void init_uart(void )
{
//Active waiting
while(UART0_FR & (1<<3)){}
//Stop UART0
UART0_CR = 0;
//GPIO 14 and 15 in ALT0
GPFSEL1 &= ~((7<<12)|(7<<15));
GPFSEL1 |= (4<<12)|(4<<15);
GPPUD = 0;
for(uint8_t i = 0; i < 150; i++){
asm volatile ("nop");
}
GPPUDCLK0 = (1<<14)|(1<<5);
for(uint8_t i = 0; i < 150; i++){
asm volatile ("nop");
}
//CLR INTR
GPPUDCLK0 = 0;
// Setup for 115200bps @3Mhz
// 3000000 /(115200 * 16) = 1.627
// 0.627 * 64 + 0.5 = 40.628 -> 40
UART0_IBRD = 1; //int part
UART0_FBRD = 40; //fract part
UART0_LCRH = 0b11 <<5; //format 8n1
UART0_CR = 0x301; //Active Tx, Rx & FIFO
}
void putc(char c){
//FIFO Full?
while(UART0_FR & (1<<5)){}
UART0_DR = c;
}

15
uart.h

@ -0,0 +1,15 @@
#pragma once
#include "mmio.h"
/* PL011 UART */
#define UART0_DR (*(volatile unsigned *)(IO_BASE + 0x00201000))
#define UART0_FR (*(volatile unsigned *)(IO_BASE + 0x00201018))
#define UART0_IBRD (*(volatile unsigned *)(IO_BASE + 0x00201024))
#define UART0_FBRD (*(volatile unsigned *)(IO_BASE + 0x00201028))
#define UART0_LCRH (*(volatile unsigned *)(IO_BASE + 0x0020102C))
#define UART0_CR (*(volatile unsigned *)(IO_BASE + 0x00201030))
#define UART0_IMSC (*(volatile unsigned *)(IO_BASE + 0x00201038))
#define UART0_ICR (*(volatile unsigned *)(IO_BASE + 0x00201044))
void init_uart(void);
void putc(char c);
Loading…
Cancel
Save