zephyr/include/arch/arm/CortexM/scb.h
Anas Nashif f367f071b6 doxygen: add @brief and capitalize
Remove function name from comment and add @brief instead.
Also capitilize first letter.

Change-Id: Ib708b49bf02e5bc89b0066637a55874e659637e0
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2016-02-05 20:14:33 -05:00

1233 lines
25 KiB
C

/* scb.h - ARM CORTEX-M System Control Block interface */
/*
* Copyright (c) 2013-2014 Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) 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.
*
* 3) Neither the name of Wind River Systems 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 HOLDER 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.
*/
/*
DESCRIPTION
Provide an interface to the System Control Block found on ARM Cortex-M
processors.
The API does not account for all possible usages of the SCB, only the
functionalities needed by the kernel. It does not contain NVIC
functionalities either: these can be found in nvic.h. MPU functionalities
are not implemented.
The same effect can be achieved by directly writing in the registers of the
SCB, with the layout available from scs.h, using the __scs.scb data
structure (or hardcoded values), but the APIs found here are less error-prone,
especially for registers with multiple instances to account for 16 exceptions.
If access to a missing functionality is needed, directly writing to the
registers is the way to implement it.
*/
#ifndef _SCB__H_
#define _SCB__H_
#ifdef _ASMLANGUAGE
/* needed by nano_cpu_atomic_idle() written in asm */
#define _SCB_SCR 0xE000ED10
#define _SCB_SCR_SEVONPEND (1 << 4)
#define _SCB_SCR_SLEEPDEEP (1 << 2)
#define _SCB_SCR_SLEEPONEXIT (1 << 1)
#else
#include <nanokernel.h>
#include <arch/cpu.h>
#include <misc/__assert.h>
#include <arch/arm/CortexM/scs.h>
#include <misc/util.h>
#include <stdint.h>
extern void _ScbSystemReset(void);
extern void _ScbNumPriGroupSet(unsigned int n);
/**
*
* @brief Find out if the NMI exception is pending
*
* @return 1 if it is pending, 0 otherwise
*/
static inline int _ScbIsNmiPending(void)
{
return !!__scs.scb.icsr.bit.nmipendset;
}
/**
*
* @brief Pend the NMI exception
*
* Pend the NMI exception: it should fire immediately.
*
* @return N/A
*/
static inline void _ScbNmiPend(void)
{
__scs.scb.icsr.bit.nmipendset = 1;
}
/**
*
* @brief Find out if the PendSV exception is pending
*
* @return 1 if it is pending, 0 otherwise
*/
static inline int _ScbIsPendsvPending(void)
{
return __scs.scb.icsr.bit.pendsvset;
}
/**
*
* @brief Set the PendSV exception
*
* Set the PendSV exception: it will be handled when the last nested exception
* returns, or immediately if running in thread mode.
*
* @return N/A
*/
static inline void _ScbPendsvSet(void)
{
__scs.scb.icsr.bit.pendsvset = 1;
}
/**
*
* @brief Clear the PendSV exception
*
* This routine clears the PendSV exception.
*
* @return N/A
*/
static inline void _ScbPendsvClear(void)
{
__scs.scb.icsr.bit.pendsvclr = 1;
}
/**
*
* @brief Find out if the SYSTICK exception is pending
*
* This routine determines if the SYSTICK exception is pending.
*
* @return 1 if it is pending, 0 otherwise
*/
static inline int _ScbIsSystickPending(void)
{
return __scs.scb.icsr.bit.pendstset;
}
/**
*
* @brief Pend the SYSTICK exception
*
* Pend the SYSTICK exception: it will be handled when returning from a higher
* priority exception or immediately if in thread mode or handling a lower
* priority exception.
*
* @return N/A
*/
static inline void _ScbSystickPendSet(void)
{
__scs.scb.icsr.bit.pendstset = 1;
}
/**
*
* @brief Clear the SYSTICK exception
*
* This routine clears the SYSTICK exception.
*
* @return N/A
*/
static inline void _ScbSystickPendClear(void)
{
__scs.scb.icsr.bit.pendstclr = 1;
}
/**
*
* @brief Find out if an external interrupt is pending
*
* Find out if an external interrupt, generated by the NVIC, is pending.
*
* @return 1 if one or more interrupt is pending, 0 otherwise
*/
static inline int _ScbIsIrqPending(void)
{
return __scs.scb.icsr.bit.isrpending;
}
/**
*
* @brief Find out the exception number of highest-priority
* pending exception (including interrupts)
*
* If one or more exceptions are pending, return the exception number of the
* highest-priority one; otherwise, return 0.
*
* @return the exception number if one is pending, 0 otherwise
*/
static inline int _ScbHiPriVectorPendingGet(void)
{
union __icsr reg;
reg.val = __scs.scb.icsr.val;
return reg.bit.vectpending;
}
/**
*
* @brief Find out if the currently executing exception is nested
*
* This routine determines if the currently executing exception is nested.
*
* @return 1 if nested, 0 otherwise
*/
static inline int _ScbIsNestedExc(void)
{
/* !bit == preempted exceptions */
return !__scs.scb.icsr.bit.rettobase;
}
/**
*
* @brief Find out if running in thread mode
*
* This routine determines if the current mode is thread mode.
*
* @return 1 if in thread mode, 0 otherwise
*/
static inline int _ScbIsInThreadMode(void)
{
/* 0 == thread mode */
return !__scs.scb.icsr.bit.vectactive;
}
/**
*
* @brief Find out if running in handler mode
*
* This routine determines if the current mode is handler mode.
*
* @return 1 if in handler mode, 0 otherwise
*/
static inline int _ScbIsInHandlerMode(void)
{
return !_ScbIsInThreadMode();
}
/**
*
* @brief Find out if handling an exception
*
* This routine determines if an exception is being handled (handler mode).
*
* @return 1 if handling an exception, 0 otherwise
*/
static inline int _ScbIsInExc(void)
{
return _ScbIsInHandlerMode();
}
/**
*
* @brief Obtain the currently executing vector
*
* If currently handling an exception/interrupt, return the exceuting vector
* number. If not, return 0.
*
* @return the currently excecuting vector number, 0 if in thread mode.
*/
static inline uint32_t _ScbActiveVectorGet(void)
{
return __scs.scb.icsr.bit.vectactive;
}
/**
*
* @brief Find out if vector table is in SRAM or ROM
*
* This routine determines if the currently executing exception is nested.
*
* @return 1 if in SRAM, 0 if in ROM
*/
static inline uint32_t _ScbIsVtableInSram(void)
{
return !!__scs.scb.vtor.bit.tblbase;
}
/**
*
* @brief Move vector table from SRAM to ROM and vice-versa
*
* This routine moves the vector table to the given memory region.
*
* @return 1 if in SRAM, 0 if in ROM
*/
static inline void _ScbVtableLocationSet(
int sram /* 1 to move vector to SRAM, 0 to move it to ROM */
)
{
__ASSERT(!(sram & 0xfffffffe), "");
__scs.scb.vtor.bit.tblbase = sram;
}
/**
*
* @brief Obtain base address of vector table
*
* This routine returs the vector table's base address.
*
* @return the base address of the vector table
*/
static inline uint32_t _ScbVtableAddrGet(void)
{
return __scs.scb.vtor.bit.tbloff;
}
/**
*
* @brief Set base address of vector table
*
* <addr> must align to the number of exception entries in vector table:
*
* numException = 16 + num_interrupts where each entry is 4 Bytes
*
* As a minimum, <addr> must be a multiple of 128:
*
* 0 <= num_interrupts < 16: multiple 0x080
* 16 <= num_interrupts < 48: multiple 0x100
* 48 <= num_interrupts < 112: multiple 0x200
* ....
*
* @return N/A
*/
static inline void _ScbVtableAddrSet(uint32_t addr /* base address, aligned on
128 minimum */
)
{
__ASSERT(!(addr & 0x7F), "invalid vtable base Addr");
__scs.scb.vtor.bit.tbloff = addr;
}
/**
*
* @brief Find out if data regions are little endian
*
* Data regions on Cortex-M devices can be either little or big endian. Code
* regions are always little endian.
*
* @return 1 if little endian, 0 if big endian
*/
static inline int _ScbIsDataLittleEndian(void)
{
return !(__scs.scb.aircr.bit.endianness);
}
/**
*
* @brief Get the programmed number of priority groups
*
* Exception priorities can be sub-divided into groups, with sub-priorities.
* Within these groups, exceptions do not preempt each other. The sub-priorities
* are only used to decide which exception will run when several are pending.
*
* @return the number of priority groups
*/
static inline int _ScbNumPriGroupGet(void)
{
return 1 << (7 - __scs.scb.aircr.bit.prigroup);
}
/**
*
* @brief CPU goes to sleep after exiting an ISR
*
* CPU never runs in thread mode until this is cancelled.
*
* This enables the feature until it is cancelled.
*
* @return N/A
*/
static inline void _ScbSleepOnExitSet(void)
{
__scs.scb.scr.bit.sleeponexit = 1;
}
/**
*
* @brief CPU does not go to sleep after exiting an ISR
*
* This routine prevents CPU sleep mode upon exiting an ISR.
* This is the normal operating mode.
*
* @return N/A
*/
static inline void _ScbSleepOnExitClear(void)
{
__scs.scb.scr.bit.sleeponexit = 0;
}
/**
*
* @brief Do not put CPU to sleep if pending exception are present
* when invoking wfe instruction
*
* By default, when invoking wfi or wfe instructions, if PRIMASK is masking
* interrupts and if an interrupt is pending, the CPU will go to sleep, and
* another interrupt is needed to wake it up. By coupling the use of the
* SEVONPEND feature and the wfe instruction (NOT wfi), pending exception will
* prevent the CPU from sleeping.
*
* This enables the feature until it is cancelled.
*
* @return N/A
*/
static inline void _ScbSevOnPendSet(void)
{
__scs.scb.scr.bit.sevonpend = 1;
}
/**
*
* @brief Clear SEVONPEND bit
*
* See _ScbSevOnPendSet().
*
* @return N/A
*/
static inline void _ScbSevOnPendClear(void)
{
__scs.scb.scr.bit.sevonpend = 0;
}
/**
*
* @brief When putting the CPU to sleep, put it in deep sleep
*
* When wfi/wfe is invoked, the CPU will go into a "deep sleep" mode, using less
* power than regular sleep mode, but with some possible side-effect.
*
* Behaviour is processor-specific.
*
* @return N/A
*/
static inline void _ScbSleepDeepSet(void)
{
__scs.scb.scr.bit.sleepdeep = 1;
}
/**
*
* @brief When putting the CPU to sleep, do not put it in deep sleep
*
* This routine prevents CPU deep sleep mode.
*
* @return N/A
*/
static inline void _ScbSleepDeepClear(void)
{
__scs.scb.scr.bit.sleepdeep = 0;
}
/**
*
* @brief Enable faulting on division by zero
*
* This routine enables the divide by zero fault.
* By default, the CPU ignores the error.
*
* @return N/A
*/
static inline void _ScbDivByZeroFaultEnable(void)
{
__scs.scb.ccr.bit.div_0_trp = 1;
}
/**
*
* @brief Ignore division by zero errors
*
* This routine disables the divide by zero fault.
* This is the default behaviour.
*
* @return N/A
*/
static inline void _ScbDivByZeroFaultDisable(void)
{
__scs.scb.ccr.bit.div_0_trp = 0;
}
/**
*
* @brief Enable faulting on unaligned access
*
* This routine enables the unaligned access fault.
* By default, the CPU ignores the error.
*
* @return N/A
*/
static inline void _ScbUnalignedFaultEnable(void)
{
__scs.scb.ccr.bit.unalign_trp = 1;
}
/**
*
* @brief Ignore unaligned access errors
*
* This routine disables the divide by zero fault.
* This is the default behaviour.
*
* @return N/A
*/
static inline void _ScbUnalignedFaultDisable(void)
{
__scs.scb.ccr.bit.unalign_trp = 0;
}
/**
*
* @brief Write the CCR all at once
*
* This routine writes the given value to the Configuration Control Register.
*
* @return N/A
*/
static inline void ScbCcrSet(uint32_t val /* value to write to CCR */
)
{
__scs.scb.ccr.val = val;
}
/**
*
* @brief Obtain priority of an exception
*
* Only works with exceptions 4 to 15, ie. do not use this for interrupts, which
* are exceptions 16+.
*
* Exceptions 1 to 3 priorities are fixed (-3, -2, -1).
*
* @return priority of exception <exc>
*/
static inline uint8_t _ScbExcPrioGet(uint8_t exc /* exception number, 4 to 15 */
)
{
/* For priority exception handler 4-15 */
__ASSERT((exc > 3) && (exc < 16), "");
return __scs.scb.shpr[exc - 4];
}
/**
*
* @brief Set priority of an exception
*
* Only works with exceptions 4 to 15, ie. do not use this for interrupts, which
* are exceptions 16+.
*
* Note that the processor might not implement all 8 bits, in which case the
* lower N bits are ignored.
*
* Exceptions 1 to 3 priorities are fixed (-3, -2, -1).
*
* @return N/A
*/
static inline void _ScbExcPrioSet(uint8_t exc, /* exception number, 4 to 15 */
uint8_t pri /* priority, 0 to 255 */
)
{
/* For priority exception handler 4-15 */
__ASSERT((exc > 3) && (exc < 16), "");
__scs.scb.shpr[exc - 4] = pri;
}
/**
*
* @brief Enable usage fault exceptions
*
* This routine enables usage faults.
* By default, the CPU does not raise usage fault exceptions.
*
* @return N/A
*/
static inline void _ScbUsageFaultEnable(void)
{
__scs.scb.shcsr.bit.usgfaultena = 1;
}
/**
*
* @brief Disable usage fault exceptions
*
* This routine disables usage faults.
* This is the default behaviour.
*
* @return N/A
*/
static inline void _ScbUsageFaultDisable(void)
{
__scs.scb.shcsr.bit.usgfaultena = 0;
}
/**
*
* @brief Enable bus fault exceptions
*
* This routine enables bus faults.
* By default, the CPU does not raise bus fault exceptions.
*
* @return N/A
*/
static inline void _ScbBusFaultEnable(void)
{
__scs.scb.shcsr.bit.busfaultena = 1;
}
/**
*
* @brief Disable bus fault exceptions
*
* This routine disables bus faults.
* This is the default behaviour.
*
* @return N/A
*/
static inline void _ScbBusFaultDisable(void)
{
__scs.scb.shcsr.bit.busfaultena = 0;
}
/**
*
* @brief Enable MPU faults exceptions
*
* This routine enables the MPU faults.
* By default, the CPU does not raise MPU fault exceptions.
*
* @return N/A
*/
static inline void _ScbMemFaultEnable(void)
{
__scs.scb.shcsr.bit.memfaultena = 1;
}
/**
*
* @brief Disable MPU fault exceptions
*
* This routine disables MPU faults.
* This is the default behaviour.
*
* @return N/A
*/
static inline void _ScbMemFaultDisable(void)
{
__scs.scb.shcsr.bit.memfaultena = 0;
}
/**
*
* @brief Find out if a hard fault is caused by
* a bus error on vector read
*
* This routine determines if a hard fault is caused by a bus error during
* a vector table read operation.
*
* @return 1 if so, 0 otherwise
*/
static inline int _ScbHardFaultIsBusErrOnVectorRead(void)
{
return __scs.scb.hfsr.bit.vecttbl;
}
/**
*
* @brief Find out if a fault was escalated to hard fault
*
* Happens if a fault cannot be triggered because of priority or because it was
* disabled.
*
* @return 1 if so, 0 otherwise
*/
static inline int _ScbHardFaultIsForced(void)
{
return __scs.scb.hfsr.bit.forced;
}
/**
*
* @brief Clear all hard faults (HFSR register)
*
* HFSR register is a 'write-one-to-clear' (W1C) register.
*
* @return 1 if so, 0 otherwise
*/
static inline int _ScbHardFaultAllFaultsReset(void)
{
return __scs.scb.hfsr.val = 0xffff;
}
/**
*
* @brief Find out if a hard fault is an MPU fault
*
* This routine determines if a hard fault is an MPU fault.
*
* @return 1 if so, 0 otherwise
*/
static inline int _ScbIsMemFault(void)
{
return !!__scs.scb.cfsr.byte.mmfsr.val;
}
/**
*
* @brief Find out if the MMFAR register contains a valid
* value
*
* The MMFAR register contains the faulting address on an MPU fault.
*
* @return 1 if so, 0 otherwise
*/
static inline int _ScbMemFaultIsMmfarValid(void)
{
return !!__scs.scb.cfsr.byte.mmfsr.bit.mmarvalid;
}
/**
*
* @brief Invalid the value in MMFAR
*
* This routine invalidates the MMFAR value. This should be done after
* processing an MPU fault.
*
* @return N/A
*/
static inline void _ScbMemFaultMmfarReset(void)
{
__scs.scb.cfsr.byte.mmfsr.bit.mmarvalid = 0;
}
/**
*
* @brief Clear all MPU faults (MMFSR register)
*
* CFSR/MMFSR register is a 'write-one-to-clear' (W1C) register.
*
* @return 1 if so, 0 otherwise
*/
static inline void _ScbMemFaultAllFaultsReset(void)
{
__scs.scb.cfsr.byte.mmfsr.val = 0xfe;
}
/**
*
* @brief Find out if an MPU fault is a stacking fault
*
* This routine determines if an MPU fault is a stacking fault.
* This may occur upon exception entry.
*
* @return 1 if so, 0 otherwise
*/
static inline int _ScbMemFaultIsStacking(void)
{
return !!__scs.scb.cfsr.byte.mmfsr.bit.mstkerr;
}
/**
*
* @brief Find out if an MPU fault is an unstacking fault
*
* This routine determines if an MPU fault is an unstacking fault.
* This may occur upon exception exit.
*
* @return 1 if so, 0 otherwise
*/
static inline int _ScbMemFaultIsUnstacking(void)
{
return !!__scs.scb.cfsr.byte.mmfsr.bit.munstkerr;
}
/**
*
* @brief Find out if an MPU fault is a data access
* violation
*
* If this routine returns 1, read the MMFAR register via _ScbMemFaultAddrGet()
* to get the faulting address.
*
* @return 1 if so, 0 otherwise
*/
static inline int _ScbMemFaultIsDataAccessViolation(void)
{
return !!__scs.scb.cfsr.byte.mmfsr.bit.daccviol;
}
/**
*
* @brief Find out if an MPU fault is an
* instruction access violation
*
* This routine determines if an MPU fault is due to an instruction access
* violation.
*
* @return 1 if so, 0 otherwise
*/
static inline int _ScbMemFaultIsInstrAccessViolation(void)
{
return !!__scs.scb.cfsr.byte.mmfsr.bit.iaccviol;
}
/**
*
* @brief Find out the faulting address on an MPU fault
*
* @return the faulting address
*/
static inline uint32_t _ScbMemFaultAddrGet(void)
{
return __scs.scb.mmfar;
}
/**
*
* @brief Find out if a hard fault is a bus fault
*
* This routine determines if a hard fault is a bus fault.
*
* @return 1 if so, 0 otherwise
*/
static inline int _ScbIsBusFault(void)
{
return !!__scs.scb.cfsr.byte.bfsr.val;
}
/**
*
* @brief Find out if the BFAR register contains a valid
* value
*
* The BFAR register contains the faulting address on bus fault.
*
* @return 1 if so, 0 otherwise
*/
static inline int _ScbBusFaultIsBfarValid(void)
{
return !!__scs.scb.cfsr.byte.bfsr.bit.bfarvalid;
}
/**
*
* @brief Invalid the value in BFAR
*
* This routine clears/invalidates the Bus Fault Address Register.
* It should be done after processing a bus fault.
*
* @return N/A
*/
static inline void _ScbBusFaultBfarReset(void)
{
__scs.scb.cfsr.byte.bfsr.bit.bfarvalid = 0;
}
/**
*
* @brief Clear all bus faults (BFSR register)
*
* CFSR/BFSR register is a 'write-one-to-clear' (W1C) register.
*
* @return N/A
*/
static inline void _ScbBusFaultAllFaultsReset(void)
{
__scs.scb.cfsr.byte.bfsr.val = 0xfe;
}
/**
*
* @brief Find out if a bus fault is a stacking fault
*
* This routine determines if a bus fault is a stacking fault.
* This may occurs upon exception entry.
*
* @return 1 if so, 0 otherwise
*/
static inline int _ScbBusFaultIsStacking(void)
{
return !!__scs.scb.cfsr.byte.bfsr.bit.stkerr;
}
/**
*
* @brief Find out if a bus fault is an unstacking fault
*
* This routine determines if a bus fault is an unstacking fault.
* This may occur upon exception exit.
*
* @return 1 if so, 0 otherwise
*/
static inline int _ScbBusFaultIsUnstacking(void)
{
return !!__scs.scb.cfsr.byte.bfsr.bit.unstkerr;
}
/**
*
* @brief Find out if a bus fault is an imprecise error
*
* This routine determines if a bus fault is an imprecise error.
*
* @return 1 if so, 0 otherwise
*/
static inline int _ScbBusFaultIsImprecise(void)
{
return !!__scs.scb.cfsr.byte.bfsr.bit.impreciserr;
}
/**
*
* @brief Find out if a bus fault is an precise error
*
* Read the BFAR register via _ScbBusFaultAddrGet() if this routine returns 1,
* as it will contain the faulting address.
*
* @return 1 if so, 0 otherwise
*/
static inline int _ScbBusFaultIsPrecise(void)
{
return !!__scs.scb.cfsr.byte.bfsr.bit.preciserr;
}
/**
*
* @brief Find out if a bus fault is an instruction bus
* error
*
* This routine determines if a bus fault is an instruction bus error.
* It is signalled only if the instruction is issued.
*
* @return 1 if so, 0 otherwise
*/
static inline int _ScbBusFaultIsInstrBusErr(void)
{
return !!__scs.scb.cfsr.byte.bfsr.bit.ibuserr;
}
/**
*
* @brief Get the faulting address on a precise bus fault
*
* This routine returns the faulting address for a precise bus fault.
*
* @return the faulting address
*/
static inline uint32_t _ScbBusFaultAddrGet(void)
{
return __scs.scb.bfar;
}
/**
*
* @brief Find out if a hard fault is a usage fault
*
* This routine determines if a hard fault is a usage fault.
*
* @return 1 if so, 0 otherwise
*/
static inline int _ScbIsUsageFault(void)
{
return !!__scs.scb.cfsr.byte.ufsr.val;
}
/**
*
* @brief Find out if a usage fault is a 'divide by zero'
* fault
*
* This routine determines if a usage fault is a 'divde by zero' fault.
*
* @return 1 if so, 0 otherwise
*/
static inline int _ScbUsageFaultIsDivByZero(void)
{
return !!__scs.scb.cfsr.byte.ufsr.bit.divbyzero;
}
/**
*
* @brief Find out if a usage fault is a unaligned access
* error
*
* This routine determines if a usage fault is an unaligned access error.
*
* @return 1 if so, 0 otherwise
*/
static inline int _ScbUsageFaultIsUnaligned(void)
{
return !!__scs.scb.cfsr.byte.ufsr.bit.unaligned;
}
/**
*
* @brief Find out if a usage fault is a coprocessor access
* error
*
* This routine determines if a usage fault is caused by a coprocessor access.
* This happens if the coprocessor is either absent or disabled.
*
* @return 1 if so, 0 otherwise
*/
static inline int _ScbUsageFaultIsNoCp(void)
{
return !!__scs.scb.cfsr.byte.ufsr.bit.nocp;
}
/**
*
* @brief Find out if a usage fault is a invalid PC
* load error
*
* Happens if the the instruction address on an exception return is not
* halfword-aligned.
*
* @return 1 if so, 0 otherwise
*/
static inline int _ScbUsageFaultIsInvalidPcLoad(void)
{
return !!__scs.scb.cfsr.byte.ufsr.bit.invpc;
}
/**
*
* @brief Find out if a usage fault is a invalid state
* error
*
* Happens if the the instruction address loaded in the PC via a branch, LDR or
* POP, or if the instruction address installed in a exception vector, does not
* have bit 0 set, ie., is not halfword-aligned.
*
* @return 1 if so, 0 otherwise
*/
static inline int _ScbUsageFaultIsInvalidState(void)
{
return !!__scs.scb.cfsr.byte.ufsr.bit.invstate;
}
/**
*
* @brief Find out if a usage fault is a undefined
* instruction error
*
* The processor tried to execute an invalid opcode.
*
* @return 1 if so, 0 otherwise
*/
static inline int _ScbUsageFaultIsUndefinedInstr(void)
{
return !!__scs.scb.cfsr.byte.ufsr.bit.undefinstr;
}
/**
*
* @brief Clear the 'division by zero' fault
*
* CFSR/UFSR register is a 'write-one-to-clear' (W1C) register.
*
* @return N/A
*/
static inline void _ScbUsageFaultDivByZeroReset(void)
{
__scs.scb.cfsr.byte.ufsr.bit.divbyzero = 1;
}
/**
*
* @brief Clear the 'unaligned access' fault
*
* CFSR/UFSR register is a 'write-one-to-clear' (W1C) register.
*
* @return N/A
*/
static inline void _ScbUsageFaultUnalignedReset(void)
{
__scs.scb.cfsr.byte.ufsr.bit.unaligned = 1;
}
/**
*
* @brief Clear the 'no co-processor' fault
*
* CFSR/UFSR register is a 'write-one-to-clear' (W1C) register.
*
* @return N/A
*/
static inline void _ScbUsageFaultNoCpReset(void)
{
__scs.scb.cfsr.byte.ufsr.bit.nocp = 1;
}
/**
*
* @brief Clear the 'invalid PC load ' fault
*
* CFSR/UFSR register is a 'write-one-to-clear' (W1C) register.
*
* @return N/A
*/
static inline void _ScbUsageFaultInvalidPcLoadReset(void)
{
__scs.scb.cfsr.byte.ufsr.bit.invpc = 1;
}
/**
*
* @brief Clear the 'invalid state' fault
*
* CFSR/UFSR register is a 'write-one-to-clear' (W1C) register.
*
* @return N/A
*/
static inline void _ScbUsageFaultInvalidStateReset(void)
{
__scs.scb.cfsr.byte.ufsr.bit.invstate = 1;
}
/**
*
* @brief Clear the 'undefined instruction' fault
*
* CFSR/UFSR register is a 'write-one-to-clear' (W1C) register.
*
* @return N/A
*/
static inline void _ScbUsageFaultUndefinedInstrReset(void)
{
__scs.scb.cfsr.byte.ufsr.bit.undefinstr = 1;
}
/**
*
* @brief Clear all usage faults (UFSR register)
*
* CFSR/UFSR register is a 'write-one-to-clear' (W1C) register.
*
* @return N/A
*/
static inline void _ScbUsageFaultAllFaultsReset(void)
{
__scs.scb.cfsr.byte.ufsr.val = 0xffff;
}
#endif /* _ASMLANGUAGE */
#endif /* _SCB__H_ */