aboutsummaryrefslogtreecommitdiffstats
path: root/os/hal
diff options
context:
space:
mode:
authorAndrew Wygle <awygle@gmail.com>2016-04-08 01:43:46 -0700
committerAndrew Wygle <awygle@gmail.com>2016-04-08 01:46:32 -0700
commitfd20f0fa17bfdf81dc28e7d30f13ca80264b7c78 (patch)
treeace5b24746120cea70c247b6cd723fc886e9e5b8 /os/hal
parent9d74dd2661b80a5ae8598591f0251b197cc51756 (diff)
downloadChibiOS-Contrib-fd20f0fa17bfdf81dc28e7d30f13ca80264b7c78.tar.gz
ChibiOS-Contrib-fd20f0fa17bfdf81dc28e7d30f13ca80264b7c78.tar.bz2
ChibiOS-Contrib-fd20f0fa17bfdf81dc28e7d30f13ca80264b7c78.zip
Initial MSP430X Port.
This port includes hal, pal, serial, and st drivers. It supports both large and small model code and data for MSP430X-class CPUs. It has only been tested on the EXP430FR5969 LaunchPad board.
Diffstat (limited to 'os/hal')
-rw-r--r--os/hal/boards/EXP430FR5969/board.c46
-rw-r--r--os/hal/boards/EXP430FR5969/board.h129
-rw-r--r--os/hal/boards/EXP430FR5969/board.mk5
-rw-r--r--os/hal/ports/MSP430X/hal_lld.c87
-rw-r--r--os/hal/ports/MSP430X/hal_lld.h245
-rw-r--r--os/hal/ports/MSP430X/hal_pal_lld.c215
-rw-r--r--os/hal/ports/MSP430X/hal_pal_lld.h390
-rw-r--r--os/hal/ports/MSP430X/hal_serial_lld.c657
-rw-r--r--os/hal/ports/MSP430X/hal_serial_lld.h320
-rw-r--r--os/hal/ports/MSP430X/hal_st_lld.c206
-rw-r--r--os/hal/ports/MSP430X/hal_st_lld.h216
-rw-r--r--os/hal/ports/MSP430X/platform.mk8
12 files changed, 2524 insertions, 0 deletions
diff --git a/os/hal/boards/EXP430FR5969/board.c b/os/hal/boards/EXP430FR5969/board.c
new file mode 100644
index 0000000..ac48ba0
--- /dev/null
+++ b/os/hal/boards/EXP430FR5969/board.c
@@ -0,0 +1,46 @@
+/*
+ ChibiOS - Copyright (C) 2016 Andrew Wygle aka awygle
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+#include "hal.h"
+
+/**
+ * @brief PAL setup.
+ * @details Digital I/O ports static configuration as defined in @p board.h.
+ * This variable is used by the HAL when initializing the PAL driver.
+ */
+#if HAL_USE_PAL || defined(__DOXYGEN__)
+const PALConfig pal_default_config =
+{
+ {VAL_IOPORT1_OUT, VAL_IOPORT1_DIR, VAL_IOPORT1_REN, VAL_IOPORT1_SEL0,
+ VAL_IOPORT1_SEL1, VAL_IOPORT1_IES, VAL_IOPORT1_IE},
+ {VAL_IOPORT2_OUT, VAL_IOPORT2_DIR, VAL_IOPORT2_REN, VAL_IOPORT2_SEL0,
+ VAL_IOPORT2_SEL1, VAL_IOPORT2_IES, VAL_IOPORT2_IE},
+ {VAL_IOPORT0_OUT, VAL_IOPORT0_DIR, VAL_IOPORT0_REN, VAL_IOPORT0_SEL0,
+ VAL_IOPORT0_SEL1, VAL_IOPORT0_IES, VAL_IOPORT0_IE}
+}; /* Set UART TX pin correctly */
+#endif /* HAL_USE_PAL */
+
+/**
+ * Board-specific initialization code.
+ */
+void boardInit(void) {
+
+ /*
+ * External interrupts setup, all disabled initially.
+ */
+ _disable_interrupts();
+
+}
diff --git a/os/hal/boards/EXP430FR5969/board.h b/os/hal/boards/EXP430FR5969/board.h
new file mode 100644
index 0000000..6b53f4b
--- /dev/null
+++ b/os/hal/boards/EXP430FR5969/board.h
@@ -0,0 +1,129 @@
+/*
+ ChibiOS - Copyright (C) 2016 Andrew Wygle aka awygle
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+#ifndef _BOARD_H_
+#define _BOARD_H_
+
+/*
+ * Setup for the Arduino Uno or board.
+ */
+
+/*
+ * Board identifier.
+ */
+#define BOARD_EXP430FR5959
+#define BOARD_NAME "MSP430FR5969 LaunchPad"
+
+/*
+ * IO lines assignments.
+ */
+#define LINE_LED_G PAL_LINE(IOPORT1, 0U)
+#define LINE_LED_R PAL_LINE(IOPORT2, 14U)
+#define LINE_SW_S1 PAL_LINE(IOPORT2, 13U)
+#define LINE_SW_S2 PAL_LINE(IOPORT1, 1U)
+
+/*
+ * I/O ports initial setup, this configuration is established soon after reset
+ * in the initialization code.
+ * Please refer to the MSP430X Family Users Guide for details.
+ */
+/*
+ * Port A setup:
+ *
+ * P1.0 - Green LED (output low)
+ * P1.1 - Switch S2 (input pullup falling-edge interrupt)
+ * P1.2 - BoosterPack BP19 (input pullup)
+ * P1.3 - BoosterPack BP11 (input pullup)
+ * P1.4 - BoosterPack BP12 (input pullup)
+ * P1.5 - BoosterPack BP13 (input pullup)
+ * P1.6 - BoosterPack BP15 (input pullup)
+ * P1.7 - BoosterPack BP14 (input pullup)
+ * P2.0 - Application UART TX (alternate 2)
+ * P2.1 - Application UART RX (alternate 2)
+ * P2.2 - BoosterPack BP7 (input pullup)
+ * P2.3 - N/C (input pullup)
+ * P2.4 - BoosterPack BP6 (input pullup)
+ * P2.5 - BoosterPack BP4 (input pullup)
+ * P2.6 - BoosterPack BP3 (input pullup)
+ * P2.7 - N/C (input pullup)
+ */
+#define VAL_IOPORT1_OUT 0xFCFE
+#define VAL_IOPORT1_DIR 0x0001
+#define VAL_IOPORT1_REN 0xFCFE
+#define VAL_IOPORT1_SEL0 0x0000
+#define VAL_IOPORT1_SEL1 0x0300
+#define VAL_IOPORT1_IES 0x0002
+#define VAL_IOPORT1_IE 0x0002
+
+/*
+ * Port B setup:
+ *
+ * P3.0 - BoosterPack BP18 (input pullup)
+ * P3.1 - N/C (input pullup)
+ * P3.2 - N/C (input pullup)
+ * P3.3 - N/C (input pullup)
+ * P3.4 - BoosterPack BP8 (input pullup)
+ * P3.5 - BoosterPack BP9 (input pullup)
+ * P3.6 - BoosterPack BP10 (input pullup)
+ * P3.7 - N/C (input pullup)
+ * P4.0 - Application UART CTS (input pullup falling-edge interrupt)
+ * P4.1 - Application UART RTS (output high)
+ * P4.2 - BoosterPack BP2 (input pullup)
+ * P4.3 - BoosterPack BP5 (input pullup)
+ * P4.4 - N/C (input pullup)
+ * P4.5 - Switch S1 (input pullup falling-edge interrupt)
+ * P4.6 - Red LED (output low)
+ * P4.7 - N/C (input pullup)
+ */
+#define VAL_IOPORT2_OUT 0xBFFF
+#define VAL_IOPORT2_DIR 0x4200
+#define VAL_IOPORT2_REN 0xBDFF
+#define VAL_IOPORT2_SEL0 0x0000
+#define VAL_IOPORT2_SEL1 0x0000
+#define VAL_IOPORT2_IES 0x2100
+#define VAL_IOPORT2_IE 0x2100
+
+/*
+ * Port J setup:
+ *
+ * PJ.0 - TDO (input pullup)
+ * PJ.1 - TDI (input pullup)
+ * PJ.2 - TMS (input pullup)
+ * PJ.3 - TCK (input pullup)
+ * PJ.4 - LFXIN (alternate 1)
+ * PJ.5 - LFXOUT (alternate 1)
+ * PJ.6 - HFXIN (N/C) (input pullup)
+ * PJ.7 - HFXOUT (N/C) (input pullup)
+ */
+#define VAL_IOPORT0_OUT 0x00FF
+#define VAL_IOPORT0_DIR 0x0000
+#define VAL_IOPORT0_REN 0x00CF
+#define VAL_IOPORT0_SEL0 0x0030
+#define VAL_IOPORT0_SEL1 0x0000
+#define VAL_IOPORT0_IES 0x0000
+#define VAL_IOPORT0_IE 0x0000
+
+#if !defined(_FROM_ASM_)
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void boardInit(void);
+#ifdef __cplusplus
+}
+#endif
+#endif /* _FROM_ASM_ */
+
+#endif /* _BOARD_H_ */
diff --git a/os/hal/boards/EXP430FR5969/board.mk b/os/hal/boards/EXP430FR5969/board.mk
new file mode 100644
index 0000000..c629257
--- /dev/null
+++ b/os/hal/boards/EXP430FR5969/board.mk
@@ -0,0 +1,5 @@
+# List of all the board related files.
+BOARDSRC = ${CHIBIOS_CONTRIB}/os/hal/boards/EXP430FR5969/board.c
+
+# Required include directories
+BOARDINC = ${CHIBIOS_CONTRIB}/os/hal/boards/EXP430FR5969
diff --git a/os/hal/ports/MSP430X/hal_lld.c b/os/hal/ports/MSP430X/hal_lld.c
new file mode 100644
index 0000000..872fe97
--- /dev/null
+++ b/os/hal/ports/MSP430X/hal_lld.c
@@ -0,0 +1,87 @@
+/*
+ ChibiOS - Copyright (C) 2016 Andrew Wygle aka awygle
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file MSP430X/hal_lld.c
+ * @brief MSP430X HAL subsystem low level driver source.
+ *
+ * @addtogroup HAL
+ * @{
+ */
+
+#include "hal.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level HAL driver initialization.
+ *
+ * @notapi
+ */
+void hal_lld_init(void) {
+ /* Disable watchdog */
+ /* TODO Real watchdog support */
+ WDTCTL = WDTPW | WDTHOLD;
+ /* Init clock system */
+ CSCTL0 = CSKEY; /* unlock clock system */
+ CSCTL1 = MSP430X_DCOSEL;
+ CSCTL2 = (MSP430X_ACLK_SRC << 8) | (MSP430X_SMCLK_SRC << 4) | (MSP430X_MCLK_SRC);
+ CSCTL3 = (DIVIDER(MSP430X_ACLK_DIV) << 8) | (DIVIDER(MSP430X_SMCLK_DIV) << 4) | (DIVIDER(MSP430X_MCLK_DIV));
+ CSCTL4 = (MSP430X_HFXTCLK_DRIVE << 14) | (MSP430X_HFXTCLK_BYPASS << 12) | (MSP430X_HFFREQ << 10) | HFXTOFF | \
+ (MSP430X_LFXTCLK_DRIVE << 6) | (MSP430X_LFXTCLK_BYPASS << 4) | VLOOFF | LFXTOFF;
+ CSCTL6 = (MODCLKREQEN) | (SMCLKREQEN) | (MCLKREQEN) | (ACLKREQEN);
+ #if defined(MSP430X_USE_HFXT) && defined(MSP430X_USE_LFXT)
+ do {
+ CSCTL5 &= ~(HFXTOFFG | LFXTOFFG);
+ SFRIFG1 &= ~OFIFG;
+ } while (SFRIFG1 & OFIFG);
+ #elif defined(MSP430X_USE_HFXT)
+ do {
+ CSCTL5 &= ~(HFXTOFFG);
+ SFRIFG1 &= ~OFIFG;
+ } while (SFRIFG1 & OFIFG);
+ #elif defined(MSP430X_USE_LFXT)
+ do {
+ CSCTL5 &= ~(LFXTOFFG);
+ SFRIFG1 &= ~OFIFG;
+ } while (SFRIFG1 & OFIFG);
+ #endif
+ CSCTL0_H = 0xFF; /* Lock clock system */
+}
+
+/** @} */
diff --git a/os/hal/ports/MSP430X/hal_lld.h b/os/hal/ports/MSP430X/hal_lld.h
new file mode 100644
index 0000000..9549453
--- /dev/null
+++ b/os/hal/ports/MSP430X/hal_lld.h
@@ -0,0 +1,245 @@
+/*
+ ChibiOS - Copyright (C) 2016 Andrew Wygle aka awygle
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file MSP430X/hal_lld.h
+ * @brief MSP430X HAL subsystem low level driver header.
+ *
+ * @addtogroup HAL
+ * @{
+ */
+
+#ifndef _HAL_LLD_H_
+#define _HAL_LLD_H_
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @brief Defines the support for realtime counters in the HAL.
+ */
+/* someday*/
+#define HAL_IMPLEMENTS_COUNTERS FALSE
+
+/**
+ * @name Platform identification macros
+ * @{
+ */
+#define PLATFORM_NAME "MSP430X"
+/** @} */
+
+#define MSP430X_LFXTCLK 0
+#define MSP430X_VLOCLK 1
+#define MSP430X_LFMODCLK 2
+#define MSP430X_DCOCLK 3
+#define MSP430X_MODCLK 4
+#define MSP430X_HFXTCLK 5
+
+#if !defined(MSP430X_LFXTCLK_FREQ)
+ #define MSP430X_LFXTCLK_FREQ 32768
+ #warning "LFXTCLK freqency not defined - assuming 32768 Hz"
+#endif
+#define MSP430X_VLOCLK_FREQ 10000
+#define MSP430X_MODCLK_FREQ 5000000
+#define MSP430X_LFMODCLK_FREQ (MSP430X_MODCLK_FREQ/128)
+#if !defined(MSP430X_DCOCLK_FREQ)
+ #define MSP430X_DCOCLK_FREQ 8000000
+ #warning "DCOCLK frequency not defined - assuming 8 MHz"
+#endif
+#if !defined(MSP430X_HFXTCLK_FREQ)
+ #define MSP430X_HFXTCLK_FREQ 0
+ #warning "HFXTCLK frequency not defined - assuming disabled"
+#endif
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name MSP430X configuration options
+ * @{
+ */
+
+/* Clock dividers */
+#if !defined(MSP430X_ACLK_DIV)
+ #define MSP430X_ACLK_DIV 1
+#endif
+#if !defined(MSP430X_MCLK_DIV)
+ #define MSP430X_MCLK_DIV 8
+#endif
+#if !defined(MSP430X_SMCLK_DIV)
+ #define MSP430X_SMCLK_DIV 8
+#endif
+
+/* Clock sources */
+#if !defined(MSP430X_ACLK_SRC)
+ #define MSP430X_ACLK_SRC MSP430X_LFXTCLK
+#endif
+#if !defined(MSP430X_MCLK_SRC)
+ #define MSP430X_MCLK_SRC MSP430X_DCOCLK
+#endif
+#if !defined(MSP430X_SMCLK_SRC)
+ #define MSP430X_SMCLK_SRC MSP430X_DCOCLK
+#endif
+
+/* HFXT and LFXT settings */
+#if !defined(MSP430X_LFXTCLK_BYPASS)
+ #define MSP430X_LFXTCLK_BYPASS 0
+#endif
+#if !defined(MSP430X_LFXTCLK_DRIVE)
+ #define MSP430X_LFXTCLK_DRIVE 3
+#endif
+#if !defined(MSP430X_HFXTCLK_BYPASS)
+ #define MSP430X_HFXTCLK_BYPASS 0
+#endif
+#if !defined(MSP430X_HFXTCLK_DRIVE)
+ #define MSP430X_HFXTCLK_DRIVE 3
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*
+ * Configuration-related checks.
+ */
+#if (MSP430X_ACLK_SRC == MSP430X_LFXTCLK) || (MSP430X_MCLK_SRC == MSP430X_LFXTCLK) || (MSP430X_SMCLK_SRC == MSP430X_LFXTCLK)
+ #define MSP430X_USE_LFXTCLK
+#endif
+#if (MSP430X_MCLK_SRC == MSP430X_HFXTCLK) || (MSP430X_SMCLK_SRC == MSP430X_HFXTCLK)
+ #define MSP430X_USE_HFXTCLK
+#endif
+
+#if defined(MSP430X_USE_HFXTCLK) && MSP430X_HFXTCLK_FREQ == 0
+ #error "HFXT requested as clock source but disabled"
+#endif
+
+/* Clock speeds */
+#if (MSP430X_ACLK_SRC == MSP430X_LFXTCLK)
+ #define MSP430X_ACLK_FREQ (MSP430X_LFXTCLK_FREQ / MSP430X_ACLK_DIV)
+#elif (MSP430X_ACLK_SRC == MSP430X_VLOCLK)
+ #define MSP430X_ACLK_FREQ (MSP430X_VLOCLK_FREQ / MSP430X_ACLK_DIV)
+#elif (MSP430X_ACLK_SRC == MSP430X_LFMODCLK)
+ #define MSP430X_ACLK_FREQ (MSP430X_LFMODCLK_FREQ / MSP430X_ACLK_DIV)
+#else
+ #error "ACLK source invalid!"
+#endif
+#if (MSP430X_MCLK_SRC == MSP430X_LFXTCLK)
+ #define MSP430X_MCLK_FREQ (MSP430X_LFXTCLK_FREQ / MSP430X_MCLK_DIV)
+#elif (MSP430X_MCLK_SRC == MSP430X_VLOCLK)
+ #define MSP430X_MCLK_FREQ (MSP430X_VLOCLK_FREQ / MSP430X_MCLK_DIV)
+#elif (MSP430X_MCLK_SRC == MSP430X_LFMODCLK)
+ #define MSP430X_MCLK_FREQ (MSP430X_LFMODCLK_FREQ / MSP430X_MCLK_DIV)
+#elif (MSP430X_MCLK_SRC == MSP430X_DCOCLK)
+ #define MSP430X_MCLK_FREQ (MSP430X_DCOCLK_FREQ / MSP430X_MCLK_DIV)
+#elif (MSP430X_MCLK_SRC == MSP430X_MODCLK)
+ #define MSP430X_MCLK_FREQ (MSP430X_MODCLK_FREQ / MSP430X_MCLK_DIV)
+#elif (MSP430X_MCLK_SRC == MSP430X_HFXTCLK)
+ #define MSP430X_MCLK_FREQ (MSP430X_HFXTCLK_FREQ / MSP430X_MCLK_DIV)
+#else
+ #error "MCLK source invalid!"
+#endif
+#if (MSP430X_SMCLK_SRC == MSP430X_LFXTCLK)
+ #define MSP430X_SMCLK_FREQ (MSP430X_LFXTCLK_FREQ / MSP430X_SMCLK_DIV)
+#elif (MSP430X_SMCLK_SRC == MSP430X_VLOCLK)
+ #define MSP430X_SMCLK_FREQ (MSP430X_VLOCLK_FREQ / MSP430X_SMCLK_DIV)
+#elif (MSP430X_SMCLK_SRC == MSP430X_LFMODCLK)
+ #define MSP430X_SMCLK_FREQ (MSP430X_LFMODCLK_FREQ / MSP430X_SMCLK_DIV)
+#elif (MSP430X_SMCLK_SRC == MSP430X_DCOCLK)
+ #define MSP430X_SMCLK_FREQ (MSP430X_DCOCLK_FREQ / MSP430X_SMCLK_DIV)
+#elif (MSP430X_SMCLK_SRC == MSP430X_MODCLK)
+ #define MSP430X_SMCLK_FREQ (MSP430X_MODCLK_FREQ / MSP430X_SMCLK_DIV)
+#elif (MSP430X_SMCLK_SRC == MSP430X_HFXTCLK)
+ #define MSP430X_SMCLK_FREQ (MSP430X_HFXTCLK_FREQ / MSP430X_SMCLK_DIV)
+#else
+ #error "SMCLK source invalid!"
+#endif
+
+#if !defined(MSP430X_MCUCONF)
+#error "Using an incorrect mcuconf.h file, MSP430X_MCUCONF not defined"
+#endif
+
+/* HFXT-specific settings */
+#if MSP430X_HFXTCLK_FREQ <= 4000000
+ #define MSP430X_HFFREQ HFFREQ_0
+#elif MSP430X_HFXTCLK_FREQ <= 8000000
+ #define MSP430X_HFFREQ HFFREQ_1
+#elif MSP430X_HFXTCLK_FREQ <= 16000000
+ #define MSP430X_HFFREQ HFFREQ_2
+#elif MSP430X_HFXTCLK_FREQ <= 24000000
+ #define MSP430X_HFFREQ HFFREQ_3
+#else
+ #error "HFXT frequency too high - must be <= 24000000"
+#endif
+
+/* DCO-specific settings */
+#if MSP430X_DCOCLK_FREQ == 1000000
+ #define MSP430X_DCOSEL DCOFSEL_0
+#elif MSP430X_DCOCLK_FREQ == 2670000
+ #define MSP430X_DCOSEL DCOFSEL_1
+#elif MSP430X_DCOCLK_FREQ == 3330000
+ #define MSP430X_DCOSEL DCOFSEL_2
+#elif MSP430X_DCOCLK_FREQ == 4000000
+ #define MSP430X_DCOSEL DCOFSEL_3
+#elif MSP430X_DCOCLK_FREQ == 5330000
+ #define MSP430X_DCOSEL DCOFSEL_4
+#elif MSP430X_DCOCLK_FREQ == 6670000
+ #define MSP430X_DCOSEL DCOFSEL_5
+#elif MSP430X_DCOCLK_FREQ == 8000000
+ #define MSP430X_DCOSEL DCOFSEL_6
+#elif MSP430X_DCOCLK_FREQ == 16000000
+ #define MSP430X_DCOSEL (DCORSEL | DCOFSEL_4)
+#elif MSP430X_DCOCLK_FREQ == 21000000
+ #define MSP430X_DCOSEL (DCORSEL | DCOFSEL_5)
+#elif MSP430X_DCOCLK_FREQ == 24000000
+ #define MSP430X_DCOSEL (DCORSEL | DCOFSEL_6)
+#else
+ #error "DCO frequency invalid"
+#endif
+
+#if MSP430X_LFXTCLK_FREQ > 50000
+ #error "LFXT frequency too high - must be <= 5000"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+#define DIVIDER(x) DIV_HELPER(x)
+#define DIV_HELPER(x) DIVM__ ## x
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void hal_lld_init(void);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _HAL_LLD_H_ */
+
+/** @} */
diff --git a/os/hal/ports/MSP430X/hal_pal_lld.c b/os/hal/ports/MSP430X/hal_pal_lld.c
new file mode 100644
index 0000000..4cfff3b
--- /dev/null
+++ b/os/hal/ports/MSP430X/hal_pal_lld.c
@@ -0,0 +1,215 @@
+/*
+ ChibiOS - Copyright (C) 2016 Andrew Wygle aka awygle
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file MSP430X/hal_pal_lld.c
+ * @brief MSP430X PAL subsystem low level driver source.
+ *
+ * @addtogroup PAL
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_PAL == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief MSP430X I/O ports configuration.
+ * @details GPIO registers initialization
+ *
+ * @param[in] config the MSP430X ports configuration
+ *
+ * @notapi
+ */
+void _pal_lld_init(const PALConfig *config) {
+
+#if defined(PA_BASE) || defined(__DOXYGEN__)
+ PAOUT = config->porta.out;
+ PADIR = config->porta.dir;
+ PAREN = config->porta.ren;
+ PASEL0 = config->porta.sel0;
+ PASEL1 = config->porta.sel1;
+ PAIES = config->porta.ies;
+ PAIE = config->porta.ie;
+#endif
+#if defined(PB_BASE) || defined(__DOXYGEN__)
+ PBOUT = config->portb.out;
+ PBDIR = config->portb.dir;
+ PBREN = config->portb.ren;
+ PBSEL0 = config->portb.sel0;
+ PBSEL1 = config->portb.sel1;
+ PBIES = config->portb.ies;
+ PBIE = config->portb.ie;
+#endif
+#if defined(PC_BASE) || defined(__DOXYGEN__)
+ PCOUT = config->portc.out;
+ PCDIR = config->portc.dir;
+ PCREN = config->portc.ren;
+ PCSEL0 = config->portc.sel0;
+ PCSEL1 = config->portc.sel1;
+ PCIES = config->portc.ies;
+ PCIE = config->portc.ie;
+#endif
+#if defined(PD_BASE) || defined(__DOXYGEN__)
+ PDOUT = config->portd.out;
+ PDDIR = config->portd.dir;
+ PDREN = config->portd.ren;
+ PDSEL0 = config->portd.sel0;
+ PDSEL1 = config->portd.sel1;
+ PDIES = config->portd.ies;
+ PDIE = config->portd.ie;
+#endif
+#if defined(PE_BASE) || defined(__DOXYGEN__)
+ PEOUT = config->porte.out;
+ PEDIR = config->porte.dir;
+ PEREN = config->porte.ren;
+ PESEL0 = config->porte.sel0;
+ PESEL1 = config->porte.sel1;
+ PEIES = config->porte.ies;
+ PEIE = config->porte.ie;
+#endif
+#if defined(PF_BASE) || defined(__DOXYGEN__)
+ PFOUT = config->portf.out;
+ PFDIR = config->portf.dir;
+ PFREN = config->portf.ren;
+ PFSEL0 = config->portf.sel0;
+ PFSEL1 = config->portf.sel1;
+ PFIES = config->portf.ies;
+ PFIE = config->portf.ie;
+#endif
+ PJOUT = config->portj.out;
+ PJDIR = config->portj.dir;
+ PJREN = config->portj.ren;
+ PJSEL0 = config->portj.sel0;
+ PJSEL1 = config->portj.sel1;
+
+ PM5CTL0 &= ~LOCKLPM5;
+}
+
+/**
+ * @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 input with pullup.
+ *
+ * @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->dir &= ~mask;
+ port->ren &= ~mask;
+ if ((port->sel0 & mask) && (port->sel1 & mask))
+ port->selc = mask;
+ else {
+ port->sel0 &= ~mask;
+ port->sel1 &= ~mask;
+ }
+ break;
+ case PAL_MODE_UNCONNECTED:
+ case PAL_MODE_INPUT_PULLUP:
+ port->dir &= ~mask;
+ port->ren |= mask;
+ port->out |= mask;
+ if ((port->sel0 & mask) && (port->sel1 & mask))
+ port->selc = mask;
+ else {
+ port->sel0 &= ~mask;
+ port->sel1 &= ~mask;
+ }
+ break;
+ case PAL_MODE_INPUT_PULLDOWN:
+ port->dir &= ~mask;
+ port->ren |= mask;
+ port->out &= ~mask;
+ if ((port->sel0 & mask) && (port->sel1 & mask))
+ port->selc = mask;
+ else {
+ port->sel0 &= ~mask;
+ port->sel1 &= ~mask;
+ }
+ break;
+ case PAL_MODE_OUTPUT_PUSHPULL:
+ port->dir |= mask;
+ if ((port->sel0 & mask) && (port->sel1 & mask))
+ port->selc = mask;
+ else {
+ port->sel0 &= ~mask;
+ port->sel1 &= ~mask;
+ }
+ break;
+ case PAL_MSP430X_ALTERNATE_1:
+ if (!(port->sel0 & mask) && (port->sel1 & mask))
+ port->selc = mask;
+ else {
+ port->sel0 |= mask;
+ port->sel1 &= ~mask;
+ }
+ break;
+ case PAL_MSP430X_ALTERNATE_2:
+ if ((port->sel0 & mask) && !(port->sel1 & mask))
+ port->selc = mask;
+ else {
+ port->sel0 &= ~mask;
+ port->sel1 |= mask;
+ }
+ break;
+ case PAL_MSP430X_ALTERNATE_3:
+ if (!(port->sel0 & mask) && !(port->sel1 & mask))
+ port->selc = mask;
+ else {
+ port->sel0 |= mask;
+ port->sel1 |= mask;
+ }
+ break;
+ }
+}
+
+#endif /* HAL_USE_PAL == TRUE */
+
+/** @} */
diff --git a/os/hal/ports/MSP430X/hal_pal_lld.h b/os/hal/ports/MSP430X/hal_pal_lld.h
new file mode 100644
index 0000000..8789ed1
--- /dev/null
+++ b/os/hal/ports/MSP430X/hal_pal_lld.h
@@ -0,0 +1,390 @@
+/*
+ ChibiOS - Copyright (C) 2016 Andrew Wygle aka awygle
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file MSP430X/hal_pal_lld.h
+ * @brief MSP430X PAL subsystem low level driver header.
+ *
+ * @addtogroup PAL
+ * @{
+ */
+
+#ifndef HAL_PAL_LLD_H
+#define HAL_PAL_LLD_H
+
+#if (HAL_USE_PAL == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Unsupported modes and specific modes */
+/*===========================================================================*/
+
+#undef PAL_MODE_INPUT_ANALOG /* configure this through the ALTERNATE macros */
+#undef PAL_MODE_OUTPUT_OPENDRAIN
+
+/**
+ * @name MSP430X-specific I/O mode flags
+ * @{
+ */
+
+/**
+ * @brief Alternate mode 1
+ */
+#define PAL_MSP430X_ALTERNATE_1 8
+
+/**
+ * @brief Alternate mode 2
+ */
+#define PAL_MSP430X_ALTERNATE_2 9
+
+/**
+ * @brief Alternate mode 3
+ */
+#define PAL_MSP430X_ALTERNATE_3 10
+
+#define ALTERNATE_HELP(n) (PAL_MSP430X_ALTERNATE_ ## n)
+/**
+ * @brief Alternate function.
+ *
+ * @param[in] n alternate function selector - 1 through 3
+ */
+#define PAL_MODE_ALTERNATE(n) (ALTERNATE_HELP(n))
+
+/** @} */
+
+/*===========================================================================*/
+/* I/O Ports Types and constants. */
+/*===========================================================================*/
+
+/**
+ * @name Port related definitions
+ * @{
+ */
+/**
+ * @brief Width, in bits, of an I/O port.
+ */
+#define PAL_IOPORTS_WIDTH 16U
+
+/**
+ * @brief Whole port mask.
+ * @details This macro specifies all the valid bits into a port.
+ */
+#define PAL_WHOLE_PORT ((ioportmask_t)0xFFFFU)
+
+/** @} */
+
+
+/**
+ * @name Line handling macros
+ * @{
+ */
+/**
+ * @brief Forms a line identifier.
+ * @details A port/pad pair are encoded into an @p ioline_t type. The encoding
+ * of this type is platform-dependent.
+ * @note In this driver the pad number is encoded in the upper 4 bits of
+ * the GPIO address which are guaranteed to be zero.
+ */
+#define PAL_LINE(port, pad) \
+ ((ioline_t)((uint16_t)(port)) | (((uint16_t)(pad)) << 12))
+
+/**
+ * @brief Decodes a port identifier from a line identifier.
+ */
+#define PAL_PORT(line) \
+ ((msp430x_gpio_registers_t *)(((uint16_t)(line)) & 0x0FFFU))
+
+/**
+ * @brief Decodes a pad identifier from a line identifier.
+ */
+#define PAL_PAD(line) \
+ ((uint16_t)((uint16_t)(line) >> 12))
+
+/**
+ * @brief Value identifying an invalid line.
+ */
+#define PAL_NOLINE 0U
+/** @} */
+
+/**
+ * @brief MSP430X register initialization
+ */
+typedef struct {
+ /** Initial value for OUT register.*/
+ uint16_t out;
+ /** Initial value for DIR register.*/
+ uint16_t dir;
+ /** Initial value for REN register.*/
+ uint16_t ren;
+ /** Initial value for SEL0 register.*/
+ uint16_t sel0;
+ /** Initial value for SEL1 register.*/
+ uint16_t sel1;
+ /** Initial value for IES register.*/
+ uint16_t ies;
+ /** Initial value for IE register.*/
+ uint16_t ie;
+} msp430x_gpio_setup_t;
+
+/**
+ * @brief MSP430X registers block
+ * @note Some ports do not support all of these fields.
+ */
+typedef struct {
+ volatile uint16_t in;
+ volatile uint16_t out;
+ volatile uint16_t dir;
+ volatile uint16_t _padding;
+ volatile uint16_t ren;
+ volatile uint16_t sel0;
+ volatile uint16_t sel1;
+ volatile uint16_t _padding1;
+ volatile uint16_t _padding2;
+ volatile uint16_t _padding3;
+ volatile uint16_t _padding4;
+ volatile uint16_t selc;
+ volatile uint16_t ies;
+ volatile uint16_t ie;
+ volatile uint16_t ifg;
+} msp430x_gpio_registers_t;
+
+/**
+ * @brief MSP430X I/O ports static initializer.
+ * @details An instance of this structure must be passed to @p palInit() at
+ * system startup time in order to initialized 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(PA_BASE) || defined(__DOXYGEN__)
+ msp430x_gpio_setup_t porta;
+#endif
+#if defined(PB_BASE) || defined(__DOXYGEN__)
+ msp430x_gpio_setup_t portb;
+#endif
+#if defined(PC_BASE) || defined(__DOXYGEN__)
+ msp430x_gpio_setup_t portc;
+#endif
+#if defined(PD_BASE) || defined(__DOXYGEN__)
+ msp430x_gpio_setup_t portd;
+#endif
+#if defined(PE_BASE) || defined(__DOXYGEN__)
+ msp430x_gpio_setup_t porte;
+#endif
+#if defined(PF_BASE) || defined(__DOXYGEN__)
+ msp430x_gpio_setup_t portf;
+#endif
+ msp430x_gpio_setup_t portj;
+} PALConfig;
+
+/**
+ * @brief Digital I/O port sized unsigned type.
+ */
+typedef uint16_t ioportmask_t;
+
+/**
+ * @brief Digital I/O modes.
+ */
+typedef uint16_t iomode_t;
+
+/**
+ * @brief Type of an I/O line.
+ */
+typedef uint16_t ioline_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 msp430x_gpio_registers_t * ioportid_t;
+
+/*===========================================================================*/
+/* I/O Ports Identifiers. */
+/*===========================================================================*/
+
+/**
+ * @brief GPIO port A identifier.
+ */
+#if defined(PA_BASE) || defined(__DOXYGEN__)
+#define IOPORT1 ((volatile msp430x_gpio_registers_t *)PA_BASE)
+#endif
+
+/**
+ * @brief GPIO port B identifier.
+ */
+#if defined(PB_BASE) || defined(__DOXYGEN__)
+#define IOPORT2 ((volatile msp430x_gpio_registers_t *)PB_BASE)
+#endif
+
+/**
+ * @brief GPIO port C identifier.
+ */
+#if defined(PC_BASE) || defined(__DOXYGEN__)
+#define IOPORT3 ((volatile msp430x_gpio_registers_t *)PC_BASE)
+#endif
+
+/**
+ * @brief GPIO port D identifier.
+ */
+#if defined(PD_BASE) || defined(__DOXYGEN__)
+#define IOPORT4 ((volatile msp430x_gpio_registers_t *)PD_BASE)
+#endif
+
+/**
+ * @brief GPIO port E identifier.
+ */
+#if defined(PE_BASE) || defined(__DOXYGEN__)
+#define IOPORT5 ((volatile msp430x_gpio_registers_t *)PE_BASE)
+#endif
+
+/**
+ * @brief GPIO port F identifier.
+ */
+#if defined(PF_BASE) || defined(__DOXYGEN__)
+#define IOPORT6 ((volatile msp430x_gpio_registers_t *)PF_BASE
+#endif
+
+/**
+ * @brief GPIO port J identifier.
+ */
+#define IOPORT0 ((volatile msp430x_gpio_registers_t *)PJ_BASE)
+
+/*===========================================================================*/
+/* 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.
+ *
+ * @param[in] config architecture-dependent ports configuration
+ *
+ * @notapi
+ */
+#define pal_lld_init(config) _pal_lld_init(config)
+
+/**
+ * @brief Reads the physical I/O port states.
+ *
+ * @param[in] port port identifier
+ * @return The port bits.
+ *
+ * @notapi
+ */
+#define pal_lld_readport(port) ((port)->in)
+
+/**
+ * @brief Reads the output latch.
+ * @details The purpose of this function is to read back the latched output
+ * value.
+ *
+ * @param[in] port port identifier
+ * @return The latched logical states.
+ *
+ * @notapi
+ */
+#define pal_lld_readlatch(port) ((port)->out)
+
+/**
+ * @brief Writes a bits mask on a I/O port.
+ *
+ * @param[in] port port identifier
+ * @param[in] bits bits to be written on the specified port
+ *
+ * @notapi
+ */
+#define pal_lld_writeport(port, bits) ((port)->out = (bits))
+
+
+/**
+ * @brief Sets a bits mask on a I/O port.
+ *
+ * @param[in] port port identifier
+ * @param[in] bits bits to be ORed on the specified port
+ *
+ * @notapi
+ */
+#define pal_lld_setport(port, bits) ((port)->out |= (bits))
+
+/**
+ * @brief Clears a bits mask on a I/O port.
+ *
+ * @param[in] port port identifier
+ * @param[in] bits bits to be cleared on the specified port
+ *
+ * @notapi
+ */
+#define pal_lld_clearport(port, bits) ((port)->out &= ~(bits))
+
+/**
+ * @brief Toggles a bits mask on a I/O port.
+ *
+ * @param[in] port port identifier
+ * @param[in] bits bits to be XORed on the specified port
+ *
+ * @notapi
+ */
+#define pal_lld_toggleport(port, bits) ((port)->out ^= (bits))
+
+/**
+ * @brief Pads group mode setup.
+ * @details This function programs a pads group belonging to the same port
+ * with the specified mode.
+ * @note Programming an unknown or unsupported mode is silently ignored.
+ *
+ * @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)
+
+/**
+ * @brief Clears a pad logical state to @p PAL_LOW.
+ * @details This function is implemented in a way which should
+ * produce a BIC instruction rather than an AND
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ *
+ * @notapi
+ */
+#define pal_lld_clearpad(port, pad) ((port)->out &= ~(BIT ## pad))
+
+#if !defined(__DOXYGEN__)
+extern const PALConfig pal_default_config;
+#endif
+
+#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 /* HAL_USE_PAL == TRUE */
+
+#endif /* _PAL_LLD_H_ */
+
+/** @} */
diff --git a/os/hal/ports/MSP430X/hal_serial_lld.c b/os/hal/ports/MSP430X/hal_serial_lld.c
new file mode 100644
index 0000000..277f6d2
--- /dev/null
+++ b/os/hal/ports/MSP430X/hal_serial_lld.c
@@ -0,0 +1,657 @@
+/*
+ ChibiOS - Copyright (C) 2016 Andrew Wygle aka awygle
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file MSP430X/hal_serial_lld.c
+ * @brief MSP430X serial subsystem low level driver source.
+ *
+ * @addtogroup SERIAL
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_SERIAL == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief USART0 serial driver identifier.*/
+#if (MSP430X_SERIAL_USE_USART0 == TRUE) || defined(__DOXYGEN__)
+#ifndef __MSP430_HAS_EUSCI_A0__
+ #error "Cannot find USCI module to use for SD0"
+#endif
+SerialDriver SD0;
+#endif
+
+/** @brief USART1 serial driver identifier.*/
+#if (MSP430X_SERIAL_USE_USART1 == TRUE) || defined(__DOXYGEN__)
+#ifndef __MSP430_HAS_EUSCI_A1__
+ #error "Cannot find USCI module to use for SD1"
+#endif
+SerialDriver SD1;
+#endif
+
+/** @brief USART2 serial driver identifier.*/
+#if (MSP430X_SERIAL_USE_USART2 == TRUE) || defined(__DOXYGEN__)
+#ifndef __MSP430_HAS_EUSCI_A2__
+ #error "Cannot find USCI module to use for SD2"
+#endif
+SerialDriver SD2;
+#endif
+
+/** @brief USART3 serial driver identifier.*/
+#if (MSP430X_SERIAL_USE_USART3 == TRUE) || defined(__DOXYGEN__)
+#ifndef __MSP430_HAS_EUSCI_A3__
+ #error "Cannot find USCI module to use for SD3"
+#endif
+SerialDriver SD3;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Driver default configuration.
+ */
+static const SerialConfig default_config = {
+ SERIAL_DEFAULT_BITRATE
+};
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief UCBRS calculation.
+ * @details This function calculates the UCBRS value for oversampled baud
+ * rates.
+ *
+ * @param[in] frac Fractional part of baud rate division, times 10000.
+ */
+static uint8_t UCBRS(uint16_t frac) {
+ /* TODO there must be a better way */
+ if (frac < 529)
+ return 0x00;
+ else if (frac < 715)
+ return 0x01;
+ else if (frac < 835)
+ return 0x02;
+ else if (frac < 1001)
+ return 0x04;
+ else if (frac < 1252)
+ return 0x08;
+ else if (frac < 1430)
+ return 0x10;
+ else if (frac < 1670)
+ return 0x20;
+ else if (frac < 2147)
+ return 0x11;
+ else if (frac < 2224)
+ return 0x21;
+ else if (frac < 2503)
+ return 0x22;
+ else if (frac < 3000)
+ return 0x44;
+ else if (frac < 3335)
+ return 0x25;
+ else if (frac < 3575)
+ return 0x49;
+ else if (frac < 3753)
+ return 0x4A;
+ else if (frac < 4003)
+ return 0x52;
+ else if (frac < 4286)
+ return 0x92;
+ else if (frac < 4378)
+ return 0x53;
+ else if (frac < 5002)
+ return 0x55;
+ else if (frac < 5715)
+ return 0xAA;
+ else if (frac < 6003)
+ return 0x6B;
+ else if (frac < 6254)
+ return 0xAD;
+ else if (frac < 6432)
+ return 0xB5;
+ else if (frac < 6667)
+ return 0xB6;
+ else if (frac < 7001)
+ return 0xD6;
+ else if (frac < 7147)
+ return 0xB7;
+ else if (frac < 7503)
+ return 0xBB;
+ else if (frac < 7861)
+ return 0xDD;
+ else if (frac < 8004)
+ return 0xED;
+ else if (frac < 8333)
+ return 0xEE;
+ else if (frac < 8464)
+ return 0xBF;
+ else if (frac < 8572)
+ return 0xDF;
+ else if (frac < 8751)
+ return 0xEF;
+ else if (frac < 9004)
+ return 0xF7;
+ else if (frac < 9170)
+ return 0xFB;
+ else if (frac < 9288)
+ return 0xFD;
+ else
+ return 0xFE;
+}
+
+/**
+ * @brief Modulation control word calculator.
+ * @details This function calculates the modulation control word from the
+ * input clock frequency and the requested baud rate.
+ *
+ * @param[in] baud Requested baud rate
+ * @param[in] freq Frequency of the clock driving the USCI module
+ */
+static uint16_t UCAxMCTLW(uint32_t baud, uint32_t freq) {
+
+ uint16_t n = freq/baud;
+ /*uint16_t frac = (freq * 10000 / baud) - ((freq / baud) * 10000);*/
+ uint16_t frac = (freq - (n * baud)) * 10000 / baud;
+ if (n > 16) {
+ while (n > 16) {
+ n -= 16;
+ }
+ return (UCBRS(frac) << 8) | (n << 4) | UCOS16;
+ }
+ return UCBRS(frac) << 8;
+}
+
+/**
+ * @brief UCBRW calculation.
+ * @details This function calculates the UCBRW value for all baud
+ * rates.
+ *
+ * @param[in] baud Requested baud rate
+ * @param[in] freq Frequency of the clock driving the USCI module
+ */
+static uint16_t UCAxBRW(uint32_t baud, uint32_t freq) {
+ uint16_t n = freq/baud;
+ if (n > 16) {
+ return n >> 4;
+ }
+ return n;
+}
+
+#if (MSP430X_SERIAL_USE_USART0 == TRUE) || defined(__DOXYGEN__)
+static void usart0_init(const SerialConfig *config) {
+ UCA0BRW = UCAxBRW(config->sc_bitrate, MSP430X_USART0_CLK_FREQ);
+ UCA0MCTLW = UCAxMCTLW(config->sc_bitrate, MSP430X_USART0_CLK_FREQ);
+ UCA0STATW = 0;
+ UCA0ABCTL = 0;
+ UCA0IRCTL = 0;
+ UCA0CTLW0 = (MSP430X_USART0_PARITY << 14) | (MSP430X_USART0_ORDER << 13) | \
+ (MSP430X_USART0_SIZE << 12) | (MSP430X_USART0_STOP << 11) | \
+ (MSP430X_USART0_UCSSEL);
+ UCA0IE = UCRXIE;
+}
+#endif
+
+#if (MSP430X_SERIAL_USE_USART1 == TRUE) || defined(__DOXYGEN__)
+static void usart1_init(const SerialConfig *config) {
+ UCA1BRW = UCAxBRW(config->sc_bitrate, MSP430X_USART1_CLK_FREQ);
+ UCA1MCTLW = UCAxMCTLW(config->sc_bitrate, MSP430X_USART1_CLK_FREQ);
+ UCA1STATW = 0;
+ UCA1ABCTL = 0;
+ UCA1IRCTL = 0;
+ UCA1IE = UCRXIE;
+ UCA1CTLW0 = (MSP430X_USART1_PARITY << 14) | (MSP430X_USART1_ORDER << 13) | \
+ (MSP430X_USART1_SIZE << 12) | (MSP430X_USART1_STOP << 11) | \
+ (MSP430X_USART1_UCSSEL);
+}
+#endif
+
+#if (MSP430X_SERIAL_USE_USART2 == TRUE) || defined(__DOXYGEN__)
+static void usart2_init(const SerialConfig *config) {
+ UCA2BRW = UCAxBRW(config->sc_bitrate, MSP430X_USART2_CLK_FREQ);
+ UCA2MCTLW = UCAxMCTLW(config->sc_bitrate);
+ UCA2STATW = 0;
+ UCA2ABCTL = 0;
+ UCA2IRCTL = 0;
+ UCA2IE = UCRXIE;
+ UCA2CTLW0 = (MSP430X_USART2_PARITY << 14) | (MSP430X_USART2_ORDER << 13) | \
+ (MSP430X_USART2_SIZE << 12) | (MSP430X_USART2_STOP << 11) | \
+ (MSP430X_USART2_UCSSEL);
+}
+#endif
+
+#if (MSP430X_SERIAL_USE_USART3 == TRUE) || defined(__DOXYGEN__)
+static void usart3_init(const SerialConfig *config) {
+ UCA3BRW = UCAxBRW(config->sc_bitrate, MSP430X_USART3_CLK_FREQ);
+ UCA3MCTLW = UCAxMCTLW(config->sc_bitrate, MSP430X_USART3_CLK_FREQ);
+ UCA3STATW = 0;
+ UCA3ABCTL = 0;
+ UCA3IRCTL = 0;
+ UCA3IE = UCRXIE;
+ UCA3CTLW0 = (MSP430X_USART3_PARITY << 14) | (MSP430X_USART3_ORDER << 13) | \
+ (MSP430X_USART3_SIZE << 12) | (MSP430X_USART3_STOP << 11) | \
+ (MSP430X_USART3_UCSSEL);
+}
+#endif
+
+#if (MSP430X_SERIAL_USE_USART0 == TRUE) || defined(__DOXYGEN__)
+static void notify0(io_queue_t *qp) {
+
+ (void)qp;
+ UCA0IE |= UCTXIE;
+}
+#endif
+
+#if (MSP430X_SERIAL_USE_USART1 == TRUE) || defined(__DOXYGEN__)
+static void notify1(io_queue_t *qp) {
+
+ (void)qp;
+ UCA1IE |= UCTXIE;
+}
+#endif
+
+#if (MSP430X_SERIAL_USE_USART2 == TRUE) || defined(__DOXYGEN__)
+static void notify2(io_queue_t *qp) {
+
+ (void)qp;
+ UCA2IE |= UCTXIE;
+}
+#endif
+
+#if (MSP430X_SERIAL_USE_USART3 == TRUE) || defined(__DOXYGEN__)
+static void notify3(io_queue_t *qp) {
+
+ (void)qp;
+ UCA3IE |= UCTXIE;
+}
+#endif
+
+/**
+ * @brief Error handling routine.
+ *
+ * @param[in] sra USCI status register containing errors
+ * @param[in] sdp pointer to a @p SerialDriver object
+ */
+static void set_error(uint16_t sra, SerialDriver *sdp) {
+ eventflags_t sts = 0;
+
+ if (sra & UCOE)
+ sts |= SD_OVERRUN_ERROR;
+ if (sra & UCPE)
+ sts |= SD_PARITY_ERROR;
+ if (sra & UCFE)
+ sts |= SD_FRAMING_ERROR;
+ osalSysLockFromISR();
+ chnAddFlagsI(sdp, sts);
+ osalSysUnlockFromISR();
+}
+
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if MSP430X_SERIAL_USE_USART0 || defined(__DOXYGEN__)
+/**
+ * @brief USART0 interrupt handler.
+ *
+ * @isr
+ */
+PORT_IRQ_HANDLER(USCI_A0_VECTOR) {
+ msg_t b;
+
+ OSAL_IRQ_PROLOGUE();
+
+ switch (__even_in_range(UCA0IV,USCI_UART_UCTXCPTIFG)) {
+ case USCI_UART_UCRXIFG: /* RX interrupt */
+
+ /* Detect errors */
+ if (UCA0STATW & UCRXERR)
+ set_error(UCA0STATW, &SD0);
+
+ /* Data available */
+ osalSysLockFromISR();
+ sdIncomingDataI(&SD0, UCA0RXBUF);
+ osalSysUnlockFromISR();
+ break;
+
+ case USCI_UART_UCTXIFG: /* TX interrupt */
+
+ /* Transmission buffer empty */
+ osalSysLockFromISR();
+ b = sdRequestDataI(&SD0);
+ if (b < Q_OK) {
+ chnAddFlagsI(&SD0, CHN_OUTPUT_EMPTY);
+ UCA0IE = (UCA0IE & ~UCTXIE) | UCTXCPTIE;
+ UCA0IFG |= UCTXIFG; /* If we don't write to TXBUF, IFG won't get set */
+ }
+ else
+ UCA0TXBUF = b;
+ osalSysUnlockFromISR();
+ break;
+
+ case USCI_UART_UCTXCPTIFG: /* TX complete interrupt */
+
+ /* Physical transmission end */
+ osalSysLockFromISR();
+ if (oqIsEmptyI(&SD0.oqueue))
+ chnAddFlagsI(&SD0, CHN_TRANSMISSION_END);
+ UCA0IE &= ~UCTXCPTIE;
+ break;
+
+ default: /* other interrupts */
+ while (1);
+ break;
+ }
+
+ OSAL_IRQ_EPILOGUE();
+
+}
+#endif
+
+#if MSP430X_SERIAL_USE_USART1 || defined(__DOXYGEN__)
+/**
+ * @brief USART1 interrupt handler.
+ *
+ * @isr
+ */
+PORT_IRQ_HANDLER(USCI_A1_VECTOR) {
+ msg_t b;
+
+ OSAL_IRQ_PROLOGUE();
+
+ switch (__even_in_range(UCA1IV,USCI_UART_UCTXCPTIFG)) {
+ case USCI_UART_UCRXIFG: /* RX interrupt */
+
+ /* Detect errors */
+ if (UCA1STATW & UCRXERR)
+ set_error(UCA1STATW, &SD1);
+
+ /* Data available */
+ osalSysLockFromISR();
+ sdIncomingDataI(&SD1, UCA1RXBUF);
+ osalSysUnlockFromISR();
+ break;
+
+ case USCI_UART_UCTXIFG: /* TX interrupt */
+
+ /* Transmission buffer empty */
+ osalSysLockFromISR();
+ b = sdRequestDataI(&SD1);
+ if (b < Q_OK) {
+ chnAddFlagsI(&SD1, CHN_OUTPUT_EMPTY);
+ UCA1IE = (UCA1IE & ~UCTXIE) | UCTXCPTIE;
+ UCA1IFG |= UCTXIFG; /* If we don't write to TXBUF, IFG won't get set */
+ }
+ else
+ UCA1TXBUF = b;
+ osalSysUnlockFromISR();
+ break;
+
+ case USCI_UART_UCTXCPTIFG: /* TX complete interrupt */
+
+ /* Physical transmission end */
+ osalSysLockFromISR();
+ if (oqIsEmptyI(&SD1.oqueue))
+ chnAddFlagsI(&SD1, CHN_TRANSMISSION_END);
+ UCA1IE &= ~UCTXCPTIE;
+ break;
+
+ default: /* other interrupts */
+ while (1);
+ break;
+ }
+
+ OSAL_IRQ_EPILOGUE();
+
+}
+#endif
+
+#if MSP430X_SERIAL_USE_USART2 || defined(__DOXYGEN__)
+/**
+ * @brief USART2 interrupt handler.
+ *
+ * @isr
+ */
+PORT_IRQ_HANDLER(USCI_A2_VECTOR) {
+ msg_t b;
+
+ OSAL_IRQ_PROLOGUE();
+
+ switch (__even_in_range(UCA2IV,USCI_UART_UCTXCPTIFG)) {
+ case USCI_UART_UCRXIFG: /* RX interrupt */
+
+ /* Detect errors */
+ if (UCA2STATW & UCRXERR)
+ set_error(UCA2STATW, &SD2);
+
+ /* Data available */
+ osalSysLockFromISR();
+ sdIncomingDataI(&SD2, UCA2RXBUF);
+ osalSysUnlockFromISR();
+ break;
+
+ case USCI_UART_UCTXIFG: /* TX interrupt */
+
+ /* Transmission buffer empty */
+ osalSysLockFromISR();
+ b = sdRequestDataI(&SD2);
+ if (b < Q_OK) {
+ chnAddFlagsI(&SD2, CHN_OUTPUT_EMPTY);
+ UCA2IE = (UCA2IE & ~UCTXIE) | UCTXCPTIE;
+ UCA2IFG |= UCTXIFG; /* If we don't write to TXBUF, IFG won't get set */
+ }
+ else
+ UCA2TXBUF = b;
+ osalSysUnlockFromISR();
+ break;
+
+ case USCI_UART_UCTXCPTIFG: /* TX complete interrupt */
+
+ /* Physical transmission end */
+ osalSysLockFromISR();
+ if (oqIsEmptyI(&SD2.oqueue))
+ chnAddFlagsI(&SD2, CHN_TRANSMISSION_END);
+ UCA2IE &= ~UCTXCPTIE;
+ break;
+
+ default: /* other interrupts */
+ while (1);
+ break;
+ }
+
+ OSAL_IRQ_EPILOGUE();
+
+}
+#endif
+
+#if MSP430X_SERIAL_USE_USART3 || defined(__DOXYGEN__)
+/**
+ * @brief USART3 interrupt handler.
+ *
+ * @isr
+ */
+PORT_IRQ_HANDLER(USCI_A3_VECTOR) {
+ msg_t b;
+
+ OSAL_IRQ_PROLOGUE();
+
+ switch (__even_in_range(UCA3IV,USCI_UART_UCTXCPTIFG)) {
+ case USCI_UART_UCRXIFG: /* RX interrupt */
+
+ /* Detect errors */
+ if (UCA3STATW & UCRXERR)
+ set_error(UCA3STATW, &SD3);
+
+ /* Data available */
+ osalSysLockFromISR();
+ sdIncomingDataI(&SD3, UCA3RXBUF);
+ osalSysUnlockFromISR();
+ break;
+
+ case USCI_UART_UCTXIFG: /* TX interrupt */
+
+ /* Transmission buffer empty */
+ osalSysLockFromISR();
+ b = sdRequestDataI(&SD3);
+ if (b < Q_OK) {
+ chnAddFlagsI(&SD3, CHN_OUTPUT_EMPTY);
+ UCA3IE = (UCA3IE & ~UCTXIE) | UCTXCPTIE;
+ UCA3IFG |= UCTXIFG; /* If we don't write to TXBUF, IFG won't get set */
+ }
+ else
+ UCA3TXBUF = b;
+ osalSysUnlockFromISR();
+ break;
+
+ case USCI_UART_UCTXCPTIFG: /* TX complete interrupt */
+
+ /* Physical transmission end */
+ osalSysLockFromISR();
+ if (oqIsEmptyI(&SD3.oqueue))
+ chnAddFlagsI(&SD3, CHN_TRANSMISSION_END);
+ UCA3IE &= ~UCTXCPTIE;
+ break;
+
+ default: /* other interrupts */
+ while (1);
+ break;
+ }
+
+ OSAL_IRQ_EPILOGUE();
+
+}
+#endif
+
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level serial driver initialization.
+ *
+ * @notapi
+ */
+void sd_lld_init(void) {
+
+#if MSP430X_SERIAL_USE_USART0 == TRUE
+ sdObjectInit(&SD0, NULL, notify0);
+#endif
+
+#if MSP430X_SERIAL_USE_USART1 == TRUE
+ sdObjectInit(&SD1, NULL, notify1);
+#endif
+
+#if MSP430X_SERIAL_USE_USART2 == TRUE
+ sdObjectInit(&SD2, NULL, notify2);
+#endif
+
+#if MSP430X_SERIAL_USE_USART3 == TRUE
+ sdObjectInit(&SD3, NULL, notify3);
+#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 (sdp->state == SD_STOP) {
+#if MSP430X_SERIAL_USE_USART0 == TRUE
+ if (&SD0 == sdp) {
+ usart0_init(config);
+ }
+#endif
+#if MSP430X_SERIAL_USE_USART1 == TRUE
+ if (&SD1 == sdp) {
+ usart1_init(config);
+ }
+#endif
+#if MSP430X_SERIAL_USE_USART2 == TRUE
+ if (&SD2 == sdp) {
+ usart2_init(config);
+ }
+#endif
+#if MSP430X_SERIAL_USE_USART3 == TRUE
+ if (&SD3 == sdp) {
+ usart3_init(config);
+ }
+#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 (sdp->state == SD_READY) {
+#if MSP430X_SERIAL_USE_USART0 == TRUE
+ if (&SD0 == sdp) {
+ UCA0CTLW0 = UCSWRST;
+ }
+#endif
+#if MSP430X_SERIAL_USE_USART1 == TRUE
+ if (&SD1 == sdp) {
+ UCA1CTLW0 = UCSWRST;
+ }
+#endif
+#if MSP430X_SERIAL_USE_USART2 == TRUE
+ if (&SD2 == sdp) {
+ UCA2CTLW0 = UCSWRST;
+ }
+#endif
+#if MSP430X_SERIAL_USE_USART3 == TRUE
+ if (&SD3 == sdp) {
+ UCA3CTLW0 = UCSWRST;
+ }
+#endif
+ }
+}
+
+#endif /* HAL_USE_SERIAL == TRUE */
+
+/** @} */
diff --git a/os/hal/ports/MSP430X/hal_serial_lld.h b/os/hal/ports/MSP430X/hal_serial_lld.h
new file mode 100644
index 0000000..389e5c8
--- /dev/null
+++ b/os/hal/ports/MSP430X/hal_serial_lld.h
@@ -0,0 +1,320 @@
+/*
+ ChibiOS - Copyright (C) 2016 Andrew Wygle aka awygle
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file MSP430X/hal_serial_lld.h
+ * @brief MSP430X serial subsystem low level driver header.
+ *
+ * @addtogroup SERIAL
+ * @{
+ */
+
+#ifndef _SERIAL_LLD_H_
+#define _SERIAL_LLD_H_
+
+#if (HAL_USE_SERIAL == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+#define NONE 0
+#define ODD 2
+#define EVEN 3
+
+#define MSB 1
+#define LSB 0
+
+#define SEVEN 1
+#define EIGHT 0
+
+#define ONE 0
+#define TWO 1
+
+#define MSP430X_SERIAL_SMCLK UCSSEL__SMCLK
+#define MSP430X_SERIAL_UCLK UCSSEL__UCLK
+#define MSP430X_SERIAL_ACLK UCSSEL__ACLK
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name USART0 configuration options
+ * @{
+ */
+/**
+ * @brief USART0 driver enable switch.
+ * @details If set to @p TRUE the support for USART1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(MSP430X_SERIAL_USE_USART0) || defined(__DOXYGEN__)
+#define MSP430X_SERIAL_USE_USART0 FALSE
+#endif
+/** @} */
+
+/**
+ * @name USART1 configuration options
+ * @{
+ */
+/**
+ * @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(MSP430X_SERIAL_USE_USART1) || defined(__DOXYGEN__)
+#define MSP430X_SERIAL_USE_USART1 FALSE
+#endif
+/** @} */
+
+/**
+ * @name USART2 configuration options
+ * @{
+ */
+/**
+ * @brief USART2 driver enable switch.
+ * @details If set to @p TRUE the support for USART1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(MSP430X_SERIAL_USE_USART2) || defined(__DOXYGEN__)
+#define MSP430X_SERIAL_USE_USART2 FALSE
+#endif
+/** @} */
+
+/**
+ * @name USART3 configuration options
+ * @{
+ */
+/**
+ * @brief USART3 driver enable switch.
+ * @details If set to @p TRUE the support for USART1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(MSP430X_SERIAL_USE_USART3) || defined(__DOXYGEN__)
+#define MSP430X_SERIAL_USE_USART3 FALSE
+#endif
+
+#if MSP430X_SERIAL_USE_USART0
+ #if !defined(MSP430X_USART0_PARITY)
+ #define MSP430X_USART0_PARITY NONE
+ #endif
+ #if !defined(MSP430X_USART0_ORDER)
+ #define MSP430X_USART0_ORDER LSB
+ #endif
+ #if !defined(MSP430X_USART0_SIZE)
+ #define MSP430X_USART0_SIZE EIGHT
+ #endif
+ #if !defined(MSP430X_USART0_STOP)
+ #define MSP430X_USART0_STOP ONE
+ #endif
+ #if !defined(MSP430X_USART0_CLK_SRC)
+ #define MSP430X_USART0_CLK_SRC MSP430X_UCLK_SRC
+ #ifndef MSP430X_USART0_CLK_FREQ
+ #error "Requested external UART0 clock but no frequency given"
+ #endif
+ #define MSP430X_USART0_UCSSEL UCSSEL__UCLK
+ #elif MSP430X_USART0_CLK_SRC == MSP430X_ACLK_SRC
+ #define MSP430X_USART0_CLK_SRC MSP430X_ACLK_SRC
+ #define MSP430X_USART0_CLK_FREQ MSP430X_ACLK_FREQ
+ #define MSP430X_USART0_UCSSEL UCSSEL__ACLK
+ #elif MSP430X_USART0_CLK_SRC == MSP430X_SMCLK_SRC
+ #define MSP430X_USART0_CLK_SRC MSP430X_SMCLK_SRC
+ #define MSP430X_USART0_CLK_FREQ MSP430X_SMCLK_FREQ
+ #define MSP430X_USART0_UCSSEL UCSSEL__SMCLK
+ #else
+ #error "MSP430X_USART0_CLK_SRC invalid"
+ #endif
+#endif
+
+#if MSP430X_SERIAL_USE_USART1
+ #if !defined(MSP430X_USART1_PARITY)
+ #define MSP430X_USART1_PARITY NONE
+ #endif
+ #if !defined(MSP430X_USART1_ORDER)
+ #define MSP430X_USART1_ORDER LSB
+ #endif
+ #if !defined(MSP430X_USART1_SIZE)
+ #define MSP430X_USART1_SIZE EIGHT
+ #endif
+ #if !defined(MSP430X_USART1_STOP)
+ #define MSP430X_USART1_STOP ONE
+ #endif
+ #if !defined(MSP430X_USART1_CLK_SRC)
+ #define MSP430X_USART1_CLK_SRC MSP430X_UCLK_SRC
+ #ifndef MSP430X_USART1_CLK_FREQ
+ #error "Requested external UART0 clock but no frequency given"
+ #endif
+ #define MSP430X_USART1_UCSSEL UCSSEL__UCLK
+ #elif MSP430X_USART1_CLK_SRC == MSP430X_ACLK_SRC
+ #define MSP430X_USART1_CLK_SRC MSP430X_ACLK_SRC
+ #define MSP430X_USART1_CLK_FREQ MSP430X_ACLK_FREQ
+ #define MSP430X_USART1_UCSSEL UCSSEL__ACLK
+ #elif MSP430X_USART1_CLK_SRC == MSP430X_SMCLK_SRC
+ #define MSP430X_USART1_CLK_SRC MSP430X_SMCLK_SRC
+ #define MSP430X_USART1_CLK_FREQ MSP430X_SMCLK_FREQ
+ #define MSP430X_USART1_UCSSEL UCSSEL__SMCLK
+ #else
+ #error "MSP430X_USART1_CLK_SRC invalid"
+ #endif
+#endif
+
+#if MSP430X_SERIAL_USE_USART2
+ #if !defined(MSP430X_USART2_PARITY)
+ #define MSP430X_USART2_PARITY NONE
+ #endif
+ #if !defined(MSP430X_USART2_ORDER)
+ #define MSP430X_USART2_ORDER LSB
+ #endif
+ #if !defined(MSP430X_USART2_SIZE)
+ #define MSP430X_USART2_SIZE EIGHT
+ #endif
+ #if !defined(MSP430X_USART2_STOP)
+ #define MSP430X_USART2_STOP ONE
+ #endif
+ #if !defined(MSP430X_USART2_CLK_SRC)
+ #define MSP430X_USART2_CLK_SRC MSP430X_UCLK_SRC
+ #ifndef MSP430X_USART2_CLK_FREQ
+ #error "Requested external UART0 clock but no frequency given"
+ #endif
+ #define MSP430X_USART2_UCSSEL UCSSEL__UCLK
+ #elif MSP430X_USART2_CLK_SRC == MSP430X_ACLK_SRC
+ #define MSP430X_USART2_CLK_SRC MSP430X_ACLK_SRC
+ #define MSP430X_USART2_CLK_FREQ MSP430X_ACLK_FREQ
+ #define MSP430X_USART2_UCSSEL UCSSEL__ACLK
+ #elif MSP430X_USART2_CLK_SRC == MSP430X_SMCLK_SRC
+ #define MSP430X_USART2_CLK_SRC MSP430X_SMCLK_SRC
+ #define MSP430X_USART2_CLK_FREQ MSP430X_SMCLK_FREQ
+ #define MSP430X_USART2_UCSSEL UCSSEL__SMCLK
+ #else
+ #error "MSP430X_USART2_CLK_SRC invalid"
+ #endif
+#endif
+
+#if MSP430X_SERIAL_USE_USART3
+ #if !defined(MSP430X_USART3_PARITY)
+ #define MSP430X_USART3_PARITY NONE
+ #endif
+ #if !defined(MSP430X_USART3_ORDER)
+ #define MSP430X_USART3_ORDER LSB
+ #endif
+ #if !defined(MSP430X_USART3_SIZE)
+ #define MSP430X_USART3_SIZE EIGHT
+ #endif
+ #if !defined(MSP430X_USART3_STOP)
+ #define MSP430X_USART3_STOP ONE
+ #endif
+ #if !defined(MSP430X_USART3_CLK_SRC)
+ #define MSP430X_USART3_CLK_SRC MSP430X_UCLK_SRC
+ #ifndef MSP430X_USART3_CLK_FREQ
+ #error "Requested external UART0 clock but no frequency given"
+ #endif
+ #define MSP430X_USART3_UCSSEL UCSSEL__UCLK
+ #elif MSP430X_USART3_CLK_SRC == MSP430X_ACLK_SRC
+ #define MSP430X_USART3_CLK_SRC MSP430X_ACLK_SRC
+ #define MSP430X_USART3_CLK_FREQ MSP430X_ACLK_FREQ
+ #define MSP430X_USART3_UCSSEL UCSSEL__ACLK
+ #elif MSP430X_USART3_CLK_SRC == MSP430X_SMCLK_SRC
+ #define MSP430X_USART3_CLK_SRC MSP430X_SMCLK_SRC
+ #define MSP430X_USART3_CLK_FREQ MSP430X_SMCLK_FREQ
+ #define MSP430X_USART3_UCSSEL UCSSEL__SMCLK
+ #else
+ #error "MSP430X_USART3_CLK_SRC invalid"
+ #endif
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief MSP430X Serial Driver configuration structure.
+ * @details An insance 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_bitrate;
+
+ /* End of the mandatory fields.*/
+} SerialConfig;
+
+/**
+ * @brief @p SerialDriver specific data.
+ */
+#define _serial_driver_data \
+ _base_asynchronous_channel_data \
+ /* Driver state.*/ \
+ sdstate_t state; \
+ /* Input queue.*/ \
+ input_queue_t iqueue; \
+ /* Output queue.*/ \
+ output_queue_t 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. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if (MSP430X_SERIAL_USE_USART0 == TRUE) && !defined(__DOXYGEN__)
+extern SerialDriver SD0;
+#endif
+
+#if (MSP430X_SERIAL_USE_USART1 == TRUE) && !defined(__DOXYGEN__)
+extern SerialDriver SD1;
+#endif
+
+#if (MSP430X_SERIAL_USE_USART2 == TRUE) && !defined(__DOXYGEN__)
+extern SerialDriver SD2;
+#endif
+
+#if (MSP430X_SERIAL_USE_USART3 == TRUE) && !defined(__DOXYGEN__)
+extern SerialDriver SD3;
+#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 == TRUE */
+
+#endif /* _SERIAL_LLD_H_ */
+
+/** @} */
diff --git a/os/hal/ports/MSP430X/hal_st_lld.c b/os/hal/ports/MSP430X/hal_st_lld.c
new file mode 100644
index 0000000..8ea1b9d
--- /dev/null
+++ b/os/hal/ports/MSP430X/hal_st_lld.c
@@ -0,0 +1,206 @@
+/*
+ ChibiOS - Copyright (C) 2016 Andrew Wygle aka awygle
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file MSP430X/hal_st_lld.c
+ * @brief MSP430X ST subsystem low level driver source.
+ *
+ * @addtogroup ST
+ * @{
+ */
+
+#include "hal.h"
+#include <msp430.h>
+
+#if (OSAL_ST_MODE != OSAL_ST_MODE_NONE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#if (OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING) || defined(__DOXYGEN__)
+ #define MSP430X_ST_DIV_CALC(x) ((MSP430X_ST_CLK_FREQ / OSAL_ST_FREQUENCY) == x)
+#endif
+
+
+#if (OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC) || defined(__DOXYGEN__)
+ #if ((MSP430X_ST_CLK_FREQ / OSAL_ST_FREQUENCY / 64) > MSP_TIMER_COUNTER_MAX)
+ #error "Frequency too low for timer - please set OSAL_ST_FREQUENCY to a higher value"
+ #endif
+
+ #define MSP430X_ST_DIV_CALC(x) ((MSP430X_ST_CLK_FREQ / OSAL_ST_FREQUENCY / x) <= MSP_TIMER_COUNTER_MAX)
+#endif
+
+/* Find suitable prescaler setting */
+#if MSP430X_ST_DIV_CALC(1)
+ #define MSP430X_ST_DIV 1
+ #define MSP430X_ST_DIV_BITS ID__1
+ #define MSP430X_ST_DIV_EX_BITS TAIDEX_0
+#elif MSP430X_ST_DIV_CALC(2)
+ #define MSP430X_ST_DIV 2
+ #define MSP430X_ST_DIV_BITS ID__1
+ #define MSP430X_ST_DIV_EX_BITS TAIDEX_1
+#elif MSP430X_ST_DIV_CALC(3)
+ #define MSP430X_ST_DIV 3
+ #define MSP430X_ST_DIV_BITS ID__1
+ #define MSP430X_ST_DIV_EX_BITS TAIDEX_2
+#elif MSP430X_ST_DIV_CALC(4)
+ #define MSP430X_ST_DIV 4
+ #define MSP430X_ST_DIV_BITS ID__1
+ #define MSP430X_ST_DIV_EX_BITS TAIDEX_3
+#elif MSP430X_ST_DIV_CALC(5)
+ #define MSP430X_ST_DIV 5
+ #define MSP430X_ST_DIV_BITS ID__1
+ #define MSP430X_ST_DIV_EX_BITS TAIDEX_4
+#elif MSP430X_ST_DIV_CALC(6)
+ #define MSP430X_ST_DIV 6
+ #define MSP430X_ST_DIV_BITS ID__1
+ #define MSP430X_ST_DIV_EX_BITS TAIDEX_5
+#elif MSP430X_ST_DIV_CALC(7)
+ #define MSP430X_ST_DIV 7
+ #define MSP430X_ST_DIV_BITS ID__1
+ #define MSP430X_ST_DIV_EX_BITS TAIDEX_6
+#elif MSP430X_ST_DIV_CALC(8)
+ #define MSP430X_ST_DIV 8
+ #define MSP430X_ST_DIV_BITS ID__1
+ #define MSP430X_ST_DIV_EX_BITS TAIDEX_7
+#elif MSP430X_ST_DIV_CALC(10)
+ #define MSP430X_ST_DIV 10
+ #define MSP430X_ST_DIV_BITS ID__2
+ #define MSP430X_ST_DIV_EX_BITS TAIDEX_4
+#elif MSP430X_ST_DIV_CALC(12)
+ #define MSP430X_ST_DIV 12
+ #define MSP430X_ST_DIV_BITS ID__2
+ #define MSP430X_ST_DIV_EX_BITS TAIDEX_5
+#elif MSP430X_ST_DIV_CALC(14)
+ #define MSP430X_ST_DIV 14
+ #define MSP430X_ST_DIV_BITS ID__2
+ #define MSP430X_ST_DIV_EX_BITS TAIDEX_6
+#elif MSP430X_ST_DIV_CALC(16)
+ #define MSP430X_ST_DIV 16
+ #define MSP430X_ST_DIV_BITS ID__2
+ #define MSP430X_ST_DIV_EX_BITS TAIDEX_7
+#elif MSP430X_ST_DIV_CALC(20)
+ #define MSP430X_ST_DIV 20
+ #define MSP430X_ST_DIV_BITS ID__4
+ #define MSP430X_ST_DIV_EX_BITS TAIDEX_4
+#elif MSP430X_ST_DIV_CALC(24)
+ #define MSP430X_ST_DIV 24
+ #define MSP430X_ST_DIV_BITS ID__4
+ #define MSP430X_ST_DIV_EX_BITS TAIDEX_5
+#elif MSP430X_ST_DIV_CALC(28)
+ #define MSP430X_ST_DIV 28
+ #define MSP430X_ST_DIV_BITS ID__4
+ #define MSP430X_ST_DIV_EX_BITS TAIDEX_6
+#elif MSP430X_ST_DIV_CALC(32)
+ #define MSP430X_ST_DIV 32
+ #define MSP430X_ST_DIV_BITS ID__4
+ #define MSP430X_ST_DIV_EX_BITS TAIDEX_7
+#elif MSP430X_ST_DIV_CALC(40)
+ #define MSP430X_ST_DIV 40
+ #define MSP430X_ST_DIV_BITS ID__8
+ #define MSP430X_ST_DIV_EX_BITS TAIDEX_4
+#elif MSP430X_ST_DIV_CALC(48)
+ #define MSP430X_ST_DIV 48
+ #define MSP430X_ST_DIV_BITS ID__8
+ #define MSP430X_ST_DIV_EX_BITS TAIDEX_5
+#elif MSP430X_ST_DIV_CALC(56)
+ #define MSP430X_ST_DIV 56
+ #define MSP430X_ST_DIV_BITS ID__8
+ #define MSP430X_ST_DIV_EX_BITS TAIDEX_6
+#elif MSP430X_ST_DIV_CALC(64)
+ #define MSP430X_ST_DIV 64
+ #define MSP430X_ST_DIV_BITS ID__8
+ #define MSP430X_ST_DIV_EX_BITS TAIDEX_7
+#else
+ #error "Error in calculating dividers - check OSAL_ST_FREQUENCY and frequency of input clock"
+#endif
+/* ugh never again*/
+
+#if (OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC) || defined(__DOXYGEN__)
+ #define MSP_TIMER_COUNTER (MSP430X_ST_CLK_FREQ / OSAL_ST_FREQUENCY / MSP430X_ST_DIV)
+ #define MSP430X_ST_CLK_FREQ_ (MSP_TIMER_COUNTER * MSP430X_ST_DIV * OSAL_ST_FREQUENCY)
+ #if (MSP430X_ST_CLK_FREQ != MSP430X_ST_CLK_FREQ_)
+ #warning "OSAL_ST_FREQUENCY cannot be generated exactly using timer"
+ #endif
+ #undef MSP430X_ST_CLK_FREQ_
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/**
+ * @brief Timer handler for both modes
+ */
+
+PORT_IRQ_HANDLER( MSP430X_ST_ISR ) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ osalSysLockFromISR();
+ osalOsTimerHandlerI();
+ osalSysUnlockFromISR();
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level ST driver initialization.
+ *
+ * @notapi
+ */
+void st_lld_init(void) {
+ #if (OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING) || defined (__DOXYGEN__)
+ /* Start disabled */
+ MSP430X_ST_CCR(MSP430X_ST_TIMER) = 0;
+ MSP430X_ST_CCTL(MSP430X_ST_TIMER) = 0;
+ MSP430X_ST_EX(MSP430X_ST_TIMER) = MSP430X_ST_DIV_EX_BITS;
+ MSP430X_ST_CTL(MSP430X_ST_TIMER) = (TACLR | MC_2 | MSP430X_ST_DIV_BITS | MSP430X_ST_TASSEL);
+ #endif /* OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING */
+
+ #if (OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC) || defined (__DOXYGEN__)
+ /* Start enabled */
+ MSP430X_ST_CCR(MSP430X_ST_TIMER) = MSP_TIMER_COUNTER - 1;
+ MSP430X_ST_CCTL(MSP430X_ST_TIMER) = CCIE;
+ MSP430X_ST_EX(MSP430X_ST_TIMER) = MSP430X_ST_DIV_EX_BITS;
+ MSP430X_ST_CTL(MSP430X_ST_TIMER) = (TACLR | MC_1 | MSP430X_ST_DIV_BITS | MSP430X_ST_TASSEL);
+ #endif /* OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC */
+}
+
+#endif /* OSAL_ST_MODE != OSAL_ST_MODE_NONE */
+
+/** @} */
diff --git a/os/hal/ports/MSP430X/hal_st_lld.h b/os/hal/ports/MSP430X/hal_st_lld.h
new file mode 100644
index 0000000..32ad970
--- /dev/null
+++ b/os/hal/ports/MSP430X/hal_st_lld.h
@@ -0,0 +1,216 @@
+/*
+ ChibiOS - Copyright (C) 2016 Andrew Wygle aka awygle
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file MSP430X/hal_st_lld.h
+ * @brief MSP430X ST subsystem low level driver header.
+ * @details This header is designed to be include-able without having to
+ * include other files from the HAL.
+ *
+ * @addtogroup MSP430X
+ * @{
+ */
+
+#ifndef _ST_LLD_H_
+#define _ST_LLD_H_
+
+#include <msp430.h>
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @brief Timer maximum value
+ */
+#define MSP_TIMER_COUNTER_MAX 65535
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief System timer clock source.
+ *
+ * @note Legal values are undefined, MSP430X_ACLK_SRC, and
+ * MSP430X_SMCLK_SRC.
+ * @note If undefined, must define MSP430X_ST_CLK_FREQ as frequency of
+ * external clock and configure PAL appropriately.
+ */
+#if !defined (MSP430X_ST_CLK_SRC)
+ #ifndef MSP430X_ST_CLK_FREQ
+ #warning "Requested external source for ST but no frequency given"
+ #warning "- assuming OSAL_ST_FREQUENCY"
+ #define MSP430X_ST_CLK_FREQ OSAL_ST_FREQUENCY
+ #endif
+ #define MSP430X_ST_TASSEL TASSEL__TACLK
+#elif MSP430X_ST_CLK_SRC == MSP430X_ACLK_SRC
+ #define MSP430X_ST_CLK_FREQ MSP430X_ACLK_FREQ
+ #define MSP430X_ST_TASSEL TASSEL__ACLK
+#elif MSP430X_ST_CLK_SRC == MSP430X_SMCLK_SRC
+ #define MSP430X_ST_CLK_FREQ MSP430X_SMCLK_FREQ
+ #define MSP430X_ST_TASSEL TASSEL__SMCLK
+#endif
+
+/* Timers */
+/**
+ * @brief Timer type (by letter) to be used for ST.
+ * @note Legal values are A and B. D support not yet implemented.
+ * @note Defaults to A
+ */
+#if !defined(MSP430X_ST_TIMER_TYPE)
+ #define MSP430X_ST_TIMER_TYPE A
+#endif
+/**
+ * @brief Timer instance (by number) to be used for ST.
+ * @note Defaults to 0
+ */
+#if !defined (MSP430X_ST_TIMER_INDEX)
+ #define MSP430X_ST_TIMER_INDEX 0
+#endif
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#define TIMER_HELPER2(x, y) x ## y
+#define TIMER_HELPER(x, y) TIMER_HELPER2(x, y)
+#define MSP430X_ST_TIMER TIMER_HELPER(MSP430X_ST_TIMER_TYPE, MSP430X_ST_TIMER_INDEX)
+#define CCR_HELPER(x) T ## x ## CCR0
+#define MSP430X_ST_CCR(x) CCR_HELPER(x)
+#define CCTL_HELPER(x) T ## x ## CCTL0
+#define MSP430X_ST_CCTL(x) CCTL_HELPER(x)
+#define EX_HELPER(x) T ## x ## EX0
+#define MSP430X_ST_EX(x) EX_HELPER(x)
+#define CTL_HELPER(x) T ## x ## CTL
+#define MSP430X_ST_CTL(x) CTL_HELPER(x)
+#define R_HELPER(x) T ## x ## R
+#define MSP430X_ST_R(x) R_HELPER(x)
+#define ISR_HELPER2(x, y) TIMER ## y ## _ ## x ## 0_VECTOR
+#define ISR_HELPER(x, y) ISR_HELPER2(x, y)
+#define MSP430X_ST_ISR ISR_HELPER(MSP430X_ST_TIMER_TYPE, MSP430X_ST_TIMER_INDEX)
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void st_lld_init(void);
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Driver inline functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Returns the time counter value.
+ *
+ * @return The counter value.
+ *
+ * @notapi
+ */
+static inline systime_t st_lld_get_counter(void) {
+
+ return (systime_t)MSP430X_ST_R(MSP430X_ST_TIMER);
+}
+
+/**
+ * @brief Starts the alarm.
+ * @note Makes sure that no spurious alarms are triggered after
+ * this call.
+ *
+ * @param[in] abstime the time to be set for the first alarm
+ *
+ * @notapi
+ */
+static inline void st_lld_start_alarm(systime_t abstime) {
+
+ MSP430X_ST_CCR(MSP430X_ST_TIMER) = abstime;
+
+ /* Reset pending interrupt */
+ MSP430X_ST_CCTL(MSP430X_ST_TIMER) &= (~CCIFG);
+
+ /* Enable interrupt */
+ MSP430X_ST_CCTL(MSP430X_ST_TIMER) |= CCIE;
+}
+
+/**
+ * @brief Stops the alarm interrupt.
+ *
+ * @notapi
+ */
+static inline void st_lld_stop_alarm(void) {
+
+ MSP430X_ST_CCTL(MSP430X_ST_TIMER) &= (~CCIE);
+}
+
+/**
+ * @brief Sets the alarm time.
+ *
+ * @param[in] abstime the time to be set for the next alarm
+ *
+ * @notapi
+ */
+static inline void st_lld_set_alarm(systime_t abstime) {
+
+ MSP430X_ST_CCR(MSP430X_ST_TIMER) = abstime;
+}
+
+/**
+ * @brief Returns the current alarm time.
+ *
+ * @return The currently set alarm time.
+ *
+ * @notapi
+ */
+static inline systime_t st_lld_get_alarm(void) {
+
+ return MSP430X_ST_CCR(MSP430X_ST_TIMER);
+}
+
+/**
+ * @brief Determines if the alarm is active.
+ *
+ * @return The alarm status.
+ * @retval false if the alarm is not active.
+ * @retval true is the alarm is active
+ *
+ * @notapi
+ */
+static inline bool st_lld_is_alarm_active(void) {
+
+ return (bool)((MSP430X_ST_CCTL(MSP430X_ST_TIMER) & CCIE) != 0);
+}
+
+#endif /* _ST_LLD_H_ */
+
+/** @} */
diff --git a/os/hal/ports/MSP430X/platform.mk b/os/hal/ports/MSP430X/platform.mk
new file mode 100644
index 0000000..b0f256e
--- /dev/null
+++ b/os/hal/ports/MSP430X/platform.mk
@@ -0,0 +1,8 @@
+# List of all the MSP430X platform files.
+PLATFORMSRC = ${CHIBIOS_CONTRIB}/os/hal/ports/MSP430X/hal_lld.c \
+ ${CHIBIOS_CONTRIB}/os/hal/ports/MSP430X/hal_st_lld.c \
+ ${CHIBIOS_CONTRIB}/os/hal/ports/MSP430X/hal_serial_lld.c \
+ ${CHIBIOS_CONTRIB}/os/hal/ports/MSP430X/hal_pal_lld.c
+
+# Required include directories
+PLATFORMINC = ${CHIBIOS_CONTRIB}/os/hal/ports/MSP430X