TNeoKernel  v1.03
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
PIC32 details

Table of Contents

PIC32 port implementation details

Context switch

The context switch is implemented using the core software 0 interrupt. It should be configured to use the lowest priority in the system:

// set up the software interrupt 0 with a priority of 1, subpriority 0
INTSetVectorPriority(INT_CORE_SOFTWARE_0_VECTOR, INT_PRIORITY_LEVEL_1);
INTSetVectorSubPriority(INT_CORE_SOFTWARE_0_VECTOR, INT_SUB_PRIORITY_LEVEL_0);
INTEnable(INT_CS0, INT_ENABLED);

The interrupt priority level used by the context switch interrupt should not be configured to use shadow register sets.

Attention
if tneokernel is built as a separate library, then the file src/arch/pic32/tn_arch_pic32_int_vec1.S must be included in the main project itself, in order to dispatch vector1 (core software interrupt 0) correctly. Do note that if we include this file in the TNeoKernel library project, it doesn't work for vector, unfortunately.
If you forgot to include this file, you got an error on the link step, like this:
undefined reference to `_you_should_add_file___tn_arch_pic32_int_vec1_S___to_the_project'
Which is much more informative than if you just get to _DefaultInterrupt when it's time to switch context.

Interrupts

For detailed information about interrupts in TNeoKernel, refer to the page Interrupts.

PIC32 port supports nested interrupts. The kernel provides C-language macros for calling C-language interrupt service routines, which can use either MIPS32 or MIPS16e mode. Both software and shadow register interrupt context saving is supported. Usage is as follows:

/* Timer 1 interrupt handler using software interrupt context saving */
tn_soft_isr(_TIMER_1_VECTOR)
{
/* here is your ISR code, including clearing of interrupt flag, and so on */
}
/* High-priority UART interrupt handler using shadow register set */
tn_srs_isr(_UART_1_VECTOR)
{
/* here is your ISR code, including clearing of interrupt flag, and so on */
}

Alternatively, you can define your ISR in a standard way, like this:

void __ISR(_TIMER_1_VECTOR) timer_1_isr(void)
{
/* here is your ISR code, including clearing of interrupt flag, and so on */
}

Then, context is saved on the task's stack instead of interrupt stack (and takes therefore much more RAM), but you save about 20 cycles for each interrupt. See the page Interrupts for details.