Giter Site home page Giter Site logo

Comments (5)

maxstreitberger avatar maxstreitberger commented on May 25, 2024 5

I found out that the raspberry pi 4 uses the GIC-400 interrupt controller. I used the CoreLinkTM GIC-400 Generic Interrupt Controller Manual, ARM Generic Interrupt Controller Architecture Specification, and the BCM2711 ARM Peripherals Manual to get information about it.

To implement the timer interrupt we need the following information:

  • The base address of the GIC-400
  • The address for the Distributor Base
  • The address for the CPU Base
  • Enable the Interrupt Set-Enable Registers
    • Allow us to forward the corresponding interrupt to the CPU interfaces.
  • Interrupt Acknowledge Register
    • Tell the processor which interrupt fired.
  • End Of Interrupt Register
    • Indicates to the Distributor that it can forward the new highest priority pending interrupt
  • Interrupt Processor Targets Registers
    • Tells the Distributor to which CPU interface it should forward the interrupt
  • Time interrupt ID
    • VideoCore interrupts start at the interrupt ID of 96 (see page 87 in the BCM2711 ARM Peripherals Manual). If you look at the table on page 86 of the BCM2711 ARM Peripherals Manual, we need the index 0, 1, 2, and 3. Which then corespondents to the IDs of 96, 97, 98, and 99.

The irq.h file would then look like this:

#ifndef _P_IRQ_H
#define _P_IRQ_H

#include <peripherals/base.h>

#define GIC_BASE 0xFF840000
#define GICD_DIST_BASE (GIC_BASE+0x00001000)
#define GICC_CPU_BASE (GIC_BASE+0x00002000)

#define GICD_ENABLE_IRQ_BASE (GICD_DIST_BASE+0x00000100)

#define GICC_IAR (GICC_CPU_BASE+0x0000000C)
#define GICC_EOIR (GICC_CPU_BASE+0x00000010)

#define GIC_IRQ_TARGET_BASE (GICD_DIST_BASE+0x00000800)

//VC (=VideoCore) starts at 96
#define SYSTEM_TIMER_IRQ_0 (0x60) //96
#define SYSTEM_TIMER_IRQ_1 (0x61) //97
#define SYSTEM_TIMER_IRQ_2 (0x62) //98
#define SYSTEM_TIMER_IRQ_3 (0x63) //99

#endif

The irq.c looks then as follows:

#include "utils.h"
#include "printf.h"
#include "timer.h"
#include "entry.h"
#include "peripherals/irq.h"
#include "arm/sysregs.h"

const char *entry_error_messages[] = {
	"SYNC_INVALID_EL1t",
	"IRQ_INVALID_EL1t",		
	"FIQ_INVALID_EL1t",		
	"ERROR_INVALID_EL1T",		

	"SYNC_INVALID_EL1h",		
	"IRQ_INVALID_EL1h",		
	"FIQ_INVALID_EL1h",		
	"ERROR_INVALID_EL1h",		

	"SYNC_INVALID_EL0_64",		
	"IRQ_INVALID_EL0_64",		
	"FIQ_INVALID_EL0_64",		
	"ERROR_INVALID_EL0_64",	

	"SYNC_INVALID_EL0_32",		
	"IRQ_INVALID_EL0_32",		
	"FIQ_INVALID_EL0_32",		
	"ERROR_INVALID_EL0_32"	
};

void enable_interrupt(unsigned int irq) {
	 printf("%x\r\n", irq);
	 unsigned int n = irq / 32;
	 unsigned int offset = irq % 32;
	 unsigned int enableRegister = GICD_ENABLE_IRQ_BASE + (4*n);
	 printf("EnableRegister: %x\r\n", enableRegister);
	 put32(enableRegister, 1 << offset);
}

void assign_target(unsigned int irq, unsigned int cpu) {
	 unsigned int n = irq / 4;
	 unsigned int targetRegister = GIC_IRQ_TARGET_BASE + (4*n);
	 // Currently we only enter the target CPU 0
	 put32(targetRegister, get32(targetRegister) | (1 << 8));
}

void show_invalid_entry_message(int type, unsigned long esr, unsigned long address) {
	 printf("%s, ESR: %x, address, %x\r\n", entry_error_messages[type], esr, address);
}

void enable_interrupt_controller() {	
	 assign_target(SYSTEM_TIMER_IRQ_1, 0);
	 enable_interrupt(SYSTEM_TIMER_IRQ_1);
}

void handle_irq(void) {
	 unsigned int irq_ack_reg = get32(GICC_IAR);
	 unsigned int irq = irq_ack_reg & 0x2FF;
	 switch (irq) {
	 	 case (SYSTEM_TIMER_IRQ_1):
	 	 	 handle_timer_irq();
	 	 	 put32(GICC_EOIR, irq_ack_reg);
	 	 	 break;
	 	 default:
	 	 	 printf("Unknown pending irq: %x\r\n", irq);
	 	 	 break;
	}
}

from raspberry-pi-os.

rhythm16 avatar rhythm16 commented on May 25, 2024 2

hello past self, here's what I think is happening after some testing:
Low Level Devel doesn't need to configure the GIC because he used a custom armstub to start the RPI4, which does not enable the GIC. The default armstub probably sets up the GIC which causes the "ARMC" interrupt handling code to fail. An interesting point is that according to the rpi docs, the GIC is enabled by default, but once I remove the GIC enabling code in the armstub, the ARMC code works again, I guess this means that the GIC needs to be explicitly enabled in the armstub.
With all this, I think ARMC is a part of the legacy interrupt controller, but still I don't know what "ARMC" stands for.
A good reference for GIC enabling code can be found in raspberrypi/tools.

from raspberry-pi-os.

maxstreitberger avatar maxstreitberger commented on May 25, 2024 1

@rhythm16 I hope I can provide some answers to your questions.

  1. I think ARMC stands for ARM-Core, which is used to send interrupts to all cores and you can find the registers in Table 117. ARMC Interrupt Registers in the BCM2711 ARM Peripherals Manual
  2. As for my understanding, the ARMC does not support VC interrupts (see Table 117. ARMC Interrupt Registers in the BCM2711 ARM Peripherals Manual and page 83)
  3. I think you don't have to configure both since all interrupts go through the GIC (if I interpret the diagram on page 87 in the BCM2711 ARM Peripherals Manual correctly)

Please correct me if I'm wrong somewhere.

from raspberry-pi-os.

rhythm16 avatar rhythm16 commented on May 25, 2024

@maxstreitberger thanks for your effort, but do you know why doesn't Low Level Devel need to configure the GIC?
I (rpi4b) also followed the youtube video and everything works fine. By now I'm just confused. The bcm2711 peripheral datasheet doesn't explain clearly,
what are the ARMC registers?
why do the ARMC registers control the VC interrupts when on page 87 the VC interrupts are connected to the GIC?
why is ARMC also listed as an interrupt source?
should I configure both the ARMC registers and the GIC?
so many questions... I'd be very thankful if anyone can help.

from raspberry-pi-os.

freewilll avatar freewilll commented on May 25, 2024

Brilliant. I spent hours trying to figure out how to get timer interrupts working on my raspberry pi 4b. The GIC-400 initialization and interrupt setup code here is what I needed. Thanks!

from raspberry-pi-os.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.