kopia lustrzana https://github.com/micropython/micropython
413 wiersze
11 KiB
C
413 wiersze
11 KiB
C
|
//*****************************************************************************
|
||
|
//
|
||
|
// cpu.c
|
||
|
//
|
||
|
// Instruction wrappers for special CPU instructions needed by the
|
||
|
// drivers.
|
||
|
//
|
||
|
// Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/
|
||
|
//
|
||
|
//
|
||
|
// Redistribution and use in source and binary forms, with or without
|
||
|
// modification, are permitted provided that the following conditions
|
||
|
// are met:
|
||
|
//
|
||
|
// Redistributions of source code must retain the above copyright
|
||
|
// notice, this list of conditions and the following disclaimer.
|
||
|
//
|
||
|
// Redistributions in binary form must reproduce the above copyright
|
||
|
// notice, this list of conditions and the following disclaimer in the
|
||
|
// documentation and/or other materials provided with the
|
||
|
// distribution.
|
||
|
//
|
||
|
// Neither the name of Texas Instruments Incorporated nor the names of
|
||
|
// its contributors may be used to endorse or promote products derived
|
||
|
// from this software without specific prior written permission.
|
||
|
//
|
||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||
|
//
|
||
|
//*****************************************************************************
|
||
|
#include "cpu.h"
|
||
|
|
||
|
//*****************************************************************************
|
||
|
//
|
||
|
// Wrapper function for the CPSID instruction. Returns the state of PRIMASK
|
||
|
// on entry.
|
||
|
//
|
||
|
//*****************************************************************************
|
||
|
#if defined(gcc)
|
||
|
unsigned long __attribute__((naked))
|
||
|
CPUcpsid(void)
|
||
|
{
|
||
|
unsigned long ulRet;
|
||
|
|
||
|
//
|
||
|
// Read PRIMASK and disable interrupts.
|
||
|
//
|
||
|
__asm(" mrs r0, PRIMASK\n"
|
||
|
" cpsid i\n"
|
||
|
" dsb \n"
|
||
|
" isb \n"
|
||
|
" bx lr\n"
|
||
|
: "=r" (ulRet));
|
||
|
|
||
|
//
|
||
|
// The return is handled in the inline assembly, but the compiler will
|
||
|
// still complain if there is not an explicit return here (despite the fact
|
||
|
// that this does not result in any code being produced because of the
|
||
|
// naked attribute).
|
||
|
//
|
||
|
return(ulRet);
|
||
|
}
|
||
|
#endif
|
||
|
#if defined(ewarm)
|
||
|
unsigned long
|
||
|
CPUcpsid(void)
|
||
|
{
|
||
|
//
|
||
|
// Read PRIMASK and disable interrupts.
|
||
|
//
|
||
|
__asm(" mrs r0, PRIMASK\n"
|
||
|
" cpsid i\n"
|
||
|
" dsb \n"
|
||
|
" isb \n");
|
||
|
|
||
|
//
|
||
|
// "Warning[Pe940]: missing return statement at end of non-void function"
|
||
|
// is suppressed here to avoid putting a "bx lr" in the inline assembly
|
||
|
// above and a superfluous return statement here.
|
||
|
//
|
||
|
#pragma diag_suppress=Pe940
|
||
|
}
|
||
|
#pragma diag_default=Pe940
|
||
|
#endif
|
||
|
#if defined(ccs)
|
||
|
unsigned long
|
||
|
CPUcpsid(void)
|
||
|
{
|
||
|
//
|
||
|
// Read PRIMASK and disable interrupts.
|
||
|
//
|
||
|
__asm(" mrs r0, PRIMASK\n"
|
||
|
" cpsid i\n"
|
||
|
" dsb \n"
|
||
|
" isb \n"
|
||
|
" bx lr\n");
|
||
|
|
||
|
//
|
||
|
// The following keeps the compiler happy, because it wants to see a
|
||
|
// return value from this function. It will generate code to return
|
||
|
// a zero. However, the real return is the "bx lr" above, so the
|
||
|
// return(0) is never executed and the function returns with the value
|
||
|
// you expect in R0.
|
||
|
//
|
||
|
return(0);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
//*****************************************************************************
|
||
|
//
|
||
|
// Wrapper function returning the state of PRIMASK (indicating whether
|
||
|
// interrupts are enabled or disabled).
|
||
|
//
|
||
|
//*****************************************************************************
|
||
|
#if defined(gcc)
|
||
|
unsigned long __attribute__((naked))
|
||
|
CPUprimask(void)
|
||
|
{
|
||
|
unsigned long ulRet;
|
||
|
|
||
|
//
|
||
|
// Read PRIMASK and disable interrupts.
|
||
|
//
|
||
|
__asm(" mrs r0, PRIMASK\n"
|
||
|
" bx lr\n"
|
||
|
: "=r" (ulRet));
|
||
|
|
||
|
//
|
||
|
// The return is handled in the inline assembly, but the compiler will
|
||
|
// still complain if there is not an explicit return here (despite the fact
|
||
|
// that this does not result in any code being produced because of the
|
||
|
// naked attribute).
|
||
|
//
|
||
|
return(ulRet);
|
||
|
}
|
||
|
#endif
|
||
|
#if defined(ewarm)
|
||
|
unsigned long
|
||
|
CPUprimask(void)
|
||
|
{
|
||
|
//
|
||
|
// Read PRIMASK and disable interrupts.
|
||
|
//
|
||
|
__asm(" mrs r0, PRIMASK\n");
|
||
|
|
||
|
//
|
||
|
// "Warning[Pe940]: missing return statement at end of non-void function"
|
||
|
// is suppressed here to avoid putting a "bx lr" in the inline assembly
|
||
|
// above and a superfluous return statement here.
|
||
|
//
|
||
|
#pragma diag_suppress=Pe940
|
||
|
}
|
||
|
#pragma diag_default=Pe940
|
||
|
#endif
|
||
|
#if defined(ccs)
|
||
|
unsigned long
|
||
|
CPUprimask(void)
|
||
|
{
|
||
|
//
|
||
|
// Read PRIMASK and disable interrupts.
|
||
|
//
|
||
|
__asm(" mrs r0, PRIMASK\n"
|
||
|
" bx lr\n");
|
||
|
|
||
|
//
|
||
|
// The following keeps the compiler happy, because it wants to see a
|
||
|
// return value from this function. It will generate code to return
|
||
|
// a zero. However, the real return is the "bx lr" above, so the
|
||
|
// return(0) is never executed and the function returns with the value
|
||
|
// you expect in R0.
|
||
|
//
|
||
|
return(0);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
//*****************************************************************************
|
||
|
//
|
||
|
// Wrapper function for the CPSIE instruction. Returns the state of PRIMASK
|
||
|
// on entry.
|
||
|
//
|
||
|
//*****************************************************************************
|
||
|
#if defined(gcc)
|
||
|
unsigned long __attribute__((naked))
|
||
|
CPUcpsie(void)
|
||
|
{
|
||
|
unsigned long ulRet;
|
||
|
|
||
|
//
|
||
|
// Read PRIMASK and enable interrupts.
|
||
|
//
|
||
|
__asm(" mrs r0, PRIMASK\n"
|
||
|
" cpsie i\n"
|
||
|
" dsb \n"
|
||
|
" isb \n"
|
||
|
" bx lr\n"
|
||
|
: "=r" (ulRet));
|
||
|
|
||
|
//
|
||
|
// The return is handled in the inline assembly, but the compiler will
|
||
|
// still complain if there is not an explicit return here (despite the fact
|
||
|
// that this does not result in any code being produced because of the
|
||
|
// naked attribute).
|
||
|
//
|
||
|
return(ulRet);
|
||
|
}
|
||
|
#endif
|
||
|
#if defined(ewarm)
|
||
|
unsigned long
|
||
|
CPUcpsie(void)
|
||
|
{
|
||
|
//
|
||
|
// Read PRIMASK and enable interrupts.
|
||
|
//
|
||
|
__asm(" mrs r0, PRIMASK\n"
|
||
|
" cpsie i\n"
|
||
|
" dsb \n"
|
||
|
" isb \n");
|
||
|
|
||
|
//
|
||
|
// "Warning[Pe940]: missing return statement at end of non-void function"
|
||
|
// is suppressed here to avoid putting a "bx lr" in the inline assembly
|
||
|
// above and a superfluous return statement here.
|
||
|
//
|
||
|
#pragma diag_suppress=Pe940
|
||
|
}
|
||
|
#pragma diag_default=Pe940
|
||
|
#endif
|
||
|
#if defined(ccs)
|
||
|
unsigned long
|
||
|
CPUcpsie(void)
|
||
|
{
|
||
|
//
|
||
|
// Read PRIMASK and enable interrupts.
|
||
|
//
|
||
|
__asm(" mrs r0, PRIMASK\n"
|
||
|
" cpsie i\n"
|
||
|
" dsb \n"
|
||
|
" isb \n"
|
||
|
" bx lr\n");
|
||
|
|
||
|
//
|
||
|
// The following keeps the compiler happy, because it wants to see a
|
||
|
// return value from this function. It will generate code to return
|
||
|
// a zero. However, the real return is the "bx lr" above, so the
|
||
|
// return(0) is never executed and the function returns with the value
|
||
|
// you expect in R0.
|
||
|
//
|
||
|
return(0);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
//*****************************************************************************
|
||
|
//
|
||
|
// Wrapper function for the WFI instruction.
|
||
|
//
|
||
|
//*****************************************************************************
|
||
|
#if defined(gcc)
|
||
|
void __attribute__((naked))
|
||
|
CPUwfi(void)
|
||
|
{
|
||
|
//
|
||
|
// Wait for the next interrupt.
|
||
|
//
|
||
|
__asm(" dsb \n"
|
||
|
" isb \n"
|
||
|
" wfi \n"
|
||
|
" bx lr\n");
|
||
|
}
|
||
|
#endif
|
||
|
#if defined(ewarm)
|
||
|
void
|
||
|
CPUwfi(void)
|
||
|
{
|
||
|
//
|
||
|
// Wait for the next interrupt.
|
||
|
//
|
||
|
__asm(" dsb \n"
|
||
|
" isb \n"
|
||
|
" wfi \n");
|
||
|
}
|
||
|
#endif
|
||
|
#if defined(ccs)
|
||
|
void
|
||
|
CPUwfi(void)
|
||
|
{
|
||
|
//
|
||
|
// Wait for the next interrupt.
|
||
|
//
|
||
|
__asm(" dsb \n"
|
||
|
" isb \n"
|
||
|
" wfi \n");
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
//*****************************************************************************
|
||
|
//
|
||
|
// Wrapper function for writing the BASEPRI register.
|
||
|
//
|
||
|
//*****************************************************************************
|
||
|
#if defined(gcc)
|
||
|
void __attribute__((naked))
|
||
|
CPUbasepriSet(unsigned long ulNewBasepri)
|
||
|
{
|
||
|
|
||
|
//
|
||
|
// Set the BASEPRI register
|
||
|
//
|
||
|
__asm(" msr BASEPRI, r0\n"
|
||
|
" dsb \n"
|
||
|
" isb \n"
|
||
|
" bx lr\n");
|
||
|
}
|
||
|
#endif
|
||
|
#if defined(ewarm)
|
||
|
void
|
||
|
CPUbasepriSet(unsigned long ulNewBasepri)
|
||
|
{
|
||
|
//
|
||
|
// Set the BASEPRI register
|
||
|
//
|
||
|
__asm(" msr BASEPRI, r0\n"
|
||
|
" dsb \n"
|
||
|
" isb \n");
|
||
|
}
|
||
|
#endif
|
||
|
#if defined(ccs)
|
||
|
void
|
||
|
CPUbasepriSet(unsigned long ulNewBasepri)
|
||
|
{
|
||
|
//
|
||
|
// Set the BASEPRI register
|
||
|
//
|
||
|
__asm(" msr BASEPRI, r0\n"
|
||
|
" dsb \n"
|
||
|
" isb \n");
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
//*****************************************************************************
|
||
|
//
|
||
|
// Wrapper function for reading the BASEPRI register.
|
||
|
//
|
||
|
//*****************************************************************************
|
||
|
#if defined(gcc)
|
||
|
unsigned long __attribute__((naked))
|
||
|
CPUbasepriGet(void)
|
||
|
{
|
||
|
unsigned long ulRet;
|
||
|
|
||
|
//
|
||
|
// Read BASEPRI
|
||
|
//
|
||
|
__asm(" mrs r0, BASEPRI\n"
|
||
|
" bx lr\n"
|
||
|
: "=r" (ulRet));
|
||
|
|
||
|
//
|
||
|
// The return is handled in the inline assembly, but the compiler will
|
||
|
// still complain if there is not an explicit return here (despite the fact
|
||
|
// that this does not result in any code being produced because of the
|
||
|
// naked attribute).
|
||
|
//
|
||
|
return(ulRet);
|
||
|
}
|
||
|
#endif
|
||
|
#if defined(ewarm)
|
||
|
unsigned long
|
||
|
CPUbasepriGet(void)
|
||
|
{
|
||
|
//
|
||
|
// Read BASEPRI
|
||
|
//
|
||
|
__asm(" mrs r0, BASEPRI\n");
|
||
|
|
||
|
//
|
||
|
// "Warning[Pe940]: missing return statement at end of non-void function"
|
||
|
// is suppressed here to avoid putting a "bx lr" in the inline assembly
|
||
|
// above and a superfluous return statement here.
|
||
|
//
|
||
|
#pragma diag_suppress=Pe940
|
||
|
}
|
||
|
#pragma diag_default=Pe940
|
||
|
#endif
|
||
|
#if defined(ccs)
|
||
|
unsigned long
|
||
|
CPUbasepriGet(void)
|
||
|
{
|
||
|
//
|
||
|
// Read BASEPRI
|
||
|
//
|
||
|
__asm(" mrs r0, BASEPRI\n"
|
||
|
" bx lr\n");
|
||
|
|
||
|
//
|
||
|
// The following keeps the compiler happy, because it wants to see a
|
||
|
// return value from this function. It will generate code to return
|
||
|
// a zero. However, the real return is the "bx lr" above, so the
|
||
|
// return(0) is never executed and the function returns with the value
|
||
|
// you expect in R0.
|
||
|
//
|
||
|
return(0);
|
||
|
}
|
||
|
#endif
|