Commit 8d8eb0d8 authored by Carles Cufi's avatar Carles Cufi Committed by Kumar Gala
Browse files

arm: Cortex-M0: Adapt core register code to M0



The Cortex-M0(+) and in general processors that support only the ARMv6-M
instruction set have a reduced set of registers and fields compared to
the ARMv7-M compliant processors.
This change goes through all core registers and disables or removes
everything that is not part of the ARMv6-M architecture when compiling
for Cortex-M0.

Jira: ZEP-1497

Change-id: I13e2637bb730e69d02f2a5ee687038dc69ad28a8
Signed-off-by: default avatarVinayak Chettimada <vinayak.kariappa.chettimada@nordicsemi.no>
Signed-off-by: default avatarCarles Cufi <carles.cufi@nordicsemi.no>
Signed-off-by: default avatarKumar Gala <kumar.gala@linaro.org>
parent 420e5c05
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -90,6 +90,7 @@ void sys_arch_reboot(int type)
	DO_REBOOT();
}

#if !defined(CONFIG_CPU_CORTEX_M0_M0PLUS)
/**
 *
 * @brief Set the number of priority groups based on the number of exception
@@ -134,3 +135,4 @@ void _ScbNumPriGroupSet(unsigned int n)

	__scs.scb.aircr.val = reg.val;
}
#endif /* !CONFIG_CPU_CORTEX_M0_M0PLUS */
+2 −0
Original line number Diff line number Diff line
@@ -372,5 +372,7 @@ void _Fault(const NANO_ESF *esf)
 */
void _FaultInit(void)
{
#if !defined(CONFIG_CPU_CORTEX_M0_M0PLUS)
	_ScbDivByZeroFaultEnable();
#endif /* !CONFIG_CPU_CORTEX_M0_M0PLUS */
}
+6 −0
Original line number Diff line number Diff line
@@ -55,8 +55,14 @@ static ALWAYS_INLINE int _IsInIsr(void)
	/*
	 * IRQs + PendSV (14) + SVC (11) + SYSTICK (15) are interrupts.
	 * Vectors 12 and 13 are reserved, we'll never be in there
	 * On ARMv6-M there is no nested execution bit, so we check exception 3,
	 * hard fault, to a detect a nested exception.
	 */
#if defined(CONFIG_CPU_CORTEX_M0_M0PLUS)
	return (vector > 10) || (vector == 3);
#else
	return (vector > 10) || (vector && _ScbIsNestedExc());
#endif /* CONFIG_CPU_CORTEX_M0_M0PLUS */
}

/**
+130 −131
Original line number Diff line number Diff line
@@ -207,21 +207,6 @@ static inline int _ScbHiPriVectorPendingGet(void)
	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
@@ -280,76 +265,6 @@ 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 returns 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
 *
 * @a 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, @a 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
 *               ....
 * @param addr base address, aligned on 128 minimum
 *
 * @return N/A
 */

static inline void _ScbVtableAddrSet(uint32_t addr)
{
	__ASSERT(!(addr & 0x7F), "invalid vtable base Addr");
	__scs.scb.vtor.bit.tbloff = addr;
}

/**
 *
 * @brief Find out if data regions are little endian
@@ -365,22 +280,6 @@ 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
@@ -478,36 +377,6 @@ 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 behavior.
 *
 * @return N/A
 */

static inline void _ScbDivByZeroFaultDisable(void)
{
	__scs.scb.ccr.bit.div_0_trp = 0;
}

/**
 *
 * @brief Enable faulting on unaligned access
@@ -614,6 +483,136 @@ static inline void _ScbExcPrioSet(uint8_t exc, uint8_t pri)
}

#if !defined(CONFIG_CPU_CORTEX_M0_M0PLUS)
/**
 *
 * @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 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 returns 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
 *
 * @a 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, @a 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
 *               ....
 * @param addr base address, aligned on 128 minimum
 *
 * @return N/A
 */

static inline void _ScbVtableAddrSet(uint32_t addr)
{
	__ASSERT(!(addr & 0x7F), "invalid vtable base Addr");
	__scs.scb.vtor.bit.tbloff = addr;
}

/**
 *
 * @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 behavior.
 *
 * @return N/A
 */

static inline void _ScbDivByZeroFaultDisable(void)
{
	__scs.scb.ccr.bit.div_0_trp = 0;
}

/**
 *
 * @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);
}

/**
 *
+34 −2
Original line number Diff line number Diff line
@@ -115,10 +115,17 @@ union __cpuid {
union __icsr {
	uint32_t val;
	struct {
#if defined(CONFIG_CPU_CORTEX_M0_M0PLUS)
		uint32_t vectactive : 9 __packed;
		uint32_t rsvd__9_10 : 2 __packed;
		uint32_t rsvd__9_10_11 : 3 __packed;
		uint32_t vectpending : 9 __packed;
		uint32_t rsvd__21 : 1 __packed;
#else
		uint32_t vectactive : 10 __packed;
		uint32_t rsvd__10 : 1 __packed;
		uint32_t rettobase : 1 __packed;
		uint32_t vectpending : 10 __packed;
#endif /* CONFIG_CPU_CORTEX_M0_M0PLUS */
		uint32_t isrpending : 1 __packed;
		uint32_t rsvd__23 : 1 __packed;
		uint32_t rsvd__24 : 1 __packed;
@@ -144,12 +151,20 @@ union __vtor {
union __aircr {
	uint32_t val;
	struct {
#if defined(CONFIG_CPU_CORTEX_M0_M0PLUS)
		uint32_t rsvd__0 : 1 __packed;
#else
		uint32_t vecreset : 1 __packed;      /* WO */
#endif /* CONFIG_CPU_CORTEX_M0_M0PLUS */
		uint32_t vectclractive : 1 __packed; /* WO */
		uint32_t sysresetreq : 1 __packed;   /* WO */
#if defined(CONFIG_CPU_CORTEX_M0_M0PLUS)
		uint32_t rsvd__3_14 : 12 __packed;
#else
		uint32_t rsvd__3_7 : 5 __packed;
		uint32_t prigroup : 3 __packed;
		uint32_t rsvd__11_14 : 4 __packed;
#endif /* CONFIG_CPU_CORTEX_M0_M0PLUS */
		uint32_t endianness : 1 __packed; /* RO */
		uint32_t vectkey : 16 __packed;
	} bit;
@@ -172,13 +187,21 @@ union __scr {
union __ccr {
	uint32_t val;
	struct {
#if defined(CONFIG_CPU_CORTEX_M0_M0PLUS)
		uint32_t rsvd_0_2 : 3 __packed;
#else
		uint32_t nonbasethrdena : 1 __packed;
		uint32_t usersetmpend : 1 __packed;
		uint32_t rsvd__2 : 1 __packed;
#endif /* CONFIG_CPU_CORTEX_M0_M0PLUS */
		uint32_t unalign_trp : 1 __packed;
#if defined(CONFIG_CPU_CORTEX_M0_M0PLUS)
		uint32_t rsvd_4_8 : 5 __packed;
#else
		uint32_t div_0_trp : 1 __packed;
		uint32_t rsvd__5_7 : 3 __packed;
		uint32_t bfhfnmign : 1 __packed;
#endif /* CONFIG_CPU_CORTEX_M0_M0PLUS */
		uint32_t stkalign : 1 __packed;
		uint32_t rsvd__10_31 : 22 __packed;
	} bit;
@@ -469,7 +492,11 @@ struct __scs {
	struct {
		union __cpuid cpuid; /* 0xd00 CPUID register */
		union __icsr icsr;   /* 0xd04 IRQ Control and Start Register */
#if defined(CONFIG_CPU_CORTEX_M0_M0PLUS)
		uint32_t rsvd_9_12;
#else
		union __vtor vtor;   /* 0xd08 Vector Table Offset Register */
#endif /* CONFIG_CPU_CORTEX_M0_M0PLUS */
		union __aircr
			aircr;    /* 0xd0c App IRQ and Reset Control Register */
		union __scr scr;  /* 0xd10 System Control Register */
@@ -485,6 +512,9 @@ struct __scs {
#endif /* CONFIG_CPU_CORTEX_M0_M0PLUS */
		union __shcsr
			shcsr;     /* 0xd24 Sys Handler Control and State Reg */
#if defined(CONFIG_CPU_CORTEX_M0_M0PLUS)
		uint32_t rsvd_40_63[6];
#else
		union __cfsr cfsr; /* 0xd28 Configurable Fault Status Register
				    */
		union __hfsr hfsr; /* 0xd2C Hard Fault Status Register */
@@ -492,6 +522,7 @@ struct __scs {
		uint32_t mmfar;    /* 0xd34 MemManage Fault Address Register */
		uint32_t bfar;     /* 0xd38 BusFault Address Register */
		uint32_t afsr;     /* 0xd3C Aux Fault Status Register */
#endif /* CONFIG_CPU_CORTEX_M0_M0PLUS */
	} scb;			   /* offset: 0xd00, size 0x040 */

	/*
@@ -548,7 +579,7 @@ extern volatile struct __scs __scs;
#endif /* CONFIG_CPU_CORTEX_M0_M0PLUS */

/* API */

#if !defined(CONFIG_CPU_CORTEX_M0_M0PLUS)
/**
 *
 * @brief Obtain the number of interrupt lines on the target
@@ -684,6 +715,7 @@ static inline void _scs_relocate_vector_table(void *new_addr)
		"isb\n\t"
		:::);
}
#endif /* !CONFIG_CPU_CORTEX_M0_M0PLUS */

#endif /* _ASMLANGUAGE */