aboutsummaryrefslogtreecommitdiffstats
path: root/os/hal
diff options
context:
space:
mode:
authorawygle <awygle@gmail.com>2016-05-04 23:47:33 -0700
committerawygle <awygle@gmail.com>2016-05-04 23:47:33 -0700
commitcf02c79b5aa7209542cbf1b0cefe703a2c0c60be (patch)
tree0557b4194870b710411fbddaf1c58eb432e2d0d4 /os/hal
parentfe1d3f21146b1d28bd281b3682a528042b80253c (diff)
downloadChibiOS-Contrib-cf02c79b5aa7209542cbf1b0cefe703a2c0c60be.tar.gz
ChibiOS-Contrib-cf02c79b5aa7209542cbf1b0cefe703a2c0c60be.tar.bz2
ChibiOS-Contrib-cf02c79b5aa7209542cbf1b0cefe703a2c0c60be.zip
Merge pull request #68 from awygle/msp430x
MSP430X DMA Support, EXP430FR6989 Demo + Makefile Updates
Diffstat (limited to 'os/hal')
-rw-r--r--os/hal/boards/EXP430FR5969/board.h16
-rw-r--r--os/hal/boards/EXP430FR6989/board.c52
-rw-r--r--os/hal/boards/EXP430FR6989/board.h217
-rw-r--r--os/hal/boards/EXP430FR6989/board.mk5
-rw-r--r--os/hal/ports/MSP430X/hal_dma_lld.c244
-rw-r--r--os/hal/ports/MSP430X/hal_dma_lld.h174
-rw-r--r--os/hal/ports/MSP430X/hal_pal_lld.c14
-rw-r--r--os/hal/ports/MSP430X/hal_serial_lld.c6
-rw-r--r--os/hal/ports/MSP430X/platform.mk3
9 files changed, 719 insertions, 12 deletions
diff --git a/os/hal/boards/EXP430FR5969/board.h b/os/hal/boards/EXP430FR5969/board.h
index 6b53f4b..97103d3 100644
--- a/os/hal/boards/EXP430FR5969/board.h
+++ b/os/hal/boards/EXP430FR5969/board.h
@@ -18,7 +18,7 @@
#define _BOARD_H_
/*
- * Setup for the Arduino Uno or board.
+ * Setup for the EXP430FR5969 LaunchPad board
*/
/*
@@ -44,7 +44,7 @@
* Port A setup:
*
* P1.0 - Green LED (output low)
- * P1.1 - Switch S2 (input pullup falling-edge interrupt)
+ * P1.1 - Switch S2 (input pullup)
* P1.2 - BoosterPack BP19 (input pullup)
* P1.3 - BoosterPack BP11 (input pullup)
* P1.4 - BoosterPack BP12 (input pullup)
@@ -65,8 +65,8 @@
#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
+#define VAL_IOPORT1_IES 0x0000
+#define VAL_IOPORT1_IE 0x0000
/*
* Port B setup:
@@ -79,12 +79,12 @@
* 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.0 - Application UART CTS (input pullup)
* 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.5 - Switch S1 (input pullup)
* P4.6 - Red LED (output low)
* P4.7 - N/C (input pullup)
*/
@@ -93,8 +93,8 @@
#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
+#define VAL_IOPORT2_IES 0x0000
+#define VAL_IOPORT2_IE 0x0000
/*
* Port J setup:
diff --git a/os/hal/boards/EXP430FR6989/board.c b/os/hal/boards/EXP430FR6989/board.c
new file mode 100644
index 0000000..a6836cf
--- /dev/null
+++ b/os/hal/boards/EXP430FR6989/board.c
@@ -0,0 +1,52 @@
+/*
+ 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_IOPORT3_OUT, VAL_IOPORT3_DIR, VAL_IOPORT3_REN, VAL_IOPORT3_SEL0,
+ VAL_IOPORT3_SEL1, VAL_IOPORT3_IES, VAL_IOPORT3_IE},
+ {VAL_IOPORT4_OUT, VAL_IOPORT4_DIR, VAL_IOPORT4_REN, VAL_IOPORT4_SEL0,
+ VAL_IOPORT4_SEL1, VAL_IOPORT4_IES, VAL_IOPORT4_IE},
+ {VAL_IOPORT5_OUT, VAL_IOPORT5_DIR, VAL_IOPORT5_REN, VAL_IOPORT5_SEL0,
+ VAL_IOPORT5_SEL1, VAL_IOPORT5_IES, VAL_IOPORT5_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/EXP430FR6989/board.h b/os/hal/boards/EXP430FR6989/board.h
new file mode 100644
index 0000000..83b8fbb
--- /dev/null
+++ b/os/hal/boards/EXP430FR6989/board.h
@@ -0,0 +1,217 @@
+/*
+ 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 EXP430FR6989 LaunchPad board
+ */
+
+/* NOTE: LCD segment pins configured as unused - controlled by LCD driver if
+ * present
+ */
+
+/*
+ * Board identifier.
+ */
+#define BOARD_EXP430FR6989
+#define BOARD_NAME "MSP430FR6989 LaunchPad"
+
+/*
+ * IO lines assignments.
+ */
+#define LINE_LED_R PAL_LINE(IOPORT1, 0U)
+#define LINE_LED_G PAL_LINE(IOPORT5, 7U)
+#define LINE_SW_S1 PAL_LINE(IOPORT1, 1U)
+#define LINE_SW_S2 PAL_LINE(IOPORT1, 2U)
+
+/*
+ * 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 - Red LED (output low)
+ * P1.1 - Switch S1 (input pullup falling-edge interrupt)
+ * P1.2 - Switch S2 (input pullup falling-edge interrupt)
+ * P1.3 - BoosterPack BP34 (input pullup)
+ * P1.4 - BoosterPack BP7 (input pullup)
+ * P1.5 - BoosterPack BP18 (input pullup)
+ * P1.6 - BoosterPack BP15 (input pullup)
+ * P1.7 - BoosterPack BP14 (input pullup)
+ * P2.0 - BoosterPack BP8 (input pullup)
+ * P2.1 - BoosterPack BP19 (input pullup)
+ * P2.2 - BoosterPack BP35 (input pullup)
+ * P2.3 - BoosterPack BP31 (input pullup)
+ * P2.4 - BoosterPack BP12 (input pullup)
+ * P2.5 - BoosterPack BP13 (input pullup)
+ * P2.6 - BoosterPack BP39 (input pullup)
+ * P2.7 - BoosterPack BP40 (input pullup)
+ */
+#define VAL_IOPORT1_OUT 0xFFFE
+#define VAL_IOPORT1_DIR 0x0001
+#define VAL_IOPORT1_REN 0xFFFE
+#define VAL_IOPORT1_SEL0 0x0000
+#define VAL_IOPORT1_SEL1 0x0000
+#define VAL_IOPORT1_IES 0x0006
+#define VAL_IOPORT1_IE 0x0006
+
+/*
+ * Port B setup:
+ *
+ * P3.0 - BoosterPack BP33 (input pullup)
+ * P3.1 - BoosterPack BP32 (input pullup)
+ * P3.2 - BoosterPack BP5 (input pullup)
+ * P3.3 - BoosterPack BP38 (input pullup)
+ * P3.4 - Application UART TX (alternate 1)
+ * P3.5 - Application UART RX (alternate 1)
+ * P3.6 - BoosterPack BP37 (input pullup)
+ * P3.7 - BoosterPack BP36 (input pullup)
+ * P4.0 - BoosterPack BP10 (input pullup)
+ * P4.1 - BoosterPack BP9 (input pullup)
+ * P4.2 - BoosterPack BP4 (input pullup)
+ * P4.3 - BoosterPack BP3 (input pullup)
+ * P4.4 - LCD S8 (input pullup)
+ * P4.5 - LCD S7 (input pullup)
+ * P4.6 - LCD S6 (input pullup)
+ * P4.7 - BoosterPack BP11 (input pullup)
+ */
+#define VAL_IOPORT2_OUT 0xFFCF
+#define VAL_IOPORT2_DIR 0x0000
+#define VAL_IOPORT2_REN 0xFFCF
+#define VAL_IOPORT2_SEL0 0x0030
+#define VAL_IOPORT2_SEL1 0x0000
+#define VAL_IOPORT2_IES 0x0000
+#define VAL_IOPORT2_IE 0x0000
+
+/*
+ * Port C setup:
+ *
+ * P5.0 - LCD S38 (input pullup)
+ * P5.1 - LCD S37 (input pullup)
+ * P5.2 - LCD S36 (input pullup)
+ * P5.3 - LCD S35 (input pullup)
+ * P5.4 - LCD S12 (input pullup)
+ * P5.5 - LCD S11 (input pullup)
+ * P5.6 - LCD S10 (input pullup)
+ * P5.7 - LCD S9 (input pullup)
+ * P6.0 - LCD R23 (input pullup)
+ * P6.1 - LCD R13 (input pullup)
+ * P6.2 - LCD R03 (input pullup)
+ * P6.3 - LCD COM0 (input pullup)
+ * P6.4 - LCD COM1 (input pullup)
+ * P6.5 - LCD COM2 (input pullup)
+ * P6.6 - LCD COM3 (input pullup)
+ * P6.7 - LCD S31 (input pullup)
+ */
+#define VAL_IOPORT3_OUT 0xFFFF
+#define VAL_IOPORT3_DIR 0x0000
+#define VAL_IOPORT3_REN 0xFFFF
+#define VAL_IOPORT3_SEL0 0x0000
+#define VAL_IOPORT3_SEL1 0x0000
+#define VAL_IOPORT3_IES 0x0000
+#define VAL_IOPORT3_IE 0x0000
+
+/*
+ * Port D setup:
+ *
+ * P7.0 - LCD S17 (input pullup)
+ * P7.1 - LCD S16 (input pullup)
+ * P7.2 - LCD S15 (input pullup)
+ * P7.3 - LCD S14 (input pullup)
+ * P7.4 - LCD S13 (input pullup)
+ * P7.5 - LCD S30 (input pullup)
+ * P7.6 - LCD S29 (input pullup)
+ * P7.7 - LCD S27 (input pullup)
+ * P8.0 - LCD S21 (input pullup)
+ * P8.1 - LCD S20 (input pullup)
+ * P8.2 - LCD S19 (input pullup)
+ * P8.3 - LCD S18 (input pullup)
+ * P8.4 - BoosterPack BP23 (input pullup)
+ * P8.5 - BoosterPack BP24 (input pullup)
+ * P8.6 - BoosterPack BP25 (input pullup)
+ * P8.7 - BoosterPack BP26 (input pullup)
+ */
+#define VAL_IOPORT4_OUT 0xFFFF
+#define VAL_IOPORT4_DIR 0x0000
+#define VAL_IOPORT4_REN 0xFFFF
+#define VAL_IOPORT4_SEL0 0x0000
+#define VAL_IOPORT4_SEL1 0x0000
+#define VAL_IOPORT4_IES 0x0000
+#define VAL_IOPORT4_IE 0x0000
+
+/*
+ * Port D setup:
+ *
+ * P9.0 - BoosterPack BP27 (input pullup)
+ * P9.1 - BoosterPack BP28 (input pullup)
+ * P9.2 - BoosterPack BP2 (input pullup)
+ * P9.3 - BoosterPack BP6 (input pullup)
+ * P9.4 - BoosterPack BP17 (input pullup)
+ * P9.5 - BoosterPack BP29 (input pullup)
+ * P9.6 - BoosterPack BP30 (input pullup)
+ * P9.7 - Green LED (output low)
+ * P10.0 - LCD S4 (input pullup)
+ * P10.1 - LCD S28 (input pullup)
+ * P10.2 - LCD S39 (input pullup)
+ * P10.3 - N/C Internally (input pullup)
+ * P10.4 - N/C Internally (input pullup)
+ * P10.5 - N/C Internally (input pullup)
+ * P10.6 - N/C Internally (input pullup)
+ * P10.7 - N/C Internally (input pullup)
+ */
+#define VAL_IOPORT5_OUT 0xFF7F
+#define VAL_IOPORT5_DIR 0x0080
+#define VAL_IOPORT5_REN 0xFF7F
+#define VAL_IOPORT5_SEL0 0x0000
+#define VAL_IOPORT5_SEL1 0x0000
+#define VAL_IOPORT5_IES 0x0000
+#define VAL_IOPORT5_IE 0x0000
+
+/*
+ * 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/EXP430FR6989/board.mk b/os/hal/boards/EXP430FR6989/board.mk
new file mode 100644
index 0000000..ea1c237
--- /dev/null
+++ b/os/hal/boards/EXP430FR6989/board.mk
@@ -0,0 +1,5 @@
+# List of all the board related files.
+BOARDSRC = ${CHIBIOS_CONTRIB}/os/hal/boards/EXP430FR6989/board.c
+
+# Required include directories
+BOARDINC = ${CHIBIOS_CONTRIB}/os/hal/boards/EXP430FR6989
diff --git a/os/hal/ports/MSP430X/hal_dma_lld.c b/os/hal/ports/MSP430X/hal_dma_lld.c
new file mode 100644
index 0000000..58293ca
--- /dev/null
+++ b/os/hal/ports/MSP430X/hal_dma_lld.c
@@ -0,0 +1,244 @@
+/*
+ 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_dma_lld.c
+ * @brief MSP430X DMA subsystem low level driver source.
+ *
+ * @addtogroup MSP430X_DMA
+ * @{
+ */
+
+#include "hal.h"
+#include "ch.h"
+#include "hal_dma_lld.h"
+
+#if (HAL_USE_DMA == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/* TODO make sure this is right... */
+static msp430x_dma_ch_reg_t * const dma_channels = (msp430x_dma_ch_reg_t *)&DMA0CTL;
+static uint8_t * const dma_ctls = (uint8_t *)&DMACTL0;
+
+static msp430x_dma_cb_t callbacks[MSP430X_DMA_CHANNELS];
+#if CH_CFG_USE_SEMAPHORES
+static semaphore_t dma_lock;
+#endif
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static void init_request(const msp430x_dma_req_t * request, uint8_t index) {
+
+ dma_ctls[index] = request->trigger;
+ callbacks[index] = request->callback;
+ msp430x_dma_ch_reg_t * ch = &dma_channels[index];
+ ch->sa = (uintptr_t)request->source_addr;
+ ch->da = (uintptr_t)request->dest_addr;
+ ch->sz = request->size;
+ ch->ctl = DMAREQ | DMAIE | DMAEN | request->data_mode | request->addr_mode
+ | request->transfer_mode;
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+PORT_IRQ_HANDLER(DMA_VECTOR) {
+ uint8_t index;
+ OSAL_IRQ_PROLOGUE();
+
+ index = (DMAIV >> 1) - 1;
+
+ if (index < MSP430X_DMA_CHANNELS) {
+ msp430x_dma_cb_t * cb = &callbacks[index];
+
+ /* WARNING: CALLBACKS ARE CALLED IN AN ISR CONTEXT! */
+ if (cb->callback != NULL) {
+ cb->callback(cb->args);
+ }
+
+ }
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Initialize the DMA engine.
+ *
+ * @init
+ */
+void dmaInit(void) {
+#if CH_CFG_USE_SEMAPHORES
+ chSemObjectInit(&dma_lock, MSP430X_DMA_CHANNELS);
+#endif
+}
+
+/**
+ * @brief Requests a DMA transfer operation from the DMA engine.
+ * @note The DMA engine uses unclaimed DMA channels to provide DMA services
+ * for one-off or infrequent uses. If all channels are busy, and
+ * semaphores are enabled, the calling thread will sleep until a
+ * channel is available or the request times out. If semaphores are
+ * disabled, the calling thread will busy-wait instead of sleeping.
+ */
+bool dmaRequest(msp430x_dma_req_t * request, systime_t timeout) {
+ /* Check if a DMA channel is available */
+#if CH_CFG_USE_SEMAPHORES
+ msg_t semresult = chSemWaitTimeout(&dma_lock, timeout);
+ if (semresult != MSG_OK)
+ return true;
+#endif
+
+#if !(CH_CFG_USE_SEMAPHORES)
+ systime_t start = chVTGetSystemTimeX();
+
+ do {
+#endif
+ /* Grab the correct DMA channel to use */
+ int i = 0;
+ for (i = 0; i < MSP430X_DMA_CHANNELS; i++) {
+ if (!(dma_channels[i].ctl & DMAEN)) {
+ break;
+ }
+ }
+#if !(CH_CFG_USE_SEMAPHORES)
+ while (chVTTimeElapsedSinceX(start) < timeout);
+#endif
+
+#if !(CH_CFG_USE_SEMAPHORES)
+ if (i == MSP430X_DMA_CHANNELS) {
+ return true;
+ }
+#endif
+
+ /* Make the request */
+ init_request(request, i);
+
+#if CH_CFG_USE_SEMAPHORES
+ chSemSignal(&dma_lock);
+#endif
+
+ return false;
+}
+
+/**
+ * @brief Acquires exclusive control of a DMA channel.
+ * @pre The channel must not be already acquired or an error is returned.
+ * @note If the channel is in use by the DMA engine, blocks until acquired.
+ * @post This channel must be interacted with using only the functions
+ * defined in this module.
+ *
+ * @param[out] channel The channel handle. Must be pre-allocated.
+ * @param[in] index The index of the channel (< MSP430X_DMA_CHANNELS).
+ * @return The operation status.
+ * @retval false no error, channel acquired.
+ * @retval true error, channel already acquired.
+ */
+bool dmaAcquire(msp430x_dma_ch_t * channel, uint8_t index) {
+ /* Acquire the channel in an idle mode */
+
+ /* Is the channel already acquired? */
+ osalDbgAssert(index < MSP430X_DMA_CHANNELS, "invalid channel index");
+ if (dma_channels[index].ctl & DMADT_4) {
+ return true;
+ }
+
+ /* Increment the DMA counter */
+#if CH_CFG_USE_SEMAPHORES
+ msg_t semresult = chSemWait(&dma_lock);
+ if (semresult != MSG_OK)
+ return true;
+#endif
+
+ while (dma_channels[index].ctl & DMAEN) ;
+
+ dma_ctls[index] = DMA_TRIGGER_MNEM(DMAREQ);
+ dma_channels[index].sz = 0;
+ dma_channels[index].ctl = DMAEN | DMAABORT | DMADT_4;
+
+ channel->registers = dma_channels + index;
+ channel->ctl = dma_ctls + index;
+ channel->cb = callbacks + index;
+
+ return false;
+}
+
+/**
+ * @brief Initiates a DMA transfer operation using an acquired channel.
+ * @pre The channel must have been acquired using @p dmaAcquire().
+ *
+ * @param[in] channel pointer to a DMA channel from @p dmaAcquire().
+ * @param[in] request pointer to a DMA request object.
+ */
+void dmaTransfer(msp430x_dma_ch_t * channel, msp430x_dma_req_t * request) {
+
+ *(channel->ctl) = request->trigger;
+
+ channel->cb->callback = request->callback.callback;
+ channel->cb->args = request->callback.args;
+
+ chSysLock();
+ channel->registers->ctl &= (~DMAEN);
+ channel->registers->sa = (uintptr_t)request->source_addr;
+ channel->registers->da = (uintptr_t)request->dest_addr;
+ channel->registers->sz = request->size;
+ channel->registers->ctl = DMAIE | request->data_mode | request->addr_mode
+ | request->transfer_mode | DMADT_4 | DMAEN | DMAREQ; /* repeated transfers */
+ chSysUnlock();
+}
+
+/**
+ * @brief Releases exclusive control of a DMA channel.
+ * @details The channel is released from control and returned to the DMA engine
+ * pool. Trying to release an unallocated channel is an illegal
+ * operation and is trapped if assertions are enabled.
+ * @pre The channel must have been acquired using @p dmaAcquire().
+ * @post The channel is returned to the DMA engine pool.
+ */
+void dmaRelease(msp430x_dma_ch_t * channel) {
+
+ osalDbgCheck(channel != NULL);
+ osalDbgAssert(channel->registers->ctl & DMADT_4, "not acquired");
+
+ /* Release the channel in an idle mode */
+ channel->registers->ctl = DMAABORT;
+
+ /* release the DMA counter */
+#if CH_CFG_USE_SEMAPHORES
+ chSemSignal(&dma_lock);
+#endif
+}
+
+#endif /* HAL_USE_DMA == TRUE */
+
+/** @} */
diff --git a/os/hal/ports/MSP430X/hal_dma_lld.h b/os/hal/ports/MSP430X/hal_dma_lld.h
new file mode 100644
index 0000000..2cce85d
--- /dev/null
+++ b/os/hal/ports/MSP430X/hal_dma_lld.h
@@ -0,0 +1,174 @@
+/*
+ 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_dma_lld.c
+ * @brief MSP430X DMA subsystem low level driver header.
+ * @note This driver is used as a DMA engine for the other
+ * low level drivers.
+ *
+ * @addtogroup MSP430X_DMA
+ * @{
+ */
+
+#ifndef HAL_MSP430X_DMA_H
+#define HAL_MSP430X_DMA_H
+
+#if (HAL_USE_DMA == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+#define MSP430X_DMA_SINGLE DMADT_0
+#define MSP430X_DMA_BLOCK DMADT_1
+#define MSP430X_DMA_BURST DMADT_2
+
+#define MSP430X_DMA_SRCINCR DMASRCINCR_3
+#define MSP430X_DMA_SRCDECR DMASRCINCR_2
+#define MSP430X_DMA_DSTINCR DMADSTINCR_3
+#define MSP430X_DMA_DSTDECR DMADSTINCR_2
+
+#define MSP430X_DMA_SRCBYTE DMASRCBYTE
+#define MSP430X_DMA_DSTBYTE DMADSTBYTE
+#define MSP430X_DMA_SRCWORD 0
+#define MSP430X_DMA_DSTWORD 0
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if !defined(DMA_BASE) && !defined(MSP430X_DMA_SOFTWARE)
+ #error "The MSP430 device in use does not support DMA. Explicitly enable"
+ #error "software support by defining MSP430X_DMA_SOFTWARE."
+#endif
+
+#if defined(__MSP430_HAS_DMAX_1__) || defined(__MSP430X_HAS_DMA_1__)
+#define MSP430X_DMA_CHANNELS 1
+#elif defined(__MSP430_HAS_DMAX_3__) || defined(__MSP430X_HAS_DMA_3__)
+#define MSP430X_DMA_CHANNELS 3
+#elif defined(__MSP430_HAS_DMAX_6__) || defined(__MSP430X_HAS_DMA_6__)
+#define MSP430X_DMA_CHANNELS 6
+#else
+ #error "Unexpected error - how many DMA channels does your MSP have?"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of DMA callback function pointer.
+ */
+typedef void (*msp430x_dma_cbp_t)(void *args);
+
+/**
+ * @brief DMA callback, function and argument.
+ */
+typedef struct {
+ msp430x_dma_cbp_t callback; /**< @brief Callback function pointer */
+ void * args; /**< @brief Callback function arguments */
+} msp430x_dma_cb_t;
+
+/**
+ * @brief MSP430X DMA request structure.
+ */
+typedef struct {
+ void * source_addr; /**< @brief Source address */
+ void * dest_addr; /**< @brief Destination address */
+ uint16_t size; /**< @brief Number of values to transfer */
+ uint16_t addr_mode; /**< @brief Address manipulation mode */
+ uint16_t data_mode; /**< @brief Data sizes (b2b, w2w, b2w, w2b) */
+ uint16_t transfer_mode; /**< @brief Transfer mode (single, block, burst) */
+ uint16_t trigger; /**< @brief Triggering event (see datasheet) */
+ msp430x_dma_cb_t callback;/**< @brief Callback function and arguments */
+} msp430x_dma_req_t;
+
+/**
+ * @brief MSP430X DMA channel register structure.
+ */
+typedef struct {
+ volatile uint16_t ctl; /**< @brief Control register */
+ volatile uint32_t sa; /**< @brief Source address register */
+ volatile uint32_t da; /**< @brief Destination address register */
+ volatile uint16_t sz; /**< @brief Size register */
+ volatile uint16_t pad1;
+ volatile uint16_t pad2;
+} msp430x_dma_ch_reg_t;
+
+/**
+ * @brief MSP430X DMA controller register structure.
+ */
+typedef struct {
+ volatile uint8_t tsel0; /**< @brief Trigger select for channel 0 */
+ volatile uint8_t tsel1; /**< @brief Trigger select for channel 1 */
+ volatile uint8_t tsel2; /**< @brief Trigger select for channel 2 */
+ volatile uint8_t tsel3; /**< @brief Trigger select for channel 3 */
+ volatile uint8_t tsel4; /**< @brief Trigger select for channel 4 */
+ volatile uint8_t tsel5; /**< @brief Trigger select for channel 5 */
+ volatile uint8_t tsel6; /**< @brief Trigger select for channel 6 */
+ volatile uint8_t tsel7; /**< @brief Trigger select for channel 7 */
+ volatile uint16_t ctl4; /**< @brief Controller register 4 */
+} msp430x_dma_ctl_reg_t;
+
+/**
+ * @brief MSP430X DMA channel structure.
+ */
+typedef struct {
+ msp430x_dma_ch_reg_t * registers; /**< @brief Pointer to channel registers */
+ volatile uint8_t * ctl; /**< @brief Pointer to channel control register */
+ msp430x_dma_cb_t * cb; /**< @brief Pointer to callback function and args */
+} msp430x_dma_ch_t;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Identifies a DMA trigger using a mnemonic.
+ *
+ * @param[in] mnem The mnemonic for the trigger, e.g. UCA0RXIFG to trigger
+ * on UART receive.
+ */
+#define DMA_TRIGGER_MNEM(mnem) DMA0TSEL__ ## mnem
+
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void dmaInit(void);
+ bool dmaRequest(msp430x_dma_req_t * request, systime_t timeout);
+ bool dmaAcquire(msp430x_dma_ch_t * channel, uint8_t index);
+ void dmaTransfer(msp430x_dma_ch_t * channel, msp430x_dma_req_t * request);
+ void dmaRelease(msp430x_dma_ch_t * channel);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_DMA == true */
+
+#endif /* HAL_MSP430X_DMA_H */
+
diff --git a/os/hal/ports/MSP430X/hal_pal_lld.c b/os/hal/ports/MSP430X/hal_pal_lld.c
index 4cfff3b..97ad170 100644
--- a/os/hal/ports/MSP430X/hal_pal_lld.c
+++ b/os/hal/ports/MSP430X/hal_pal_lld.c
@@ -68,6 +68,7 @@ void _pal_lld_init(const PALConfig *config) {
PASEL1 = config->porta.sel1;
PAIES = config->porta.ies;
PAIE = config->porta.ie;
+ PAIFG = 0;
#endif
#if defined(PB_BASE) || defined(__DOXYGEN__)
PBOUT = config->portb.out;
@@ -77,6 +78,7 @@ void _pal_lld_init(const PALConfig *config) {
PBSEL1 = config->portb.sel1;
PBIES = config->portb.ies;
PBIE = config->portb.ie;
+ PBIFG = 0;
#endif
#if defined(PC_BASE) || defined(__DOXYGEN__)
PCOUT = config->portc.out;
@@ -84,8 +86,11 @@ void _pal_lld_init(const PALConfig *config) {
PCREN = config->portc.ren;
PCSEL0 = config->portc.sel0;
PCSEL1 = config->portc.sel1;
+#if defined(PCIE) || defined(__DOXYGEN__)
PCIES = config->portc.ies;
PCIE = config->portc.ie;
+ PCIFG = 0;
+#endif
#endif
#if defined(PD_BASE) || defined(__DOXYGEN__)
PDOUT = config->portd.out;
@@ -93,8 +98,11 @@ void _pal_lld_init(const PALConfig *config) {
PDREN = config->portd.ren;
PDSEL0 = config->portd.sel0;
PDSEL1 = config->portd.sel1;
+#if defined(PDIE) || defined(__DOXYGEN__)
PDIES = config->portd.ies;
PDIE = config->portd.ie;
+ PDIFG = 0;
+#endif
#endif
#if defined(PE_BASE) || defined(__DOXYGEN__)
PEOUT = config->porte.out;
@@ -102,8 +110,11 @@ void _pal_lld_init(const PALConfig *config) {
PEREN = config->porte.ren;
PESEL0 = config->porte.sel0;
PESEL1 = config->porte.sel1;
+#if defined(PEIE) || defined(__DOXYGEN__)
PEIES = config->porte.ies;
PEIE = config->porte.ie;
+ PEIFG = 0;
+#endif
#endif
#if defined(PF_BASE) || defined(__DOXYGEN__)
PFOUT = config->portf.out;
@@ -111,8 +122,11 @@ void _pal_lld_init(const PALConfig *config) {
PFREN = config->portf.ren;
PFSEL0 = config->portf.sel0;
PFSEL1 = config->portf.sel1;
+#if defined(PFIE) || defined(__DOXYGEN__)
PFIES = config->portf.ies;
PFIE = config->portf.ie;
+ PFIFG = 0;
+#endif
#endif
PJOUT = config->portj.out;
PJDIR = config->portj.dir;
diff --git a/os/hal/ports/MSP430X/hal_serial_lld.c b/os/hal/ports/MSP430X/hal_serial_lld.c
index 277f6d2..bc002cb 100644
--- a/os/hal/ports/MSP430X/hal_serial_lld.c
+++ b/os/hal/ports/MSP430X/hal_serial_lld.c
@@ -223,10 +223,10 @@ static void usart1_init(const SerialConfig *config) {
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);
+ UCA1IE = UCRXIE;
}
#endif
@@ -237,10 +237,10 @@ static void usart2_init(const SerialConfig *config) {
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);
+ UCA2IE = UCRXIE;
}
#endif
@@ -251,10 +251,10 @@ static void usart3_init(const SerialConfig *config) {
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);
+ UCA3IE = UCRXIE;
}
#endif
diff --git a/os/hal/ports/MSP430X/platform.mk b/os/hal/ports/MSP430X/platform.mk
index b0f256e..6947785 100644
--- a/os/hal/ports/MSP430X/platform.mk
+++ b/os/hal/ports/MSP430X/platform.mk
@@ -2,7 +2,8 @@
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
+ ${CHIBIOS_CONTRIB}/os/hal/ports/MSP430X/hal_pal_lld.c \
+ ${CHIBIOS_CONTRIB}/os/hal/ports/MSP430X/hal_dma_lld.c
# Required include directories
PLATFORMINC = ${CHIBIOS_CONTRIB}/os/hal/ports/MSP430X