diff --git a/os/common/ports/e200/compilers/GCC/ivor.s b/os/common/ports/e200/compilers/GCC/ivor.s index 2f000c531..6d24c0b30 100644 --- a/os/common/ports/e200/compilers/GCC/ivor.s +++ b/os/common/ports/e200/compilers/GCC/ivor.s @@ -58,8 +58,8 @@ .globl _IVOR10 .type _IVOR10, @function _IVOR10: - /* Creation of the external stack frame (extctx structure).*/ - stwu %sp, -80(%sp) /* Size of the extctx structure.*/ + /* Saving the external context (port_extctx structure).*/ + stwu %sp, -80(%sp) #if PPC_USE_VLE && PPC_SUPPORTS_VLE_MULTI e_stmvsrrw 8(%sp) /* Saves PC, MSR. */ e_stmvsprw 16(%sp) /* Saves CR, LR, CTR, XER. */ @@ -90,6 +90,11 @@ _IVOR10: stw %r12, 72(%sp) #endif /* !(PPC_USE_VLE && PPC_SUPPORTS_VLE_MULTI) */ + /* Increasing the SPGR0 register.*/ + mfspr %r0, 272 + eaddi %r0, %r0, 1 + mtspr 272, %r0 + /* Reset DIE bit in TSR register.*/ lis %r3, 0x0800 /* DIS bit mask. */ mtspr 336, %r3 /* TSR register. */ @@ -122,8 +127,8 @@ _IVOR10: .globl _IVOR4 .type _IVOR4, @function _IVOR4: - /* Creation of the external stack frame (extctx structure).*/ - stwu %sp, -80(%sp) /* Size of the extctx structure.*/ + /* Saving the external context (port_extctx structure).*/ + stwu %sp, -80(%sp) #if PPC_USE_VLE && PPC_SUPPORTS_VLE_MULTI e_stmvsrrw 8(%sp) /* Saves PC, MSR. */ e_stmvsprw 16(%sp) /* Saves CR, LR, CTR, XER. */ @@ -154,6 +159,11 @@ _IVOR4: stw %r12, 72(%sp) #endif /* !(PPC_USE_VLE && PPC_SUPPORTS_VLE_MULTI) */ + /* Increasing the SPGR0 register.*/ + mfspr %r0, 272 + eaddi %r0, %r0, 1 + mtspr 272, %r0 + /* Software vector address from the INTC register.*/ lis %r3, INTC_IACKR@h ori %r3, %r3, INTC_IACKR@l /* IACKR register address. */ @@ -195,6 +205,13 @@ _ivor_exit: #if CH_DBG_SYSTEM_STATE_CHECK bl dbg_check_unlock #endif + + /* Decreasing the SPGR0 register.*/ + mfspr %r0, 272 + eaddi %r0, %r0, -1 + mtspr 272, %r0 + + /* Restoring the external context.*/ #if PPC_USE_VLE && PPC_SUPPORTS_VLE_MULTI e_lmvgprw 32(%sp) /* Restores GPR0, GPR3...GPR12. */ e_lmvsprw 16(%sp) /* Restores CR, LR, CTR, XER. */ diff --git a/os/rt/ports/e200/chcore.h b/os/rt/ports/e200/chcore.h index 70bddf239..7901ed44d 100644 --- a/os/rt/ports/e200/chcore.h +++ b/os/rt/ports/e200/chcore.h @@ -347,10 +347,19 @@ struct context { * @brief Writes to a special register. * * @param[in] spr special register number - * @param[in] val value to be written + * @param[in] val value to be written, must be an automatic variable */ -#define port_mtspr(spr, val) \ - asm volatile ("mtspr %0, %1" : : "n" (spr), "r" (val)) +#define port_write_spr(spr, val) \ + asm volatile ("mtspr %[p0], %[p1]" : : [p0] "n" (spr), [p1] "r" (val)) + +/** + * @brief Writes to a special register. + * + * @param[in] spr special register number + * @param[in] val returned value, must be an automatic variable + */ +#define port_read_spr(spr, val) \ + asm volatile ("mfspr %[p0], %[p1]" : [p0] "=r" (val) : [p1] "n" (spr)) /*===========================================================================*/ /* External declarations. */ @@ -384,14 +393,20 @@ extern "C" { * @details IVOR4 and IVOR10 initialization. */ static inline void port_init(void) { + uint32_t n; + + /* Initializing the SPRG0 register to zero, it is required for interrupts + handling.*/ + n = 0; + port_write_spr(272, n); #if PPC_SUPPORTS_IVORS - /* The CPU supports IVOR registers, the kernel requires IVOR4 and IVOR10 - and the initialization is performed here.*/ - asm volatile ("li %%r3, _IVOR4@l \t\n" - "mtIVOR4 %%r3 \t\n" - "li %%r3, _IVOR10@l \t\n" - "mtIVOR10 %%r3" : : : "memory"); + /* The CPU supports IVOR registers, the kernel requires IVOR4 and IVOR10 + and the initialization is performed here.*/ + asm volatile ("li %%r3, _IVOR4@l \t\n" + "mtIVOR4 %%r3 \t\n" + "li %%r3, _IVOR10@l \t\n" + "mtIVOR10 %%r3" : : : "r3", "memory"); #endif } @@ -403,7 +418,7 @@ static inline void port_init(void) { static inline syssts_t port_get_irq_status(void) { uint32_t sts; - sts = 0; + asm volatile ("mfmsr %[p0]" : [p0] "=r" (sts) :); return sts; } @@ -418,7 +433,7 @@ static inline syssts_t port_get_irq_status(void) { */ static inline bool port_irq_enabled(syssts_t sts) { - return (sts & 1) == 0; + return (bool)((sts & (1 << 15)) != 0); } /** @@ -429,9 +444,12 @@ static inline bool port_irq_enabled(syssts_t sts) { * @retval true running in ISR mode. */ static inline bool port_is_isr_context(void) { + uint32_t sprg0; -// return (bool)((__get_IPSR() & 0x1FF) != 0); - return false; + /* The SPRG0 register is increased before entering interrupt handlers and + decreased at the end.*/ + port_read_spr(272, sprg0); + return (bool)(sprg0 > 0); } /**