Search code examples
armstm32qemucortex-m

How to make qemu generate external interrupt and jump to isr (bare metal code)


I have an stm32 (arm-cortexm3) firmware running in qemu and want to emulate a hw interrupt, say uart rx interrupt. How can I make qemu to make a jump to the isr implemented in my firmware?

I have placed the isr at correct place in the vector table. I have set the irq number in my emulated uart. But when I call qemu_set_irq() and then cpu_interrupt(&env, CPU_INTERRUPT_HARD), qemu interrupts but aborts with "hwerror, interrupt but no vector".

Something is missing. Does anyone know about this?

EDIT: Using qemu-stable-2.10

nvic = armv7m_init(system_memory, flash_size, NUM_IRQ_LINES, kernel_filename, cpu_model);
qemu_irq uart_irq = qdev_get_gpio_in(nvic, 1);
uart = sysbus_create_simple(TYPE_VCPU_UART, 0x40020000, uart_irq);

If I later do:

qemu_set_irq(uart_irq ,1);

I would expect a jump to the uart isr, but it does not occur.

Is this correct hook up of nvic/irq, or is something more missing?

EDIT2 I realized that I had not enabled the interrupts in the firmware code! Oops! After setting proper bits in NVIC Set Enable register it works!


Solution

  • You shouldn't be calling cpu_interrupt() yourself (it is an internal function within QEMU's CPU model code, not one intended to be called from a board or device model). The Arm M-profile CPU has a very tightly integrated interrupt controller (the NVIC), which in QEMU's emulation is also closely connected to the CPU. You should have your board model wire up the UART's interrupt line to the NVIC, and then the NVIC will take care of telling the CPU which interrupt needs to be taken (based on interrupt priorities, masking, etc). The error message you're getting is because your incorrect call to cpu_interrupt() is effectively telling one half of this system (the cpu) about the interrupt but not the other half (the NVIC) -- so when the cpu asks the NVIC about this interrupt the NVIC says "never heard of it" and aborts. If you use the proper interface for telling the NVIC about interrupts it will work correctly. (The existing QEMU M profile board models will have code which does this.)

    Important note: the M profile interrupt handling was significantly rewritten in QEMU 2.9, as it was quite buggy before then, and we fixed some further exception related bugs in 2.10. If you are using M profile I strongly recommend using 2.10 or later. I can tell you aren't because that particular error message is part of the old and buggy code.