# Learning External interrupts

**URL:** <https://forums.sifive.com/t/learning-external-interrupts/6358>\
**Category:** HiFive1 Rev B\
**Created:** [December 26, 2023, 10:40am UTC](https://forums.sifive.com/t/learning-external-interrupts/6358 "2023-12-26T10:40:28Z")\
**Posts on this page:** 1\
**Showing post:** 2

<div class="post-metadata">

**Author:** ![pds](https://avatars.discourse-cdn.com/v4/letter/p/8edcca/32.png) [@pds](https://forums.sifive.com/u/pds)\
**Post date:** [December 27, 2023, 8:19pm UTC](https://forums.sifive.com/t/learning-external-interrupts/6358/2 "2023-12-27T20:19:29Z")

</div>

Hi @Ted usually `mie` is the last thing to enable, certainly after setting up everything else and, most importantly, `mtvec`. It’s good you remember to keep the handler on an 64-byte boundary. The first two bits determine _absolute_ or _vectored_ mode, you might check with `gdb` to make sure PC is going where you think.

Here is a discussion and picture of the [PLIC interrupt flow](https://forums.sifive.com/t/what-is-plic-interrupt-source-start-and-end-in-interrupt-source-mapping/5705/9) and some tips I put together to [initialize and set up GPIO pins for PLIC](https://forums.sifive.com/t/initialize-and-set-up-of-gpio-pins/6127/6); they are from an assembly code perspective, which I think is clearer to work with.

You may also find my github repo [Demonstrating MTVEC](https://github.com/psherman42/Demonstrating-MTVEC) helpful: look at the `start.s` file.

When an interrupt occurs, you should first determine whether it’s a _synchronous exception_ or _asynchronous interrupt_. Then, in latter case, you should determine whether the source of interrupt is _software_, _timer_, or _external/PLIC_. In that latter case you `claim` and acknowledge (`complete`) the interrupt, and jump as directed to the appropriate _source ID_.

Make sure the jump tables are on 2-byte or four-byte boundaries, depending whether you use _compressed_ or long form versions of the `j` instruction.

Lastly, don’t forget the `mret` at the end, which automatically clears the `mip` flag.

It is easy to mix up the interrupt enable bits of `CSR_MIE_MxIE` (where `x` is `S`, `T`, or `E` for Software, Timer, or External, respectively) with `CSR_MSTATUS_MIE` which is the main on/off switch for the entire interrupt process. It looks like your C-code already does this correctly, though.

---

_[View the full topic](https://forums.sifive.com/t/learning-external-interrupts/6358)._
