Quantcast
Viewing all articles
Browse latest Browse all 5261

Bare metal, Assembly language • Re: Using the GIC-400 of the raspberry pi 5 (bcm2712)

Oh my bad, I had misunderstood the memory map of the GIC-400. I neglected the 0x1000 reserved bits at the start, hence the resultant base address just comes down to be the same.

I have a few questions regarding the above approach you have described:
1. Which exception level is the code executing in? I am asking this, because I am not able to perform the write operations into the `cntp_tval_el0` or the `cntp_ctl_el0` registers when in EL1, but can do it successfully in EL2.
2. Looking at the above implementation, I see that you have maintained an array of function pointers to the respective handlers. So a separate initialisation of the vector table is not required for the GIC-400?
3. I tried implementing the same code in C, but I don't seem to get any interrupts raised.

This is my code:

timer_init()

Code:

.globl timer_inittimer_init:  mrs x0, cntfrq_el0  msr cntp_tval_el0, x0  mov x0, #1  msr cntp_ctl_el0, x0  ret
GIC functions:

Code:

void gic_init() {  for (int i = 0; i < GIC_NUM_IRQ >> 5; i++) {    mmio_write_32(GIC_D_DISABLE + 4 * i, 0xffffffff);  }  mmio_write_32(GIC_C_PRI_MASK, 0xff);  for (int i = 0; i < GIC_NUM_IRQ; i++) {    mmio_write_32(GIC_D_PRI + 4 * i, 0x7f);  }  for (int i = 0; i < GIC_NUM_IRQ >> 4; i++) {    mmio_write_32(GIC_D_CONFIG + 4 * i, 0x55555555);  }  for (int i = 0; i < GIC_NUM_IRQ; i++) {    if (i < 32)      continue;    mmio_write_32(GIC_D_TARGET + 4 * i, 0xff);  }  mmio_write_32(GIC_D_CTLR, 0x1);  mmio_write_32(GIC_C_CTLR, 0x1);}void register_irq_handler(unsigned int irq) {  unsigned int val = 0x1 << (irq & 0x1f);  unsigned int n = irq >> 5;  mmio_write_32(GIC_D_ENABLE + 4 * n, val);}void gic_dispatch() {  while (1) {    unsigned int interrupt_spi = mmio_read_32(GIC_C_ACK);    unsigned int interrupt_id = interrupt_spi & 0x3FF;    uart_puts("Dispatch Triggered!\n\0");    if (interrupt_id >= GIC_NUM_IRQ) {      uart_puts("Spurious interrupt received: \0");      char buff[9] = "";      int_to_str(interrupt_id, buff);      uart_puts(buff);      uart_putc('\n');      __asm__("msr daifclr, #3\n\t"              "wfi\n\t");      continue;    }    if (interrupt_id == 30) {      uart_puts("Timer interrupt received!\n\0");    } else {      uart_puts("Unknown interrupt received!\n\0");    }    mmio_write_32(GIC_C_EOI, interrupt_spi);  }}
All the constants used are verified to be matching with the addresses you have used in your code.
I get interrupt id 1023 (spurious interrupt) when I execute the `dispatch()` function after initialising the GIC, initialising the timer, and then registering the interrupt... I believe this is the case because the reset value of `GIC_C_ACK` (the Interrupt Acknowledge Register) is 0x3FF, and hence seems to be not initialised appropriately.

Statistics: Posted by kvp_933 — Mon Jun 10, 2024 9:26 am



Viewing all articles
Browse latest Browse all 5261

Trending Articles