mirror of
				https://github.com/FreeRTOS/FreeRTOS-Kernel.git
				synced 2025-11-04 11:09:01 +01:00 
			
		
		
		
	* Fix spelling --------- Co-authored-by: Rahul Kar <118818625+kar-rahul-aws@users.noreply.github.com>
		
			
				
	
	
		
			426 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			426 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * FreeRTOS Kernel <DEVELOPMENT BRANCH>
 | 
						|
 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 | 
						|
 *
 | 
						|
 * SPDX-License-Identifier: MIT
 | 
						|
 *
 | 
						|
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 | 
						|
 * this software and associated documentation files (the "Software"), to deal in
 | 
						|
 * the Software without restriction, including without limitation the rights to
 | 
						|
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 | 
						|
 * the Software, and to permit persons to whom the Software is furnished to do so,
 | 
						|
 * subject to the following conditions:
 | 
						|
 *
 | 
						|
 * The above copyright notice and this permission notice shall be included in all
 | 
						|
 * copies or substantial portions of the Software.
 | 
						|
 *
 | 
						|
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
						|
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 | 
						|
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 | 
						|
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 | 
						|
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
						|
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
						|
 *
 | 
						|
 * https://www.FreeRTOS.org
 | 
						|
 * https://github.com/FreeRTOS
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
/*
 | 
						|
Changes from V3.0.0
 | 
						|
 | 
						|
Changes from V3.0.1
 | 
						|
*/
 | 
						|
#ifndef PORTMACRO_H
 | 
						|
#define PORTMACRO_H
 | 
						|
 | 
						|
#if !defined(_SERIES) || _SERIES != 18
 | 
						|
    #error "WizC supports FreeRTOS on the Microchip PIC18-series only"
 | 
						|
#endif
 | 
						|
 | 
						|
#if !defined(QUICKCALL) || QUICKCALL != 1
 | 
						|
    #error "QuickCall must be enabled (see ProjectOptions/Optimisations)"
 | 
						|
#endif
 | 
						|
 | 
						|
#include <stddef.h>
 | 
						|
#include <pic.h>
 | 
						|
 | 
						|
#define portCHAR        char
 | 
						|
#define portFLOAT       float
 | 
						|
#define portDOUBLE      portFLOAT
 | 
						|
#define portLONG        long
 | 
						|
#define portSHORT       short
 | 
						|
#define portSTACK_TYPE  uint8_t
 | 
						|
#define portBASE_TYPE   char
 | 
						|
 | 
						|
typedef portSTACK_TYPE StackType_t;
 | 
						|
typedef signed char BaseType_t;
 | 
						|
typedef unsigned char UBaseType_t;
 | 
						|
 | 
						|
 | 
						|
#if( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS )
 | 
						|
    typedef uint16_t TickType_t;
 | 
						|
    #define portMAX_DELAY ( TickType_t )    ( 0xFFFF )
 | 
						|
#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS )
 | 
						|
    typedef uint32_t TickType_t;
 | 
						|
    #define portMAX_DELAY ( TickType_t )    ( 0xFFFFFFFFUL )
 | 
						|
#else
 | 
						|
    #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width.
 | 
						|
#endif
 | 
						|
 | 
						|
#define portBYTE_ALIGNMENT          1
 | 
						|
 | 
						|
/*-----------------------------------------------------------*/
 | 
						|
 | 
						|
/*
 | 
						|
 * Constant used for context switch macro when we require the interrupt
 | 
						|
 * enable state to be forced when the interrupted task is switched back in.
 | 
						|
 */
 | 
						|
#define portINTERRUPTS_FORCED               (0x01)
 | 
						|
 | 
						|
/*
 | 
						|
 * Constant used for context switch macro when we require the interrupt
 | 
						|
 * enable state to be unchanged when the interrupted task is switched back in.
 | 
						|
 */
 | 
						|
#define portINTERRUPTS_UNCHANGED            (0x00)
 | 
						|
 | 
						|
/* Initial interrupt enable state for newly created tasks.  This value is
 | 
						|
 * used when a task switches in for the first time.
 | 
						|
 */
 | 
						|
#define portINTERRUPTS_INITIAL_STATE        (portINTERRUPTS_FORCED)
 | 
						|
 | 
						|
/*
 | 
						|
 * Macros to modify the global interrupt enable bit in INTCON.
 | 
						|
 */
 | 
						|
#define portDISABLE_INTERRUPTS()    \
 | 
						|
    do                              \
 | 
						|
    {                               \
 | 
						|
        bGIE=0;                     \
 | 
						|
    } while(bGIE)   // MicroChip recommends this check!
 | 
						|
 | 
						|
#define portENABLE_INTERRUPTS()     \
 | 
						|
    do                              \
 | 
						|
    {                               \
 | 
						|
        bGIE=1;                     \
 | 
						|
    } while(0)
 | 
						|
 | 
						|
/*-----------------------------------------------------------*/
 | 
						|
 | 
						|
/*
 | 
						|
 * Critical section macros.
 | 
						|
 */
 | 
						|
extern uint8_t ucCriticalNesting;
 | 
						|
 | 
						|
#define portNO_CRITICAL_SECTION_NESTING     ( ( uint8_t ) 0 )
 | 
						|
 | 
						|
#define portENTER_CRITICAL()                                        \
 | 
						|
    do                                                              \
 | 
						|
    {                                                               \
 | 
						|
        portDISABLE_INTERRUPTS();                                   \
 | 
						|
                                                                    \
 | 
						|
        /*                                                          \
 | 
						|
         * Now interrupts are disabled ucCriticalNesting            \
 | 
						|
         * can be accessed directly. Increment                      \
 | 
						|
         * ucCriticalNesting to keep a count of how                 \
 | 
						|
         * many times portENTER_CRITICAL() has been called.         \
 | 
						|
         */                                                         \
 | 
						|
        ucCriticalNesting++;                                        \
 | 
						|
    } while(0)
 | 
						|
 | 
						|
#define portEXIT_CRITICAL()                                         \
 | 
						|
    do                                                              \
 | 
						|
    {                                                               \
 | 
						|
        if(ucCriticalNesting > portNO_CRITICAL_SECTION_NESTING)     \
 | 
						|
        {                                                           \
 | 
						|
            /*                                                      \
 | 
						|
             * Decrement the nesting count as we are leaving a      \
 | 
						|
             * critical section.                                    \
 | 
						|
             */                                                     \
 | 
						|
            ucCriticalNesting--;                                    \
 | 
						|
        }                                                           \
 | 
						|
                                                                    \
 | 
						|
        /*                                                          \
 | 
						|
         * If the nesting level has reached zero then               \
 | 
						|
         * interrupts should be re-enabled.                         \
 | 
						|
         */                                                         \
 | 
						|
        if( ucCriticalNesting == portNO_CRITICAL_SECTION_NESTING )  \
 | 
						|
        {                                                           \
 | 
						|
            portENABLE_INTERRUPTS();                                \
 | 
						|
        }                                                           \
 | 
						|
    } while(0)
 | 
						|
 | 
						|
/*-----------------------------------------------------------*/
 | 
						|
 | 
						|
/*
 | 
						|
 * The minimal stacksize is calculated on the first reference of
 | 
						|
 * portMINIMAL_STACK_SIZE. Some input to this calculation is
 | 
						|
 * compile time determined, other input is port-defined (see port.c)
 | 
						|
 */
 | 
						|
extern uint16_t usPortCALCULATE_MINIMAL_STACK_SIZE( void );
 | 
						|
extern uint16_t usCalcMinStackSize;
 | 
						|
 | 
						|
#define portMINIMAL_STACK_SIZE                  \
 | 
						|
    ((usCalcMinStackSize == 0)                  \
 | 
						|
        ? usPortCALCULATE_MINIMAL_STACK_SIZE()  \
 | 
						|
        : usCalcMinStackSize )
 | 
						|
 | 
						|
/*
 | 
						|
 * WizC uses a downgrowing stack
 | 
						|
 */
 | 
						|
#define portSTACK_GROWTH            ( -1 )
 | 
						|
 | 
						|
/*-----------------------------------------------------------*/
 | 
						|
 | 
						|
/*
 | 
						|
 * Macro's that pushes all the registers that make up the context of a task onto
 | 
						|
 * the stack, then saves the new top of stack into the TCB. TOSU and TBLPTRU
 | 
						|
 * are only saved/restored on devices with more than 64kB (32k Words) ROM.
 | 
						|
 *
 | 
						|
 * The stackpointer is held by WizC in FSR2 and points to the first free byte.
 | 
						|
 * WizC uses a "downgrowing" stack. There is no framepointer.
 | 
						|
 *
 | 
						|
 * We keep track of the interruptstatus using ucCriticalNesting. When this
 | 
						|
 * value equals zero, interrupts have to be enabled upon exit from the
 | 
						|
 * portRESTORE_CONTEXT macro.
 | 
						|
 *
 | 
						|
 * If this is called from an ISR then the interrupt enable bits must have been
 | 
						|
 * set for the ISR to ever get called.  Therefore we want to save
 | 
						|
 * ucCriticalNesting with value zero. This means the interrupts will again be
 | 
						|
 * re-enabled when the interrupted task is switched back in.
 | 
						|
 *
 | 
						|
 * If this is called from a manual context switch (i.e. from a call to yield),
 | 
						|
 * then we want to keep the current value of ucCriticalNesting so it is restored
 | 
						|
 * with its current value. This allows a yield from within a critical section.
 | 
						|
 *
 | 
						|
 * The compiler uses some locations at the bottom of RAM for temporary
 | 
						|
 * storage. The compiler may also have been instructed to optimize
 | 
						|
 * function-parameters and local variables to global storage. The compiler
 | 
						|
 * uses an area called LocOpt for this wizC feature.
 | 
						|
 * The total overheadstorage has to be saved in it's entirety as part of
 | 
						|
 * a task context. These macro's store/restore from data address 0x0000 to
 | 
						|
 * (OVERHEADPAGE0-LOCOPTSIZE+MAXLOCOPTSIZE - 1).
 | 
						|
 * OVERHEADPAGE0, LOCOPTSIZE and MAXLOCOPTSIZE are compiler-generated
 | 
						|
 * assembler definitions.
 | 
						|
 */
 | 
						|
 | 
						|
#define portSAVE_CONTEXT( ucInterruptForced )                       \
 | 
						|
    do                                                              \
 | 
						|
    {                                                               \
 | 
						|
        portDISABLE_INTERRUPTS();                                   \
 | 
						|
                                                                    \
 | 
						|
        _Pragma("asm")                                              \
 | 
						|
            ;                                                       \
 | 
						|
            ; Push the relevant SFR's onto the task's stack         \
 | 
						|
            ;                                                       \
 | 
						|
            movff   STATUS,POSTDEC2                                 \
 | 
						|
            movff   WREG,POSTDEC2                                   \
 | 
						|
            movff   BSR,POSTDEC2                                    \
 | 
						|
            movff   PRODH,POSTDEC2                                  \
 | 
						|
            movff   PRODL,POSTDEC2                                  \
 | 
						|
            movff   FSR0H,POSTDEC2                                  \
 | 
						|
            movff   FSR0L,POSTDEC2                                  \
 | 
						|
            movff   FSR1H,POSTDEC2                                  \
 | 
						|
            movff   FSR1L,POSTDEC2                                  \
 | 
						|
            movff   TABLAT,POSTDEC2                                 \
 | 
						|
            if __ROMSIZE > 0x8000                                   \
 | 
						|
                movff   TBLPTRU,POSTDEC2                            \
 | 
						|
            endif                                                   \
 | 
						|
            movff   TBLPTRH,POSTDEC2                                \
 | 
						|
            movff   TBLPTRL,POSTDEC2                                \
 | 
						|
            if __ROMSIZE > 0x8000                                   \
 | 
						|
                movff   PCLATU,POSTDEC2                             \
 | 
						|
            endif                                                   \
 | 
						|
            movff   PCLATH,POSTDEC2                                 \
 | 
						|
            ;                                                       \
 | 
						|
            ; Store the compiler-scratch-area as described above.   \
 | 
						|
            ;                                                       \
 | 
						|
            movlw   OVERHEADPAGE0-LOCOPTSIZE+MAXLOCOPTSIZE          \
 | 
						|
            clrf    FSR0L,ACCESS                                    \
 | 
						|
            clrf    FSR0H,ACCESS                                    \
 | 
						|
        _rtos_S1:                                                   \
 | 
						|
            movff   POSTINC0,POSTDEC2                               \
 | 
						|
            decfsz  WREG,W,ACCESS                                   \
 | 
						|
            SMARTJUMP _rtos_S1                                      \
 | 
						|
            ;                                                       \
 | 
						|
            ; Save the pic call/return-stack belonging to the       \
 | 
						|
            ; current task by copying it to the task's software-    \
 | 
						|
            ; stack. We save the hardware stack pointer (which      \
 | 
						|
            ; is the number of addresses on the stack) in the       \
 | 
						|
            ; W-register first because we need it later and it      \
 | 
						|
            ; is modified in the save-loop by executing pop's.      \
 | 
						|
            ; After the loop the W-register is stored on the        \
 | 
						|
            ; stack, too.                                           \
 | 
						|
            ;                                                       \
 | 
						|
            movf    STKPTR,W,ACCESS                                 \
 | 
						|
            bz      _rtos_s3                                        \
 | 
						|
        _rtos_S2:                                                   \
 | 
						|
            if __ROMSIZE > 0x8000                                   \
 | 
						|
                movff   TOSU,POSTDEC2                               \
 | 
						|
            endif                                                   \
 | 
						|
            movff   TOSH,POSTDEC2                                   \
 | 
						|
            movff   TOSL,POSTDEC2                                   \
 | 
						|
            pop                                                     \
 | 
						|
            tstfsz  STKPTR,ACCESS                                   \
 | 
						|
            SMARTJUMP _rtos_S2                                      \
 | 
						|
        _rtos_s3:                                                   \
 | 
						|
            movwf   POSTDEC2,ACCESS                                 \
 | 
						|
            ;                                                       \
 | 
						|
            ; Next the value for ucCriticalNesting used by the      \
 | 
						|
            ; task is stored on the stack. When                     \
 | 
						|
            ; (ucInterruptForced == portINTERRUPTS_FORCED), we save \
 | 
						|
            ; it as 0 (portNO_CRITICAL_SECTION_NESTING).            \
 | 
						|
            ;                                                       \
 | 
						|
            if ucInterruptForced == portINTERRUPTS_FORCED           \
 | 
						|
                clrf POSTDEC2,ACCESS                                \
 | 
						|
            else                                                    \
 | 
						|
                movff   ucCriticalNesting,POSTDEC2                  \
 | 
						|
            endif                                                   \
 | 
						|
            ;                                                       \
 | 
						|
            ; Save the new top of the software stack in the TCB.    \
 | 
						|
            ;                                                       \
 | 
						|
            movff   pxCurrentTCB,FSR0L                              \
 | 
						|
            movff   pxCurrentTCB+1,FSR0H                            \
 | 
						|
            movff   FSR2L,POSTINC0                                  \
 | 
						|
            movff   FSR2H,POSTINC0                                  \
 | 
						|
        _Pragma("asmend")                                           \
 | 
						|
    } while(0)
 | 
						|
 | 
						|
/************************************************************/
 | 
						|
 | 
						|
/*
 | 
						|
 * This is the reverse of portSAVE_CONTEXT.
 | 
						|
 */
 | 
						|
#define portRESTORE_CONTEXT()                                       \
 | 
						|
    do                                                              \
 | 
						|
    {                                                               \
 | 
						|
        _Pragma("asm")                                              \
 | 
						|
            ;                                                       \
 | 
						|
            ; Set FSR0 to point to pxCurrentTCB->pxTopOfStack.      \
 | 
						|
            ;                                                       \
 | 
						|
            movff   pxCurrentTCB,FSR0L                              \
 | 
						|
            movff   pxCurrentTCB+1,FSR0H                            \
 | 
						|
            ;                                                       \
 | 
						|
            ; De-reference FSR0 to set the address it holds into    \
 | 
						|
            ; FSR2 (i.e. *( pxCurrentTCB->pxTopOfStack ) ). FSR2    \
 | 
						|
            ; is used by wizC as stackpointer.                      \
 | 
						|
            ;                                                       \
 | 
						|
            movff   POSTINC0,FSR2L                                  \
 | 
						|
            movff   POSTINC0,FSR2H                                  \
 | 
						|
            ;                                                       \
 | 
						|
            ; Next, the value for ucCriticalNesting used by the     \
 | 
						|
            ; task is retrieved from the stack.                     \
 | 
						|
            ;                                                       \
 | 
						|
            movff   PREINC2,ucCriticalNesting                       \
 | 
						|
            ;                                                       \
 | 
						|
            ; Rebuild the pic call/return-stack. The number of      \
 | 
						|
            ; return addresses is the next item on the task stack.  \
 | 
						|
            ; Save this number in PRODL. Then fetch the addresses   \
 | 
						|
            ; and store them on the hardwarestack.                  \
 | 
						|
            ; The datasheets say we can't use movff here...         \
 | 
						|
            ;                                                       \
 | 
						|
            movff   PREINC2,PRODL   // Use PRODL as tempregister    \
 | 
						|
            clrf    STKPTR,ACCESS                                   \
 | 
						|
        _rtos_R1:                                                   \
 | 
						|
            push                                                    \
 | 
						|
            movf    PREINC2,W,ACCESS                                \
 | 
						|
            movwf   TOSL,ACCESS                                     \
 | 
						|
            movf    PREINC2,W,ACCESS                                \
 | 
						|
            movwf   TOSH,ACCESS                                     \
 | 
						|
            if __ROMSIZE > 0x8000                                   \
 | 
						|
                movf    PREINC2,W,ACCESS                            \
 | 
						|
                movwf   TOSU,ACCESS                                 \
 | 
						|
            else                                                    \
 | 
						|
                clrf    TOSU,ACCESS                                 \
 | 
						|
            endif                                                   \
 | 
						|
            decfsz  PRODL,F,ACCESS                                  \
 | 
						|
            SMARTJUMP _rtos_R1                                      \
 | 
						|
            ;                                                       \
 | 
						|
            ; Restore the compiler's working storage area to page 0 \
 | 
						|
            ;                                                       \
 | 
						|
            movlw   OVERHEADPAGE0-LOCOPTSIZE+MAXLOCOPTSIZE          \
 | 
						|
            movwf   FSR0L,ACCESS                                    \
 | 
						|
            clrf    FSR0H,ACCESS                                    \
 | 
						|
        _rtos_R2:                                                   \
 | 
						|
            decf    FSR0L,F,ACCESS                                  \
 | 
						|
            movff   PREINC2,INDF0                                   \
 | 
						|
            tstfsz  FSR0L,ACCESS                                    \
 | 
						|
            SMARTJUMP _rtos_R2                                      \
 | 
						|
            ;                                                       \
 | 
						|
            ; Restore the sfr's forming the tasks context.          \
 | 
						|
            ; We cannot yet restore bsr, w and status because       \
 | 
						|
            ; we need these registers for a final test.             \
 | 
						|
            ;                                                       \
 | 
						|
            movff   PREINC2,PCLATH                                  \
 | 
						|
            if __ROMSIZE > 0x8000                                   \
 | 
						|
                movff   PREINC2,PCLATU                              \
 | 
						|
            else                                                    \
 | 
						|
                clrf    PCLATU,ACCESS                               \
 | 
						|
            endif                                                   \
 | 
						|
            movff   PREINC2,TBLPTRL                                 \
 | 
						|
            movff   PREINC2,TBLPTRH                                 \
 | 
						|
            if __ROMSIZE > 0x8000                                   \
 | 
						|
                movff   PREINC2,TBLPTRU                             \
 | 
						|
            else                                                    \
 | 
						|
                clrf    TBLPTRU,ACCESS                              \
 | 
						|
            endif                                                   \
 | 
						|
            movff   PREINC2,TABLAT                                  \
 | 
						|
            movff   PREINC2,FSR1L                                   \
 | 
						|
            movff   PREINC2,FSR1H                                   \
 | 
						|
            movff   PREINC2,FSR0L                                   \
 | 
						|
            movff   PREINC2,FSR0H                                   \
 | 
						|
            movff   PREINC2,PRODL                                   \
 | 
						|
            movff   PREINC2,PRODH                                   \
 | 
						|
            ;                                                       \
 | 
						|
            ; The return from portRESTORE_CONTEXT() depends on      \
 | 
						|
            ; the value of ucCriticalNesting. When it is zero,      \
 | 
						|
            ; interrupts need to be enabled. This is done via a     \
 | 
						|
            ; retfie instruction because we need the                \
 | 
						|
            ; interrupt-enabling and the return to the restored     \
 | 
						|
            ; task to be uninterruptible.                           \
 | 
						|
            ; Because bsr, status and W are affected by the test    \
 | 
						|
            ; they are restored after the test.                     \
 | 
						|
            ;                                                       \
 | 
						|
            movlb   ucCriticalNesting>>8                            \
 | 
						|
            tstfsz  ucCriticalNesting,BANKED                        \
 | 
						|
            SMARTJUMP _rtos_R4                                      \
 | 
						|
        _rtos_R3:                                                   \
 | 
						|
            movff   PREINC2,BSR                                     \
 | 
						|
            movff   PREINC2,WREG                                    \
 | 
						|
            movff   PREINC2,STATUS                                  \
 | 
						|
            retfie  0       ; Return enabling interrupts            \
 | 
						|
        _rtos_R4:                                                   \
 | 
						|
            movff   PREINC2,BSR                                     \
 | 
						|
            movff   PREINC2,WREG                                    \
 | 
						|
            movff   PREINC2,STATUS                                  \
 | 
						|
            return  0       ; Return without affecting interrupts   \
 | 
						|
        _Pragma("asmend")                                           \
 | 
						|
    } while(0)
 | 
						|
 | 
						|
/*-----------------------------------------------------------*/
 | 
						|
 | 
						|
#define portTICK_PERIOD_MS  ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
 | 
						|
 | 
						|
/*-----------------------------------------------------------*/
 | 
						|
 | 
						|
extern void vPortYield( void );
 | 
						|
#define portYIELD()             vPortYield()
 | 
						|
 | 
						|
#define portNOP()   _Pragma("asm")                                  \
 | 
						|
                        nop                                         \
 | 
						|
                    _Pragma("asmend")
 | 
						|
 | 
						|
/*-----------------------------------------------------------*/
 | 
						|
 | 
						|
#define portTASK_FUNCTION( xFunction, pvParameters )        \
 | 
						|
    void pointed xFunction( void *pvParameters )        \
 | 
						|
    _Pragma(asmfunc xFunction)
 | 
						|
 | 
						|
#define portTASK_FUNCTION_PROTO     portTASK_FUNCTION
 | 
						|
/*-----------------------------------------------------------*/
 | 
						|
 | 
						|
 | 
						|
#define volatile
 | 
						|
#define register
 | 
						|
 | 
						|
#endif /* PORTMACRO_H */
 |