mirror of
https://github.com/danog/baremetal.git
synced 2024-11-26 20:15:01 +01:00
First commit
This commit is contained in:
commit
01af0bade1
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
*.o
|
||||
*.img
|
||||
build
|
37
Makefile
Normal file
37
Makefile
Normal file
@ -0,0 +1,37 @@
|
||||
ARMGNU ?= aarch64-linux-gnu
|
||||
|
||||
COPS = -Wall -nostdlib -nostartfiles -ffreestanding -Iinclude -mgeneral-regs-only
|
||||
ASMOPS = -Iinclude
|
||||
|
||||
BUILD_DIR = build
|
||||
SRC_DIR = src
|
||||
|
||||
all: kernel8.img
|
||||
|
||||
install: all
|
||||
udisksctl mount -b /dev/mmcblk0p1
|
||||
cp kernel8.img /run/media/daniil/*/
|
||||
umount /run/media/daniil/*
|
||||
sync
|
||||
|
||||
clean:
|
||||
rm -rf $(BUILD_DIR) *.img
|
||||
|
||||
$(BUILD_DIR)/%_c.o: $(SRC_DIR)/%.c
|
||||
mkdir -p $(@D)
|
||||
$(ARMGNU)-gcc $(COPS) -MMD -c $< -o $@
|
||||
|
||||
$(BUILD_DIR)/%_s.o: $(SRC_DIR)/%.S
|
||||
$(ARMGNU)-gcc $(ASMOPS) -MMD -c $< -o $@
|
||||
|
||||
C_FILES = $(wildcard $(SRC_DIR)/*.c)
|
||||
ASM_FILES = $(wildcard $(SRC_DIR)/*.S)
|
||||
OBJ_FILES = $(C_FILES:$(SRC_DIR)/%.c=$(BUILD_DIR)/%_c.o)
|
||||
OBJ_FILES += $(ASM_FILES:$(SRC_DIR)/%.S=$(BUILD_DIR)/%_s.o)
|
||||
|
||||
DEP_FILES = $(OBJ_FILES:%.o=%.d)
|
||||
-include $(DEP_FILES)
|
||||
|
||||
kernel8.img: $(SRC_DIR)/linker.ld $(OBJ_FILES)
|
||||
$(ARMGNU)-ld -T $(SRC_DIR)/linker.ld -o $(BUILD_DIR)/kernel8.elf $(OBJ_FILES)
|
||||
$(ARMGNU)-objcopy $(BUILD_DIR)/kernel8.elf -O binary kernel8.img
|
6
include/mini_uart.h
Normal file
6
include/mini_uart.h
Normal file
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
void uart_init(void);
|
||||
void uart_send(char c);
|
||||
char uart_recv();
|
||||
void uart_send_string(const char *str);
|
4
include/mm.h
Normal file
4
include/mm.h
Normal file
@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
// Lower memory limit at 4mb, kernel stack grows down back to 0 but we don't need much, 4mb is enough.
|
||||
#define LOW_MEMORY (4 << 20)
|
22
include/reg.h
Normal file
22
include/reg.h
Normal file
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#define BUS_OFFSET 0x3F000000
|
||||
|
||||
#define AUX_MU_IER_REG (0x7E215044 - BUS_OFFSET)
|
||||
|
||||
#define GPFSEL1 (0x7E200004 - BUS_OFFSET)
|
||||
#define GPPUD (0x7E200094 - BUS_OFFSET)
|
||||
#define GPPUDCLK0 (0x7E200098 - BUS_OFFSET)
|
||||
#define AUX_ENABLES (0x7E215004 - BUS_OFFSET)
|
||||
#define AUX_MU_CNTL_REG (0x7E215060 - BUS_OFFSET)
|
||||
#define AUX_MU_IO_REG (0x7E215040 - BUS_OFFSET)
|
||||
#define AUX_MU_IER_REG (0x7E215044 - BUS_OFFSET)
|
||||
#define AUX_MU_IIR_REG (0x7E215048 - BUS_OFFSET)
|
||||
#define AUX_MU_LCR_REG (0x7E21504c - BUS_OFFSET)
|
||||
#define AUX_MU_MCR_REG (0x7E215050 - BUS_OFFSET)
|
||||
#define AUX_MU_LSR_REG (0x7E215054 - BUS_OFFSET)
|
||||
#define AUX_MU_BAUD_REG (0x7E215068 - BUS_OFFSET)
|
||||
|
||||
#define UART_BASE (0x7E201000-BUS_OFFSET)
|
||||
|
||||
#define ST_CLO (0x7e003004 - BUS_OFFSET)
|
6
include/utils.h
Normal file
6
include/utils.h
Normal file
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
extern void put32(unsigned long reg, unsigned int value);
|
||||
extern unsigned int get32(unsigned long reg);
|
||||
|
||||
extern void delay(unsigned long duration);
|
20
src/boot.S
Normal file
20
src/boot.S
Normal file
@ -0,0 +1,20 @@
|
||||
#include "mm.h"
|
||||
|
||||
.section ".text.boot"
|
||||
|
||||
.globl _start
|
||||
_start:
|
||||
mrs x0, mpidr_el1 // Copy processor affinity register into x0
|
||||
and x0, x0, #0xFF // Affinity 0 @ 0:7 is the core ID
|
||||
cbnz x0, halt // Halt if core != 0
|
||||
|
||||
adr x0, bss_begin // Argument 1: bss_begin
|
||||
adr x1, bss_end
|
||||
sub x1, x1, x0 // Argument 2: bss_end-bss_begin
|
||||
bl memzero // memzero(bss_begin, bss_end-bss_begin)
|
||||
|
||||
mov sp, #LOW_MEMORY // Initialize the kernel stack pointer to +4mb, growing downwards
|
||||
bl kernel_main // kernel_main()
|
||||
|
||||
halt:
|
||||
b halt
|
13
src/kernel.c
Normal file
13
src/kernel.c
Normal file
@ -0,0 +1,13 @@
|
||||
#include "mini_uart.h"
|
||||
#include "reg.h"
|
||||
#include "utils.h"
|
||||
|
||||
void kernel_main(void)
|
||||
{
|
||||
uart_init();
|
||||
uart_send_string("Hello, world!\r\n");
|
||||
|
||||
while (1) {
|
||||
uart_send(uart_recv());
|
||||
}
|
||||
}
|
11
src/linker.ld
Normal file
11
src/linker.ld
Normal file
@ -0,0 +1,11 @@
|
||||
SECTIONS
|
||||
{
|
||||
.text.boot : { *(.text.boot) }
|
||||
.text : { *(.text) }
|
||||
.rodata : { *(.rodata) }
|
||||
.data : { *(.data) }
|
||||
. = ALIGN(0x8);
|
||||
bss_begin = .;
|
||||
.bss : { *(.bss*) }
|
||||
bss_end = .;
|
||||
}
|
89
src/mini_uart.c
Normal file
89
src/mini_uart.c
Normal file
@ -0,0 +1,89 @@
|
||||
#include "mini_uart.h"
|
||||
#include "reg.h"
|
||||
|
||||
#define UART_DR (UART_BASE+0x0)
|
||||
#define UART_FR (UART_BASE+0x18)
|
||||
|
||||
#define UART_IBRD (UART_BASE+0x24)
|
||||
#define UART_FBRD (UART_BASE+0x28)
|
||||
#define UART_LCRH (UART_BASE+0x2C)
|
||||
#define UART_CR (UART_BASE+0x30)
|
||||
#define UART_ICR (UART_BASE+0x44)
|
||||
|
||||
// UART clock baud rate divisor register
|
||||
// Why is this undocumented??
|
||||
#define CM_UARTDIV (0x7e1010f4-BUS_OFFSET)
|
||||
|
||||
// UART control register
|
||||
// Why is this undocumented??
|
||||
#define CM_UARTCTL 0x7e1010f0
|
||||
|
||||
|
||||
// cucumber moment
|
||||
#define CM_PASSWORD 0x5a000000
|
||||
#define CM_SRC_OSC 1
|
||||
|
||||
#define CM_UARTCTL_FRAC_SET 0x00000200
|
||||
#define CM_UARTCTL_ENAB_SET 0x00000010
|
||||
|
||||
void uart_init(void)
|
||||
{
|
||||
unsigned int selector;
|
||||
|
||||
selector = get32(GPFSEL1);
|
||||
selector &= ~(7<<12); // clean gpio14
|
||||
selector |= 4<<12; // set alt1 for gpio14
|
||||
selector &= ~(7<<15); // clean gpio15
|
||||
selector |= 4<<15; // set alt1 for gpio 15
|
||||
put32(GPFSEL1,selector);
|
||||
|
||||
put32(UART_CR, 0);
|
||||
|
||||
put32(GPPUD,0);
|
||||
delay(150);
|
||||
put32(GPPUDCLK0,(1<<14)|(1<<15));
|
||||
delay(150);
|
||||
put32(GPPUDCLK0,0);
|
||||
|
||||
/*put32(AUX_ENABLES,1); //Enable mini uart (this also enables access to its registers)
|
||||
put32(AUX_MU_CNTL_REG,0); //Disable auto flow control and disable receiver and transmitter (for now)
|
||||
put32(AUX_MU_IER_REG,0); //Disable receive and transmit interrupts
|
||||
put32(AUX_MU_LCR_REG,3); //Enable 8 bit mode
|
||||
put32(AUX_MU_MCR_REG,0); //Set RTS line to be always high
|
||||
put32(AUX_MU_BAUD_REG,270); //Set baud rate to 115200
|
||||
|
||||
put32(AUX_MU_CNTL_REG,3); //Finally, enable transmitter and receiver*/
|
||||
|
||||
put32(CM_UARTDIV, CM_PASSWORD | 0x6666);
|
||||
put32(CM_UARTDIV, CM_PASSWORD | CM_SRC_OSC | CM_UARTCTL_FRAC_SET | CM_UARTCTL_ENAB_SET);
|
||||
|
||||
put32(UART_ICR, 0x7FF);
|
||||
put32(UART_IBRD, 1);
|
||||
put32(UART_FBRD, 40);
|
||||
put32(UART_LCRH, 0x70);
|
||||
put32(UART_CR, 0x301);
|
||||
}
|
||||
|
||||
void uart_send(char c)
|
||||
{
|
||||
//while(!(get32(AUX_MU_LSR_REG) & 0x20));
|
||||
//put32(AUX_MU_IO_REG, c);
|
||||
|
||||
while(get32(UART_FR) & 0x20);
|
||||
put32(UART_DR, c);
|
||||
}
|
||||
char uart_recv()
|
||||
{
|
||||
//while (!(get32(AUX_MU_LSR_REG) & 0x1));
|
||||
//return get32(AUX_MU_IO_REG) & 0xFF;
|
||||
|
||||
while(get32(UART_FR) & 0x10);
|
||||
return put32(UART_DR) & 0xFF;
|
||||
}
|
||||
|
||||
void uart_send_string(const char *str)
|
||||
{
|
||||
for (int i = 0; str[i] != '\0'; i++) {
|
||||
uart_send(str[i]);
|
||||
}
|
||||
}
|
22
src/utils.S
Normal file
22
src/utils.S
Normal file
@ -0,0 +1,22 @@
|
||||
.globl put32
|
||||
put32:
|
||||
str w1,[x0]
|
||||
ret
|
||||
|
||||
.globl get32
|
||||
get32:
|
||||
ldr w0,[x0]
|
||||
ret
|
||||
|
||||
.globl delay
|
||||
delay:
|
||||
subs x0, x0, #1
|
||||
bne delay
|
||||
ret
|
||||
|
||||
.globl memzero
|
||||
memzero:
|
||||
str xzr, [x0], #8
|
||||
subs x1, x1, #8
|
||||
b.gt memzero
|
||||
ret
|
Loading…
Reference in New Issue
Block a user