Interrupts
From XCore Exchange
This page gives some description of, and example code showing how to use interrupts in the XS1 ISA. The details are all included in the XS1 Architecture manual, but this is intended to be a higher-level and more practical description.
Interrupts are a special kind of event that trigger entry to a predefined point of the program whilst saving the program counter (pc), status register (sr) and exception data (ed) registers in the saved pc (spc), sr (ssr) and ed (sed) registers respectively. This allows execution to resume at the point of interruption once the cause has been dealt with.
Contents |
Generating interrupts
Interrupts can be generated in three ways: by exceptions, kernel calls and resources. An exception may be raised automatically by an illegal operation, such as an unaligned memory access, or explicitly by an ECALL instruction. In both cases, pc, sr and ed are saved, and control is transferred to the kernel entry point (kep). A kernel call can be made by executing the KCALL instruction, which again saves state and sets the pc to kep+64. Resources can also be setup to generate interrupts, and each can be assigned its own interrupt handler: the event vector (ev). The following example code shows how to setup a channel resource to generate interrupts on receiving a message.
getr r11, XS1_RES_TYPE_CHANEND # Get a channel eeu res[r11] # Enable events and interrupts on the channel setc res[r11], XS1_SETC_IE_MODE_INTERRUPT # Set the resource control bits to generate interrupts ldap r10, intrhandler # Load the address of the interrupt handler setv res[r11], r10 # Set the event vector to the interrupt handler
The kernel
Interrupts are intended to interrupt the normal execution of the program, possibly at an unexpected moment. This is in contrast with events which are waited on to occur. Whether the interrupt is caused by an exception, kernel call or resource action, the general idea is to deal with the cause and then return to the original location and state of execution. This can be achieved with the use of a kernel to save all of the execution state, handle the interrupt and then restore it to resume.
Its stack
The kep can be initialised using the SETKEP instruction. Once in the interrupt handler, the kernel may operate using the program stack or with a seperate kernel stack, by executing KENTSP instead of ENTSP. There is no specific instruction to set the kernel stack pointer (ksp), but it can be set using the following sequence:
set sp, r11 # Set the stack pointer stw r11, sp[0] # Copy this into the location krestsp expects to find sp krestsp 0 # Execute KRESTSP to set ksp = sp
Preserving execution state
On entering the kernel in the event of an interrupt, the state of the executing program (i.e. the registers available to it), must be preserved so none are overwritten by the execution of the handler. There are several instructions provided to store/load special saved regsiters: spc, ssr, sed, to/from the stack. As an example, on entry to the kernel, we can store all the registers that might be used by the handler:
kentsp 17 # Switch to kernel stack and allocate 17 words stw spc, sp[1] stw ssr, sp[2] stw sed, sp[3] stw r0, sp[4] stw r1, sp[5] stw r2, sp[6] stw r3, sp[7] stw r4, sp[8] stw r5, sp[9] stw r6, sp[10] stw r7, sp[11] stw r8, sp[12] stw r9, sp[13] stw r10, sp[14] stw r11, sp[15] stw lr, sp[16]
And then restore them, when we exit the kernel:
ldw spc, sp[1] ldw ssr, sp[2] ldw sed, sp[3] ldw r0, sp[4] ldw r1, sp[5] ldw r2, sp[6] ldw r3, sp[7] ldw r4, sp[8] ldw r5, sp[9] ldw r6, sp[10] ldw r7, sp[11] ldw r8, sp[12] ldw r9, sp[13] ldw r10, sp[14] ldw r11, sp[15] ldw lr, sp[16] krestsp 17 # Contract the kernel stack and switch to user stack kret # Return from interrupt
Enabling interrupts
When the source has been configured, the interrupt handler set and you are ready to receive interrupts, the status register of the thread must be set using SETSR:
clrsr SR_EEBLE # If events are enabled, clear this bit setsr SR_IEBLE # Enable interrupts
Things to be aware of
- Receiving on a channel with interrupts or events enabled will cause an ILLEGAL_RESOURCE exception. Disable events and interrupts before attempting to use a channel for input.
