mirror of
https://github.com/isometimes/rpi4-osdev
synced 2024-11-23 18:50:40 +00:00
Compare commits
5 commits
753489b857
...
71c3b30bd0
Author | SHA1 | Date | |
---|---|---|---|
|
71c3b30bd0 | ||
|
31bb21b323 | ||
|
e087746a5d | ||
|
9566e13a7f | ||
|
3faf8d10ff |
9 changed files with 26 additions and 4 deletions
|
@ -35,6 +35,7 @@ The timers are set up using these calls:
|
||||||
```c
|
```c
|
||||||
irq_init_vectors();
|
irq_init_vectors();
|
||||||
enable_interrupt_controller();
|
enable_interrupt_controller();
|
||||||
|
irq_barrier();
|
||||||
irq_enable();
|
irq_enable();
|
||||||
timer_init();
|
timer_init();
|
||||||
```
|
```
|
||||||
|
@ -77,7 +78,7 @@ In the middle we simply call a function called `handle_irq()` which is written i
|
||||||
void handle_irq() {
|
void handle_irq() {
|
||||||
unsigned int irq = REGS_IRQ->irq0_pending_0;
|
unsigned int irq = REGS_IRQ->irq0_pending_0;
|
||||||
|
|
||||||
while(irq) {
|
while(irq & (SYS_TIMER_IRQ_1 | SYS_TIMER_IRQ_3)) {
|
||||||
if (irq & SYS_TIMER_IRQ_1) {
|
if (irq & SYS_TIMER_IRQ_1) {
|
||||||
irq &= ~SYS_TIMER_IRQ_1;
|
irq &= ~SYS_TIMER_IRQ_1;
|
||||||
|
|
||||||
|
@ -117,7 +118,9 @@ To begin receiving interrupts, we need to take one more step: unmasking all type
|
||||||
|
|
||||||
Masking is a technique used by the CPU to prevent a particular piece of code from being stopped in its tracks by an interrupt. It's used to protect important code that *must* complete. Imagine what would happen if our `kernel_entry` code (that saves register state) was interrupted halfway through! In this case, the register state would be overwritten and lost. This is why the CPU automatically masks all interrupts when an exception handler is executed.
|
Masking is a technique used by the CPU to prevent a particular piece of code from being stopped in its tracks by an interrupt. It's used to protect important code that *must* complete. Imagine what would happen if our `kernel_entry` code (that saves register state) was interrupted halfway through! In this case, the register state would be overwritten and lost. This is why the CPU automatically masks all interrupts when an exception handler is executed.
|
||||||
|
|
||||||
The `irq_enable` and `irq_disable` functions in _utils.S_ are responsible for masking and unmasking interrupts:
|
The `irq_enable` and `irq_disable` functions in _utils.S_ are responsible for masking and unmasking interrupts.
|
||||||
|
|
||||||
|
They are helped by the `irq_barrier` function which ensures that the `enable_interrupt_controller()` call properly finishes before the `irq_enable()` call is made:
|
||||||
|
|
||||||
```c
|
```c
|
||||||
.globl irq_enable
|
.globl irq_enable
|
||||||
|
@ -129,6 +132,11 @@ irq_enable:
|
||||||
irq_disable:
|
irq_disable:
|
||||||
msr daifset, #2
|
msr daifset, #2
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
.globl irq_barrier
|
||||||
|
irq_barrier:
|
||||||
|
dsb sy
|
||||||
|
ret
|
||||||
```
|
```
|
||||||
|
|
||||||
As soon as `irq_enable()` is called from `main()` in _kernel.c_, the timer handler is run when the timer interrupt fires. Well, sort of...!
|
As soon as `irq_enable()` is called from `main()` in _kernel.c_, the timer handler is run when the timer interrupt fires. Well, sort of...!
|
||||||
|
|
|
@ -11,7 +11,7 @@ void disable_interrupt_controller() {
|
||||||
void handle_irq() {
|
void handle_irq() {
|
||||||
unsigned int irq = REGS_IRQ->irq0_pending_0;
|
unsigned int irq = REGS_IRQ->irq0_pending_0;
|
||||||
|
|
||||||
while(irq) {
|
while(irq & (SYS_TIMER_IRQ_1 | SYS_TIMER_IRQ_3)) {
|
||||||
if (irq & SYS_TIMER_IRQ_1) {
|
if (irq & SYS_TIMER_IRQ_1) {
|
||||||
irq &= ~SYS_TIMER_IRQ_1;
|
irq &= ~SYS_TIMER_IRQ_1;
|
||||||
|
|
||||||
|
|
|
@ -120,6 +120,7 @@ void main(void)
|
||||||
|
|
||||||
irq_init_vectors();
|
irq_init_vectors();
|
||||||
enable_interrupt_controller();
|
enable_interrupt_controller();
|
||||||
|
irq_barrier();
|
||||||
irq_enable();
|
irq_enable();
|
||||||
timer_init();
|
timer_init();
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@ enum vc_irqs {
|
||||||
|
|
||||||
void irq_init_vectors();
|
void irq_init_vectors();
|
||||||
void irq_enable();
|
void irq_enable();
|
||||||
|
void irq_barrier();
|
||||||
void irq_disable();
|
void irq_disable();
|
||||||
void enable_interrupt_controller();
|
void enable_interrupt_controller();
|
||||||
void disable_interrupt_controller();
|
void disable_interrupt_controller();
|
||||||
|
|
|
@ -13,3 +13,8 @@ irq_enable:
|
||||||
irq_disable:
|
irq_disable:
|
||||||
msr daifset, #2
|
msr daifset, #2
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
.globl irq_barrier
|
||||||
|
irq_barrier:
|
||||||
|
dsb sy
|
||||||
|
ret
|
||||||
|
|
|
@ -11,7 +11,7 @@ void disable_interrupt_controller() {
|
||||||
void handle_irq() {
|
void handle_irq() {
|
||||||
unsigned int irq = REGS_IRQ->irq0_pending_0;
|
unsigned int irq = REGS_IRQ->irq0_pending_0;
|
||||||
|
|
||||||
while(irq) {
|
while(irq & (SYS_TIMER_IRQ_1 | SYS_TIMER_IRQ_3)) {
|
||||||
if (irq & SYS_TIMER_IRQ_1) {
|
if (irq & SYS_TIMER_IRQ_1) {
|
||||||
irq &= ~SYS_TIMER_IRQ_1;
|
irq &= ~SYS_TIMER_IRQ_1;
|
||||||
|
|
||||||
|
|
|
@ -147,6 +147,7 @@ void main(void)
|
||||||
|
|
||||||
irq_init_vectors();
|
irq_init_vectors();
|
||||||
enable_interrupt_controller();
|
enable_interrupt_controller();
|
||||||
|
irq_barrier();
|
||||||
irq_enable();
|
irq_enable();
|
||||||
timer_init();
|
timer_init();
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@ enum vc_irqs {
|
||||||
|
|
||||||
void irq_init_vectors();
|
void irq_init_vectors();
|
||||||
void irq_enable();
|
void irq_enable();
|
||||||
|
void irq_barrier();
|
||||||
void irq_disable();
|
void irq_disable();
|
||||||
void enable_interrupt_controller();
|
void enable_interrupt_controller();
|
||||||
void disable_interrupt_controller();
|
void disable_interrupt_controller();
|
||||||
|
|
|
@ -13,3 +13,8 @@ irq_enable:
|
||||||
irq_disable:
|
irq_disable:
|
||||||
msr daifset, #2
|
msr daifset, #2
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
.globl irq_barrier
|
||||||
|
irq_barrier:
|
||||||
|
dsb sy
|
||||||
|
ret
|
||||||
|
|
Loading…
Reference in a new issue