183 lines
6.3 KiB
C
183 lines
6.3 KiB
C
|
/*
|
||
|
* FreeRTOS Kernel V10.2.1
|
||
|
* Copyright (C) 2019 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.
|
||
|
*
|
||
|
* http://www.FreeRTOS.org
|
||
|
* http://aws.amazon.com/freertos
|
||
|
*
|
||
|
* 1 tab == 4 spaces!
|
||
|
*/
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------
|
||
|
* Components that can be compiled to either ARM or THUMB mode are
|
||
|
* contained in port.c The ISR routines, which can only be compiled
|
||
|
* to ARM mode, are contained in this file.
|
||
|
*----------------------------------------------------------*/
|
||
|
|
||
|
/*
|
||
|
*/
|
||
|
|
||
|
/* Scheduler includes. */
|
||
|
#include "FreeRTOS.h"
|
||
|
#include "task.h"
|
||
|
|
||
|
/* Constants required to handle critical sections. */
|
||
|
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
|
||
|
|
||
|
volatile uint32_t ulCriticalNesting = 9999UL;
|
||
|
|
||
|
/*-----------------------------------------------------------*/
|
||
|
|
||
|
/*
|
||
|
* The scheduler can only be started from ARM mode, hence the inclusion of this
|
||
|
* function here.
|
||
|
*/
|
||
|
void vPortISRStartFirstTask( void );
|
||
|
/*-----------------------------------------------------------*/
|
||
|
|
||
|
void vPortISRStartFirstTask( void )
|
||
|
{
|
||
|
/* Simply start the scheduler. This is included here as it can only be
|
||
|
called from ARM mode. */
|
||
|
asm volatile ( \
|
||
|
"LDR R0, =pxCurrentTCB \n\t" \
|
||
|
"LDR R0, [R0] \n\t" \
|
||
|
"LDR LR, [R0] \n\t" \
|
||
|
\
|
||
|
/* The critical nesting depth is the first item on the stack. */ \
|
||
|
/* Load it into the ulCriticalNesting variable. */ \
|
||
|
"LDR R0, =ulCriticalNesting \n\t" \
|
||
|
"LDMFD LR!, {R1} \n\t" \
|
||
|
"STR R1, [R0] \n\t" \
|
||
|
\
|
||
|
/* Get the SPSR from the stack. */ \
|
||
|
"LDMFD LR!, {R0} \n\t" \
|
||
|
"MSR SPSR, R0 \n\t" \
|
||
|
\
|
||
|
/* Restore all system mode registers for the task. */ \
|
||
|
"LDMFD LR, {R0-R14}^ \n\t" \
|
||
|
"NOP \n\t" \
|
||
|
\
|
||
|
/* Restore the return address. */ \
|
||
|
"LDR LR, [LR, #+60] \n\t" \
|
||
|
\
|
||
|
/* And return - correcting the offset in the LR to obtain the */ \
|
||
|
/* correct address. */ \
|
||
|
"SUBS PC, LR, #4 \n\t" \
|
||
|
);
|
||
|
}
|
||
|
/*-----------------------------------------------------------*/
|
||
|
|
||
|
void vPortTickISR( void )
|
||
|
{
|
||
|
/* Increment the RTOS tick count, then look for the highest priority
|
||
|
task that is ready to run. */
|
||
|
if( xTaskIncrementTick() != pdFALSE )
|
||
|
{
|
||
|
vTaskSwitchContext();
|
||
|
}
|
||
|
|
||
|
/* Ready for the next interrupt. */
|
||
|
TB_ClearITPendingBit( TB_IT_Update );
|
||
|
}
|
||
|
|
||
|
/*-----------------------------------------------------------*/
|
||
|
|
||
|
/*
|
||
|
* The interrupt management utilities can only be called from ARM mode. When
|
||
|
* THUMB_INTERWORK is defined the utilities are defined as functions here to
|
||
|
* ensure a switch to ARM mode. When THUMB_INTERWORK is not defined then
|
||
|
* the utilities are defined as macros in portmacro.h - as per other ports.
|
||
|
*/
|
||
|
#ifdef THUMB_INTERWORK
|
||
|
|
||
|
void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||
|
void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||
|
|
||
|
void vPortDisableInterruptsFromThumb( void )
|
||
|
{
|
||
|
asm volatile (
|
||
|
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||
|
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||
|
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */
|
||
|
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||
|
"LDMIA SP!, {R0} \n\t" /* Pop R0. */
|
||
|
"BX R14" ); /* Return back to thumb. */
|
||
|
}
|
||
|
|
||
|
void vPortEnableInterruptsFromThumb( void )
|
||
|
{
|
||
|
asm volatile (
|
||
|
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||
|
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||
|
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */
|
||
|
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||
|
"LDMIA SP!, {R0} \n\t" /* Pop R0. */
|
||
|
"BX R14" ); /* Return back to thumb. */
|
||
|
}
|
||
|
|
||
|
#endif /* THUMB_INTERWORK */
|
||
|
/*-----------------------------------------------------------*/
|
||
|
|
||
|
void vPortEnterCritical( void )
|
||
|
{
|
||
|
/* Disable interrupts as per portDISABLE_INTERRUPTS(); */
|
||
|
asm volatile (
|
||
|
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||
|
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||
|
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */
|
||
|
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||
|
"LDMIA SP!, {R0}" ); /* Pop R0. */
|
||
|
|
||
|
/* Now interrupts are disabled ulCriticalNesting can be accessed
|
||
|
directly. Increment ulCriticalNesting to keep a count of how many times
|
||
|
portENTER_CRITICAL() has been called. */
|
||
|
ulCriticalNesting++;
|
||
|
}
|
||
|
/*-----------------------------------------------------------*/
|
||
|
|
||
|
void vPortExitCritical( void )
|
||
|
{
|
||
|
if( ulCriticalNesting > portNO_CRITICAL_NESTING )
|
||
|
{
|
||
|
/* Decrement the nesting count as we are leaving a critical section. */
|
||
|
ulCriticalNesting--;
|
||
|
|
||
|
/* If the nesting level has reached zero then interrupts should be
|
||
|
re-enabled. */
|
||
|
if( ulCriticalNesting == portNO_CRITICAL_NESTING )
|
||
|
{
|
||
|
/* Enable interrupts as per portEXIT_CRITICAL(). */
|
||
|
asm volatile (
|
||
|
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||
|
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||
|
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */
|
||
|
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||
|
"LDMIA SP!, {R0}" ); /* Pop R0. */
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|