Skip to content

Commit 050c803

Browse files
authored
Merge pull request #9 from sandbox-science/Develop
Vector Table Implementation
2 parents 8f55ffb + 071025b commit 050c803

File tree

8 files changed

+312
-53
lines changed

8 files changed

+312
-53
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ clean:
5151

5252
qemu:
5353
@echo "Press Ctrl-A then X to exit QEMU"
54-
@qemu-system-arm -M versatileab -cpu cortex-a8 -nographic -kernel $(OUT_DIR)kernel.bin
54+
@qemu-system-arm -M versatileab -m 128M -cpu cortex-a8 -nographic -kernel $(OUT_DIR)kernel.elf
5555

5656
docker:
5757
docker build -t "astra-kernel" .

check-kernel.sh

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#!/usr/bin/env bash
2+
# This file contain multiple sanity check for testing purpose of the
3+
# vectors table alginement and such.
4+
# run chmod +x ./check-kernel.sh before hand
5+
set -e
6+
7+
ELF=build/kernel.elf
8+
9+
echo "=== Running sanity checks on $ELF ==="
10+
11+
# Check .vectors at 0x0
12+
if arm-none-eabi-objdump -h "$ELF" | grep -q '\.vectors.*00000000'; then
13+
echo "[PASS] .vectors section is mapped at VMA 0x00000000"
14+
else
15+
echo "[FAIL] .vectors not at 0x0!"
16+
fi
17+
18+
# Check entry point is _start
19+
ENTRY=$(arm-none-eabi-readelf -h "$ELF" | grep 'Entry point' | awk '{print $4}' | sed 's/^0x//')
20+
START_ADDR=$(arm-none-eabi-nm -n "$ELF" | grep " T _start" | awk '{print $1}')
21+
if [ $((16#$ENTRY)) -eq $((16#$START_ADDR)) ]; then
22+
echo "[PASS] Entry point matches _start (0x$ENTRY)"
23+
else
24+
echo "[FAIL] Entry point mismatch: entry=0x$ENTRY, _start=0x$START_ADDR"
25+
fi
26+
27+
# Check vector table branches correctly
28+
DISASM=$(arm-none-eabi-objdump -d -j .vectors "$ELF")
29+
30+
if echo "$DISASM" | grep -q "b.*<_start>"; then
31+
echo "[PASS] Reset vector branches to _start"
32+
else
33+
echo "[FAIL] Reset vector does not branch to _start!"
34+
fi
35+
36+
if echo "$DISASM" | grep -q "b.*<irq_entry>"; then
37+
echo "[PASS] IRQ vector branches to irq_entry"
38+
else
39+
echo "[FAIL] IRQ vector does not branch to irq_entry!"
40+
fi
41+
42+
# Check that irq_entry symbol exists
43+
if arm-none-eabi-nm -n "$ELF" | grep -q " T irq_entry"; then
44+
echo "[PASS] irq_entry symbol is defined"
45+
else
46+
echo "[FAIL] irq_entry missing!"
47+
fi
48+
49+
# Check BSS symbols exist
50+
if arm-none-eabi-nm -n "$ELF" | grep -q "__bss_start" && \
51+
arm-none-eabi-nm -n "$ELF" | grep -q "__bss_end"; then
52+
echo "[PASS] __bss_start and __bss_end are defined"
53+
else
54+
echo "[FAIL] Missing __bss_start/__bss_end!"
55+
fi
56+
57+
echo "=== Checks complete ==="

include/irq.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#ifndef IRQ_H
2+
#define IRQ_H
3+
4+
#include <stdint.h>
5+
6+
#ifdef __cplusplus
7+
extern "C"
8+
{
9+
#endif
10+
11+
void irq_handler(void);
12+
13+
void irq_enable(void);
14+
void irq_disable(void);
15+
16+
extern volatile unsigned int tick;
17+
18+
#ifdef __cplusplus
19+
}
20+
#endif
21+
22+
#endif // IRQ_H

kernel.ld

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,60 @@
1-
/* kernel.ld file */
21
ASSERT(SIZEOF(.text) < 0x00100000, "Error: .text grew beyond the 1 MiB safety window");
32
OUTPUT_ARCH(arm)
43
OUTPUT_FORMAT("elf32-littlearm","elf32-bigarm","elf32-littlearm")
54
6-
75
ENTRY(_start)
86
97
MEMORY
108
{
11-
ram : ORIGIN = 0x00000000, LENGTH = 0x07FFFFFF
9+
ram : ORIGIN = 0x00000000, LENGTH = 0x08000000 /* 128 MB */
1210
}
1311
1412
SECTIONS
1513
{
16-
. = 0x10000; /* Start at 64KB for the kernel */
14+
/* Exception vector table at 0x00000000
15+
* the . line can be removed at some point
16+
* if we want, as the VBAR alone determine where
17+
* exceptions land. This will be done once the MMU
18+
* is fully enabled. For this, we will need to have
19+
* the page table in place (vector Virtual Addres (VA) mapped)
20+
*/
21+
. = 0x00000000;
22+
.vectors ALIGN(32) :
23+
{
24+
KEEP(*(.vectors))
25+
} > ram
26+
27+
/* Main kernel starts at 64KB */
28+
. = 0x10000;
1729
.text BLOCK(4K) : ALIGN(4K)
1830
{
1931
*(.text)
2032
*(.text*)
21-
}
33+
} > ram
2234
2335
.rodata BLOCK(4K) : ALIGN(4K)
2436
{
2537
*(.rodata)
2638
*(.rodata*)
27-
}
39+
} > ram
2840
2941
.data BLOCK(4K) : ALIGN(4K)
3042
{
31-
*(.data)
32-
}
33-
43+
*(.data)
44+
} > ram
45+
3446
.bss BLOCK(4K) : ALIGN(4K)
3547
{
36-
__bss_start = .;
37-
*(.bss)
48+
__bss_start = .;
49+
*(.bss)
3850
*(.bss*)
39-
*(COMMON)
40-
__bss_end = .;
41-
}
42-
43-
/* Top‐of‐RAM stack pointer */
51+
*(COMMON)
52+
__bss_end = .;
53+
} > ram
54+
55+
/* Stack pointer = top of RAM */
4456
_estack = ORIGIN(ram) + LENGTH(ram);
4557
4658
/* Heap starts right after .bss */
47-
_eheap = ALIGN( __bss_end );
48-
49-
}
59+
_eheap = ALIGN(__bss_end);
60+
}

kernel/irq.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#include <stdint.h>
2+
3+
#include "irq.h"
4+
5+
volatile unsigned int tick = 0;
6+
7+
void irq_handler(void)
8+
{
9+
tick++;
10+
}
11+
12+
inline void irq_disable(void)
13+
{
14+
__asm__ volatile("cpsid i" ::: "memory"); // mask IRQ
15+
}
16+
17+
inline void irq_enable(void)
18+
{
19+
__asm__ volatile("cpsie i" ::: "memory"); // unmask IRQ
20+
__asm__ volatile("isb" ::: "memory"); // take effect immediately
21+
}

kernel/kernel.c

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
#include "printf.h"
66
#include "clear.h"
77
#include "string.h"
8+
#include "irq.h"
9+
810

911
static const char *banner[] = {
1012
"========================================\r\n",
@@ -26,17 +28,47 @@ static void init_message(void)
2628
{
2729
puts(banner[i]);
2830
}
31+
32+
printf("AstraKernel is running...\r\n");
33+
printf("Press Ctrl-A and then X to exit QEMU.\r\n");
34+
printf("\r\n");
35+
}
36+
37+
void irq_sanity_check(void)
38+
{
39+
irq_disable();
40+
unsigned before = tick;
41+
42+
irq_enable();
43+
irq_disable();
44+
45+
unsigned after = tick;
46+
47+
if (before == after)
48+
{
49+
puts("\r\nA1 Sanity PASS: no spurious IRQs\r\n");
50+
}
51+
else
52+
{
53+
puts("\r\nA1 Sanity FAIL: unexpected IRQs\r\n");
54+
}
2955
}
3056

57+
/* The following macros are for testing purposes. */
58+
#define SANITY_CHECK irq_sanity_check()
59+
#define CALL_SVC_0 __asm__ volatile ("svc #0")
60+
3161
// Entry point for the kernel
3262
void kernel_main(void)
3363
{
3464
clear();
3565

66+
/* TEST */
67+
SANITY_CHECK;
68+
CALL_SVC_0;
69+
70+
/* Back to normal operations */
3671
init_message();
37-
printf("AstraKernel is running...\r\n");
38-
printf("Press Ctrl-A and then X to exit QEMU.\r\n");
39-
printf("\r\n");
4072

4173
char input_buffer[100];
4274

@@ -59,25 +91,25 @@ void kernel_main(void)
5991
break;
6092
case 'e':
6193
int result = strcmp("abc", "abc"); // Expect 0
62-
printf("Expect 0 -> %d\n", result);
94+
printf("Expect 0 -> %d\r\n", result);
6395

6496
result = strcmp("abc", "abd"); // Expect -1
65-
printf("Expect -1 -> %d\n", result);
97+
printf("Expect -1 -> %d\r\n", result);
6698

6799
result = strcmp("abc", "ABC"); // Expect 1
68-
printf("Expect 1 -> %d\n", result);
100+
printf("Expect 1 -> %d\r\n", result);
69101

70102
result = strcmp("ABC", "abc"); // Expect -1
71-
printf("Expect -1 -> %d\n", result);
103+
printf("Expect -1 -> %d\r\n", result);
72104

73105
result = strcmp("\x01\x02\x03", "\x01\x02\x03"); // Expect 0
74-
printf("Expect 0 -> %d\n", result);
106+
printf("Expect 0 -> %d\r\n", result);
75107

76108
result = strcmp("\x01\x02\x03", "\x01\x02\x04"); // Expect -1
77-
printf("Expect -1 -> %d\n", result);
109+
printf("Expect -1 -> %d\r\n", result);
78110

79111
result = strcmp("\x01\x02\x04", "\x01\x02\x03"); // Expect 1
80-
printf("Expect 1 -> %d\n", result);
112+
printf("Expect 1 -> %d\r\n", result);
81113
break;
82114
case 'q': // Check for exit command
83115
printf("Exiting...\r\n");
@@ -89,11 +121,11 @@ void kernel_main(void)
89121

90122
case 't': // Check for time command
91123
gettime(&time_struct);
92-
printf("Current time(GMT): %d:%d:%d\n", time_struct.hrs, time_struct.mins, time_struct.secs);
124+
printf("Current time(GMT): %d:%d:%d\r\n", time_struct.hrs, time_struct.mins, time_struct.secs);
93125
break;
94126
case 'd': // Check for date command
95127
getdate(&date_struct);
96-
printf("Current date(MM-DD-YYYY): %d-%d-%d\n", date_struct.month, date_struct.day, date_struct.year);
128+
printf("Current date(MM-DD-YYYY): %d-%d-%d\r\n", date_struct.month, date_struct.day, date_struct.year);
97129
break;
98130
default:
99131
printf("Unknown command. Type 'h' for help.\r\n");

0 commit comments

Comments
 (0)