Skip to content

Commit f4afe1a

Browse files
authored
Merge pull request #10 from sandbox-science/Develop
Basic Timer Interrupt
2 parents 050c803 + 17e30a2 commit f4afe1a

File tree

8 files changed

+93
-3
lines changed

8 files changed

+93
-3
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ $(OUT_DIR)start.o: kernel/start.s
3636
# Pattern rule for any .c → build/*.o
3737
$(OUT_DIR)%.o: %.c
3838
@mkdir -p $(OUT_DIR)
39-
$(CC) $(CFLAGS) -c $< -o $@
39+
$(CC) $(CFLAGS) -c $< -o $@ $(KFLAGS) # KFLAGS is used for custom kernel flags
4040

4141
# Link everything
4242
$(OUT_DIR)kernel.elf: $(OUT_DIR)start.o $(OBJS) kernel.ld

README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ Make sure you have an ARM cross-compiler installed (e.g., `arm-none-eabi-gcc`) a
3434
make
3535
```
3636

37+
Developers also have the option to run the kernel with custom flags such as:
38+
```sh
39+
make KFLAGS="-USE_KTESTS -MY_DEFFLAG"
40+
```
41+
3742
> [!IMPORTANT]
3843
>
3944
> `make` will clean, build, and run the kernel in QEMU. You can also run
@@ -64,4 +69,4 @@ For more details about this kernel, refer to the [AstraKernel Documentation](htt
6469
6570
## License
6671

67-
This project is licensed under the GNU GENERAL PUBLIC License. See the [LICENSE](LICENSE) file for details.
72+
This project is licensed under the GNU GENERAL PUBLIC License. See the [LICENSE](LICENSE) file for details.

include/interrupt.h

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#ifndef INTERRUPT_H
2+
#define INTERRUPT_H
3+
4+
#include <stdint.h>
5+
6+
#ifdef __cplusplus
7+
extern "C"
8+
{
9+
#endif
10+
11+
// PL190 VIC (interrupt controller)
12+
// ref: PrimeCell Vectored Interrupt Controller (PL190) TRM (Page3-7)
13+
#define VIC_BASE 0x10140000u
14+
#define VIC_INTSELECT (*(volatile uint32_t *)(VIC_BASE + 0x00C)) // 0=IRQ,1=FIQ
15+
#define VIC_INTENABLE (*(volatile uint32_t *)(VIC_BASE + 0x010)) // set bit=enable
16+
#define VIC_INT_ENCLR (*(volatile utin32_t *)(VIC_BASE + 0x014))
17+
#define VIC_SOFT_INT (*(volatile uint32_t *)(VIC_BASE + 0x018))
18+
#define VIC_SOFT_INTCLR (*(volatile uint32_t *)(VIC_BASE + 0x01C))
19+
20+
// SP804 Timer0 in the 0/1 block
21+
// ref: ARM Dual-Time Module (SP804) TRM (Page 3-2)
22+
#define T01_BASE 0x101E2000u
23+
#define T0_LOAD (*(volatile uint32_t *)(T01_BASE + 0x00))
24+
#define T0_VALUE (*(volatile uint32_t *)(T01_BASE + 0x04))
25+
#define T0_CONTROL (*(volatile uint32_t *)(T01_BASE + 0x08))
26+
#define T0_INTCLR (*(volatile uint32_t *)(T01_BASE + 0x0C))
27+
#define T0_MIS (*(volatile uint32_t *)(T01_BASE + 0x14))
28+
29+
// Bits for CONTROL (SP804)
30+
// ref: ARM Dual-Time Module (SP804) TRM (Page 3-5)
31+
#define TCTRL_ENABLE (1u << 7) // EN=bit7
32+
#define TCTRL_PERIODIC (1u << 6) // PERIODIC=bit6
33+
#define TCTRL_INTEN (1u << 5) // INTEN=bit5
34+
#define TCTRL_32BIT (1u << 1) // 32BIT=bit1
35+
36+
// VIC line number for Timer0/1 on Versatile
37+
#define IRQ_TIMER01 4
38+
39+
static inline void timer0_start_periodic(uint32_t load)
40+
{
41+
T0_CONTROL = 0; // disable while reconfig
42+
T0_LOAD = load; // ex: 10000 for ~100 Hz if TIMCLK≈1 MHz
43+
T0_INTCLR = 1; // clear any pending interrupt
44+
T0_CONTROL = TCTRL_32BIT | TCTRL_PERIODIC | TCTRL_INTEN | TCTRL_ENABLE;
45+
}
46+
47+
static inline void vic_enable_timer01_irq(void)
48+
{
49+
VIC_INTSELECT &= ~(1u << IRQ_TIMER01); // route to IRQ
50+
VIC_INTENABLE |= (1u << IRQ_TIMER01); // enable line 4
51+
}
52+
#ifdef __cplusplus
53+
}
54+
#endif
55+
56+
#endif // INTERRUPT_H

kernel/irq.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
#include <stdint.h>
22

33
#include "irq.h"
4+
#include "interrupt.h"
45

56
volatile unsigned int tick = 0;
67

78
void irq_handler(void)
89
{
10+
T0_INTCLR = 1; // this ack/clear the device (SP804)
911
tick++;
1012
}
1113

kernel/kernel.c

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "clear.h"
77
#include "string.h"
88
#include "irq.h"
9+
#include "interrupt.h"
910

1011

1112
static const char *banner[] = {
@@ -54,7 +55,30 @@ void irq_sanity_check(void)
5455
}
5556
}
5657

58+
// This function is for testing purposes.
59+
// It test that the timer interrupt is firing as expected.
60+
void not_main(void)
61+
{
62+
puts("Time0 IRQ firing test!\r\n");
63+
64+
vic_enable_timer01_irq();
65+
timer0_start_periodic(10000);
66+
irq_enable();
67+
68+
unsigned last = 0;
69+
for (;;)
70+
{
71+
unsigned n = tick;
72+
if (n != last && (n % 100) == 0)
73+
{
74+
puts(".");
75+
last = n;
76+
}
77+
}
78+
}
79+
5780
/* The following macros are for testing purposes. */
81+
#define TIMER_TICK_TEST not_main()
5882
#define SANITY_CHECK irq_sanity_check()
5983
#define CALL_SVC_0 __asm__ volatile ("svc #0")
6084

@@ -63,9 +87,12 @@ void kernel_main(void)
6387
{
6488
clear();
6589

66-
/* TEST */
90+
/* TESTS */
91+
#ifdef USE_KTESTS
6792
SANITY_CHECK;
6893
CALL_SVC_0;
94+
TIMER_TICK_TEST;
95+
#endif
6996

7097
/* Back to normal operations */
7198
init_message();
2.78 MB
Binary file not shown.
383 KB
Binary file not shown.
515 KB
Binary file not shown.

0 commit comments

Comments
 (0)