Difference between revisions of "OCEOS/oceos kernel/interrupt"
Okhoruzhyy (talk | contribs) |
Okhoruzhyy (talk | contribs) |
||
Line 141: | Line 141: | ||
enum DIRECTIVE_STATUS status; | enum DIRECTIVE_STATUS status; | ||
node.source = 12; | node.source = 12; | ||
node.handler = | node.handler = interrupt_handler; | ||
node.arg = NULL; | node.arg = NULL; | ||
status = oceos_interrupt_handle_register(&node); | status = oceos_interrupt_handle_register(&node); | ||
Line 190: | Line 190: | ||
enum DIRECTIVE_STATUS status; | enum DIRECTIVE_STATUS status; | ||
node.source = 12; | node.source = 12; | ||
node.handler = | node.handler = interrupt_handler; | ||
node.arg = NULL; | node.arg = NULL; | ||
status = oceos_interrupt_handle_unregister(&node); | status = oceos_interrupt_handle_unregister(&node); |
Latest revision as of 17:49, 23 March 2022
OCEOS Interrupts
Introduction
SPARC
Interrupt handler code is written by the application developer. Normal practice is to keep interrupt handlers as short as possible, and to delegate processing to an appropriate task by placing a job on the ready queue. If this is done, to ensure a high priority job is started immediately, the scheduler needs to be called at the end of interrupt processing, i.e. at the end of the outermost nested interrupt if nesting is used.
SPARC Interrupts Introduction
Interrupting traps are controlled by the Processor Interrupt Level (PIL) field of the Processor Status Register (PSR) and by the Trap Enable (ET) field of the PSR.
The Trap Base Address (TBA) in the Trap Base register (TBR) must be set to the top 20 bits of the trap table address, which must be on a 4k boundary for MVT.
When the target hardware is configured to support single vector trapping (SVT), the -qsvt switch can be used with the linker to build an image which uses a two-level trap dispatch table rather than the standard one-level
trap table. The code saving amounts to ~4KiB for the trap table and trap handling is slightly slower with single vector trapping. The number of extra instructions needed for single vector trapping dispatching is constant.
Interrupts are re-enabled automatically on exit from the interrupt handler, when the processor state is restored to its previous value. Alternatively, the interrupt handler itself can re-enable interrupts before processing of the current interrupt is complete. If this is done a higher priority interrupt can pre-empt the processor from the current interrupt handler and 'interrupt nesting' occur.
OCEOS can be configured to use interrupt nesting.
During OCEOS initialization, each IRQ handler entry in Vector table is replaced with OCEOS interrupt handler for Multi or Single Vector Table (MVT or SVT). User must call OCEOS directives for registering and unregistering IRQ handlers. If IRQ is asserted, then OCEOS service code runs first, then user code => to handle IRQ and then finishes OCEOS handler code. This way the scheduling is possible to perform and other necessary OCEOS system calls.
SPARC Interrupts Configurations
User must not modify Interrupt Vector Table directly. User must use OCEOS directive oceos_interrupt_handle_register() and oceos_interrupt_handle_unregister() to register/unregister Interrupt handlers.
Interrupt nesting is disabled by default in BCC, meaning that an interrupt service routine can not be preempted by any other interrupt.
/* * Create the application configuration structure */ struct application_configuration app_config = {0}; app_config.interrupt_nesting_enabled = FALSE;Disable interrupt nesting in OCEOS. PSR.PIL will be raised to 0xf (highest) when an interrupt occurs on any level.
/* * Create the application configuration structure */ struct application_configuration app_config = {0}; app_config.interrupt_nesting_enabled = TRUE;Enable interrupt nesting in OCEOS. PSR.PIL will be raised to the current interrupt level when an interrupt occurs.
Support for single vector trapping (SVT) in OCEOS is enabled when application developer passes -qsvt switch to BCC Linker
ARM Cortex-M
ARM Cortex-M Interrupts Introduction
ARM Cortex-M uses Nested Interrupt Controller. User must modify Vector Trap table to add IRQ handlers for required IRQs.
Note
OCEOS uses some Exception handlers for own needs. User must pay attention to such handlers and not replace :
- oceos_SysTick_Handler()
- oceos_PendSV_Handler()
ARM Cortex-M processor has two modes:
- Thread Mode
- Handler Mode
OCEOS is running in Thread mode. OCEOS uses only one stack (main stack). When task is started by IRQ handler (in Handler mode) OCEOS has to switch to Thread mode in order to schedule execution of the task. For this purpose, OCEOS uses PendSV exception and implements oceos_PendSV_Handler() which must be present in Vector table (user responsibility).
Note
OCEOS initializes PendSV exception to the lowest priority (0xFF) and no other exceptions must have the same priority (user responsibility).
When task is started in IRQ handler, OCEOS asserts PendSV exception and because it is the lowest priority, it is serviced at the end when nesting level is zero.
ARM Cortex-M Interrupts Configurations
User must add described above labels to the Vector table.
.extern oceos_SysTick_Handler .extern oceos_PendSV_Handler .section .isr_vector .align 2 .globl __isr_vector __isr_vector: .long __StackTop /*0: Top of Stack */ .long Reset_Handler /*1: Reset Handler */ .long NMI_Handler /*2: NMI Handler */ .long HardFault_Handler /*3: Hard Fault Handler */ .long MemManage_Handler /*4: MPU Fault Handler */ .long BusFault_Handler /*5: Bus Fault Handler */ .long UsageFault_Handler /*6: Usage Fault Handler */ .long 0 /* Reserved */ /*7: Reserved */ .long 0 /* Reserved */ /*8: Reserved */ .long 0 /* Reserved */ /*9: Reserved */ .long 0 /* Reserved */ /*10: Reserved */ .long SVC_Handler /*11: SVCall Handler */ .long 0 /* Reserved */ /*12: Debug Monitor Handler */ .long 0 /* Reserved */ /*13: Reserved */ .long oceos_PendSV_Handler /*14: PendSV Handler */ .long oceos_SysTick_Handler /*15: SysTick Handler */
API Functions (SPARC only)
Directive | Description | main | task | IRQ handler |
---|---|---|---|---|
oceos_interrupt_handle_register() | Register IRQ Handler | * | * | * |
oceos_interrupt_handle_unregister() | Unregister IRQ Handler | * | * | * |
oceos_interrupt_handle_register()
Header File
oceos_interrupt.h
Description
OCEOS Wrapper around bcc_isr_register_node(struct bcc_isr_node *isr_node) in order to check if user not interfering with OCEOS internal configurations. Sets the function to be used for the given interrupt number.
This directive can be called from main() after oceos_init().Prototype
enum DIRECTIVE_STATUS oceos_interrupt_handle_register( struct bcc_isr_node *isr_node );Parameters
Parameter Description isr_node Pointer to struct bcc_isr_node Returns
This function returns U64_t.
enum DIRECTIVE_STATUS Description NOT_CONFIGURED Tried to call before initialization INVALID_NODE isr_node is NULL INVALID_NUMBER Source number is used by OCEOS internally SUCCESSFUL All OK Example Usage
struct bcc_isr_node node; enum DIRECTIVE_STATUS status; node.source = 12; node.handler = interrupt_handler; node.arg = NULL; status = oceos_interrupt_handle_register(&node); if (SUCCESSFUL != status) { // Handle ERROR }
oceos_interrupt_handle_unregister()
Header File
oceos_interrupt.h
Description
OCEOS Wrapper around bcc_isr_unregister_node(struct bcc_isr_node *isr_node) in order to check if user not interfering with OCEOS internal configurations. Removes the function for the given interrupt number.
This directive can be called from main() after oceos_init().Prototype
enum DIRECTIVE_STATUS oceos_interrupt_handle_unregister( const struct bcc_isr_node *isr_node );Parameters
Parameter Description isr_node Pointer to struct bcc_isr_node Returns
This function returns U64_t.
enum DIRECTIVE_STATUS Description NOT_CONFIGURED Tried to call before initialization INVALID_NODE isr_node is NULL INVALID_NUMBER Source number is used by OCEOS internally SUCCESSFUL All OK Example Usage
struct bcc_isr_node node; enum DIRECTIVE_STATUS status; node.source = 12; node.handler = interrupt_handler; node.arg = NULL; status = oceos_interrupt_handle_unregister(&node); if (SUCCESSFUL != status) { // Handle ERROR }