FreeRTOS on Arduino Nano Every

The FreeRTOS contributor that has the Arduino port hasn’t updated for the ATmega4809 in the Arduino Nano Every. I’ve managed to get it working. The mods do not apply to the Arduino Uno Wifi which also uses the ATmega4809. I’m not putting this in the current book I’m working on, so am posting what needs to be done here. You start with the current distribution from https://github.com/feilipu/Arduino_FreeRTOS_Library. See also https://tomalmy.com/the-continuing-adventure-of-freertos/ which has a further change to the FreeRTOS library that fixes a problem with yielding. There is also a link there with patching instructions.

in variants/nona4809/variant.c, remove or comment out the initVariant function. This will not affect operation of any programs but allows FreeRTOS to compile.

The remaining changes are to the FreeRTOS library. The changes involve switching from using the WDT interrupt, which is not implemented in the ATmega4809, with the PIT interrupt. Interrupts will be roughly every 15ms, the same as the default WDT use in FreeRTOS.

The FreeRTOS type TCB_t conflicts with the ATmega4809 library. So change all “TCB_t” to something else. I used “TCb_t”.

In file portable.h, find the line #include <avr/wdt.h>. Add before that line:

#if defined (__AVR_ATmega4809__)
#else

Go down to the line #include “mpu_wrappers.h” and add a line #endif before it.

In file port.c, find the line that defines portScheduler_ISR and replace it with:

#if defined (__AVR_ATmega4809__)
#define portSCHEDULER_ISR RTC_PIT_vect
#else
#define    portSCHEDULER_ISR            WDT_vect
#endif

in the function vPortYieldFromTick after the line(s) portSAVE_CONTEXT() add:

#if defined (__AVR_ATmega4809__)
	  RTC_PITINTFLAGS = 1; // clear interrupt
#endif

Replace the function prvSetupTimerInterrupt with:

void prvSetupTimerInterrupt( void )
{
#if defined (__AVR_ATmega4809__)
	RTC_CLKSEL = 0; // 32.767kHz
	RTC_PITINTCTRL = 1; // Enable interrupt
	RTC_PITCTRLA = (8 << 3) | 1; // Divide by 512; 15msec rate
#else
    /* reset watchdog */
    wdt_reset();

    /* set up WDT Interrupt (rather than the WDT Reset). */
    wdt_interrupt_enable( portUSE_WDTO );
#endif
}

Finally, in the second ISR(portSCHEDULER_ISR), the one that calls xTaskIncrementTick, add the lines:

#if defined (__AVR_ATmega4809__)
          RTC_PITINTFLAGS = 1; // clear interrupt
#endif

I’ve tried several sample programs and they all work. I can’t guarantee all freeRTOS features will work. I’ll be contributing this back to the freeRTOS project.