📄 portisr.c
字号:
/*
* MODBUS Library: SAM7X Port
* Copyright (c) 2007 Christian Walter <wolti@sil.at>
* All rights reserved.
*
* $Id: portISR.c,v 1.1 2007/09/12 10:15:56 wolti Exp $
*/
/*
* FreeRTOS.org V4.4.0 - Copyright (C) 2003-2007 Richard Barry.
*
* This file is part of the FreeRTOS.org distribution.
*
* FreeRTOS.org is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* FreeRTOS.org is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with FreeRTOS.org; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* A special exception to the GPL can be applied should you wish to distribute
* a combined work that includes FreeRTOS.org, without being obliged to provide
* the source code for any proprietary components. See the licensing section
* of http://www.FreeRTOS.org for full details of how and when the exception
* can be applied.
*
****************************************************************************
* See http://www.FreeRTOS.org for documentation, latest information, license
* and contact details. Please ensure to read the configuration and relevant
* port sections of the online documentation.
*
* Also see http://www.SafeRTOS.com for an IEC 61508 compliant version along
* with commercial development and support options.
***************************************************************************
*/
/* ----------------------- System includes ----------------------------------*/
#include <stdlib.h>
/* ----------------------- FreeRTOS includes --------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
/* ----------------------- Platform includes --------------------------------*/
#include "AT91SAM7X256.h"
#include "lib_AT91SAM7X256.h"
/* ----------------------- Defines ------------------------------------------*/
#define portTIMER_MATCH_ISR_BIT ( ( unsigned portCHAR ) 0x01 )
#define portCLEAR_VIC_INTERRUPT ( ( unsigned portLONG ) 0 )
#define portNO_CRITICAL_NESTING ( ( unsigned portLONG ) 0 )
volatile unsigned portLONG ulCriticalNesting = 9999UL;
/* ----------------------- Type definitions ---------------------------------*/
/* ----------------------- Static variables ---------------------------------*/
/* ----------------------- Function prototypes ------------------------------*/
void vPortDisableInterruptsFromThumb( void ) __attribute__ ( ( naked ) );
void vPortEnableInterruptsFromThumb( void ) __attribute__ ( ( naked ) );
void vNonPreemptiveTick( void ) __attribute__ ( ( interrupt( "IRQ" ) ) );
void vPreemptiveTick( void ) __attribute__ ( ( naked ) );
void vPortYieldProcessor( void ) __attribute__ ( ( interrupt( "SWI" ), naked ) );
void vPortISRStartFirstTask( void );
/* ----------------------- Static functions ---------------------------------*/
/* ----------------------- Start implementation -----------------------------*/
void
vPortISRStartFirstTask( void )
{
/* Simply start the scheduler. This is included here as it can only be
* called from ARM mode.
*/
portRESTORE_CONTEXT( );
}
/*
* Called by portYIELD() or taskYIELD() to manually force a context switch.
*
* When a context switch is performed from the task level the saved task
* context is made to look as if it occurred from within the tick ISR. This
* way the same restore context function can be used when restoring the context
* saved from the ISR or that saved from a call to vPortYieldProcessor.
*/
void
vPortYieldProcessor( void )
{
/* Within an IRQ ISR the link register has an offset from the true return
* address, but an SWI ISR does not. Add the offset manually so the same
* ISR return code can be used in both cases.
*/
asm volatile ( "ADD LR, LR, #4" );
/* Perform the context switch. First save the context of the current task. */
portSAVE_CONTEXT( );
/* Find the highest priority task that is ready to run. */
vTaskSwitchContext( );
/* Restore the context of the new task. */
portRESTORE_CONTEXT( );
}
/*
* The ISR used for the scheduler tick depends on whether the cooperative or
* the preemptive scheduler is being used.
*/
#if configUSE_PREEMPTION == 0
void
vNonPreemptiveTick( void )
{
unsigned portLONG ulDummy;
/* Increment the tick count - which may wake some tasks but as the
* preemptive scheduler is not being used any woken task is not given
* processor time no matter what its priority.
*/
vTaskIncrementTick( );
/* Clear the PIT interrupt. */
AT91C_BASE_AIC->AIC_EOICR = AT91C_BASE_PITC->PITC_PIVR;
}
#else
void
vPreemptiveTick( void )
{
/* Save the context of the current task. */
portSAVE_CONTEXT( );
/* Increment the tick count - this may wake a task. */
vTaskIncrementTick( );
/* Find the highest priority task that is ready to run. */
vTaskSwitchContext( );
/* End the interrupt in the AIC. */
AT91C_BASE_AIC->AIC_EOICR = AT91C_BASE_PITC->PITC_PIVR;;
portRESTORE_CONTEXT( );
}
#endif
/*
* 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.
*/
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. */
}
/* The code generated by the GCC compiler uses the stack in different ways at
* different optimisation levels. The interrupt flags can therefore not always
* be saved to the stack. Instead the critical section nesting level is stored
* in a variable, which is then saved as part of the stack context.
*/
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. */
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -