Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

0886003 lab7 lab8 #235

Open
wants to merge 2 commits into
base: 0886003
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
3 changes: 3 additions & 0 deletions lab7/.vs/ProjectSettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"CurrentProjectSetting": "沒有任何組態"
}
10 changes: 10 additions & 0 deletions lab7/.vs/VSWorkspaceState.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"ExpandedNodes": [
"",
"\\kernel",
"\\user_program",
"\\user_program\\fat32_test2"
],
"SelectedNode": "\\user_program\\fat32_test2\\fat32_test2.c",
"PreviewInSolutionExplorer": false
}
Binary file added lab7/.vs/lab7/v16/.suo
Binary file not shown.
Binary file added lab7/.vs/lab7/v16/Browse.VC.db
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added lab7/.vs/slnx.sqlite
Binary file not shown.
1 change: 1 addition & 0 deletions lab7/FATTEST.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This is for fat32 test read/write.
Binary file added lab7/bcm2710-rpi-3-b-plus.dtb
Binary file not shown.
45 changes: 45 additions & 0 deletions lab7/bootloader/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# define variable
# -g for gdb debug
# -Wall is show warning message
# -fno-builtin is Don’t recognize built-in functions, ex. strlen, strcmp
CC = aarch64-linux-gnu-gcc
LD = aarch64-linux-gnu-ld
OBJCOPY = aarch64-linux-gnu-objcopy
CFLAGS = -g -Wall -fno-builtin
LD_FLAGS = -T linker.ld

# 'all' keyword represent this makefile target, so target is generate bootloader.img
all: bootloader.img

# compile startup.s, generate startup.o
startup.o: startup.s
$(CC) -c $< -o $@

# compile all *.c and generate *.o
%.o : %.c
$(CC) $(CFLAGS) -c $< -o $@

# generate bootloader.img, need startup.o main.o util.o uart.o reboot.o linker.ld
bootloader.img: startup.o main.o util.o uart.o reboot.o kernel.o linker.ld
$(LD) $(LD_FLAGS) -o bootloader.elf startup.o main.o util.o uart.o reboot.o kernel.o
$(OBJCOPY) -O binary bootloader.elf $@

# clean all generate file
clean:
rm *.o bootloader.elf bootloader.img

# check asm by qemu
asm: all
qemu-system-aarch64 -M raspi3 -kernel bootloader.img -display none -d in_asm

# run bootloader.img for test
run: all
qemu-system-aarch64 -M raspi3 -kernel bootloader.img -display none -serial null -serial stdio

# pseudo TTY
tty: all
qemu-system-aarch64 -M raspi3 -kernel bootloader.img -display none -serial null -serial pty

# gdb debug
debug: all
qemu-system-aarch64 -M raspi3 -kernel bootloader.img -display none -S -s
21 changes: 21 additions & 0 deletions lab7/bootloader/auxilary.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#ifndef AUXILARY_H
#define AUXILARY_H

#include "mmio.h"

// Auxilary mini UART registers
// Use volatile tells the compiler that the value of the variable may change at any time by hardware
#define AUX_ENABLE ((volatile unsigned int*)(MMIO_BASE+0x00215004))
#define AUX_MU_IO ((volatile unsigned int*)(MMIO_BASE+0x00215040))
#define AUX_MU_IER ((volatile unsigned int*)(MMIO_BASE+0x00215044))
#define AUX_MU_IIR ((volatile unsigned int*)(MMIO_BASE+0x00215048))
#define AUX_MU_LCR ((volatile unsigned int*)(MMIO_BASE+0x0021504C))
#define AUX_MU_MCR ((volatile unsigned int*)(MMIO_BASE+0x00215050))
#define AUX_MU_LSR ((volatile unsigned int*)(MMIO_BASE+0x00215054))
#define AUX_MU_MSR ((volatile unsigned int*)(MMIO_BASE+0x00215058))
#define AUX_MU_SCRATCH ((volatile unsigned int*)(MMIO_BASE+0x0021505C))
#define AUX_MU_CNTL ((volatile unsigned int*)(MMIO_BASE+0x00215060))
#define AUX_MU_STAT ((volatile unsigned int*)(MMIO_BASE+0x00215064))
#define AUX_MU_BAUD ((volatile unsigned int*)(MMIO_BASE+0x00215068))

#endif
12 changes: 12 additions & 0 deletions lab7/bootloader/gpio.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#ifndef GPIO_H
#define GPIO_H

#include "mmio.h"

// GPIO registers
// Use volatile tells the compiler that the value of the variable may change at any time by hardware
#define GPFSEL1 ((volatile unsigned int*)(MMIO_BASE+0x00200004)) // GPIO Function Select Registers
#define GPPUD ((volatile unsigned int*)(MMIO_BASE+0x00200094)) // GPIO Pull-up/down Register
#define GPPUDCLK0 ((volatile unsigned int*)(MMIO_BASE+0x00200098)) // GPIO Pull-up/down Clock Register

#endif
87 changes: 87 additions & 0 deletions lab7/bootloader/kernel.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#include "kernel.h"
#include "uart.h"
#include "util.h"

extern char _end[];
extern char __kernel_begin[];
extern char __kernel_size[];
unsigned long int backup_address = 0x60000;

void load_new_kernel()
{
uart_putstr("Start Loading kernel image...\n");

// 1. define new kernel address
long long address_int = 0x80000;

// 2. send kernel (use sendimg.py)
uart_putstr("Please send kernel image from UART now...\n");

// 3. read kernel size
char k_size[20] = {0};
uart_read_cmd(k_size);
int kernel_size = atoi(k_size);

// 4. show kernel size and load address
uart_putstr("Kernel size: ");
uart_putstr(k_size);
uart_putstr("\t");
uart_putstr("Load address: 0x");
uart_putstr("Load address: 0x80000");
uart_putstr("\n");

// 5. read new kernel form uart, start on new_address(0x80000)
uart_putstr("Starting to load target kernel\n");

char* new_address = (char*)address_int;
for (int i = 0; i < kernel_size; i++)
{
char c = uart_getchar(); // all char should be get
new_address[i] = c;
}

uart_putstr("Finished load target kernel and running.\n");

// 6. load new kernel
void (*new_kernel)(void) = (void *)new_address;
new_kernel();
}

void backup_old_kernel()
{
char *kernel = __kernel_begin;
unsigned long int size = (unsigned long int)__kernel_size;
char *backup = (char *)(backup_address);

uart_putstr("Starting to backup bootloader\n");

// move bootloader to backup_address(0x60000)
while (size--)
{
*backup = *kernel;
kernel++;
backup++;
}

uart_putstr("Finished backup bootloader\n");
}

void load_image()
{
// 1. backup bootloader kernel to 0x60000
backup_old_kernel();

// 2. calculate new 'load_new_kernel' funciton address

// because old kernel are backup to backup_address
// so load_new_kernel function need move to new address
// offest = load_target_func_address - kernel_start

void (*load_target_ptr)() = load_new_kernel;
unsigned long int load_target_func_address = (unsigned long int) load_target_ptr;
void (*load_kernel)() =
(void (*)())( backup_address + (load_target_func_address - (unsigned long int)__kernel_begin) );

// 3. load new kernel form uart
load_kernel();
}
8 changes: 8 additions & 0 deletions lab7/bootloader/kernel.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#ifndef KERNEL
#define KERNEL

void load_image();
void backup_old_kernel();
void load_new_kernel();

#endif
46 changes: 46 additions & 0 deletions lab7/bootloader/linker.ld
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
SECTIONS /* Use the SECTIONS keyword to declare a section, the following is its content */
{
. = 0x80000; /* move the 'location counter' to 0x30000 */
__kernel_begin = .;
.text : /* assign .text section */
{
KEEP(*(.text.boot)) /* make sure .text.boot will not be remove by linker-time garbage collection. */
*(.text .text.*) /* *(.text .text.*) is all .text and .text. */
}
.rodata : /* assign .rodata section */
{
*(.rodata .rodata.*) /* *(.rodata .rodata.*) is all .rodata and .rodata. */
}
.data : /* assign .data section */
{
*(.data .data.*) /* *(.data .data.*) is all .data and .data. */
}
.bss (NOLOAD) : /* assign .bss section, NOLOAD means not load at runtime */
{
. = ALIGN(16); /* aligned to 16-byte boundaries. ex.0x0000000000080000 */
__bss_start = .; /* assign __bss_start to the current memory position */
*(.bss .bss.*) /* *(.bss .bss.*) is all .bss and .bss. */
*(COMMON) /* assign uninitialized data section */
__bss_end = .; /* assign __bss_end to the current memory position */
}
_end = .; /* assign _end to the current memory position */
}
__bss_size = (__bss_end - __bss_start) >> 3; /* _bss_size set to 8 */
__kernel_size = (_end - __kernel_begin);

/*
KEEP: make sure the section will not be remove by linker-time garbage collection.
.text: code section
.rodata: stores read-only data, e.g. const variables and strings
.bss : uninitialized data section (weak symbol) e.g. global var init to zero
.data : initialized data section (strong symbol)
NOLOAD : Does not load at runtime (because bss section is full of zero)
COMMON : uninitialized data section (weak symbol) e.g. global var just declare

[example]
const int a = 0; // .rodata
int b = 3; // .data
int c = 0; // .bss
int d; // COMMON

*/
69 changes: 69 additions & 0 deletions lab7/bootloader/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#include "uart.h"
#include "util.h"
#include "reboot.h"
#include "kernel.h"

#define CMDSIZE 64
char cmd[CMDSIZE] = {0};

void cmd_init()
{
for(int i = 0; i < CMDSIZE; i++)
cmd[i] = 0;
}

void cmd_handle() // parse command
{
if (strcmp(cmd, "help"))
{
uart_putstr("help print all available commands \n");
uart_putstr("loadimg load new kernel from uart \n");
uart_putstr("reboot reboot raspi3 \n");
}
else if (strcmp(cmd, "loadimg"))
{
load_image();
}
else if(strcmp(cmd, "reboot"))
{
uart_putstr("reboot .... \n");
raspi3_reboot(100);
while(1); // wait for reboot
}
else if(strlen(cmd) != 0)
{
uart_putstr("command \"");
uart_putstr(cmd);
uart_putstr("\" not found, try <help> \n");
}

uart_putstr("# ");
}

void main()
{
cmd_init();
uart_init();

// put welcome ascii art
uart_putstr("\n");
uart_putstr(" .~~. .~~. \n");
uart_putstr(" '. \\ ' ' / .' \n");
uart_putstr(" .~ .~~~..~. \n");
uart_putstr(" : .~.'~'.~. : \n");
uart_putstr(" ~ ( ) ( ) ~ \n");
uart_putstr(" ( : '~'.~.'~' : ) \n");
uart_putstr(" ~ .~ ( ) ~. ~ \n");
uart_putstr(" ( : '~' : ) This is bootloader !! \n");
uart_putstr(" '~ .~~~. ~' \n");
uart_putstr(" '~' \n");
uart_putstr("# ");

while(1)
{
uart_read_cmd(cmd);
cmd_handle();
cmd_init();
}

}
10 changes: 10 additions & 0 deletions lab7/bootloader/mmio.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#ifndef MMIO_H
#define MMIO_H

//rpi3 access peripheral registers by memory mapped io (MMIO).
//There is a VideoCore/ARM MMU sit between ARM CPU and peripheral bus.
//This MMU maps ARM’s physical address 0x3f000000 to 0x7e000000.

#define MMIO_BASE 0x3F000000

#endif
13 changes: 13 additions & 0 deletions lab7/bootloader/reboot.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include "reboot.h"

void raspi3_reboot(int ticks) // reboot after watchdog timer expire
{
*PM_RSTC = PM_PASSWORD | 0x20; // full reset
*PM_WDOG = PM_PASSWORD | ticks; // number of watchdog tick
}

void cancel_reset()
{
*PM_RSTC = PM_PASSWORD | 0; // full reset
*PM_WDOG = PM_PASSWORD | 0; // number of watchdog tick
}
12 changes: 12 additions & 0 deletions lab7/bootloader/reboot.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#ifndef REBOOT
#define REBOOT

#define PM_PASSWORD 0x5A000000

#define PM_RSTC ((volatile unsigned int*)0x3F10001C)
#define PM_WDOG ((volatile unsigned int*)0x3F100024)

void raspi3_reboot(int ticks); // reboot after watchdog timer expire
void cancel_reset(); // cancel_reset

#endif
38 changes: 38 additions & 0 deletions lab7/bootloader/startup.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
.section ".text.boot" // Declare a section of .text.boot

.global _start /* The .global keyword is used to make a symbol visible to the linker
.global _start makes the _start symbol to a visible global symbol */

// The bootloader of rpi3 loads kernel8.img to RAM (address 0x80000) by GPU
// After that, 4 CPU cores start to run the same code simultaneously.
// So, let only one core proceed, and let others enter a busy loop.

_start: // _start represents the program start entry symbol, the following is its execution content
mrs x1, mpidr_el1 // gets the processor ID from the 'mpidr_el1' system register to x1
and x1, x1, #3 // and bit, because rpi3 have 4 CPU cores, so and #3
cbz x1, init // compare, if cpu id = 0 jump to init.
b busy_loop // else jump to busy_loop

busy_loop:
wfe // Let ARM enter the 'low-power standby state' amd wait for event
b busy_loop // b means jump, the this sentence means jump back to busy_loop

init:
ldr x1, =0x9000000
str x0, [x1]

ldr x1, =__bss_start // init bss segment, bss segment are initialized to 0, .bss start address to x1
ldr x2, =__bss_size // size of the .bss section to x2

loop_clear_bss:
cbz x2, entry_point // if .bss size = 0, jump to entry_point
str xzr, [x1], #8 // store register. xzr is zero register. *x1 = 0; x1 += 8;
sub x2, x2, #1 // x2 = x2 - 1; (because __bss_size / 8)
cbnz x2, loop_clear_bss // if .bss size > 0 jump to loop_clear_bss.

entry_point:
ldr x1, =_start // sp is stack pointer, mov _start to stack top
mov sp, x1 //
bl main // jump to our main() method of main.c
b busy_loop // should never come here, if failure jump to busy_loop

Loading