diff --git a/os/hal/platforms/SPC560Pxx/hal_lld.c b/os/hal/platforms/SPC560Pxx/hal_lld.c index 3992aba8b..d84203e81 100644 --- a/os/hal/platforms/SPC560Pxx/hal_lld.c +++ b/os/hal/platforms/SPC560Pxx/hal_lld.c @@ -45,6 +45,25 @@ /* Driver interrupt handlers. */ /*===========================================================================*/ +/** + * @brief PIT channel 3 interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(vector127) { + + CH_IRQ_PROLOGUE(); + + chSysLockFromIsr(); + chSysTimerHandlerI(); + chSysUnlockFromIsr(); + + /* Resets the PIT channel 3 IRQ flag.*/ + PIT.CH[3].TFLG.R = 1; + + CH_IRQ_EPILOGUE(); +} + /*===========================================================================*/ /* Driver exported functions. */ /*===========================================================================*/ @@ -55,11 +74,31 @@ * @notapi */ void hal_lld_init(void) { + extern void _vectors(void); + uint32_t reg; /* The system is switched to the RUN0 mode, the default for normal operations.*/ if (halSPC560PSetRunMode(SPC560P_RUNMODE_RUN0) == CH_FAILED) chSysHalt(); + + /* INTC initialization, software vector mode, 4 bytes vectors, starting + at priority 0.*/ + INTC.MCR.R = 0; + INTC.CPR.R = 0; + INTC.IACKR.R = (uint32_t)_vectors; + + /* PIT channel 3 initialization for Kernel ticks, the PIT is configured + to run in DRUN,RUN0...RUN3 and HALT0 modes, the clock is gated in other + modes.*/ + INTC.PSR[127].R = SPC560P_PIT3_IRQ_PRIORITY; + ME.PCTL[92].R = SPC560P_ME_PCTL_RUN(2) | SPC560P_ME_PCTL_LP(2); + reg = halSPC560PGetSystemClock() / CH_FREQUENCY - 1; + PIT.PITMCR.R = 1; /* PIT clock enabled, stop while debugging. */ + PIT.CH[3].LDVAL.R = reg; + PIT.CH[3].CVAL.R = reg; + PIT.CH[3].TFLG.R = 1; /* Interrupt flag cleared. */ + PIT.CH[3].TCTRL.R = 3; /* Timer active, interrupt enabled. */ } /** @@ -100,12 +139,30 @@ void spc560p_clock_init(void) { ME.SAFE.R = SPC560P_ME_SAFE_MC_BITS; /* SAFE run mode. */ ME.DRUN.R = SPC560P_ME_DRUN_MC_BITS; /* DRUN run mode. */ ME.RUN[0].R = SPC560P_ME_RUN0_MC_BITS; /* RUN0 run mode. */ - ME.RUN[1].R = SPC560P_ME_RUN1_MC_BITS; /* RUN0 run mode. */ - ME.RUN[2].R = SPC560P_ME_RUN2_MC_BITS; /* RUN0 run mode. */ + ME.RUN[1].R = SPC560P_ME_RUN1_MC_BITS; /* RUN1 run mode. */ + ME.RUN[2].R = SPC560P_ME_RUN2_MC_BITS; /* RUN2 run mode. */ ME.RUN[3].R = SPC560P_ME_RUN3_MC_BITS; /* RUN0 run mode. */ ME.HALT0.R = SPC560P_ME_HALT0_MC_BITS; /* HALT0 run mode. */ ME.STOP0.R = SPC560P_ME_STOP0_MC_BITS; /* STOP0 run mode. */ + /* Peripherals run and low power modes initialization.*/ + ME.RUNPC[0].R = SPC560P_ME_RUN_PC0_BITS; + ME.RUNPC[1].R = SPC560P_ME_RUN_PC1_BITS; + ME.RUNPC[2].R = SPC560P_ME_RUN_PC2_BITS; + ME.RUNPC[3].R = SPC560P_ME_RUN_PC3_BITS; + ME.RUNPC[4].R = SPC560P_ME_RUN_PC4_BITS; + ME.RUNPC[5].R = SPC560P_ME_RUN_PC5_BITS; + ME.RUNPC[6].R = SPC560P_ME_RUN_PC6_BITS; + ME.RUNPC[7].R = SPC560P_ME_RUN_PC7_BITS; + ME.LPPC[0].R = SPC560P_ME_LP_PC0_BITS; + ME.LPPC[1].R = SPC560P_ME_LP_PC1_BITS; + ME.LPPC[2].R = SPC560P_ME_LP_PC2_BITS; + ME.LPPC[3].R = SPC560P_ME_LP_PC3_BITS; + ME.LPPC[4].R = SPC560P_ME_LP_PC4_BITS; + ME.LPPC[5].R = SPC560P_ME_LP_PC5_BITS; + ME.LPPC[6].R = SPC560P_ME_LP_PC6_BITS; + ME.LPPC[7].R = SPC560P_ME_LP_PC7_BITS; + /* Switches again to DRUN mode (current mode) in order to update the settings.*/ if (halSPC560PSetRunMode(SPC560P_RUNMODE_DRUN) == CH_FAILED) @@ -116,8 +173,14 @@ void spc560p_clock_init(void) { /** * @brief Switches the system to the specified run mode. + * + * @param[in] mode one of the possible run modes + * + * @return The operation status. + * @retval CH_SUCCESS if the switch operation has been completed. + * @retval CH_FAILED if the switch operation failed. */ -bool_t halSPC560PSetRunMode(spc560prunmode_t mode) { +bool_t halSPC560PSetRunMode(spc560prunmode_t mode) { /* Starts a transition process.*/ ME.MCTL.R = SPC560P_ME_MCTL_MODE(mode) | SPC560P_ME_MCTL_KEY; @@ -133,9 +196,34 @@ bool_t halSPC560PSetRunMode(spc560prunmode_t mode) { /* Verifies that the mode has been effectively switched.*/ if (ME.GS.B.S_CURRENTMODE != mode) - return TRUE; + return CH_FAILED; - return FALSE; + return CH_SUCCESS; } +#if !SPC560P_NO_INIT || defined(__DOXYGEN__) +/** + * @brief Returns the system clock under the current run mode. + * + * @return The system clock in Hertz. + */ +uint32_t halSPC560PGetSystemClock(void) { + uint32_t sysclk; + + sysclk = ME.GS.B.S_SYSCLK; + switch (sysclk) { + case SPC560P_ME_GS_SYSCLK_IRC: + return SPC560P_IRC_CLK; + case SPC560P_ME_GS_SYSCLK_XOSC: + return SPC560P_XOSC_CLK; + case SPC560P_ME_GS_SYSCLK_FMPLL0: + return SPC560P_FMPLL0_CLK; + case SPC560P_ME_GS_SYSCLK_FMPLL1: + return SPC560P_FMPLL1_CLK; + default: + return 0; + } +} +#endif /* !SPC560P_NO_INIT */ + /** @} */ diff --git a/os/hal/platforms/SPC560Pxx/hal_lld.h b/os/hal/platforms/SPC560Pxx/hal_lld.h index 706b7f5c9..f9c1e099c 100644 --- a/os/hal/platforms/SPC560Pxx/hal_lld.h +++ b/os/hal/platforms/SPC560Pxx/hal_lld.h @@ -119,6 +119,17 @@ #define SPC560P_FMPLL_ODF_DIV16 (3U << 24) /** @} */ +/** + * @name ME_GS register bits definitions + * @{ + */ +#define SPC560P_ME_GS_SYSCLK_MASK (15U << 0) +#define SPC560P_ME_GS_SYSCLK_IRC (0U << 0) +#define SPC560P_ME_GS_SYSCLK_XOSC (2U << 0) +#define SPC560P_ME_GS_SYSCLK_FMPLL0 (4U << 0) +#define SPC560P_ME_GS_SYSCLK_FMPLL1 (5U << 0) +/** @} */ + /** * @name ME_ME register bits definitions * @{ @@ -174,6 +185,38 @@ #define SPC560P_ME_MCTL_MODE(n) ((n) << 28) /** @} */ +/** + * @name ME_RUN_PCx registers bits definitions + * @{ + */ +#define SPC560P_ME_RUN_PC_TEST (1U << 1) +#define SPC560P_ME_RUN_PC_SAFE (1U << 2) +#define SPC560P_ME_RUN_PC_DRUN (1U << 3) +#define SPC560P_ME_RUN_PC_RUN0 (1U << 4) +#define SPC560P_ME_RUN_PC_RUN1 (1U << 5) +#define SPC560P_ME_RUN_PC_RUN2 (1U << 6) +#define SPC560P_ME_RUN_PC_RUN3 (1U << 7) +/** @} */ + +/** + * @name ME_LP_PCx registers bits definitions + * @{ + */ +#define SPC560P_ME_LP_PC_HALT0 (1U << 8) +#define SPC560P_ME_LP_PC_STOP0 (1U << 10) +/** @} */ + +/** + * @name ME_PCTL registers bits definitions + * @{ + */ +#define SPC560P_ME_PCTL_RUN_MASK (7U << 0) +#define SPC560P_ME_PCTL_RUN(n) ((n) << 0) +#define SPC560P_ME_PCTL_LP_MASK (7U << 3) +#define SPC560P_ME_PCTL_LP(n) ((n) << 3) +#define SPC560P_ME_PCTL_DBG (1U << 6) +/** @} */ + /*===========================================================================*/ /* Driver pre-compile time settings. */ /*===========================================================================*/ @@ -369,6 +412,180 @@ SPC560P_ME_MC_MVRON) #endif +/** + * @brief Peripheral mode 0 (run mode). + * @note Do not change this setting, it is expected to be the "always run" + * mode. + */ +#if !defined(SPC560P_ME_RUN_PC0_BITS) || defined(__DOXYGEN__) +#define SPC560P_ME_RUN_PC0_BITS (SPC560P_ME_RUN_PC_TEST | \ + SPC560P_ME_RUN_PC_SAFE | \ + SPC560P_ME_RUN_PC_DRUN | \ + SPC560P_ME_RUN_PC_RUN0 | \ + SPC560P_ME_RUN_PC_RUN1 | \ + SPC560P_ME_RUN_PC_RUN2 | \ + SPC560P_ME_RUN_PC_RUN3) +#endif + +/** + * @brief Peripheral mode 1 (run mode). + * @note Do not change this setting, it is expected to be the "never run" + * mode. + */ +#if !defined(SPC560P_ME_RUN_PC1_BITS) || defined(__DOXYGEN__) +#define SPC560P_ME_RUN_PC1_BITS 0 +#endif + +/** + * @brief Peripheral mode 2 (run mode). + * @note Do not change this setting, it is expected to be the "only during + * normal run" mode. + */ +#if !defined(SPC560P_ME_RUN_PC2_BITS) || defined(__DOXYGEN__) +#define SPC560P_ME_RUN_PC2_BITS (SPC560P_ME_RUN_PC_DRUN | \ + SPC560P_ME_RUN_PC_RUN0 | \ + SPC560P_ME_RUN_PC_RUN1 | \ + SPC560P_ME_RUN_PC_RUN2 | \ + SPC560P_ME_RUN_PC_RUN3) +#endif + +/** + * @brief Peripheral mode 3 (run mode). + * @note Not defined, available to application-specific modes. + */ +#if !defined(SPC560P_ME_RUN_PC3_BITS) || defined(__DOXYGEN__) +#define SPC560P_ME_RUN_PC3_BITS (SPC560P_ME_RUN_PC_RUN0 | \ + SPC560P_ME_RUN_PC_RUN1 | \ + SPC560P_ME_RUN_PC_RUN2 | \ + SPC560P_ME_RUN_PC_RUN3) +#endif + +/** + * @brief Peripheral mode 4 (run mode). + * @note Not defined, available to application-specific modes. + */ +#if !defined(SPC560P_ME_RUN_PC4_BITS) || defined(__DOXYGEN__) +#define SPC560P_ME_RUN_PC4_BITS (SPC560P_ME_RUN_PC_RUN0 | \ + SPC560P_ME_RUN_PC_RUN1 | \ + SPC560P_ME_RUN_PC_RUN2 | \ + SPC560P_ME_RUN_PC_RUN3) +#endif + +/** + * @brief Peripheral mode 5 (run mode). + * @note Not defined, available to application-specific modes. + */ +#if !defined(SPC560P_ME_RUN_PC5_BITS) || defined(__DOXYGEN__) +#define SPC560P_ME_RUN_PC5_BITS (SPC560P_ME_RUN_PC_RUN0 | \ + SPC560P_ME_RUN_PC_RUN1 | \ + SPC560P_ME_RUN_PC_RUN2 | \ + SPC560P_ME_RUN_PC_RUN3) +#endif + +/** + * @brief Peripheral mode 6 (run mode). + * @note Not defined, available to application-specific modes. + */ +#if !defined(SPC560P_ME_RUN_PC6_BITS) || defined(__DOXYGEN__) +#define SPC560P_ME_RUN_PC6_BITS (SPC560P_ME_RUN_PC_RUN0 | \ + SPC560P_ME_RUN_PC_RUN1 | \ + SPC560P_ME_RUN_PC_RUN2 | \ + SPC560P_ME_RUN_PC_RUN3) +#endif + +/** + * @brief Peripheral mode 7 (run mode). + * @note Not defined, available to application-specific modes. + */ +#if !defined(SPC560P_ME_RUN_PC7_BITS) || defined(__DOXYGEN__) +#define SPC560P_ME_RUN_PC7_BITS (SPC560P_ME_RUN_PC_RUN0 | \ + SPC560P_ME_RUN_PC_RUN1 | \ + SPC560P_ME_RUN_PC_RUN2 | \ + SPC560P_ME_RUN_PC_RUN3) +#endif + +/** + * @brief Peripheral mode 0 (low power mode). + * @note Do not change this setting, it is expected to be the "always run" + * mode. + */ +#if !defined(SPC560P_ME_LP_PC0_BITS) || defined(__DOXYGEN__) +#define SPC560P_ME_LP_PC0_BITS (SPC560P_ME_LP_PC_HALT0 | \ + SPC560P_ME_LP_PC_STOP0) +#endif + +/** + * @brief Peripheral mode 1 (low power mode). + * @note Do not change this setting, it is expected to be the "never run" + * mode. + */ +#if !defined(SPC560P_ME_LP_PC1_BITS) || defined(__DOXYGEN__) +#define SPC560P_ME_LP_PC1_BITS 0 +#endif + +/** + * @brief Peripheral mode 2 (low power mode). + * @note Do not change this setting, it is expected to be the "halt only" + * mode. + */ +#if !defined(SPC560P_ME_LP_PC2_BITS) || defined(__DOXYGEN__) +#define SPC560P_ME_LP_PC2_BITS (SPC560P_ME_LP_PC_HALT0) +#endif + +/** + * @brief Peripheral mode 3 (low power mode). + * @note Do not change this setting, it is expected to be the "stop only" + * mode. + */ +#if !defined(SPC560P_ME_LP_PC3_BITS) || defined(__DOXYGEN__) +#define SPC560P_ME_LP_PC3_BITS (SPC560P_ME_LP_PC_STOP0) +#endif + +/** + * @brief Peripheral mode 4 (low power mode). + * @note Not defined, available to application-specific modes. + */ +#if !defined(SPC560P_ME_LP_PC4_BITS) || defined(__DOXYGEN__) +#define SPC560P_ME_LP_PC4_BITS (SPC560P_ME_LP_PC_HALT0 | \ + SPC560P_ME_LP_PC_STOP0) +#endif + +/** + * @brief Peripheral mode 5 (low power mode). + * @note Not defined, available to application-specific modes. + */ +#if !defined(SPC560P_ME_LP_PC5_BITS) || defined(__DOXYGEN__) +#define SPC560P_ME_LP_PC5_BITS (SPC560P_ME_LP_PC_HALT0 | \ + SPC560P_ME_LP_PC_STOP0) +#endif + +/** + * @brief Peripheral mode 6 (low power mode). + * @note Not defined, available to application-specific modes. + */ +#if !defined(SPC560P_ME_LP_PC6_BITS) || defined(__DOXYGEN__) +#define SPC560P_ME_LP_PC6_BITS (SPC560P_ME_LP_PC_HALT0 | \ + SPC560P_ME_LP_PC_STOP0) +#endif + +/** + * @brief Peripheral mode 7 (low power mode). + * @note Not defined, available to application-specific modes. + */ +#if !defined(SPC560P_ME_LP_PC7_BITS) || defined(__DOXYGEN__) +#define SPC560P_ME_LP_PC7_BITS (SPC560P_ME_LP_PC_HALT0 | \ + SPC560P_ME_LP_PC_STOP0) +#endif + +/** + * @brief PIT channel 3 IRQ priority. + * @note This PIT channel is allocated permanently for system tick + * generation. + */ +#if !defined(SPC560P_PIT3_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define SPC560P_PIT3_IRQ_PRIORITY 4 +#endif + /*===========================================================================*/ /* Derived constants and error checks. */ /*===========================================================================*/ @@ -501,6 +718,9 @@ extern "C" { void hal_lld_init(void); void spc560p_clock_init(void); bool_t halSPC560PSetRunMode(spc560prunmode_t mode); +#if !SPC560P_NO_INIT +uint32_t halSPC560PGetSystemClock(void); +#endif #ifdef __cplusplus } #endif diff --git a/os/hal/platforms/SPC560Pxx/platform.mk b/os/hal/platforms/SPC560Pxx/platform.mk index 93deebba8..847e7e821 100644 --- a/os/hal/platforms/SPC560Pxx/platform.mk +++ b/os/hal/platforms/SPC560Pxx/platform.mk @@ -1,5 +1,7 @@ # List of all the SPC560Pxx platform files. -PLATFORMSRC = ${CHIBIOS}/os/hal/platforms/SPC560Pxx/hal_lld.c +PLATFORMSRC = ${CHIBIOS}/os/hal/platforms/SPC560Pxx/hal_lld.c \ + ${CHIBIOS}/os/hal/platforms/SPC5xx/LINFlex_v1/serial_lld.c # Required include directories -PLATFORMINC = ${CHIBIOS}/os/hal/platforms/SPC560Pxx +PLATFORMINC = ${CHIBIOS}/os/hal/platforms/SPC560Pxx \ + ${CHIBIOS}/os/hal/platforms/SPC5xx/LINFlex_v1 diff --git a/os/hal/platforms/SPC5xx/LINFlex_v1/serial_lld.c b/os/hal/platforms/SPC5xx/LINFlex_v1/serial_lld.c new file mode 100644 index 000000000..e562b6c2d --- /dev/null +++ b/os/hal/platforms/SPC5xx/LINFlex_v1/serial_lld.c @@ -0,0 +1,294 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011,2012 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file SPC56x/serial_lld.c + * @brief SPC563 low level serial driver code. + * + * @addtogroup SERIAL + * @{ + */ + +#include "ch.h" +#include "hal.h" + +#if HAL_USE_SERIAL || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief eSCI-A serial driver identifier. + */ +#if USE_SPC563_ESCIA || defined(__DOXYGEN__) +SerialDriver SD1; +#endif + +/** + * @brief eSCI-B serial driver identifier. + */ +#if USE_SPC563_ESCIB || defined(__DOXYGEN__) +SerialDriver SD2; +#endif + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +/** + * @brief Driver default configuration. + */ +static const SerialConfig default_config = { + SERIAL_DEFAULT_BITRATE, + SD_MODE_NORMAL | SD_MODE_PARITY_NONE +}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief eSCI initialization. + * @details This function must be invoked with interrupts disabled. + * + * @param[in] sdp pointer to a @p SerialDriver object + * @param[in] config the architecture-dependent serial driver configuration + */ +static void esci_init(SerialDriver *sdp, const SerialConfig *config) { + volatile struct ESCI_tag *escip = sdp->escip; + uint8_t mode = config->sc_mode; + + escip->CR2.R = 0; /* MDIS off. */ + escip->CR1.R = 0; + escip->LCR.R = 0; + escip->CR1.B.SBR = SPC563_SYSCLK / (16 * config->sc_speed); + if (mode & SD_MODE_LOOPBACK) + escip->CR1.B.LOOPS = 1; + switch (mode & SD_MODE_PARITY) { + case SD_MODE_PARITY_ODD: + escip->CR1.B.PT = 1; + case SD_MODE_PARITY_EVEN: + escip->CR1.B.PE = 1; + escip->CR1.B.M = 1; /* Makes it 8 bits data + 1 bit parity. */ + default: + ; + } + escip->LPR.R = 0; + escip->CR1.R |= 0x0000002C; /* RIE, TE, RE to 1. */ + escip->CR2.R |= 0x000F; /* ORIE, NFIE, FEIE, PFIE to 1. */ +} + +/** + * @brief eSCI de-initialization. + * @details This function must be invoked with interrupts disabled. + * + * @param[in] escip pointer to an eSCI I/O block + */ +static void esci_deinit(volatile struct ESCI_tag *escip) { + + escip->LPR.R = 0; + escip->SR.R = 0xFFFFFFFF; + escip->CR1.R = 0; + escip->CR2.R = 0x8000; /* MDIS on. */ +} + +/** + * @brief Error handling routine. + * + * @param[in] sdp pointer to a @p SerialDriver object + * @param[in] sr eSCI SR register value + */ +static void set_error(SerialDriver *sdp, uint32_t sr) { + flagsmask_t sts = 0; + + if (sr & 0x08000000) + sts |= SD_OVERRUN_ERROR; + if (sr & 0x04000000) + sts |= SD_NOISE_ERROR; + if (sr & 0x02000000) + sts |= SD_FRAMING_ERROR; + if (sr & 0x01000000) + sts |= SD_PARITY_ERROR; +/* if (sr & 0x00000000) + sts |= SD_BREAK_DETECTED;*/ + chSysLockFromIsr(); + chnAddFlagsI(sdp, sts); + chSysUnlockFromIsr(); +} + +/** + * @brief Common IRQ handler. + * + * @param[in] sdp pointer to a @p SerialDriver object + */ +static void serve_interrupt(SerialDriver *sdp) { + volatile struct ESCI_tag *escip = sdp->escip; + + uint32_t sr = escip->SR.R; + escip->SR.R = 0x3FFFFFFF; /* Does not clear TDRE | TC.*/ + if (sr & 0x0F000000) /* OR | NF | FE | PF. */ + set_error(sdp, sr); + if (sr & 0x20000000) { /* RDRF. */ + chSysLockFromIsr(); + sdIncomingDataI(sdp, escip->DR.B.D); + chSysUnlockFromIsr(); + } + if (escip->CR1.B.TIE && (sr & 0x80000000)) { /* TDRE. */ + msg_t b; + chSysLockFromIsr(); + b = chOQGetI(&sdp->oqueue); + if (b < Q_OK) { + chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY); + escip->CR1.B.TIE = 0; + } + else { + ESCI_A.SR.B.TDRE = 1; + escip->DR.R = (uint16_t)b; + } + chSysUnlockFromIsr(); + } +} + +#if USE_SPC563_ESCIA || defined(__DOXYGEN__) +static void notify1(GenericQueue *qp) { + + (void)qp; + if (ESCI_A.SR.B.TDRE) { + msg_t b = sdRequestDataI(&SD1); + if (b != Q_EMPTY) { + ESCI_A.SR.B.TDRE = 1; + ESCI_A.CR1.B.TIE = 1; + ESCI_A.DR.R = (uint16_t)b; + } + } +} +#endif + +#if USE_SPC563_ESCIB || defined(__DOXYGEN__) +static void notify2(GenericQueue *qp) { + + (void)qp; + if (ESCI_B.SR.B.TDRE) { + msg_t b = sdRequestDataI(&SD2); + if (b != Q_EMPTY) { + ESCI_B.SR.B.TDRE = 1; + ESCI_B.CR1.B.TIE = 1; + ESCI_B.DR.R = (uint16_t)b; + } + } +} +#endif + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if USE_SPC563_ESCIA || defined(__DOXYGEN__) +/** + * @brief eSCI-A interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(vector146) { + + CH_IRQ_PROLOGUE(); + + serve_interrupt(&SD1); + + CH_IRQ_EPILOGUE(); +} +#endif + +#if USE_SPC563_ESCIB || defined(__DOXYGEN__) +/** + * @brief eSCI-B interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(vector149) { + + CH_IRQ_PROLOGUE(); + + serve_interrupt(&SD2); + + CH_IRQ_EPILOGUE(); +} +#endif + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level serial driver initialization. + * + * @notapi + */ +void sd_lld_init(void) { + +#if USE_SPC563_ESCIA + sdObjectInit(&SD1, NULL, notify1); + SD1.escip = &ESCI_A; + ESCI_A.CR2.R = 0x8000; /* MDIS ON. */ + INTC.PSR[146].R = SPC563_ESCIA_PRIORITY; +#endif + +#if USE_SPC563_ESCIB + sdObjectInit(&SD2, NULL, notify2); + SD2.escip = &ESCI_B; + ESCI_B.CR2.R = 0x8000; /* MDIS ON. */ + INTC.PSR[149].R = SPC563_ESCIB_PRIORITY; +#endif +} + +/** + * @brief Low level serial driver configuration and (re)start. + * + * @param[in] sdp pointer to a @p SerialDriver object + * @param[in] config the architecture-dependent serial driver configuration. + * If this parameter is set to @p NULL then a default + * configuration is used. + * + * @notapi + */ +void sd_lld_start(SerialDriver *sdp, const SerialConfig *config) { + + if (config == NULL) + config = &default_config; + esci_init(sdp, config); +} + +/** + * @brief Low level serial driver stop. + * + * @param[in] sdp pointer to a @p SerialDriver object + * + * @notapi + */ +void sd_lld_stop(SerialDriver *sdp) { + + if (sdp->state == SD_READY) + esci_deinit(sdp->escip); +} + +#endif /* HAL_USE_SERIAL */ + +/** @} */ diff --git a/os/hal/platforms/SPC5xx/LINFlex_v1/serial_lld.h b/os/hal/platforms/SPC5xx/LINFlex_v1/serial_lld.h new file mode 100644 index 000000000..fcc2273bd --- /dev/null +++ b/os/hal/platforms/SPC5xx/LINFlex_v1/serial_lld.h @@ -0,0 +1,149 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011,2012 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file SPC5xx/serial_lld.h + * @brief SPC5xx low level serial driver header. + * + * @addtogroup SERIAL + * @{ + */ + +#ifndef _SERIAL_LLD_H_ +#define _SERIAL_LLD_H_ + +#if HAL_USE_SERIAL || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @brief eSCI-A driver enable switch. + * @details If set to @p TRUE the support for eSCI-A is included. + * @note The default is @p TRUE. + */ +#if !defined(USE_SPC563_ESCIA) || defined(__DOXYGEN__) +#define USE_SPC563_ESCIA FALSE +#endif + +/** + * @brief eSCI-B driver enable switch. + * @details If set to @p TRUE the support for eSCI-B is included. + * @note The default is @p TRUE. + */ +#if !defined(USE_SPC563_ESCIB) || defined(__DOXYGEN__) +#define USE_SPC563_ESCIB FALSE +#endif + +/** + * @brief eSCI-A interrupt priority level setting. + */ +#if !defined(SPC563_ESCIA_PRIORITY) || defined(__DOXYGEN__) +#define SPC563_ESCIA_PRIORITY 8 +#endif + +/** + * @brief eSCI-B interrupt priority level setting. + */ +#if !defined(SPC563_ESCIB_PRIORITY) || defined(__DOXYGEN__) +#define SPC563_ESCIB_PRIORITY 8 +#endif + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Generic Serial Driver configuration structure. + * @details An instance of this structure must be passed to @p sdStart() + * in order to configure and start a serial driver operations. + * @note This structure content is architecture dependent, each driver + * implementation defines its own version and the custom static + * initializers. + */ +typedef struct { + /** + * @brief Bit rate. + */ + uint32_t sc_speed; + /** + * @brief Mode flags. + */ + uint8_t sc_mode; +} SerialConfig; + +/** + * @brief @p SerialDriver specific data. + */ +#define _serial_driver_data \ + _base_asynchronous_channel_data \ + /* Driver state.*/ \ + sdstate_t state; \ + /* Input queue.*/ \ + InputQueue iqueue; \ + /* Output queue.*/ \ + OutputQueue oqueue; \ + /* Input circular buffer.*/ \ + uint8_t ib[SERIAL_BUFFERS_SIZE]; \ + /* Output circular buffer.*/ \ + uint8_t ob[SERIAL_BUFFERS_SIZE]; \ + /* End of the mandatory fields.*/ \ + /* Pointer to the volatile eSCI registers block.*/ \ + volatile struct ESCI_tag *escip; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if USE_SPC563_ESCIA && !defined(__DOXYGEN__) +extern SerialDriver SD1; +#endif +#if USE_SPC563_ESCIB && !defined(__DOXYGEN__) +extern SerialDriver SD2; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void sd_lld_init(void); + void sd_lld_start(SerialDriver *sdp, const SerialConfig *config); + void sd_lld_stop(SerialDriver *sdp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_SERIAL */ + +#endif /* _SERIAL_LLD_H_ */ + +/** @} */ diff --git a/os/ports/GCC/PPC/SPC560Pxx/ld/SPC560P44.ld b/os/ports/GCC/PPC/SPC560Pxx/ld/SPC560P44.ld index cf2216867..49b182721 100644 --- a/os/ports/GCC/PPC/SPC560Pxx/ld/SPC560P44.ld +++ b/os/ports/GCC/PPC/SPC560Pxx/ld/SPC560P44.ld @@ -47,13 +47,17 @@ SECTIONS . = ORIGIN(flash); .boot : ALIGN(16) SUBALIGN(16) { - __ivpr_base__ = .; KEEP(*(.bam)) KEEP(*(.crt0)) . = ALIGN(0x00000800); - KEEP(*(.handlers)) - . = ALIGN(0x00001000); KEEP(*(.vectors)) + /* Note, have to waste the first 64KB because the IVPR register + requires an alignment of 64KB and the first 64KB cannot be used, + IVOR0 would conflict with the BAM word. Applications could + allocate code or data in the first 64KB by using special sections.*/ + . = ALIGN(0x00010000); + __ivpr_base__ = .; + KEEP(*(.handlers)) } > flash constructors : ALIGN(4) SUBALIGN(4) diff --git a/os/ports/GCC/PPC/crt0.s b/os/ports/GCC/PPC/crt0.s index cec9a306f..4a2bc4dea 100644 --- a/os/ports/GCC/PPC/crt0.s +++ b/os/ports/GCC/PPC/crt0.s @@ -44,6 +44,7 @@ _boot_address: * IVPR initialization. */ lis %r4, __ivpr_base__@h + ori %r4, %r4, __ivpr_base__@l mtIVPR %r4 /* * Small sections registers initialization.