Skip to content

multigiorgiplex/PIC18F_XC8_FreeRTOS

 
 

Repository files navigation

PIC18F_XC8_FreeRTOS

A port of FreeRTOS for PIC18F and XC8.

Motivation

I needed a 5V solution. There is a port for PIC18F452 (old...) and C18 (old...). So I tried to port for PIC18F and XC8.

I only tested with PIC18F27Q43 but I believe other recent PIC18F MCUs are applicable. Because FreeRTOS code size is a bit large, 64KB or more flash memory is favored.

If I needed a 3.3V solution, maybe I chose STM32L. I am not familiar with AVR MCUs, by the way.

Cooperative scheduler only

Because the stack pointer consists of two registers FSR1L and FSR1H, calculations of the stack pointer are not atomic. There is a critical section between modifying FSR1L and modifying FSR1H.

The following is an example picked up from .lst file. Beginning of a function which has total 6-byte local variables:

  2454  004964  0E06                movlw   6
  2455  004966  26E1                addwf   fsr1l,f,c
  2456  004968  0E00                movlw   0
  2457  00496A  22E2                addwfc  fsr1h,f,c

FreeRTOS usually saves a task context on top of the stack. If the preemptive scheduler is used and the tick timer interrupt occurs after addwf fsr1l,f,c but before addwfc fsr1h,f,c, the stack pointer calculation is incomplete, and then the task context could be saved on the bad location.

This is a very small window but cannot be ignored. So I decided this port is for the cooperative scheduler only.

Pre-emptive branch

An extension of this porting aimed at adding preemptive support is present under the branch preemption.

The code that contains the critical sections mentioned above is still there, the occurrences can be checked in the .lst file.

By checking the state of the INTCON0.GIEH bit with the simulator, every time the critical code gets executed, the interrupts are inhibited, or it's an ISR itself.

This suggests that the XC8 compiler could be aware of the state of the interrupts while dealing with the stack, and so put the critical code only when the interrupts are disabled.

This is still a speculation and needs further analysis.

Context switching time

Multi-tasking is not suitable scope of PIC18F MCUs. Many instructions are needed to maintain context switching.

The portYIELD() macro performs a context switch, which gets about 650 instruction cycles. When Fosc=64MHz, 16 instruction cycles per microsecond, about 40 microseconds per context switching.

LED flashing Demo

This repository contains a MPLAB X IDE project of LED flashing demo. Open your git cloned folder with MPLAB X IDE.

    Demo/                       : written by me.
    FreeRTOS/                   : copied from the FreeRTOS repository.
        Demo/                   : contains the LED flashing demo: flash.c
        Source/                 : contains the FreeRTOS kernel.
    mcc_generated_files/        : generated by the MCC, MPLAB Code Configurator.
    nbproject/                  : MPLAB X IDE project folder.
    portable/                   : written by me.
    FreeRTOSConfig.h            : copied from the FreeRTOS repository and modified.
    main.c                      : generated by the MCC and modified.
    Makefile                    : generated by the MCC.
    PIC18F_XC8_FreeRTOS.mc3     : MCC config file.

- MPLAB X IDE v5.50
- XC8 v2.32
- PIC18F-Q_DFP 1.12.193
- MPLAB Code Configurator 5.0.3

Note on pre-emptive branch

Under the preemption branch, the demo has been extended with a blocking task vBlockingTask which has a lower priority than the vLEDFlashTasks.

When the scheduler is working in cooperative mode, the blocking task blocks the system and prevents other tasks from running.

When the scheduler is working in preemptive mode, all the tasks get CPU time.

Adjusting the compiler

The XC8 tries to optimize aggressively. If the XC8 considers one function is not called any time, the function is not compiled and is ignored. If the XC8 considers one pointer is not used any time, the pointer is regarded as always NULL and is compiled in that way.

Task processing functions are sometimes considered "not called" by the XC8. To prevent this, I put dummy call of task processing function in pxPortInitialiseStack. Also I put dummy call of vPortAdjustCompiler in xPortStartScheduler, however sometimes the XC8 overkills. You might need to examine .lst and .map files carefully if you face a strange behavior.

Copyright and license

Some files are copied from the FreeRTOS repository and its license is applied. Some files are generated by the MPLAB X IDE and the MPLAB Code Configurator and their license is applied. Other files are written by me and in public domain.

About

A port of FreeRTOS for PIC18F and XC8.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • C 99.6%
  • Makefile 0.4%