2

I'm looking into how to make an operating system for Raspberry Pi, and in the OSDev barebones tutorial for the Raspberry Pi, the following code is used to clear any pending interrupts.

// Clear pending interrupts.
mmio_write(UART0_ICR, 0x7FF);

The function mmio_write is as follows.

static inline void mmio_write(uint32_t reg, uint32_t data){
    *(volatile uint32_t *)reg = data;
}

Why is this value significant, and how does it clear the interrupts?

Jerome Carter
  • 237
  • 1
  • 4
  • 18
  • You need to read up on the definition of UART0_ICR. Likely the bits you write to it (0x7ff) are used to clear interrupt pending flags for each interrupt channel (In this case it would be 12 bits / 12 interrupt channels cleared) – PaulHK Sep 06 '16 at 04:11

1 Answers1

2

This line:

// Clear pending interrupts.
mmio_write(UART0_ICR, 0x7FF);

will write value of 0x7FF to the register at address UART0_ICR. Most likely, UART0_ICR is a value defined some else where in the code, which refers to the address of a corresponding register inside the BCM2835, maybe something similar to this:

#define UART0_ICR (UART0_BASE + 0x44)

Why is this value significant, and how does it clear the interrupts?

To understand this, you need to read the data sheet of the device, which is BCM2835 in your case (a quick search gives me this link). Look at the UART register section, you can see the description for UART_ICR register, which is the Interupt Clear Register.

It's quite obvious from the bit table description of that register: it's a 32-bit register, bit 31-11 is not used, while bit from 0 to 10 (11 bit) is used as flags for clearing various kinds of interrupt. Writing value of 0x7FF to this register is literally setting on all those flags, hence it will clear all the pending UART interrupts.

theman
  • 598
  • 1
  • 7
  • 19
  • It is perhaps obvious but the convention of clearing interrupt flags by writing a 1-bit into the appropriate position of a packed flag register instead of manually unmasking the position and writing back the required state is that a race may occur between another incoming interrupt being flagged and the read-modify-write cycle, thereby ending up silently ignoring the event. – doynax Sep 06 '16 at 05:02
  • @doynax Thanks for your idea. Could you elaborate more on how it should be done to clear interrupts? What is about race, read-modify-write cycle? Can you show some sample code? – theman Sep 06 '16 at 07:24
  • It isn't an idea, or at least not mine. When first encountered it may be slightly counter-intuitive to writes one-bits to clear flags. The _reason_ for this convention is that if writes were to directly set and cleared pending status, then manually lowering a bit (that is reading the register value, masking off the desired flag and writing back the result) might end up acknowledging any interrupts raised between the read and the write. Hence the hardware module itself typically gets to take on the responsibility for atomically acknowledging events. – doynax Sep 06 '16 at 15:36