diff options
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | docs/interrupts.png | bin | 0 -> 38473 bytes | |||
-rw-r--r-- | interrupt_vector.S | 6 | ||||
-rw-r--r-- | interrupts.c | 33 | ||||
-rw-r--r-- | interrupts.h | 128 | ||||
-rw-r--r-- | kernel.c | 0 | ||||
-rw-r--r-- | psr.h | 2 | ||||
-rwxr-xr-x | readfromrpi.sh | 4 |
8 files changed, 172 insertions, 3 deletions
@@ -1,3 +1,5 @@ +.gitignore +.idea *.o *.elf *.img diff --git a/docs/interrupts.png b/docs/interrupts.png Binary files differnew file mode 100644 index 0000000..8973fa8 --- /dev/null +++ b/docs/interrupts.png diff --git a/interrupt_vector.S b/interrupt_vector.S index 9404839..1ec80f7 100644 --- a/interrupt_vector.S +++ b/interrupt_vector.S @@ -49,4 +49,8 @@ fiq_handler_caller: ldr sp, =_fiq_stack_top ldr r5, =fiq_handler bx r5 - + +irq: + mov sp, #0x8000 + ldr r5, =abort_handler + subs pc,lr,#4 diff --git a/interrupts.c b/interrupts.c index bf7ed02..51cab25 100644 --- a/interrupts.c +++ b/interrupts.c @@ -3,6 +3,10 @@ #include "svc_interface.h" #include "armclock.h" #include "scheduler.h" +/** + @brief The undefined instruction interrupt handler +**/ + void __attribute__((noreturn)) setup(void); @@ -31,7 +35,7 @@ uint32_t supervisor_call_handler(uint32_t regs[14]) int c; if ((c = getchar_non_blocking()) == -1) schedule_wait_for_input(regs); - + regs[0] = c; break; } @@ -102,3 +106,30 @@ void fiq_handler(void) error("fiq happened"); } + +/* Here is your interrupt function */ +void +__attribute__((interrupt("IRQ"))) +__attribute__((section(".interrupt_vectors.text"))) +irq_handler2(void) { + /* You code goes here */ +// uart_puts("GOT INTERRUPT!\r\n"); + + local_timer_clr_reload_reg_t temp = { .IntClear = 1, .Reload = 1 }; + QA7->TimerClearReload = temp; // Clear interrupt & reload +} + +/* here is your main */ +int enable_timer(void) { + + QA7->TimerRouting.Routing = LOCALTIMER_TO_CORE0_IRQ; // Route local timer IRQ to Core0 + QA7->TimerControlStatus.ReloadValue = 100; // Timer period set + QA7->TimerControlStatus.TimerEnable = 1; // Timer enabled + QA7->TimerControlStatus.IntEnable = 1; // Timer IRQ enabled + QA7->TimerClearReload.IntClear = 1; // Clear interrupt + QA7->TimerClearReload.Reload = 1; // Reload now + QA7->Core0TimerIntControl.nCNTPNSIRQ_IRQ = 1; // We are in NS EL1 so enable IRQ to core0 that level + QA7->Core0TimerIntControl.nCNTPNSIRQ_FIQ = 0; // Make sure FIQ is zero +// uart_puts("Enabled Timer\r\n"); + return(0); +}
\ No newline at end of file diff --git a/interrupts.h b/interrupts.h new file mode 100644 index 0000000..e9ade80 --- /dev/null +++ b/interrupts.h @@ -0,0 +1,128 @@ +#ifndef RPI_MMU_EXAMPLE_INTERRUPTS_H +#define RPI_MMU_EXAMPLE_INTERRUPTS_H + +#include <stdint.h> + + //offset of peripherals+ offset for first addresable register for interupt controller +#define RPI_INTERRUPT_CONTROLLER_BASE ( 0x3F000000UL + 0xB200 ) + +// Bits in the Enable_Basic_IRQs register to enable various interrupts. +// According to the BCM2835 ARM Peripherals manual, section 7.5 */ + +#define RPI_BASIC_ARM_TIMER_IRQ (1 << 0) +#define RPI_BASIC_ARM_MAILBOX_IRQ (1 << 1) +#define RPI_BASIC_ARM_DOORBELL_0_IRQ (1 << 2) +#define RPI_BASIC_ARM_DOORBELL_1_IRQ (1 << 3) +#define RPI_BASIC_GPU_0_HALTED_IRQ (1 << 4) +#define RPI_BASIC_GPU_1_HALTED_IRQ (1 << 5) +#define RPI_BASIC_ACCESS_ERROR_1_IRQ (1 << 6) +#define RPI_BASIC_ACCESS_ERROR_0_IRQ (1 << 7) + +// @brief The interrupt controller memory mapped register set +typedef struct { + volatile uint32_t IRQ_basic_pending; + volatile uint32_t IRQ_pending_1; + volatile uint32_t IRQ_pending_2; + volatile uint32_t FIQ_control; + volatile uint32_t Enable_IRQs_1; + volatile uint32_t Enable_IRQs_2; + volatile uint32_t Enable_Basic_IRQs; + volatile uint32_t Disable_IRQs_1; + volatile uint32_t Disable_IRQs_2; + volatile uint32_t Disable_Basic_IRQs; +} rpi_irq_controller_t; + +extern rpi_irq_controller_t* RPI_GetIrqController(void); + +//TIMER + +/*--------------------------------------------------------------------------} +{ LOCAL TIMER INTERRUPT ROUTING REGISTER - QA7_rev3.4.pdf page 18 } +{--------------------------------------------------------------------------*/ +typedef union +{ + struct + { + enum { + LOCALTIMER_TO_CORE0_IRQ = 0, + LOCALTIMER_TO_CORE1_IRQ = 1, + LOCALTIMER_TO_CORE2_IRQ = 2, + LOCALTIMER_TO_CORE3_IRQ = 3, + LOCALTIMER_TO_CORE0_FIQ = 4, + LOCALTIMER_TO_CORE1_FIQ = 5, + LOCALTIMER_TO_CORE2_FIQ = 6, + LOCALTIMER_TO_CORE3_FIQ = 7, + } Routing: 3; // @0-2 Local Timer routing + unsigned unused : 29; // @3-31 + }; + uint32_t Raw32; // Union to access all 32 bits as a uint32_t +} local_timer_int_route_reg_t; + +/*--------------------------------------------------------------------------} +{ LOCAL TIMER CONTROL AND STATUS REGISTER - QA7_rev3.4.pdf page 17 } +{--------------------------------------------------------------------------*/ +typedef union +{ + struct + { + unsigned ReloadValue : 28; // @0-27 Reload value + unsigned TimerEnable : 1; // @28 Timer enable (1 = enabled) + unsigned IntEnable : 1; // @29 Interrupt enable (1= enabled) + unsigned unused : 1; // @30 Unused + unsigned IntPending : 1; // @31 Timer Interrupt flag (Read-Only) + }; + uint32_t Raw32; // Union to access all 32 bits as a uint32_t +} local_timer_ctrl_status_reg_t; + +/*--------------------------------------------------------------------------} +{ LOCAL TIMER CLEAR AND RELOAD REGISTER - QA7_rev3.4.pdf page 18 } +{--------------------------------------------------------------------------*/ +typedef union +{ + struct + { + unsigned unused : 30; // @0-29 unused + unsigned Reload : 1; // @30 Local timer-reloaded when written as 1 + unsigned IntClear : 1; // @31 Interrupt flag clear when written as 1 + }; + uint32_t Raw32; // Union to access all 32 bits as a uint32_t +} local_timer_clr_reload_reg_t; + +/*--------------------------------------------------------------------------} +{ GENERIC TIMER INTERRUPT CONTROL REGISTER - QA7_rev3.4.pdf page 13 } +{--------------------------------------------------------------------------*/ +typedef union +{ + struct + { + unsigned nCNTPSIRQ_IRQ : 1; // @0 Secure physical timer event IRQ enabled, This bit is only valid if bit 4 is clear otherwise it is ignored. + unsigned nCNTPNSIRQ_IRQ : 1; // @1 Non-secure physical timer event IRQ enabled, This bit is only valid if bit 5 is clear otherwise it is ignored + unsigned nCNTHPIRQ_IRQ : 1; // @2 Hypervisor physical timer event IRQ enabled, This bit is only valid if bit 6 is clear otherwise it is ignored + unsigned nCNTVIRQ_IRQ : 1; // @3 Virtual physical timer event IRQ enabled, This bit is only valid if bit 7 is clear otherwise it is ignored + unsigned nCNTPSIRQ_FIQ : 1; // @4 Secure physical timer event FIQ enabled, If set, this bit overrides the IRQ bit (0) + unsigned nCNTPNSIRQ_FIQ : 1; // @5 Non-secure physical timer event FIQ enabled, If set, this bit overrides the IRQ bit (1) + unsigned nCNTHPIRQ_FIQ : 1; // @6 Hypervisor physical timer event FIQ enabled, If set, this bit overrides the IRQ bit (2) + unsigned nCNTVIRQ_FIQ : 1; // @7 Virtual physical timer event FIQ enabled, If set, this bit overrides the IRQ bit (3) + unsigned reserved : 24; // @8-31 reserved + }; + uint32_t Raw32; // Union to access all 32 bits as a uint32_t +} generic_timer_int_ctrl_reg_t; + +struct __attribute__((__packed__, aligned(4))) QA7Registers { + local_timer_int_route_reg_t TimerRouting; // 0x24 + uint32_t GPIORouting; // 0x28 + uint32_t AXIOutstandingCounters; // 0x2C + uint32_t AXIOutstandingIrq; // 0x30 + local_timer_ctrl_status_reg_t TimerControlStatus; // 0x34 + local_timer_clr_reload_reg_t TimerClearReload; // 0x38 + uint32_t unused; // 0x3C + generic_timer_int_ctrl_reg_t Core0TimerIntControl; // 0x40 + generic_timer_int_ctrl_reg_t Core1TimerIntControl; // 0x44 + generic_timer_int_ctrl_reg_t Core2TimerIntControl; // 0x48 + generic_timer_int_ctrl_reg_t Core3TimerIntControl; // 0x4C +}; +#define QA7 ((volatile __attribute__((aligned(4))) struct QA7Registers*)(uintptr_t)(0x40000024)) +//40000040 + +int enable_timer(void); +#endif //RPI_MMU_EXAMPLE_INTERRUPTS_H diff --git a/kernel.c b/kernel.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/kernel.c @@ -60,7 +60,7 @@ inline static PSR_t read_CPSR(void) PSR_t CPSR; // get content of current program status register asm("mrs %0, cpsr" : "=r" (CPSR.raw) :: "memory"); - + return CPSR; } diff --git a/readfromrpi.sh b/readfromrpi.sh new file mode 100755 index 0000000..3ebc469 --- /dev/null +++ b/readfromrpi.sh @@ -0,0 +1,4 @@ +#!/bin/bash +sudo stty -F /dev/ttyUSB0 115200 cs8 -cstopb -parenb +sudo chmod 777 /dev/ttyUSB0 +#cat -v < /dev/ttyUSB0 |