Timer interrupt

Implemented timer. First, it needs interrupt vector table at address 0x00000000.
The following (not optimized my first) arm code “_init_vector_table” copies _initialize_vector_start to _initialize_vector_end to 0x00000000.

First, I tried to copy that in C, but uint32_t* vector_table; *vector_table=… was not compiled as I expected by cross gcc 4.9 perhaps because 0 is NULL in C and *NULL is illegal.

.global  _initialize_vector_start
        ldr     pc, _vec_Reset
        ldr     pc, _vec_Undef
        ldr     pc, _vec_SWI
        ldr     pc, _vec_PrefAbort
        ldr     pc, _vec_DataAbort
        ldr     pc, _vec_Reserved
        ldr     pc, _vec_IRQ
        ldr     pc, _vec_FIQ
_vec_Reset:             .word   _start
_vec_Undef:             .word   _hangup
_vec_SWI:               .word   _hangup
_vec_PrefAbort: .word   _hangup
_vec_DataAbort: .word   _hangup
_vec_Reserved:  .word   _hangup
_vec_IRQ:               .word   _IRQ_iterrupt
_vec_FIQ:               .word   _hangup
        .global  _initialize_vector_end
# dummy instruction to keep initialize_vector_end label
        mov r0,r0

.global _init_vector_table
  ldr r0, =0x0
  ldr r1, =_initialize_vector_start
  ldr r3, =_initialize_vector_end
  cmp r1, r3
  bxeq lr
  ldr r2, [r1]
  str r2, [r0]
  add r1, #4
  add r0, #4
  cmp r1, r3
  bne _init_vector_table_loop
  bx lr

Then, _IRQ_iterrupt calls C function IRQ_handler.

	stmfd	r13!, {r0-r12,lr}
	bl	IRQ_handler
	ldmfd	r13!, {r0-r12,lr}
	subs	pc,lr, #4

IRQ_handler sets g_interrupt flag.

volatile static bool g_interrupt = false;

// called by _IRQ_interrupt in startup.s
void IRQ_handler(void) {
  // disable IRQ

  if (*INTERRUPT_IRQ_BASIC_PENDING & 0x01 != 0) {
    // Timer interrupt handler
    g_interrupt = true;
    // clear interrupt flag
    *TIMER_IRQ_CLR = 0;

  // enable IRQ

Then dirty main loop is checking the flag. I’ll change it to wait for interrupt like another x86 OS is doing.

  while (true) {
    if (true == g_interrupt) {
      g_interrupt = false;
    } else {

Today’s code: https://github.com/sokoide/rpi-baremetal -> 004_timer_interrupt.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.