From e01d0f6f287023e79ef661e27f37c6109de75186 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sat, 10 Nov 2012 08:32:19 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@4811 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/MSP430X/hal_lld.c | 78 ++++++ os/hal/platforms/MSP430X/pal_lld.c | 176 +++++++++++++ os/hal/platforms/MSP430X/pal_lld.h | 457 ++++++++++++++++++++++++++++++++++ os/hal/platforms/MSP430X/platform.dox | 103 ++++++++ os/hal/platforms/MSP430X/serial_lld.c | 362 +++++++++++++++++++++++++++ os/hal/platforms/MSP430X/serial_lld.h | 140 +++++++++++ 6 files changed, 1316 insertions(+) create mode 100644 os/hal/platforms/MSP430X/hal_lld.c create mode 100644 os/hal/platforms/MSP430X/pal_lld.c create mode 100644 os/hal/platforms/MSP430X/pal_lld.h create mode 100644 os/hal/platforms/MSP430X/platform.dox create mode 100644 os/hal/platforms/MSP430X/serial_lld.c create mode 100644 os/hal/platforms/MSP430X/serial_lld.h (limited to 'os/hal/platforms') diff --git a/os/hal/platforms/MSP430X/hal_lld.c b/os/hal/platforms/MSP430X/hal_lld.c new file mode 100644 index 000000000..5cee3e972 --- /dev/null +++ b/os/hal/platforms/MSP430X/hal_lld.c @@ -0,0 +1,78 @@ +/* + 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 MSP430/hal_lld.c + * @brief MSP430 HAL subsystem low level driver source. + * + * @addtogroup HAL + * @{ + */ + +#include "ch.h" +#include "hal.h" +#include "F5XX_F6XX_CORE_LIB/HAL_PMM.h" +#include "F5XX_F6XX_CORE_LIB/HAL_UCS.h" + +#define HZ_TO_KHZ(f_Hz) (f_Hz/1000) + +#define SELECT_PMMCOREV(f_Hz) (f_Hz <= 8000000ul ? PMMCOREV_0 : \ + (f_Hz <= 12000000ul ? PMMCOREV_1 : \ + (f_Hz <= 20000000ul ? PMMCOREV_2 : PMMCOREV_3))) + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level HAL driver initialization. + * + * @notapi + */ +void hal_lld_init(void) { + #if MSP430_USE_CLOCK == MSP430_CLOCK_SOURCE_XT2CLK + #error "XT2CLK is not implemented" + #elif MSP430_USE_CLOCK == MSP430_CLOCK_SOURCE_DCOCLK + SetVCore(SELECT_PMMCOREV(DCOCLK)); /* Set core voltage */ + SELECT_FLLREF(SELREF__REFOCLK); /* Set DCO FLL reference = REFO */ + SELECT_ACLK(SELA__REFOCLK); /* Set ACLK = REFO */ + Init_FLL_Settle(HZ_TO_KHZ(DCOCLK),DCOCLK/LFXT1CLK); + #else + #error "unknown clock source specified" + #endif +} + +/** @} */ diff --git a/os/hal/platforms/MSP430X/pal_lld.c b/os/hal/platforms/MSP430X/pal_lld.c new file mode 100644 index 000000000..e68111022 --- /dev/null +++ b/os/hal/platforms/MSP430X/pal_lld.c @@ -0,0 +1,176 @@ +/* + 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 MSP430/pal_lld.c + * @brief MSP430 Digital I/O low level driver code. + * + * @addtogroup PAL + * @{ + */ + +#include "ch.h" +#include "hal.h" + +#if HAL_USE_PAL || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief MSP430 I/O ports configuration. + * @note The @p PxIFG, @p PxIE and @p PxSEL registers are cleared. @p PxOUT + * and @p PxDIR are configured as specified. + * + * @param[in] config the MSP430 ports configuration + * + * @notapi + */ +void _pal_lld_init(const PALConfig *config) { + +#if defined(__MSP430_HAS_PORTA_R__) || defined(__MSP430_HAS_PORT1_R__) + IOPORT1->iop_full.ie = 0; + IOPORT1->iop_full.ifg = 0; + IOPORT1->iop_full.sel = 0; + IOPORT1->iop_common.out = config->P1Data.out; + IOPORT1->iop_common.dir = config->P1Data.dir; +#endif + +#if defined(__MSP430_HAS_PORTA_R__) || defined(__MSP430_HAS_PORT2_R__) + IOPORT2->iop_full.ie = 0; + IOPORT2->iop_full.ifg = 0; + IOPORT2->iop_full.sel = 0; + IOPORT2->iop_common.out = config->P2Data.out; + IOPORT2->iop_common.dir = config->P2Data.dir; +#endif + +#if defined(__MSP430_HAS_PORTB_R__) || defined(__MSP430_HAS_PORT3_R__) + IOPORT3->iop_simple.sel = 0; + IOPORT3->iop_common.out = config->P3Data.out; + IOPORT3->iop_common.dir = config->P3Data.dir; +#endif + +#if defined(__MSP430_HAS_PORTB_R__) || defined(__MSP430_HAS_PORT4_R__) + IOPORT4->iop_simple.sel = 0; + IOPORT4->iop_common.out = config->P4Data.out; + IOPORT4->iop_common.dir = config->P4Data.dir; +#endif + +#if defined(__MSP430_HAS_PORTC_R__) || defined(__MSP430_HAS_PORT5_R__) + IOPORT5->iop_simple.sel = 0; + IOPORT5->iop_common.out = config->P5Data.out; + IOPORT5->iop_common.dir = config->P5Data.dir; +#endif + +#if defined(__MSP430_HAS_PORTC_R__) || defined(__MSP430_HAS_PORT6_R__) + IOPORT6->iop_simple.sel = 0; + IOPORT6->iop_common.out = config->P6Data.out; + IOPORT6->iop_common.dir = config->P6Data.dir; +#endif + +#if defined(__MSP430_HAS_PORTD_R__) || defined(__MSP430_HAS_PORT7_R__) + IOPORT7->iop_simple.sel = 0; + IOPORT7->iop_common.out = config->P7Data.out; + IOPORT7->iop_common.dir = config->P7Data.dir; +#endif + +#if defined(__MSP430_HAS_PORTD_R__) || defined(__MSP430_HAS_PORT8_R__) + IOPORT8->iop_simple.sel = 0; + IOPORT8->iop_common.out = config->P8Data.out; + IOPORT8->iop_common.dir = config->P8Data.dir; +#endif + +#if defined(__MSP430_HAS_PORTE_R__) || defined(__MSP430_HAS_PORT9_R__) + IOPORT9->iop_simple.sel = 0; + IOPORT9->iop_common.out = config->P9Data.out; + IOPORT9->iop_common.dir = config->P9Data.dir; +#endif + +#if defined(__MSP430_HAS_PORTE_R__) || defined(__MSP430_HAS_PORT10_R__) + IOPORT10->iop_simple.sel = 0; + IOPORT10->iop_common.out = config->P10Data.out; + IOPORT10->iop_common.dir = config->P10Data.dir; +#endif + +#if defined(__MSP430_HAS_PORTF_R__) || defined(__MSP430_HAS_PORT11_R__) + IOPORT11->iop_simple.sel = 0; + IOPORT11->iop_common.out = config->P11Data.out; + IOPORT11->iop_common.dir = config->P11Data.dir; +#endif + +#if defined(__MSP430_HAS_PORTJ_R__) + IOPORT12->iop_common.out = config->P12Data.out; + IOPORT12->iop_common.dir = config->P12Data.dir; +#endif +} + +/** + * @brief Pads mode setup. + * @details This function programs a pads group belonging to the same port + * with the specified mode. + * @note @p PAL_MODE_UNCONNECTED is implemented as output as recommended by + * the MSP430x1xx Family User's Guide. Unconnected pads are set to + * high logic state by default. + * @note This function does not alter the @p PxSEL registers. Alternate + * functions setup must be handled by device-specific code. + * + * @param[in] port the port identifier + * @param[in] mask the group mask + * @param[in] mode the mode + * + * @notapi + */ +void _pal_lld_setgroupmode(ioportid_t port, + ioportmask_t mask, + iomode_t mode) { + + switch (mode) { + case PAL_MODE_RESET: + case PAL_MODE_INPUT: + port->iop_common.dir &= ~mask; + break; + case PAL_MODE_UNCONNECTED: + port->iop_common.out |= mask; + case PAL_MODE_OUTPUT_PUSHPULL: + port->iop_common.dir |= mask; + break; + } +} + +#endif /* HAL_USE_PAL */ + +/** @} */ diff --git a/os/hal/platforms/MSP430X/pal_lld.h b/os/hal/platforms/MSP430X/pal_lld.h new file mode 100644 index 000000000..bcc850502 --- /dev/null +++ b/os/hal/platforms/MSP430X/pal_lld.h @@ -0,0 +1,457 @@ +/* + 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 MSP430/pal_lld.h + * @brief MSP430 Digital I/O low level driver header. + * + * @addtogroup PAL + * @{ + */ + +#ifndef _PAL_LLD_H_ +#define _PAL_LLD_H_ + +#if HAL_USE_PAL || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Unsupported modes and specific modes */ +/*===========================================================================*/ + +#undef PAL_MODE_INPUT_PULLUP +#undef PAL_MODE_INPUT_PULLDOWN +#undef PAL_MODE_INPUT_ANALOG +#undef PAL_MODE_OUTPUT_OPENDRAIN + +/*===========================================================================*/ +/* I/O Ports Types and constants. */ +/*===========================================================================*/ + +/** + * @brief Simple MSP430 I/O port. + */ +struct msp430_port_simple_t { + volatile uint8_t in; + volatile uint8_t in_h; + volatile uint8_t out; + volatile uint8_t out_h; + volatile uint8_t dir; + volatile uint8_t dir_h; + volatile uint8_t ren; + volatile uint8_t ren_h; + volatile uint8_t ds; + volatile uint8_t ds_h; +#if defined(__MSP430_HAS_PORT1_R__) || defined(__MSP430_HAS_PORT2_R__) || defined(__MSP430_HAS_PORTA_R__) || \ + defined(__MSP430_HAS_PORT3_R__) || defined(__MSP430_HAS_PORT4_R__) || defined(__MSP430_HAS_PORTB_R__) || \ + defined(__MSP430_HAS_PORT5_R__) || defined(__MSP430_HAS_PORT6_R__) || defined(__MSP430_HAS_PORTC_R__) || \ + defined(__MSP430_HAS_PORT7_R__) || defined(__MSP430_HAS_PORT8_R__) || defined(__MSP430_HAS_PORTD_R__) || \ + defined(__MSP430_HAS_PORT9_R__) || defined(__MSP430_HAS_PORT10_R__) || defined(__MSP430_HAS_PORTE_R__) || \ + defined(__MSP430_HAS_PORT11_R__) || defined(__MSP430_HAS_PORTF_R__) + volatile uint8_t sel; + volatile uint8_t sel_h; +#endif +}; + +/** + * @brief Full MSP430 I/O port. + */ +struct msp430_port_full_t { + volatile uint8_t in; + volatile uint8_t in_h; + volatile uint8_t out; + volatile uint8_t out_h; + volatile uint8_t dir; + volatile uint8_t dir_h; + volatile uint8_t ren; + volatile uint8_t ren_h; + volatile uint8_t ds; + volatile uint8_t ds_h; +#if defined(__MSP430_HAS_PORT1_R__) || defined(__MSP430_HAS_PORT2_R__) || defined(__MSP430_HAS_PORTA_R__) || \ + defined(__MSP430_HAS_PORT3_R__) || defined(__MSP430_HAS_PORT4_R__) || defined(__MSP430_HAS_PORTB_R__) || \ + defined(__MSP430_HAS_PORT5_R__) || defined(__MSP430_HAS_PORT6_R__) || defined(__MSP430_HAS_PORTC_R__) || \ + defined(__MSP430_HAS_PORT7_R__) || defined(__MSP430_HAS_PORT8_R__) || defined(__MSP430_HAS_PORTD_R__) || \ + defined(__MSP430_HAS_PORT9_R__) || defined(__MSP430_HAS_PORT10_R__) || defined(__MSP430_HAS_PORTE_R__) || \ + defined(__MSP430_HAS_PORT11_R__) || defined(__MSP430_HAS_PORTF_R__) + volatile uint8_t sel; + volatile uint8_t sel_h; +#endif +#if defined(__MSP430_HAS_PORT1_R__) || defined(__MSP430_HAS_PORT2_R__) || defined(__MSP430_HAS_PORTA_R__) + volatile uint8_t pad[14]; + volatile uint8_t ies; + volatile uint8_t ies_h; + volatile uint8_t ie; + volatile uint8_t ie_h; + volatile uint8_t ifg; + volatile uint8_t ifg_h; +#endif +}; + +/** + * @brief Simplified MSP430 I/O port representation. + * @details This structure represents the common part of all the MSP430 I/O + * ports. + */ +struct msp430_port_common { + volatile uint8_t in; + volatile uint8_t in_h; + volatile uint8_t out; + volatile uint8_t out_h; + volatile uint8_t dir; + volatile uint8_t dir_h; +}; + +/** + * @brief Generic MSP430 I/O port. + */ +typedef union { + struct msp430_port_common iop_common; + struct msp430_port_simple_t iop_simple; + struct msp430_port_full_t iop_full; +} msp430_ioport_t; + +/** + * @brief Setup registers common to all the MSP430 ports. + */ +typedef struct { + volatile uint8_t out; + volatile uint8_t dir; +} msp430_dio_setup_t; + +/** + * @brief MSP430 I/O ports static initializer. + * @details An instance of this structure must be passed to @p palInit() at + * system startup time in order to initialize the digital I/O + * subsystem. This represents only the initial setup, specific pads + * or whole ports can be reprogrammed at later time. + */ +typedef struct { +#if defined(__MSP430_HAS_PORT1_R__) || \ + defined(__MSP430_HAS_PORTA_R__) || \ + defined(__DOXYGEN__) + /** @brief Port 1 setup data.*/ + msp430_dio_setup_t P1Data; +#endif +#if defined(__MSP430_HAS_PORT2_R__) || \ + defined(__MSP430_HAS_PORTA_R__) || \ + defined(__DOXYGEN__) + /** @brief Port 2 setup data.*/ + msp430_dio_setup_t P2Data; +#endif +#if defined(__MSP430_HAS_PORT3_R__) || \ + defined(__MSP430_HAS_PORTB_R__) || \ + defined(__DOXYGEN__) + /** @brief Port 3 setup data.*/ + msp430_dio_setup_t P3Data; +#endif +#if defined(__MSP430_HAS_PORT4_R__) || \ + defined(__MSP430_HAS_PORTB_R__) || \ + defined(__DOXYGEN__) + /** @brief Port 4 setup data.*/ + msp430_dio_setup_t P4Data; +#endif +#if defined(__MSP430_HAS_PORT5_R__) || \ + defined(__MSP430_HAS_PORTC_R__) || \ + defined(__DOXYGEN__) + /** @brief Port 5 setup data.*/ + msp430_dio_setup_t P5Data; +#endif +#if defined(__MSP430_HAS_PORT6_R__) || \ + defined(__MSP430_HAS_PORTC_R__) || \ + defined(__DOXYGEN__) + /** @brief Port 6 setup data.*/ + msp430_dio_setup_t P6Data; +#endif +#if defined(__MSP430_HAS_PORT7_R__) || \ + defined(__MSP430_HAS_PORTD_R__) || \ + defined(__DOXYGEN__) + /** @brief Port 7 setup data.*/ + msp430_dio_setup_t P7Data; +#endif +#if defined(__MSP430_HAS_PORT8_R__) || \ + defined(__MSP430_HAS_PORTD_R__) || \ + defined(__DOXYGEN__) + /** @brief Port 8 setup data.*/ + msp430_dio_setup_t P8Data; +#endif +#if defined(__MSP430_HAS_PORT9_R__) || \ + defined(__MSP430_HAS_PORTE_R__) || \ + defined(__DOXYGEN__) + /** @brief Port 9 setup data.*/ + msp430_dio_setup_t P9Data; +#endif +#if defined(__MSP430_HAS_PORT10_R__) || \ + defined(__MSP430_HAS_PORTE_R__) || \ + defined(__DOXYGEN__) + /** @brief Port 10 setup data.*/ + msp430_dio_setup_t P10Data; +#endif +#if defined(__MSP430_HAS_PORT11_R__) || \ + defined(__MSP430_HAS_PORTF_R__) || \ + defined(__DOXYGEN__) + /** @brief Port 11 setup data.*/ + msp430_dio_setup_t P11Data; +#endif +#if defined(__MSP430_HAS_PORTJ_R__) || \ + defined(__DOXYGEN__) + /** @brief Port 12 setup data.*/ + msp430_dio_setup_t P12Data; +#endif +} PALConfig; + +/** + * @brief Width, in bits, of an I/O port. + */ +#define PAL_IOPORTS_WIDTH 8 + +/** + * @brief Whole port mask. + * @details This macro specifies all the valid bits into a port. + */ +#define PAL_WHOLE_PORT ((ioportmask_t)0xFF) + +/** + * @brief Digital I/O port sized unsigned type. + */ +typedef uint8_t ioportmask_t; + +/** + * @brief Digital I/O modes. + */ +typedef uint16_t iomode_t; + +/** + * @brief Port Identifier. + * @details This type can be a scalar or some kind of pointer, do not make + * any assumption about it, use the provided macros when populating + * variables of this type. + */ +typedef msp430_ioport_t *ioportid_t; + +/*===========================================================================*/ +/* I/O Ports Identifiers. */ +/*===========================================================================*/ + +/** + * @brief I/O port A identifier. + * @details This port identifier is mapped on the MSP430 port 1 (P1). + */ +#if defined(__MSP430_HAS_PORT1_R__) || \ + defined(__MSP430_HAS_PORTA_R__) || \ + defined(__DOXYGEN__) +#define IOPORT1 ((ioportid_t)(PAIN_+0)) +#endif + +/** + * @brief I/O port A identifier. + * @details This port identifier is mapped on the MSP430 port 2 (P2). + */ +#if defined(__MSP430_HAS_PORT2_R__) || \ + defined(__MSP430_HAS_PORTA_R__) || \ + defined(__DOXYGEN__) +#define IOPORT2 ((ioportid_t)(PAIN_+1)) +#endif + +/** + * @brief I/O port B identifier. + * @details This port identifier is mapped on the MSP430 port 3 (P3). + */ +#if defined(__MSP430_HAS_PORT3_R__) || \ + defined(__MSP430_HAS_PORTB_R__) || \ + defined(__DOXYGEN__) +#define IOPORT3 ((ioportid_t)(PBIN_+0)) +#endif + +/** + * @brief I/O port B identifier. + * @details This port identifier is mapped on the MSP430 port 4 (P4). + */ +#if defined(__MSP430_HAS_PORT4_R__) || \ + defined(__MSP430_HAS_PORTB_R__) || \ + defined(__DOXYGEN__) +#define IOPORT4 ((ioportid_t)(PBIN_+1)) +#endif + +/** + * @brief I/O port C identifier. + * @details This port identifier is mapped on the MSP430 port 5 (P5). + */ +#if defined(__MSP430_HAS_PORT5_R__) || \ + defined(__MSP430_HAS_PORTC_R__) || \ + defined(__DOXYGEN__) +#define IOPORT5 ((ioportid_t)(PCIN_+0)) +#endif + +/** + * @brief I/O port C identifier. + * @details This port identifier is mapped on the MSP430 port 6 (P6). + */ +#if defined(__MSP430_HAS_PORT6_R__) || \ + defined(__MSP430_HAS_PORTC_R__) || \ + defined(__DOXYGEN__) +#define IOPORT6 ((ioportid_t)(PCIN_+1)) +#endif + +/** + * @brief I/O port D identifier. + * @details This port identifier is mapped on the MSP430 port 7 (P7). + */ +#if defined(__MSP430_HAS_PORT7_R__) || \ + defined(__MSP430_HAS_PORTD_R__) || \ + defined(__DOXYGEN__) +#define IOPORT7 ((ioportid_t)(PDIN_+0)) +#endif + +/** + * @brief I/O port D identifier. + * @details This port identifier is mapped on the MSP430 port 8 (P8). + */ +#if defined(__MSP430_HAS_PORT8_R__) || \ + defined(__MSP430_HAS_PORTD_R__) || \ + defined(__DOXYGEN__) +#define IOPORT8 ((ioportid_t)(PDIN_+1)) +#endif + +/** + * @brief I/O port E identifier. + * @details This port identifier is mapped on the MSP430 port 9 (P9). + */ +#if defined(__MSP430_HAS_PORT9_R__) || \ + defined(__MSP430_HAS_PORTE_R__) || \ + defined(__DOXYGEN__) +#define IOPORT9 ((ioportid_t)(PEIN_+0)) +#endif + +/** + * @brief I/O port E identifier. + * @details This port identifier is mapped on the MSP430 port 10 (P10). + */ +#if defined(__MSP430_HAS_PORT10_R__) || \ + defined(__MSP430_HAS_PORTE_R__) || \ + defined(__DOXYGEN__) +#define IOPORT10 ((ioportid_t)(PEIN_+1)) +#endif + +/** + * @brief I/O port F identifier. + * @details This port identifier is mapped on the MSP430 port 11 (P11). + */ +#if defined(__MSP430_HAS_PORT11_R__) || \ + defined(__MSP430_HAS_PORTF_R__) || \ + defined(__DOXYGEN__) +#define IOPORT11 ((ioportid_t)(PFIN_+0)) +#endif + +/** + * @brief I/O port J identifier. + * @details This port identifier is mapped on the MSP430 port J (P12). + */ +#if defined(__MSP430_HAS_PORTJ_R__) || \ + defined(__DOXYGEN__) +#define IOPORT12 ((ioportid_t)(PJIN_+0)) +#endif + +/*===========================================================================*/ +/* Implementation, some of the following macros could be implemented as */ +/* functions, if so please put them in pal_lld.c. */ +/*===========================================================================*/ + +/** + * @brief Low level PAL subsystem initialization. + * @details In MSP430 programs all the ports as input. + * + * @param[in] config the MSP430 ports configuration + * + * @notapi + */ +#define pal_lld_init(config) _pal_lld_init(config) + +/** + * @brief Reads the physical I/O port states. + * @details This function is implemented by reading the PxIN register, the + * implementation has no side effects. + * + * @param[in] port port identifier + * @return The port bits. + * + * @notapi + */ +#define pal_lld_readport(port) ((port)->iop_common.in) + +/** + * @brief Reads the output latch. + * @details This function is implemented by reading the PxOUT register, the + * implementation has no side effects. + * + * @param[in] port port identifier + * @return The latched logical states. + * + * @notapi + */ +#define pal_lld_readlatch(port) ((port)->iop_common.out) + +/** + * @brief Writes a bits mask on a I/O port. + * @details This function is implemented by writing the PxOUT register, the + * implementation has no side effects. + * + * @param[in] port port identifier + * @param[in] bits bits to be written on the specified port + * + * @notapi + */ +#define pal_lld_writeport(port, bits) ((port)->iop_common.out = (bits)) + +/** + * @brief Pads group mode setup. + * @details This function programs a pads group belonging to the same port + * with the specified mode. + * @note @p PAL_MODE_UNCONNECTED is implemented as output as recommended by + * the MSP430x1xx Family User's Guide. + * @note This function does not alter the @p PxSEL registers. Alternate + * functions setup must be handled by device-specific code. + * + * @param[in] port port identifier + * @param[in] mask group mask + * @param[in] offset group bit offset within the port + * @param[in] mode group mode + * + * @notapi + */ +#define pal_lld_setgroupmode(port, mask, offset, mode) \ + _pal_lld_setgroupmode(port, mask << offset, mode) + +extern const PALConfig pal_default_config; + +#ifdef __cplusplus +extern "C" { +#endif + void _pal_lld_init(const PALConfig *config); + void _pal_lld_setgroupmode(ioportid_t port, + ioportmask_t mask, + iomode_t mode); +#ifdef __cplusplus +} +#endif + +#endif /* _PAL_LLD_H_ */ + +#endif /* HAL_USE_PAL */ + +/** @} */ diff --git a/os/hal/platforms/MSP430X/platform.dox b/os/hal/platforms/MSP430X/platform.dox new file mode 100644 index 000000000..528e80570 --- /dev/null +++ b/os/hal/platforms/MSP430X/platform.dox @@ -0,0 +1,103 @@ +/* + 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 . +*/ + +/** + * @defgroup MSP430_DRIVERS MSP430 Drivers + * @details This section describes all the supported drivers on the MSP430 + * platform and the implementation details of the single drivers. + * + * @ingroup platforms + */ + +/** + * @defgroup MSP430_HAL MSP430 Initialization Support + * @details The MSP430 HAL support is responsible for system initialization. + * + * @section msp430_hal_1 Supported HW resources + * - DCOCTL. + * - BCSCTL1. + * - BCSCTL2. + * . + * @section msp430_hal_2 MSP430 HAL driver implementation features + * - Clock source selection. + * . + * @ingroup MSP430_DRIVERS + */ + +/** + * @defgroup MSP430_PAL MSP430 PAL Support + * @details The MSP430 PAL driver uses the PORT peripherals. + * + * @section msp430_pal_1 Supported HW resources + * - PORT1 (where present). + * - PORT2 (where present). + * - PORT3 (where present). + * - PORT4 (where present). + * - PORT5 (where present). + * - PORT6 (where present). + * - PORT7 (where present). + * - PORT8 (where present). + * - PORT9 (where present). + * - PORT10 (where present). + * - PORT11 (where present). + * - PORT12 (PORT_J) (where present). + * . + * @section msp430_pal_2 MSP430 PAL driver implementation features + * The PAL driver implementation fully supports the following hardware + * capabilities: + * - 8 bits wide ports. + * - Atomic set/reset/toggle functions because special MSP430 instruction set. + * - Output latched regardless of the pad setting. + * - Direct read of input pads regardless of the pad setting. + * . + * @section msp430_pal_3 Supported PAL setup modes + * The MSP430 PAL driver supports the following I/O modes: + * - @p PAL_MODE_RESET. + * - @p PAL_MODE_UNCONNECTED. + * - @p PAL_MODE_INPUT. + * - @p PAL_MODE_OUTPUT_PUSHPULL. + * . + * Any attempt to setup an invalid mode is ignored. + * + * @section msp430_pal_4 Suboptimal behavior + * The MSP430 PORT is less than optimal in several areas, the limitations + * should be taken in account while using the PAL driver: + * - Bus/group writes is not atomic. + * - Pad/group mode setup is not atomic. + * . + * @ingroup MSP430_DRIVERS + */ + +/** + * @defgroup MSP430_SERIAL MSP430 Serial Support + * @details The MSP430 Serial driver uses the USART peripherals in a + * buffered, interrupt driven, implementation. + * + * @section msp430_serial_1 Supported HW resources + * The serial driver can support any of the following hardware resources: + * - USART0. + * - USART1. + * . + * @section msp430_serial_2 MSP430 Serial driver implementation features + * - Each USART can be independently enabled and programmed. + * - Fully interrupt driven. + * . + * @ingroup MSP430_DRIVERS + */ diff --git a/os/hal/platforms/MSP430X/serial_lld.c b/os/hal/platforms/MSP430X/serial_lld.c new file mode 100644 index 000000000..39f89e057 --- /dev/null +++ b/os/hal/platforms/MSP430X/serial_lld.c @@ -0,0 +1,362 @@ +/* + 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 MSP430/serial_lld.c + * @brief MSP430 low level serial driver code. + * + * @addtogroup SERIAL + * @{ + */ + +#include "ch.h" +#include "hal.h" + +#if HAL_USE_SERIAL || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +#if USE_MSP430_USART0 || defined(__DOXYGEN__) +/** @brief USART0 serial driver identifier.*/ +SerialDriver SD1; +#endif +#if USE_MSP430_USART1 || defined(__DOXYGEN__) +/** @brief USART1 serial driver identifier.*/ +SerialDriver SD2; +#endif + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +/** @brief Driver default configuration.*/ +static const SerialConfig default_config = { + UBR(SERIAL_DEFAULT_BITRATE), + UCBRS_0 + UCBRF_13 + UCOS16, /* Modln UCBRSx=0, UCBRFx=0, over sampling */ + 0x00 /* parity disabled, 8-bit data, one stop bit, UART mode, asynchronous mode */ +}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +static void set_error(SerialDriver *sdp, uint8_t urctl) { + ioflags_t sts = 0; + + if (urctl & UCOE) + sts |= SD_OVERRUN_ERROR; + if (urctl & UCPE) + sts |= SD_PARITY_ERROR; + if (urctl & UCFE) + sts |= SD_FRAMING_ERROR; + if (urctl & UCBRK) + sts |= SD_BREAK_DETECTED; + chSysLockFromIsr(); + chIOAddFlagsI(sdp, sts); + chSysUnlockFromIsr(); +} + +#if USE_MSP430_USART0 || defined(__DOXYGEN__) +static void notify1(GenericQueue *qp) { + + (void)qp; + if (!(UCA0IE & UCTXIE)) { + msg_t b = sdRequestDataI(&SD1); + if (b != Q_EMPTY) { + UCA0IE |= UCTXIE; + UCA0TXBUF = (uint8_t)b; + } + } +} + +/** + * @brief USART0 initialization. + * + * @param[in] config the architecture-dependent serial driver configuration + */ +static void usart0_init(const SerialConfig *config) { + UCA0CTL1 = UCSWRST; /* Put state machine in reset. */ + /* USART init */ + P3SEL |= (P3_O_TXD0_MASK | P3_I_RXD0_MASK); + UCA0CTL1 |= UCSSEL_2; /* SMCLK as clock source. */ + UCA0MCTL = config->sc_mod; /* Modulator. */ + UCA0BR1 = (uint8_t)(config->sc_div >> 8); /* Divider high. */ + UCA0BR0 = (uint8_t)(config->sc_div >> 0); /* Divider low. */ + /* Clear USART status.*/ + (void)UCA0RXBUF; + /* USART enable.*/ + UCA0CTL0 = config->sc_ctl; /* Various settings. */ + UCA0CTL1 &= ~UCSWRST; /* Initialize USCI state machine. */ + UCA0IE |= UCRXIE; /* Enables RX interrupt. */ +} + +/** + * @brief USART0 de-initialization. + */ +static void usart0_deinit(void) { + + UCA0IE &= ~UCRXIE; /* Disables RX interrupt. */ + UCA0CTL1 |= UCSWRST; /* Put state machine in reset. */ +} +#endif /* USE_MSP430_USART0 */ + +#if USE_MSP430_USART1 || defined(__DOXYGEN__) +static void notify2(GenericQueue *qp) { + + (void)qp; + if (!(UCA1IE & UCTXIE)) { + msg_t b = sdRequestDataI(&SD2); + if (b != Q_EMPTY) { + UCA1IE |= UCTXIE; + UCA1TXBUF = (uint8_t)b; + } + } +} + +/** + * @brief USART1 initialization. + * + * @param[in] config the architecture-dependent serial driver configuration + */ +static void usart1_init(const SerialConfig *config) { + UCA1CTL1 = UCSWRST; /* Put state machine in reset. */ + /* USART init */ + P5SEL |= (P5_O_TXD1_MASK | P5_I_RXD1_MASK); + UCA1CTL1 |= UCSSEL_2; /* SMCLK as clock source. */ + UCA1MCTL = config->sc_mod; /* Modulator. */ + UCA1BR1 = (uint8_t)(config->sc_div >> 8); /* Divider high. */ + UCA1BR0 = (uint8_t)(config->sc_div >> 0); /* Divider low. */ + /* Clear USART status.*/ + (void)UCA1RXBUF; + /* USART enable.*/ + UCA1CTL0 = config->sc_ctl; /* Various settings. */ + UCA1CTL1 &= ~UCSWRST; /* Initialize USCI state machine. */ + UCA1IE |= UCRXIE; /* Enables RX interrupt. */ +} + +/** + * @brief USART1 de-initialization. + */ +static void usart1_deinit(void) { + + UCA1IE &= ~UCRXIE; /* Disables RX interrupt. */ + UCA1CTL1 |= UCSWRST; /* Put state machine in reset. */ +} +#endif /* USE_MSP430_USART1 */ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if USE_MSP430_USART0 || defined(__DOXYGEN__) +/** + * @brief USART0 TX interrupt handler segment. + */ +#define _USART0_TRANSMIT_ISR() { \ + msg_t b; \ + chSysLockFromIsr(); \ + b = sdRequestDataI(&SD1); \ + chSysUnlockFromIsr(); \ + if (b < Q_OK) \ + UCA0IE &= ~UCTXIE; \ + else \ + UCA0TXBUF = b; \ +} + +/** + * @brief USART0 RX interrupt handler segment. + */ +#define _USART0_RECEIVE_ISR() { \ + uint8_t urctl; \ + if ((urctl = UCA0STAT) & UCRXERR) \ + set_error(&SD1, urctl); \ + chSysLockFromIsr(); \ + sdIncomingDataI(&SD1, UCA0RXBUF); \ + chSysUnlockFromIsr(); \ +} + +/** + * @brief USART0 TX/RX interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(USCI_A0) { + + CH_IRQ_PROLOGUE(); + + #if defined(__IAR_SYSTEMS_ICC__) + switch(__even_in_range(UCA0IV,4)) + #else + switch(*(volatile uint16_t*)UCA0IV) + #endif + { + case 2: /* Vector 2 - RXIFG */ + _USART0_RECEIVE_ISR(); + break; + + case 4: /* Vector 4 - TXIFG */ + _USART0_TRANSMIT_ISR(); + break; + + default: + break; + } + + CH_IRQ_EPILOGUE(); +} +#endif /* USE_MSP430_USART0 */ + +#if USE_MSP430_USART1 || defined(__DOXYGEN__) +/** + * @brief USART1 TX interrupt handler segment. + */ +#define _USART1_TRANSMIT_ISR() { \ + msg_t b; \ + chSysLockFromIsr(); \ + b = sdRequestDataI(&SD2); \ + chSysUnlockFromIsr(); \ + if (b < Q_OK) \ + UCA1IE &= ~UCTXIE; \ + else \ + UCA1TXBUF = b; \ +} + +/** + * @brief USART0 RX interrupt handler segment. + */ +#define _USART1_RECEIVE_ISR() { \ + uint8_t urctl; \ + if ((urctl = UCA1STAT) & UCRXERR) \ + set_error(&SD2, urctl); \ + chSysLockFromIsr(); \ + sdIncomingDataI(&SD2, UCA1RXBUF); \ + chSysUnlockFromIsr(); \ +} + +/** + * @brief USART1 TX/RX interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(USCI_A1) { + + CH_IRQ_PROLOGUE(); + + #if defined(__IAR_SYSTEMS_ICC__) + switch(__even_in_range(UCA1IV,4)) + #else + switch(*(volatile uint16_t*)UCA1IV) + #endif + { + case 2: /* Vector 2 - RXIFG */ + _USART1_RECEIVE_ISR(); + break; + + case 4: /* Vector 4 - TXIFG */ + _USART1_TRANSMIT_ISR(); + break; + + default: + break; + } + + CH_IRQ_EPILOGUE(); +} +#endif /* USE_MSP430_USART1 */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level serial driver initialization. + * + * @notapi + */ +void sd_lld_init(void) { + +#if USE_MSP430_USART0 + sdObjectInit(&SD1, NULL, notify1); +#endif + +#if USE_MSP430_USART1 + sdObjectInit(&SD2, NULL, notify2); +#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; + +#if USE_MSP430_USART0 + if (&SD1 == sdp) { + usart0_init(config); + return; + } +#endif +#if USE_MSP430_USART1 + if (&SD2 == sdp) { + usart1_init(config); + return; + } +#endif +} + +/** + * @brief Low level serial driver stop. + * @details De-initializes the USART, stops the associated clock, resets the + * interrupt vector. + * + * @param[in] sdp pointer to a @p SerialDriver object + * + * @notapi + */ +void sd_lld_stop(SerialDriver *sdp) { + +#if USE_MSP430_USART0 + if (&SD1 == sdp) { + usart0_deinit(); + return; + } +#endif +#if USE_MSP430_USART1 + if (&SD2 == sdp) { + usart1_deinit(); + return; + } +#endif +} + +#endif /* HAL_USE_SERIAL */ + +/** @} */ diff --git a/os/hal/platforms/MSP430X/serial_lld.h b/os/hal/platforms/MSP430X/serial_lld.h new file mode 100644 index 000000000..8f3d69d43 --- /dev/null +++ b/os/hal/platforms/MSP430X/serial_lld.h @@ -0,0 +1,140 @@ +/* + 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 MSP430/serial_lld.h + * @brief MSP430 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 USART0 driver enable switch. + * @details If set to @p TRUE the support for USART0 is included. + * @note The default is @p TRUE. + */ +#if !defined(USE_MSP430_USART0) || defined(__DOXYGEN__) +#define USE_MSP430_USART0 TRUE +#endif + +/** + * @brief USART1 driver enable switch. + * @details If set to @p TRUE the support for USART1 is included. + * @note The default is @p FALSE. + */ +#if !defined(USE_MSP430_USART1) || defined(__DOXYGEN__) +#define USE_MSP430_USART1 TRUE +#endif + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief MSP430 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. + */ +typedef struct { + /** + * @brief Initialization value for the UBRx registers. + */ + uint16_t sc_div; + /** + * @brief Initialization value for the MOD register. + */ + uint8_t sc_mod; + /** + * @brief Initialization value for the CTL register. + */ + uint8_t sc_ctl; +} 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.*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Macro for baud rate computation. + * @note Make sure the final baud rate is within tolerance. + */ +#define UBR(b) (SMCLK / (b) / 16) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if USE_MSP430_USART0 && !defined(__DOXYGEN__) +extern SerialDriver SD1; +#endif +#if USE_MSP430_USART1 && !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_ */ + +/** @} */ -- cgit v1.2.3