Skip to content

Commit 87a0323

Browse files
Merge pull request #223 from szediwy/master
Solved lesson 01 exercise 3 for Raspberry Pi 4B
2 parents a26ead7 + f601eb8 commit 87a0323

File tree

16 files changed

+381
-0
lines changed

16 files changed

+381
-0
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
ARMGNU ?= aarch64-linux-gnu
2+
3+
COPS = -Wall -nostdlib -nostartfiles -ffreestanding -Iinclude -mgeneral-regs-only
4+
ASMOPS = -Iinclude
5+
6+
BUILD_DIR = build
7+
SRC_DIR = src
8+
9+
.PHONY: clean
10+
11+
all : kernel8.img
12+
13+
clean :
14+
rm -rf $(BUILD_DIR) *.img
15+
@echo "clean: [SUCCESS]"
16+
17+
$(BUILD_DIR)/%_c.o: $(SRC_DIR)/%.c
18+
mkdir -p $(@D)
19+
$(ARMGNU)-gcc $(COPS) -MMD -c $< -o $@
20+
21+
$(BUILD_DIR)/%_s.o: $(SRC_DIR)/%.S
22+
$(ARMGNU)-gcc $(ASMOPS) -MMD -c $< -o $@
23+
24+
C_FILES = $(wildcard $(SRC_DIR)/*.c)
25+
ASM_FILES = $(wildcard $(SRC_DIR)/*.S)
26+
OBJ_FILES = $(C_FILES:$(SRC_DIR)/%.c=$(BUILD_DIR)/%_c.o)
27+
OBJ_FILES += $(ASM_FILES:$(SRC_DIR)/%.S=$(BUILD_DIR)/%_s.o)
28+
29+
DEP_FILES = $(OBJ_FILES:%.o=%.d)
30+
-include $(DEP_FILES)
31+
32+
kernel8.img: $(SRC_DIR)/linker.ld $(OBJ_FILES)
33+
$(ARMGNU)-ld -T $(SRC_DIR)/linker.ld -o $(BUILD_DIR)/kernel8.elf $(OBJ_FILES)
34+
$(ARMGNU)-objcopy $(BUILD_DIR)/kernel8.elf -O binary kernel8.img
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
docker run --rm -v %cd%:/app -w /app smatyukevich/raspberry-pi-os-builder make %1
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/bash
2+
3+
docker run --rm -v $(pwd):/app -w /app smatyukevich/raspberry-pi-os-builder make $1
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#ifndef _MINI_UART_H
2+
#define _MINI_UART_H
3+
4+
void uart_init ( void );
5+
char uart_recv ( void );
6+
void uart_send ( char c );
7+
void uart_send_string(char* str);
8+
9+
#endif /*_MINI_UART_H */
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#ifndef _MM_H
2+
#define _MM_H
3+
4+
#define PAGE_SHIFT 12
5+
#define TABLE_SHIFT 9
6+
#define SECTION_SHIFT (PAGE_SHIFT + TABLE_SHIFT)
7+
8+
#define PAGE_SIZE (1 << PAGE_SHIFT)
9+
#define SECTION_SIZE (1 << SECTION_SHIFT)
10+
11+
#define LOW_MEMORY (2 * SECTION_SIZE)
12+
13+
#ifndef __ASSEMBLER__
14+
15+
void memzero(unsigned long src, unsigned long n);
16+
17+
#endif
18+
19+
#endif /*_MM_H */
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#ifndef _P_BASE_H
2+
#define _P_BASE_H
3+
4+
// #define PBASE 0x3F000000
5+
// So a peripheral described in this document as being at legacy address 0x7Enn_nnnn is available in the 35-bit address
6+
// space at 0x4_7Enn_nnnn, and visible to the ARM at 0x0_FEnn_nnnn if Low Peripheral mode is enabled.
7+
// 0x7E000000 (legacy) -> 0x4_7E00_0000 (35-bit) -> 0x0_FE00_0000 (low peripheral)
8+
#define PBASE 0xFE000000
9+
10+
#endif /*_P_BASE_H */
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#ifndef _P_GPIO_H
2+
#define _P_GPIO_H
3+
4+
#include "peripherals/base.h"
5+
6+
#define GPFSEL1 (PBASE+0x00200004)
7+
// #define GPSET0 (PBASE+0x0020001C)
8+
// #define GPCLR0 (PBASE+0x00200028)
9+
// #define GPPUD (PBASE+0x00200094)
10+
// #define GPPUDCLK0 (PBASE+0x00200098)
11+
#define GPIO_PUP_PDN_CNTRL_REG0 (PBASE+0x002000E4)
12+
#define UART0_DR (PBASE+0x00201000)
13+
#define UART0_FR (PBASE+0x00201018)
14+
#define UART0_IBRD (PBASE+0x00201024)
15+
#define UART0_FBRD (PBASE+0x00201028)
16+
#define UART0_LCRH (PBASE+0x0020102C)
17+
#define UART0_CR (PBASE+0x00201030)
18+
#define UART0_IMSC (PBASE+0x00201038)
19+
20+
#endif /*_P_GPIO_H */
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#ifndef _P_MINI_UART_H
2+
#define _P_MINI_UART_H
3+
4+
#include "peripherals/base.h"
5+
6+
#define AUX_ENABLES (PBASE+0x00215004)
7+
#define AUX_MU_IO_REG (PBASE+0x00215040)
8+
#define AUX_MU_IER_REG (PBASE+0x00215044)
9+
#define AUX_MU_IIR_REG (PBASE+0x00215048)
10+
#define AUX_MU_LCR_REG (PBASE+0x0021504C)
11+
#define AUX_MU_MCR_REG (PBASE+0x00215050)
12+
#define AUX_MU_LSR_REG (PBASE+0x00215054)
13+
#define AUX_MU_MSR_REG (PBASE+0x00215058)
14+
#define AUX_MU_SCRATCH (PBASE+0x0021505C)
15+
#define AUX_MU_CNTL_REG (PBASE+0x00215060)
16+
#define AUX_MU_STAT_REG (PBASE+0x00215064)
17+
#define AUX_MU_BAUD_REG (PBASE+0x00215068)
18+
19+
#endif /*_P_MINI_UART_H */
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#ifndef _BOOT_H
2+
#define _BOOT_H
3+
4+
extern void delay ( unsigned long);
5+
extern void put32 ( unsigned long, unsigned int );
6+
extern unsigned int get32 ( unsigned long );
7+
8+
#endif /*_BOOT_H */
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
#include "mm.h"
2+
3+
.section ".text.boot"
4+
5+
.globl _start
6+
_start:
7+
mrs x0, mpidr_el1
8+
and x0, x0, #0x3
9+
cbz x0, init_bss
10+
/* If processor id is not 0 then pending lock processor
11+
* (wait for `sev` instruction)
12+
*/
13+
wfe
14+
b master
15+
16+
proc_hang:
17+
b proc_hang
18+
19+
init_bss:
20+
adr x0, bss_begin
21+
adr x1, bss_end
22+
sub x1, x1, x0
23+
bl memzero
24+
25+
sev
26+
27+
/***********************************************************************/
28+
/* Enable the other cores
29+
link: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/arm64/booting.rst?h=v5.3#n255
30+
31+
The boot loader is expected to enter the kernel on each CPU in the
32+
following manner:
33+
34+
- The primary CPU must jump directly to the first instruction of the
35+
kernel image. The device tree blob passed by this CPU must contain
36+
an 'enable-method' property for each cpu node. The supported
37+
enable-methods are described below.
38+
39+
It is expected that the bootloader will generate these device tree
40+
properties and insert them into the blob prior to kernel entry.
41+
42+
- CPUs with a "spin-table" enable-method must have a 'cpu-release-addr'
43+
property in their cpu node. This property identifies a
44+
naturally-aligned 64-bit zero-initalised memory location.
45+
46+
These CPUs should spin outside of the kernel in a reserved area of
47+
memory (communicated to the kernel by a /memreserve/ region in the
48+
device tree) polling their cpu-release-addr location, which must be
49+
contained in the reserved region. A wfe instruction may be inserted
50+
to reduce the overhead of the busy-loop and a sev will be issued by
51+
the primary CPU. When a read of the location pointed to by the
52+
cpu-release-addr returns a non-zero value, the CPU must jump to this
53+
value. The value will be written as a single 64-bit little-endian
54+
value, so CPUs must convert the read value to their native endianness
55+
before jumping to it.
56+
57+
- CPUs with a "psci" enable method should remain outside of
58+
the kernel (i.e. outside of the regions of memory described to the
59+
kernel in the memory node, or in a reserved area of memory described
60+
to the kernel by a /memreserve/ region in the device tree). The
61+
kernel will issue CPU_ON calls as described in ARM document number ARM
62+
DEN 0022A ("Power State Coordination Interface System Software on ARM
63+
processors") to bring CPUs into the kernel.
64+
65+
The device tree should contain a 'psci' node, as described in
66+
Documentation/devicetree/bindings/arm/psci.yaml.
67+
68+
- Secondary CPU general-purpose register settings
69+
x0 = 0 (reserved for future use)
70+
x1 = 0 (reserved for future use)
71+
x2 = 0 (reserved for future use)
72+
x3 = 0 (reserved for future use)
73+
*/
74+
75+
/* cpu0: cpu@0 {
76+
device_type = "cpu";
77+
compatible = "arm,cortex-a72";
78+
reg = <0>;
79+
enable-method = "spin-table";
80+
cpu-release-addr = <0x0 0x000000d8>;
81+
};
82+
83+
cpu1: cpu@1 {
84+
device_type = "cpu";
85+
compatible = "arm,cortex-a72";
86+
reg = <1>;
87+
enable-method = "spin-table";
88+
cpu-release-addr = <0x0 0x000000e0>;
89+
};
90+
91+
cpu2: cpu@2 {
92+
device_type = "cpu";
93+
compatible = "arm,cortex-a72";
94+
reg = <2>;
95+
enable-method = "spin-table";
96+
cpu-release-addr = <0x0 0x000000e8>;
97+
};
98+
99+
cpu3: cpu@3 {
100+
device_type = "cpu";
101+
compatible = "arm,cortex-a72";
102+
reg = <3>;
103+
enable-method = "spin-table";
104+
cpu-release-addr = <0x0 0x000000f0>;
105+
}; */
106+
/****************************************************/
107+
mov x0, #0
108+
adr x0, master
109+
110+
mov x1, #0xe0
111+
str x0, [x1]
112+
mov x1, #0xe8
113+
str x0, [x1]
114+
mov x1, #0xf0
115+
str x0, [x1]
116+
117+
master:
118+
mrs x0, mpidr_el1
119+
and x0, x0, #0x3
120+
121+
mov x1, #SECTION_SIZE
122+
mul x1, x1, x0
123+
add x1, x1, #LOW_MEMORY
124+
mov sp, x1
125+
126+
bl kernel_main
127+
b proc_hang

0 commit comments

Comments
 (0)