diff options
author | Wojtek Kosior <kwojtus@protonmail.com> | 2020-01-02 13:24:29 +0100 |
---|---|---|
committer | Wojtek Kosior <kwojtus@protonmail.com> | 2020-01-02 13:24:29 +0100 |
commit | 3941fe97783c7a31ab04fbfb127f5026dd31ef78 (patch) | |
tree | 523b0b1d626969c3eb52545b672ca909dd5ae31b | |
parent | ea465f85cf7a47f488332509a2f6d7ae5c88057c (diff) | |
download | rpi-MMU-example-3941fe97783c7a31ab04fbfb127f5026dd31ef78.tar.gz rpi-MMU-example-3941fe97783c7a31ab04fbfb127f5026dd31ef78.zip |
demo of arm timer irq
-rw-r--r-- | PL0_test.c | 29 | ||||
-rw-r--r-- | armclock.h | 53 | ||||
-rw-r--r-- | demo_functionality.c | 4 | ||||
-rw-r--r-- | interrupts.c | 14 | ||||
-rw-r--r-- | setup.c | 9 |
5 files changed, 78 insertions, 31 deletions
@@ -5,25 +5,30 @@ void PL0_main(void) { // If loading program to userspace and handling of svc are // implemented correctly, this shall get printed - puts("Hello userspace!"); + puts("Hello userspace! Type 'f' if you want me to try accessing " + "kernel memory!"); - // if we're indeed in PL0, we should trigger the abort handler now, - // when trying to access memory we're not allowed to - puts("Attempting to meddle with kernel memory from userspace :d"); - char first_kernel_byte[2]; - - first_kernel_byte[0] = *(char*) 0x0; - first_kernel_byte[1] = '\0'; - - puts(first_kernel_byte); - while (1) { char c = getchar(); if (c == '\r') putchar('\n'); - + putchar(c); + + if (c == 'f') + { + // if we're indeed in PL0, we should trigger the abort + // handler now, when trying to access memory we're not + // allowed to + puts("Attempting to read kernel memory from userspace :d"); + char first_kernel_byte[2]; + + first_kernel_byte[0] = *(char*) 0x0; + first_kernel_byte[1] = '\0'; + + puts(first_kernel_byte); + } } } @@ -1,6 +1,8 @@ #ifndef ARMCLOCK_H #define ARMCLOCK_H +#include <stdint.h> + #include "global.h" #define ARMCLK_LOAD (ARM_BASE + 0x400) @@ -15,35 +17,56 @@ #define ARMCLK_LOAD_FREE_RUNNING_COUNTER (ARM_BASE + 0x420) #define BCMCLK_ENABLE_BASIC_IRQS (ARM_BASE + 0x218) +#define BCMCLK_DISABLE_BASIC_IRQS (ARM_BASE + 0x224) -static inline void armclk_enable_timer_irq(void) +typedef union armclk_control { - // uint32_t control_reg = *(uint32_t volatile*) ARMCLK_CONTROL; - // control_reg |= 1 << 5; - // *(uint32_t volatile*) ARMCLK_CONTROL = control_reg; - *(uint32_t volatile*) ARMCLK_CONTROL = 0x00000000; - *(uint32_t volatile*) ARMCLK_LOAD_PRE_DRIVER = 0x000000f9; - *(uint32_t volatile*) ARMCLK_LOAD_RELOAD = 0x4C4B40; //50 times a Sec by 250Mhz - *(uint32_t volatile*) ARMCLK_LOAD = 0x4C4B40;//50 times a Sec by 250Mhz - *(uint32_t volatile*) ARMCLK_IRQ_CLR_ACK = 0x00000000; - *(uint32_t volatile*) ARMCLK_CONTROL = 0x000000a2; - + uint32_t raw; + struct + { + uint32_t one_shot_mode : 1; // bit 0; unused in RPi + uint32_t counter_23bit : 1; // bit 1 + uint32_t pre_scale : 2; // bits 3:2 + uint32_t bit_4 : 1; // bit 4 + uint32_t interrupt_enable : 1; // bit 5 + uint32_t periodic_mode : 1; // bit 6; unused in RPi + uint32_t timer_enable : 1; // bit 7 + uint32_t halt_in_debug : 1; // bit 8 + uint32_t free_running_enable : 1; // bit 9 + uint32_t bits_15_10 : 6; // bits 15:10 + uint32_t free_running_pre_scaler : 8; // bits 23:16 + uint32_t bits_31_24 : 8; // bits 31:24 + } fields; +} armclk_control_t; +static inline void armclk_init(void) +{ + armclk_control_t ctrl = (armclk_control_t) (uint32_t) 0; + ctrl.fields.timer_enable = 1; + ctrl.fields.interrupt_enable = 1; + ctrl.fields.counter_23bit = 1; + *(uint32_t volatile*) ARMCLK_CONTROL = ctrl.raw; +} - +static inline void armclk_enable_timer_irq(void) +{ *(uint32_t volatile*) BCMCLK_ENABLE_BASIC_IRQS = 1; } static inline void armclk_disable_timer_irq(void) { - uint32_t control_reg = *(uint32_t volatile*) ARMCLK_CONTROL; - control_reg &= ~((uint32_t) 1 << 5); - *(uint32_t volatile*) ARMCLK_CONTROL = control_reg; + *(uint32_t volatile*) BCMCLK_DISABLE_BASIC_IRQS = 1; } static inline void armclk_set_timer_match_timeout(uint32_t timeout) { + *(uint32_t volatile*) ARMCLK_IRQ_CLR_ACK = 0; *(uint32_t volatile*) ARMCLK_LOAD = timeout; } +static inline _Bool armclk_irq_pending(void) +{ + return *(uint32_t volatile*) ARMCLK_LOAD_RAW_IRQ; +} + #endif // ARMCLOCK_H diff --git a/demo_functionality.c b/demo_functionality.c index 3cf5b8f..a2d8550 100644 --- a/demo_functionality.c +++ b/demo_functionality.c @@ -5,6 +5,7 @@ #include "ramfs.h" #include "strings.h" #include "paging.h" +#include "armclock.h" void demo_paging_support(void) { @@ -120,10 +121,13 @@ void demo_go_unprivileged(void) PSR_t new_SPSR = read_CPSR(); new_SPSR.fields.PSR_MODE_4_0 = MODE_USER; + new_SPSR.fields.PSR_IRQ_MASK_BIT = 0; write_SPSR(new_SPSR); puts("All ready, jumping to PL0 code"); + armclk_set_timer_match_timeout(0x00100000); + asm volatile("cps %[sysmode]\n\r" "mov sp, %[stackaddr]\n\r" "cps %[supmode]\n\r" diff --git a/interrupts.c b/interrupts.c index c6e3f17..62c644b 100644 --- a/interrupts.c +++ b/interrupts.c @@ -1,5 +1,6 @@ #include "io.h" #include "svc_interface.h" +#include "armclock.h" void __attribute__((noreturn)) setup(void); @@ -58,9 +59,16 @@ void generic_handler(void) void irq_handler(void) { - puts("irq happened"); - - while(1); + if (armclk_irq_pending()) + { + puts("<<irq from timer>>"); + armclk_set_timer_match_timeout(0x00100000); + } + else + { + puts("unknown irq"); + while(1); + } } void fiq_handler(void) @@ -5,6 +5,7 @@ #include "atags.h" // for POWER_OF_2() macro... perhaps the macro should be moved #include "memory.h" +#include "armclock.h" void setup(uint32_t r0, uint32_t machine_type, struct atag_header *atags) @@ -14,7 +15,7 @@ void setup(uint32_t r0, uint32_t machine_type, // When we attach screen session after loading kernel with socat // we miss kernel's greeting... So we'll make the kernel wait for // one char we're going to send from within screen - //getchar(); + getchar(); puts("Hello, kernel World!"); @@ -97,6 +98,12 @@ void setup(uint32_t r0, uint32_t machine_type, // loads a blob there demo_setup_PL0(); + // sets some general settings for arm timer + armclk_init(); + + // turns on irq from arm timer + armclk_enable_timer_irq(); + // jumps to unprivileged code... never, ever, ever returns demo_go_unprivileged(); |