mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-05-09 22:59:05 -04:00
* Add XMOS XCore ports Some minor modifications are also made to the kernel to support the XCore compiler's automatic stack size calculation. * Update kernel to support SMP The XMOS XCore ports are also updated to support SMP. * Fix compiler warnings in xcore ports The port set and clear interrupt mask from ISR macros were removed from the ports so that the default macros found in FreeRTOS.h are used instead. The default macros do not result in warnings when they are used. * Remove inline function from timers.h Inline function converted to macro. This should now build when optimizations are off and inlining is disabled. * Fix compiler warnings in xcore ports and tasks.c * fixed documentation for ulTaskNotifyTake() and ulTaskNotifyTakeIndexed() * spelling fixes for tasks.c Co-authored-by: Michael Bruno <mikeb@xmos.com>
424 lines
14 KiB
C
424 lines
14 KiB
C
/*
|
|
* FreeRTOS Kernel V10.4.3
|
|
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
*
|
|
* 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
|
|
*
|
|
* 1 tab == 4 spaces!
|
|
*/
|
|
|
|
/*
|
|
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( configUSE_16_BIT_TICKS == 1 )
|
|
typedef uint16_t TickType_t;
|
|
#define portMAX_DELAY ( TickType_t ) ( 0xFFFF )
|
|
#else
|
|
typedef uint32_t TickType_t;
|
|
#define portMAX_DELAY ( TickType_t ) ( 0xFFFFFFFF )
|
|
#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
|
|
* compiletime 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 helt 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 ucCritialNesting 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 uninterruptable. \
|
|
; 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 */
|
|
|