Reputation: 456
I am trying to enable periodic APIC Timer in x86 architecture based 64 bit OS.
void apic_timer_init(uint32_t frequency) {
disable_interrupts();
// Ensure APIC is enabled (set Spurious Interrupt Vector Register)
printf("\nLAPIC_SVR before enable: %x\n", mmio_read(LAPIC_BASE + LAPIC_SVR));
mmio_write((LAPIC_BASE + LAPIC_SVR), mmio_read(LAPIC_BASE + LAPIC_SVR) | 0x100);
printf("LAPIC_SVR after enable: %x\n", mmio_read(LAPIC_BASE + LAPIC_SVR));
// Set timer divide configuration (Divide by 16)
mmio_write((LAPIC_BASE + LAPIC_TDCR), 0x3);
printf("LAPIC_TDCR: %x\n", mmio_read(LAPIC_BASE + LAPIC_TDCR));
// Set initial count for calibration (large value)
mmio_write((LAPIC_BASE + LAPIC_TICR), 0xFFFFFFFF);
printf("LAPIC_TICR after set: %x\n", mmio_read(LAPIC_BASE + LAPIC_TICR));
// Wait a bit (using PIT or another timer for calibration)
for (volatile int i = 0; i < 1000000; i++);
// Measure elapsed ticks (TSC or another timer)
uint32_t elapsed = 0xFFFFFFFF - mmio_read(LAPIC_BASE + LAPIC_TCCR);
printf("Elapsed ticks: %x\n", elapsed);
// Calculate the required APIC timer count for the desired frequency
uint32_t ticks_per_ms = elapsed / 10; // Assuming 10ms elapsed
uint32_t initial_count = ticks_per_ms * (1000 / frequency);
// Set the APIC Timer to periodic mode
mmio_write((LAPIC_BASE + LAPIC_TIMER), TIMER_VECTOR | 0x20000);
printf("LAPIC_TIMER: %x\n", mmio_read(LAPIC_BASE + LAPIC_TIMER));
printf("LAPIC_TCCR before start: %x\n", mmio_read(LAPIC_BASE + LAPIC_TCCR));
mmio_write((LAPIC_BASE + LAPIC_TICR), initial_count); // Periodic mode, vector 0x20
printf("LAPIC_TCCR after start: %x\n", mmio_read(LAPIC_BASE + LAPIC_TCCR));
// install apic timer interrupt handler apic_timerHandler
interrupt_install_handler(TIMER_VECTOR, &apic_timerHandler);
apic_remap_timer(initial_count);
enable_interrupts();
printf("APIC Timer initialized for periodic mode.\n");
}
The above function is showing LAPIC_SVR, LAPIC_TDCR, LAPIC_TICR, LAPIC_TCCR value is 0 before and after mmio_write. I am sure APIC is available and enabled as APIC keyboard is working. The LAPIC_BASE value is 0xFEE00000.
I am also using below functions
// Write to a memory-mapped I/O address
void mmio_write(uint32_t address, uint32_t value) {
*((volatile uint32_t*)address) = value;
}
// Read from a memory-mapped I/O address
uint64_t mmio_read(uint32_t address) {
return *((volatile uint64_t*)address);
}
What is the reason LAPIC_SVR, LAPIC_TDCR, LAPIC_TICR, LAPIC_TCCR register's values are not updating?
Upvotes: 0
Views: 21