FPU support for CM4 (not working yet).

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@3591 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
gdisirio 2011-12-11 12:58:51 +00:00
parent ea9053eb9e
commit 26dc203d65
4 changed files with 200 additions and 31 deletions

View File

@ -5,7 +5,7 @@
# Compiler options here. # Compiler options here.
ifeq ($(USE_OPT),) ifeq ($(USE_OPT),)
USE_OPT = -O2 -ggdb -fomit-frame-pointer USE_OPT = -O2 -ggdb -fomit-frame-pointer -mhard-float
endif endif
# C specific options here (added to USE_OPT). # C specific options here (added to USE_OPT).
@ -120,7 +120,7 @@ INCDIR = $(PORTINC) $(KERNINC) $(TESTINC) \
# Compiler settings # Compiler settings
# #
MCU = cortex-m3 MCU = cortex-m4
#TRGT = arm-elf- #TRGT = arm-elf-
TRGT = arm-none-eabi- TRGT = arm-none-eabi-

View File

@ -31,18 +31,36 @@
/** /**
* @brief Internal context stacking. * @brief Internal context stacking.
*/ */
#if CORTEX_USE_FPU || defined(__DOXYGEN__)
#define PUSH_CONTEXT() { \
asm volatile ("vpush {s16-s31}" \
: : : "memory"); \
asm volatile ("push {r4, r5, r6, r7, r8, r9, r10, r11, lr}" \
: : : "memory"); \
}
#else /* !CORTEX_USE_FPU */
#define PUSH_CONTEXT() { \ #define PUSH_CONTEXT() { \
asm volatile ("push {r4, r5, r6, r7, r8, r9, r10, r11, lr}" \ asm volatile ("push {r4, r5, r6, r7, r8, r9, r10, r11, lr}" \
: : : "memory"); \ : : : "memory"); \
} }
#endif /* !CORTEX_USE_FPU */
/** /**
* @brief Internal context unstacking. * @brief Internal context unstacking.
*/ */
#if CORTEX_USE_FPU || defined(__DOXYGEN__)
#define POP_CONTEXT() { \
asm volatile ("pop {r4, r5, r6, r7, r8, r9, r10, r11, pc}" \
: : : "memory"); \
asm volatile ("vpop {s16-s31}" \
: : : "memory"); \
}
#else /* !CORTEX_USE_FPU */
#define POP_CONTEXT() { \ #define POP_CONTEXT() { \
asm volatile ("pop {r4, r5, r6, r7, r8, r9, r10, r11, pc}" \ asm volatile ("pop {r4, r5, r6, r7, r8, r9, r10, r11, pc}" \
: : : "memory"); \ : : : "memory"); \
} }
#endif /* !CORTEX_USE_FPU */
#if !CH_OPTIMIZE_SPEED #if !CH_OPTIMIZE_SPEED
void _port_lock(void) { void _port_lock(void) {
@ -80,12 +98,21 @@ CH_IRQ_HANDLER(SysTickVector) {
* @note The PendSV vector is only used in advanced kernel mode. * @note The PendSV vector is only used in advanced kernel mode.
*/ */
void SVCallVector(void) { void SVCallVector(void) {
uint32_t *psp;
register struct extctx *ctxp; register struct extctx *ctxp;
/* Current PSP value.*/
asm volatile ("mrs %0, PSP" : "=r" (psp) : : "memory");
#if CORTEX_USE_FPU
/* Restoring the special registers SCB_FPCCR and FPCAR.*/
SCB_FPCAR = *psp++;
SCB_FPCCR = *psp++;
#endif
/* Discarding the current exception context and positioning the stack to /* Discarding the current exception context and positioning the stack to
point to the real one.*/ point to the real one.*/
asm volatile ("mrs %0, PSP" : "=r" (ctxp) : : "memory"); ctxp = (struct extctx *)psp + 1;
ctxp++;
asm volatile ("msr PSP, %0" : : "r" (ctxp) : "memory"); asm volatile ("msr PSP, %0" : : "r" (ctxp) : "memory");
port_unlock_from_isr(); port_unlock_from_isr();
} }
@ -99,16 +126,61 @@ void SVCallVector(void) {
* @note The PendSV vector is only used in compact kernel mode. * @note The PendSV vector is only used in compact kernel mode.
*/ */
void PendSVVector(void) { void PendSVVector(void) {
uint32_t *psp;
register struct extctx *ctxp; register struct extctx *ctxp;
/* Current PSP value.*/
asm volatile ("mrs %0, PSP" : "=r" (psp) : : "memory");
#if CORTEX_USE_FPU
/* Restoring the special registers SCB_FPCCR and FPCAR.*/
SCB_FPCAR = *psp++;
SCB_FPCCR = *psp++;
#endif
/* Discarding the current exception context and positioning the stack to /* Discarding the current exception context and positioning the stack to
point to the real one.*/ point to the real one.*/
asm volatile ("mrs %0, PSP" : "=r" (ctxp) : : "memory"); ctxp = (struct extctx *)psp + 1;
ctxp++;
asm volatile ("msr PSP, %0" : : "r" (ctxp) : "memory"); asm volatile ("msr PSP, %0" : : "r" (ctxp) : "memory");
} }
#endif /* CORTEX_SIMPLIFIED_PRIORITY */ #endif /* CORTEX_SIMPLIFIED_PRIORITY */
/**
* @brief Port-related initialization code.
*/
void _port_init(void) {
uint32_t reg;
/* Initialization of the vector table and priority related settings.*/
SCB_VTOR = CORTEX_VTOR_INIT;
SCB_AIRCR = AIRCR_VECTKEY | AIRCR_PRIGROUP(0);
#if CORTEX_USE_FPU
/* CP10 and CP11 set to full access.*/
SCB_CPACR |= 0x00F00000;
/* Enables FPU context save/restore on exception entry/exit (FPCA bit).*/
asm volatile ("mrs %0, CONTROL" : "=r" (reg) : : "memory");
reg |= 4;
asm volatile ("msr CONTROL, %0" : : "r" (reg) : "memory");
/* FPSCR and FPDSCR initially zero.*/
reg = 0;
asm volatile ("vmsr FPSCR, %0" : : "r" (reg) : "memory");
SCB_FPDSCR = reg;
/* Initializing the FPU context save in lazy mode.*/
SCB_FPCCR = FPCCR_LSPEN;
#endif
/* Initialization of the system vectors used by the port.*/
NVICSetSystemHandlerPriority(HANDLER_SVCALL,
CORTEX_PRIORITY_MASK(CORTEX_PRIORITY_SVCALL));
NVICSetSystemHandlerPriority(HANDLER_PENDSV,
CORTEX_PRIORITY_MASK(CORTEX_PRIORITY_PENDSV));
NVICSetSystemHandlerPriority(HANDLER_SYSTICK,
CORTEX_PRIORITY_MASK(CORTEX_PRIORITY_SYSTICK));
}
/** /**
* @brief Exception exit redirection to _port_switch_from_isr(). * @brief Exception exit redirection to _port_switch_from_isr().
*/ */
@ -116,12 +188,29 @@ void _port_irq_epilogue(void) {
port_lock_from_isr(); port_lock_from_isr();
if ((SCB_ICSR & ICSR_RETTOBASE)) { if ((SCB_ICSR & ICSR_RETTOBASE)) {
register struct extctx *ctxp; uint32_t *psp;
struct extctx *ctxp;
/* Current PSP value.*/
asm volatile ("mrs %0, PSP" : "=r" (psp) : : "memory");
#if CORTEX_USE_FPU
{
uint32_t fpccr;
/* Saving the special registers SCB_FPCCR and FPCAR as extra context.*/
*--psp = fpccr = SCB_FPCCR;
*--psp = SCB_FPCAR;
/* Now the FPCCR is modified in order to not restore the FPU status
from the artificial return context.*/
SCB_FPCCR = fpccr | FPCCR_LSPACT;
}
#endif
/* Adding an artificial exception return context, there is no need to /* Adding an artificial exception return context, there is no need to
populate it fully.*/ populate it fully.*/
asm volatile ("mrs %0, PSP" : "=r" (ctxp) : : "memory"); ctxp = (struct extctx *)psp - 1;
ctxp--;
asm volatile ("msr PSP, %0" : : "r" (ctxp) : "memory"); asm volatile ("msr PSP, %0" : : "r" (ctxp) : "memory");
ctxp->pc = _port_switch_from_isr; ctxp->pc = _port_switch_from_isr;
ctxp->xpsr = (regarm_t)0x01000000; ctxp->xpsr = (regarm_t)0x01000000;

View File

@ -129,8 +129,12 @@
#elif (CORTEX_MODEL == CORTEX_M4) #elif (CORTEX_MODEL == CORTEX_M4)
#define CH_ARCHITECTURE_ARM_v7ME #define CH_ARCHITECTURE_ARM_v7ME
#define CH_ARCHITECTURE_NAME "ARMv7-ME" #define CH_ARCHITECTURE_NAME "ARMv7-ME"
#if CORTEX_USE_FPU
#define CH_CORE_VARIANT_NAME "Cortex-M4F"
#else
#define CH_CORE_VARIANT_NAME "Cortex-M4" #define CH_CORE_VARIANT_NAME "Cortex-M4"
#endif #endif
#endif
/** /**
* @brief Port-specific information string. * @brief Port-specific information string.
@ -162,6 +166,27 @@ struct extctx {
regarm_t lr_thd; regarm_t lr_thd;
regarm_t pc; regarm_t pc;
regarm_t xpsr; regarm_t xpsr;
#if CORTEX_USE_FPU || defined(__DOXYGEN__)
regarm_t s0;
regarm_t s1;
regarm_t s2;
regarm_t s3;
regarm_t s4;
regarm_t s5;
regarm_t s6;
regarm_t s7;
regarm_t s8;
regarm_t s9;
regarm_t s10;
regarm_t s11;
regarm_t s12;
regarm_t s13;
regarm_t s14;
regarm_t s15;
regarm_t s16;
regarm_t fpscr;
regarm_t reserved;
#endif /* CORTEX_USE_FPU */
}; };
struct intctx { struct intctx {
@ -174,6 +199,24 @@ struct intctx {
regarm_t r10; regarm_t r10;
regarm_t r11; regarm_t r11;
regarm_t lr; regarm_t lr;
#if CORTEX_USE_FPU || defined(__DOXYGEN__)
regarm_t s16;
regarm_t s17;
regarm_t s18;
regarm_t s19;
regarm_t s20;
regarm_t s21;
regarm_t s22;
regarm_t s23;
regarm_t s24;
regarm_t s25;
regarm_t s26;
regarm_t s27;
regarm_t s28;
regarm_t s29;
regarm_t s30;
regarm_t s31;
#endif /* CORTEX_USE_FPU */
}; };
#endif #endif
@ -208,16 +251,7 @@ struct intctx {
/** /**
* @brief Port-related initialization code. * @brief Port-related initialization code.
*/ */
#define port_init() { \ #define port_init() _port_init()
SCB_VTOR = CORTEX_VTOR_INIT; \
SCB_AIRCR = AIRCR_VECTKEY | AIRCR_PRIGROUP(0); \
NVICSetSystemHandlerPriority(HANDLER_SVCALL, \
CORTEX_PRIORITY_MASK(CORTEX_PRIORITY_SVCALL)); \
NVICSetSystemHandlerPriority(HANDLER_PENDSV, \
CORTEX_PRIORITY_MASK(CORTEX_PRIORITY_PENDSV)); \
NVICSetSystemHandlerPriority(HANDLER_SYSTICK, \
CORTEX_PRIORITY_MASK(CORTEX_PRIORITY_SYSTICK)); \
}
/** /**
* @brief Kernel-lock action. * @brief Kernel-lock action.
@ -357,6 +391,7 @@ struct intctx {
extern "C" { extern "C" {
#endif #endif
void port_halt(void); void port_halt(void);
void _port_init(void);
void _port_switch(Thread *ntp, Thread *otp); void _port_switch(Thread *ntp, Thread *otp);
void _port_irq_epilogue(void); void _port_irq_epilogue(void);
void _port_switch_from_isr(void); void _port_switch_from_isr(void);

View File

@ -53,11 +53,6 @@ typedef volatile uint32_t IOREG32; /**< 32 bits I/O register type. */
*/ */
#define NVIC_ITCR (*((IOREG32 *)0xE000E004)) #define NVIC_ITCR (*((IOREG32 *)0xE000E004))
/**
* @brief NVIC STIR register.
*/
#define NVIC_STIR (*((IOREG32 *)0xE000EF00))
/** /**
* @brief Structure representing the SYSTICK I/O space. * @brief Structure representing the SYSTICK I/O space.
*/ */
@ -66,12 +61,12 @@ typedef struct {
IOREG32 RVR; IOREG32 RVR;
IOREG32 CVR; IOREG32 CVR;
IOREG32 CBVR; IOREG32 CBVR;
} CM3_ST; } CMx_ST;
/** /**
* @brief SYSTICK peripheral base address. * @brief SYSTICK peripheral base address.
*/ */
#define STBase ((CM3_ST *)0xE000E010) #define STBase ((CMx_ST *)0xE000E010)
#define ST_CSR (STBase->CSR) #define ST_CSR (STBase->CSR)
#define ST_RVR (STBase->RVR) #define ST_RVR (STBase->RVR)
#define ST_CVR (STBase->CVR) #define ST_CVR (STBase->CVR)
@ -111,18 +106,21 @@ typedef struct {
IOREG32 IABR[8]; IOREG32 IABR[8];
IOREG32 unused5[56]; IOREG32 unused5[56];
IOREG32 IPR[60]; IOREG32 IPR[60];
} CM3_NVIC; IOREG32 unused6[644];
IOREG32 STIR;
} CMx_NVIC;
/** /**
* @brief NVIC peripheral base address. * @brief NVIC peripheral base address.
*/ */
#define NVICBase ((CM3_NVIC *)0xE000E100) #define NVICBase ((CMx_NVIC *)0xE000E100)
#define NVIC_ISER(n) (NVICBase->ISER[n]) #define NVIC_ISER(n) (NVICBase->ISER[n])
#define NVIC_ICER(n) (NVICBase->ICER[n]) #define NVIC_ICER(n) (NVICBase->ICER[n])
#define NVIC_ISPR(n) (NVICBase->ISPR[n]) #define NVIC_ISPR(n) (NVICBase->ISPR[n])
#define NVIC_ICPR(n) (NVICBase->ICPR[n]) #define NVIC_ICPR(n) (NVICBase->ICPR[n])
#define NVIC_IABR(n) (NVICBase->IABR[n]) #define NVIC_IABR(n) (NVICBase->IABR[n])
#define NVIC_IPR(n) (NVICBase->IPR[n]) #define NVIC_IPR(n) (NVICBase->IPR[n])
#define NVIC_STIR (NVICBase->STIR)
/** /**
* @brief Structure representing the System Control Block I/O space. * @brief Structure representing the System Control Block I/O space.
@ -142,12 +140,19 @@ typedef struct {
IOREG32 MMFAR; IOREG32 MMFAR;
IOREG32 BFAR; IOREG32 BFAR;
IOREG32 AFSR; IOREG32 AFSR;
} CM3_SCB; IOREG32 PFR[2];
IOREG32 DFR;
IOREG32 ADR;
IOREG32 MMFR[4];
IOREG32 SAR[5];
IOREG32 unused1[5];
IOREG32 CPACR;
} CMx_SCB;
/** /**
* @brief SCB peripheral base address. * @brief SCB peripheral base address.
*/ */
#define SCBBase ((CM3_SCB *)0xE000ED00) #define SCBBase ((CMx_SCB *)0xE000ED00)
#define SCB_CPUID (SCBBase->CPUID) #define SCB_CPUID (SCBBase->CPUID)
#define SCB_ICSR (SCBBase->ICSR) #define SCB_ICSR (SCBBase->ICSR)
#define SCB_VTOR (SCBBase->VTOR) #define SCB_VTOR (SCBBase->VTOR)
@ -162,6 +167,12 @@ typedef struct {
#define SCB_MMFAR (SCBBase->MMFAR) #define SCB_MMFAR (SCBBase->MMFAR)
#define SCB_BFAR (SCBBase->BFAR) #define SCB_BFAR (SCBBase->BFAR)
#define SCB_AFSR (SCBBase->AFSR) #define SCB_AFSR (SCBBase->AFSR)
#define SCB_PFR(n) (SCBBase->PFR[n])
#define SCB_DFR (SCBBase->DFR)
#define SCB_ADR (SCBBase->ADR)
#define SCB_MMFR(n) (SCBBase->MMFR[n])
#define SCB_SAR(n) (SCBBase->SAR[n])
#define SCB_CPACR (SCBBase->CPACR)
#define ICSR_VECTACTIVE_MASK (0x1FF << 0) #define ICSR_VECTACTIVE_MASK (0x1FF << 0)
#define ICSR_RETTOBASE (0x1 << 11) #define ICSR_RETTOBASE (0x1 << 11)
@ -172,12 +183,46 @@ typedef struct {
#define ICSR_PENDSTSET (0x1 << 26) #define ICSR_PENDSTSET (0x1 << 26)
#define ICSR_PENDSVCLR (0x1 << 27) #define ICSR_PENDSVCLR (0x1 << 27)
#define ICSR_PENDSVSET (0x1 << 28) #define ICSR_PENDSVSET (0x1 << 28)
#define ICSR_NMIPENDSET (0x1 << 31) #define ICSR_NMIPENDSET (0x1U << 31)
#define AIRCR_VECTKEY 0x05FA0000 #define AIRCR_VECTKEY 0x05FA0000
#define AIRCR_PRIGROUP_MASK (0x7 << 8) #define AIRCR_PRIGROUP_MASK (0x7 << 8)
#define AIRCR_PRIGROUP(n) ((n) << 8) #define AIRCR_PRIGROUP(n) ((n) << 8)
typedef struct {
IOREG32 unused1[1];
IOREG32 FPCCR;
IOREG32 FPCAR;
IOREG32 FPDSCR;
IOREG32 MVFR0;
IOREG32 MVFR1;
} CMx_FPU;
/**
* @brief FPU peripheral base address.
*/
#define FPUBase ((CMx_FPU *)0xE000EF30L)
#define SCB_FPCCR (FPUBase->FPCCR)
#define SCB_FPCAR (FPUBase->FPCAR)
#define SCB_FPDSCR (FPUBase->FPDSCR)
#define SCB_MVFR0 (FPUBase->MVFR0)
#define SCB_MVFR1 (FPUBase->MVFR1)
#define FPCCR_ASPEN (0x1U << 31)
#define FPCCR_LSPEN (0x1U << 30)
#define FPCCR_MONRDY (0x1U << 8)
#define FPCCR_BFRDY (0x1U << 6)
#define FPCCR_MMRDY (0x1U << 5)
#define FPCCR_HFRDY (0x1U << 4)
#define FPCCR_THREAD (0x1U << 3)
#define FPCCR_USER (0x1U << 1)
#define FPCCR_LSPACT (0x1U << 0)
#define FPDSCR_AHP (0x1U << 26)
#define FPDSCR_DN (0x1U << 25)
#define FPDSCR_FZ (0x1U << 24)
#define FPDSCR_RMODE(n) ((n) << 22)
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif