MrGrimod
Posts: 24
Joined: Tue Jul 31, 2018 11:06 am

Timer Interrupt not firing after Context Switch

Wed Nov 23, 2022 10:11 am

Hi,
I'm currently working on a bare metal raspberry 3b scheduler implementation.
I enabled System Timer C1, by enablign its IRQ1 interrupt in the interrupt controller and setting the timer C1 reg to the timerClock-Reg content + 200000 as interval.
The irq timer handler than does the same (updating the timerC1 reg the same way) and calls the scheduler which eventually calls the contextSwitch.
That does work, but when the scheduler (called by the timer) is actually envoking the cpu contextSwitch and the new task is executed (which works just fine) the timer interrupt is not being called again and thus the scheduler stays in that context.
If I remove the context switch function, the issue does not arise and the timer irq continues to fire.
That's what my contextSwithc fn looks like:

Code: Select all

fn switchCpuContext(from: *Task, to: *Task) void {
            kprint("from: {*} to {*} \n", .{ from, to });

            asm volatile ("mov x8, %[from_addr]"
                :
                : [from_addr] "rax" (@ptrToInt(from)),
            );

            asm volatile ("mov x9, sp");
            // store callee-saved registers
            asm volatile ("stp x19, x20, [x8], #16");
            asm volatile ("stp x21, x22, [x8], #16");
            asm volatile ("stp x23, x24, [x8], #16");
            asm volatile ("stp x25, x26, [x8], #16");
            asm volatile ("stp x27, x28, [x8], #16");
            asm volatile ("stp x29, x9, [x8], #16");
            asm volatile ("str x30, [x8]");

            asm volatile ("mov x8, %[to_addr]"
                :
                : [to_addr] "rax" (@ptrToInt(to)),
            );
            // restore callee regs
            asm volatile ("ldp x19, x20, [x8], #16");
            asm volatile ("ldp x21, x22, [x8], #16");
            asm volatile ("ldp x23, x24, [x8], #16");
            asm volatile ("ldp x25, x26, [x8], #16");
            asm volatile ("ldp x27, x28, [x8], #16");
            asm volatile ("ldp x29, x9, [x8], #16");
            asm volatile ("ldr x30, [x8]");
            asm volatile ("mov sp, x9");
            asm volatile ("ret");
        }
}
(it's Zig(https://ziglang.org/) code but reads just like C)
Something in there stops my timer interrupts from firing (although the funciton intself is wokring as intended....).

I've checked if irqs are DAIF masked, the interrupt is enabled and the CS reg which is 0b10, so there should defenitely be an IRQ invoked...
GDB says that I end up in the final context loop, not in a somehow failed call to the exception vector table or something like that, so it seems like it's the irq not even being invoked.
The ESR, FAR regs are empty.

I'm thankful for any input, greets!

Return to “Bare metal, Assembly language”