TNeo  v1.08
Architecture-specific details

Table of Contents

Architecture-specific details

PIC32 port details

Context switch

The context switch is implemented using the core software 0 interrupt (CS0), which is configured by the kernel to the lowest priority (1). This interrupt is handled completely by the kernel, application should never touch it.

The interrupt priority level 1 should not be configured to use shadow register sets.

Multi-vectored interrupt mode should be enabled.

Attention
if tneo is built as a separate library (which is typically the case), 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 TNeo 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 generic information about interrupts in TNeo, refer to the page Interrupts.

PIC32 port has system interrupts only, there are no user 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_p32_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_p32_srs_isr(_UART_1_VECTOR)
{
/* here is your ISR code, including clearing of interrupt flag, and so on */
}

In spite of the fact that the kernel provides separate stack for interrupt, this isn't a mandatory on PIC32: you're able to define your ISR in a standard way, making it use stask of interrupted task and work a bit faster. Like this:

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

There is always a tradeoff. There are no additional constraints on ISR defined without kernel-provided macro: in either ISR, you can call the same set of kernel services.

When you make a decision on whether particular ISR should use separate stack, consider the following:

Building

For generic information on building TNeo, refer to the page Building TNeo.

MPLABX project for PIC32 port resides in the lib_project/pic32/tneo_pic32.X directory. This is a library project in terms of MPLABX, so if you use MPLABX you can easily add it to your application project by right-clicking Libraries -> Add Library Project .... Alternatively, of course you can just build it and use resulting tneo_pic32.X.a file in whatever way you like.

If you want to build TNeo manually, refer to the section Building manually for generic notes about it, and there is a couple of arch-dependent sources you need to add to the project:

Attention
There is one more file: tn_arch_pic32_int_vec1.S, which should be included in your application project to make things work. It is needed to dispatch vector1 (Core Software Interrupt 0) correctly.

PIC24/dsPIC port details

Context switch

The context switch is implemented using the external interrupt 0 (INT0). It is handled completely by the kernel, application should never touch it.

Interrupts

For generic information about interrupts in TNeo, refer to the page Interrupts.

PIC24/dsPIC TNeo port supports nested interrupts. It allows to specify the range of system interrupt priorities. Refer to the subsection Interrupt types for details on what is system interrupt.

System interrupts use separate interrupt stack instead of the task's stack. This approach saves a lot of RAM.

The range is specified by just a single number: TN_P24_SYS_IPL, which represents maximum system interrupt priority. Here is a list of available priorities and their characteristics:

The kernel provides C-language macro for calling C-language system interrupt service routines.

Usage is as follows:

/*
* Timer 1 interrupt handler using software interrupt context saving,
* PSV is handled automatically:
*/
tn_p24_soft_isr(_T1Interrupt, auto_psv)
{
//-- clear interrupt flag
IFS0bits.T1IF = 0;
//-- do something useful
}
Attention
do not use this macro for non-system interrupt (that is, for interrupt of priority higher than TN_P24_SYS_IPL). Use standard way to define it. If TN_CHECK_PARAM is on, kernel checks it: if you violate this rule, debugger will be halted by the kernel when entering ISR. In release build, CPU is just reset.

Atomic access to the structure bit field

The problem with PIC24/dsPIC is that when we write something like:

IPC0bits.INT0IP = 0x05;

We actually have read-modify-write sequence which can be interrupted, so that resulting data could be corrupted. PIC24/dsPIC port provides several macros that offer atomic access to the structure bit field.

The kernel would not probably provide that kind of functionality, but TNeo itself needs it, so, it is made public so that application can use it too.

Refer to the page Atomic bit-field access macros for details.

Building

For generic information on building TNeo, refer to the page Building TNeo.

MPLABX project for PIC24/dsPIC port resides in the lib_project/pic24_dspic/tneo_pic24_dspic.X directory. This is a library project in terms of MPLABX, so if you use MPLABX you can easily add it to your main project by right-clicking Libraries -> Add Library Project ....

Alternatively, of course you can just build it and use resulting .a file in whatever way you like.

Attention
there are two configurations of this project: eds and no_eds, for devices with and without extended data space, respectively. When you add library project to your application project, you should select correct configuration for your device; otherwise, you get "undefined reference" errors at linker step.

If you want to build TNeo manually, refer to the section Building manually for generic notes about it, and additionally you should add arch-dependent sources: all .c and .S files from src/arch/pic24_dspic

Cortex-M0/M0+/M3/M4/M4F port details

Context switch

The context switch is implemented in a standard for Cortex-M CPUs way: the PendSV exception. SVC exception is used for _tn_arch_context_switch_now_nosave(). These two exceptions are configured by the kernel to the lowest priority.

Interrupts

For generic information about interrupts in TNeo, refer to the page Interrupts.

Cortex-M port has system interrupts only, there are no user interrupts.

Interrupts use separate interrupt stack, i.e. MSP (Main Stack Pointer). Tasks use PSP (Process Stack Pointer).

There are no constraints on ISRs: no special macros for ISR definition, or whatever. This is because Cortex-M processors are designed with OS applications in mind, so a number of featureas are available to make OS implementation easier and make OS operations more efficient.

Building

For generic information on building TNeo, refer to the page Building TNeo.

There are many environments for building for Cortex-M CPUs (Keil, Eclipse, CooCox), all available projects reside in lib_project/cortex_m directory. They usually are pretty enough if you want to just build the kernel with non-default configuration.

If, however, you want to build it not using provided project, refer to the section Building manually for generic notes about it, and additionally you should add arch-dependent sources: all .c and .S files from src/arch/cortex_m.

There are some additional tips depending on the build environment:

Keil 5, ARMCC compiler

To satisfy building requirements, a couple of actions needed:

Keil 5, GCC compiler

Unfortunately, when GCC toolchain is used from Keil uVision IDE, for .S files it calls arm-none-eabi-as, which does not call C preprocessor.

Instead, arm-none-eabi-gcc should be used, but unfortunately I was unable to make Keil uVision issue arm-none-eabi-gcc for .S files, the only way to use GCC toolchain in Keil uVision that I'm aware of is to preprocess the file manually, like that:

cpp -P -undef tn_arch_cortex_m.S                         \
      -D __GNUC__ -D __ARM_ARCH -D __ARM_ARCH_7M__       \
      -I ../.. -I ../../core                             \
      > tn_arch_cortex_m3_gcc.s

(this example is for Cortex-M3, you may check the file tn_arch_detect.h to see what should you define instead of __ARM_ARCH_7M__ for other cores)

And then, add the output file tn_arch_cortex_m3_gcc.s to the project instead of tn_arch_cortex_m.S