­

Interrupts are registered in the Target Model Builder to simulate hardware interrupts. To add an Interrupt to a target, first create a callback function in your target with no parameters and a void return type, and build the target.

Now that the callback function is compiled and linked into the target, open the Timers tab in the Target Model Builder.

Click on the yellow ‘New’ icon in the lower left corner, or right click in the tab body area and select ‘New’, or press Control+N to create a new timer. The timer creation dialog will open as shown.

Start typing the name of your timer callback function, and you will see it filtered from all void(void) functions in your target. Select your callback function.

Your interrupt will now appear as a port on your target which can be connected to an interrupt source. In the example below, a momentary push button’s ButtonClicked event is connected to the MyInterruptISR interrupt event handler.

Any event source, such as the Timer component’s TimeElapsed event, can be used to drive an interrupt. When interrupts are invoked on a Target, the interrupt service routines will by default execute on the Virtuoso framework’s internal synchronization thread, in parallel with the executing target thread. However the execution of the ISR can be dispatched to execute non-concurrently in a non-critical section of the target code (like an interrupt executing on a microcontroller). See the FreeRTOS target template as the example for halting execution of the target to run the ISR.

As a brief explanation of how this works, both the target thread and a supervising thread are Windows threads which are constrained to execute only on a single logical processor, and the supervising thread is configured with a higher priority than the target thread. The supervising thread allows the target thread to run by waiting on operating system synchronization signals which may come from the host or the target. When there is no signal to process, the target executes on the logical processor. When the target performs an RTOS yield or when the host signals an interrupt, the supervisor thread executes. Since both the supervising thread and the target are constrained to run on the same CPU, the target thread will be paused while the supervising thread executes. The supervising thread can then dispatch the appropriate interrupt, check for context switching, and resume operation of the target. The supervising thread also coordinates with the target to ensure that interrupts aren’t invoked during a critical section.