aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--os/common/ports/MSP430X/chcore.c7
-rw-r--r--os/common/ports/MSP430X/chcore.h11
-rw-r--r--os/hal/boards/EXP430FR5969/board.c6
-rw-r--r--os/hal/boards/EXP430FR5969/board.h6
-rw-r--r--os/hal/boards/EXP430FR6989/board.c12
-rw-r--r--os/hal/boards/EXP430FR6989/board.h14
-rw-r--r--os/hal/ports/MSP430X/hal_adc_lld.c354
-rw-r--r--os/hal/ports/MSP430X/hal_adc_lld.h516
-rw-r--r--os/hal/ports/MSP430X/hal_dma_lld.c237
-rw-r--r--os/hal/ports/MSP430X/hal_dma_lld.h4
-rw-r--r--os/hal/ports/MSP430X/hal_lld.c4
-rw-r--r--os/hal/ports/MSP430X/hal_lld.h2
-rw-r--r--os/hal/ports/MSP430X/hal_serial_lld.c15
-rw-r--r--os/hal/ports/MSP430X/hal_spi_lld.c24
-rw-r--r--os/hal/ports/MSP430X/hal_spi_lld.h2
-rw-r--r--os/hal/ports/MSP430X/platform.mk3
-rw-r--r--testhal/MSP430X/EXP430FR5969/ADC/Makefile206
-rw-r--r--testhal/MSP430X/EXP430FR5969/ADC/chconf.h274
-rw-r--r--testhal/MSP430X/EXP430FR5969/ADC/halconf.h388
-rw-r--r--testhal/MSP430X/EXP430FR5969/ADC/main.c270
-rw-r--r--testhal/MSP430X/EXP430FR5969/ADC/mcuconf.h68
-rw-r--r--testhal/MSP430X/EXP430FR5969/ADC/msp_vectors.c286
-rw-r--r--testhal/MSP430X/EXP430FR5969/DMA/main.c74
-rw-r--r--testhal/MSP430X/EXP430FR5969/DMA/msp_vectors.c22
-rw-r--r--testhal/MSP430X/EXP430FR5969/SPI/msp_vectors.c24
-rw-r--r--testhal/MSP430X/EXP430FR6989/ADC/Makefile206
-rw-r--r--testhal/MSP430X/EXP430FR6989/ADC/chconf.h274
-rw-r--r--testhal/MSP430X/EXP430FR6989/ADC/halconf.h388
-rw-r--r--testhal/MSP430X/EXP430FR6989/ADC/main.c254
-rw-r--r--testhal/MSP430X/EXP430FR6989/ADC/mcuconf.h68
-rw-r--r--testhal/MSP430X/EXP430FR6989/ADC/msp_vectors.c286
31 files changed, 4070 insertions, 235 deletions
diff --git a/os/common/ports/MSP430X/chcore.c b/os/common/ports/MSP430X/chcore.c
index 7a8d7f2..b9001b0 100644
--- a/os/common/ports/MSP430X/chcore.c
+++ b/os/common/ports/MSP430X/chcore.c
@@ -32,6 +32,8 @@
/* Module exported variables. */
/*===========================================================================*/
+bool __msp430x_in_isr;
+
/*===========================================================================*/
/* Module local types. */
/*===========================================================================*/
@@ -98,6 +100,11 @@ void _port_thread_start(void) {
asm volatile ("mov R5, R12");
asm volatile ("call R4");
#endif
+#if defined(_CHIBIOS_RT_CONF_)
+ chThdExit(MSG_OK);
+#endif
+#if defined(_CHIBIOS_NIL_CONF_)
chSysHalt(0);
+#endif
}
/** @} */
diff --git a/os/common/ports/MSP430X/chcore.h b/os/common/ports/MSP430X/chcore.h
index 3683c1d..9e1efa8 100644
--- a/os/common/ports/MSP430X/chcore.h
+++ b/os/common/ports/MSP430X/chcore.h
@@ -28,6 +28,8 @@
#include <msp430.h>
#include <in430.h>
+extern bool __msp430x_in_isr;
+
/*===========================================================================*/
/* Module constants. */
/*===========================================================================*/
@@ -225,7 +227,7 @@ struct port_context {
* @details This macro must be inserted at the start of all IRQ handlers
* enabled to invoke system APIs.
*/
-#define PORT_IRQ_PROLOGUE()
+#define PORT_IRQ_PROLOGUE() __msp430x_in_isr = true;
/**
* @brief IRQ epilogue code.
@@ -233,6 +235,7 @@ struct port_context {
* enabled to invoke system APIs.
*/
#define PORT_IRQ_EPILOGUE() { \
+ __msp430x_in_isr = false; \
_dbg_check_lock(); \
if (chSchIsPreemptionRequired()) \
chSchDoReschedule(); \
@@ -298,7 +301,7 @@ extern "C" {
* @brief Port-related initialization code.
*/
static inline void port_init(void) {
-
+ __msp430x_in_isr = false;
}
/**
@@ -333,9 +336,7 @@ static inline bool port_irq_enabled(syssts_t sts) {
* @retval true running in ISR mode.
*/
static inline bool port_is_isr_context(void) {
- /* Efficiency would be enhanced by not doing this,
- * because of implementation details */
- return __get_SR_register() & GIE;
+ return __msp430x_in_isr;
}
/**
diff --git a/os/hal/boards/EXP430FR5969/board.c b/os/hal/boards/EXP430FR5969/board.c
index ac48ba0..0643cce 100644
--- a/os/hal/boards/EXP430FR5969/board.c
+++ b/os/hal/boards/EXP430FR5969/board.c
@@ -25,11 +25,11 @@
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_IOPORT1_SEL1},
{VAL_IOPORT2_OUT, VAL_IOPORT2_DIR, VAL_IOPORT2_REN, VAL_IOPORT2_SEL0,
- VAL_IOPORT2_SEL1, VAL_IOPORT2_IES, VAL_IOPORT2_IE},
+ VAL_IOPORT2_SEL1},
{VAL_IOPORT0_OUT, VAL_IOPORT0_DIR, VAL_IOPORT0_REN, VAL_IOPORT0_SEL0,
- VAL_IOPORT0_SEL1, VAL_IOPORT0_IES, VAL_IOPORT0_IE}
+ VAL_IOPORT0_SEL1}
}; /* Set UART TX pin correctly */
#endif /* HAL_USE_PAL */
diff --git a/os/hal/boards/EXP430FR5969/board.h b/os/hal/boards/EXP430FR5969/board.h
index 97103d3..3abe1cc 100644
--- a/os/hal/boards/EXP430FR5969/board.h
+++ b/os/hal/boards/EXP430FR5969/board.h
@@ -65,8 +65,6 @@
#define VAL_IOPORT1_REN 0xFCFE
#define VAL_IOPORT1_SEL0 0x0000
#define VAL_IOPORT1_SEL1 0x0300
-#define VAL_IOPORT1_IES 0x0000
-#define VAL_IOPORT1_IE 0x0000
/*
* Port B setup:
@@ -93,8 +91,6 @@
#define VAL_IOPORT2_REN 0xBDFF
#define VAL_IOPORT2_SEL0 0x0000
#define VAL_IOPORT2_SEL1 0x0000
-#define VAL_IOPORT2_IES 0x0000
-#define VAL_IOPORT2_IE 0x0000
/*
* Port J setup:
@@ -113,8 +109,6 @@
#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
diff --git a/os/hal/boards/EXP430FR6989/board.c b/os/hal/boards/EXP430FR6989/board.c
index a6836cf..475a2ea 100644
--- a/os/hal/boards/EXP430FR6989/board.c
+++ b/os/hal/boards/EXP430FR6989/board.c
@@ -25,17 +25,17 @@
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_IOPORT1_SEL1},
{VAL_IOPORT2_OUT, VAL_IOPORT2_DIR, VAL_IOPORT2_REN, VAL_IOPORT2_SEL0,
- VAL_IOPORT2_SEL1, VAL_IOPORT2_IES, VAL_IOPORT2_IE},
+ VAL_IOPORT2_SEL1},
{VAL_IOPORT3_OUT, VAL_IOPORT3_DIR, VAL_IOPORT3_REN, VAL_IOPORT3_SEL0,
- VAL_IOPORT3_SEL1, VAL_IOPORT3_IES, VAL_IOPORT3_IE},
+ VAL_IOPORT3_SEL1},
{VAL_IOPORT4_OUT, VAL_IOPORT4_DIR, VAL_IOPORT4_REN, VAL_IOPORT4_SEL0,
- VAL_IOPORT4_SEL1, VAL_IOPORT4_IES, VAL_IOPORT4_IE},
+ VAL_IOPORT4_SEL1},
{VAL_IOPORT5_OUT, VAL_IOPORT5_DIR, VAL_IOPORT5_REN, VAL_IOPORT5_SEL0,
- VAL_IOPORT5_SEL1, VAL_IOPORT5_IES, VAL_IOPORT5_IE},
+ VAL_IOPORT5_SEL1},
{VAL_IOPORT0_OUT, VAL_IOPORT0_DIR, VAL_IOPORT0_REN, VAL_IOPORT0_SEL0,
- VAL_IOPORT0_SEL1, VAL_IOPORT0_IES, VAL_IOPORT0_IE}
+ VAL_IOPORT0_SEL1}
}; /* Set UART TX pin correctly */
#endif /* HAL_USE_PAL */
diff --git a/os/hal/boards/EXP430FR6989/board.h b/os/hal/boards/EXP430FR6989/board.h
index 83b8fbb..d5afe29 100644
--- a/os/hal/boards/EXP430FR6989/board.h
+++ b/os/hal/boards/EXP430FR6989/board.h
@@ -69,8 +69,6 @@
#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:
@@ -97,8 +95,6 @@
#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:
@@ -125,8 +121,6 @@
#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:
@@ -153,11 +147,9 @@
#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:
+ * Port E setup:
*
* P9.0 - BoosterPack BP27 (input pullup)
* P9.1 - BoosterPack BP28 (input pullup)
@@ -181,8 +173,6 @@
#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:
@@ -201,8 +191,6 @@
#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
diff --git a/os/hal/ports/MSP430X/hal_adc_lld.c b/os/hal/ports/MSP430X/hal_adc_lld.c
new file mode 100644
index 0000000..42d3cbe
--- /dev/null
+++ b/os/hal/ports/MSP430X/hal_adc_lld.c
@@ -0,0 +1,354 @@
+/*
+ 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 hal_adc_lld.c
+ * @brief MSP430X ADC subsystem low level driver source.
+ *
+ * @addtogroup ADC
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_ADC == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief ADC1 driver identifier.
+ */
+#if (MSP430X_ADC_USE_ADC1 == TRUE) || defined(__DOXYGEN__)
+ADCDriver ADCD1;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static void restart_dma(ADCDriver * adcp) {
+ /* TODO timeouts? */
+ /* Restart DMA transfer */
+ if (adcp->dma.registers == NULL) {
+ /* Acquire a DMA stream because dmaTransfer can be called from ISRs */
+ osalSysLockFromISR();
+ dmaAcquireI(&(adcp->dma), adcp->dma.index);
+ osalSysUnlockFromISR();
+ dmaTransfer(&(adcp->dma), &(adcp->req));
+ }
+ else {
+ dmaTransfer(&(adcp->dma), &(adcp->req));
+ }
+}
+
+static void dma_callback(void * args) {
+ ADCDriver * adcp = (ADCDriver *)args;
+
+ if (adcp->grpp == NULL)
+ return;
+
+ adcp->count++;
+
+ if (adcp->count == adcp->depth / 2) {
+ /* half-full interrupt */
+ _adc_isr_half_code(adcp);
+ }
+
+ if (adcp->count == adcp->depth) {
+ /* full interrupt */
+
+ /* adc_lld_stop_conversion is called automatically here if needed */
+ _adc_isr_full_code(adcp);
+ /* after isr_full, adcp->grpp is only non-NULL if it's a circular group */
+ if (adcp->grpp) {
+ /* Reset the buffer pointer */
+ adcp->req.dest_addr = adcp->samples;
+
+ restart_dma(adcp);
+
+ /* Reset the count */
+ adcp->count = 0;
+
+ /* Start next sequence */
+ adcp->regs->ctl[0] |= ADC12SC;
+ }
+ }
+ else {
+ /* Advance the buffer pointer */
+ adcp->req.dest_addr = adcp->samples + (adcp->req.size * adcp->count);
+
+ restart_dma(adcp);
+
+ /* Start next sequence */
+ adcp->regs->ctl[0] |= ADC12SC;
+ }
+}
+
+static void populate_tlv(ADCDriver * adcp) {
+ uint8_t * tlv_addr = (uint8_t *)TLV_START;
+
+ while (*tlv_addr != TLV_TAGEND && tlv_addr < (uint8_t *)TLV_END) {
+ if (*tlv_addr == TLV_ADC12CAL) {
+ adcp->adc_cal = (msp430x_adc_cal_t *)(tlv_addr + 2);
+ }
+ else if (*tlv_addr == TLV_REFCAL) {
+ adcp->ref_cal = (msp430x_ref_cal_t *)(tlv_addr + 2);
+ }
+ tlv_addr += (tlv_addr[1] + 2);
+ }
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+PORT_IRQ_HANDLER(ADC12_VECTOR) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ switch (__even_in_range(ADC12IV, ADC12IV_ADC12TOVIFG)) {
+
+ case ADC12IV_ADC12OVIFG: {
+ if (ADCD1.grpp == NULL)
+ break;
+ _adc_isr_error_code(&ADCD1, ADC_ERR_OVERFLOW);
+ break;
+ }
+ case ADC12IV_ADC12TOVIFG: {
+ if (ADCD1.grpp == NULL)
+ break;
+ _adc_isr_error_code(&ADCD1, ADC_ERR_AWD);
+ break;
+ }
+ default:
+ osalDbgAssert(false, "unhandled ADC exception");
+ _adc_isr_error_code(&ADCD1, ADC_ERR_UNKNOWN);
+ }
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level ADC driver initialization.
+ *
+ * @notapi
+ */
+void adc_lld_init(void) {
+
+#if MSP430X_ADC_USE_ADC1 == TRUE
+ /* Driver initialization.*/
+ adcObjectInit(&ADCD1);
+ ADCD1.regs = (msp430x_adc_reg_t *)(&ADC12CTL0);
+ populate_tlv(&ADCD1);
+#endif
+}
+
+/**
+ * @brief Configures and activates the ADC peripheral.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_start(ADCDriver * adcp) {
+
+ if (adcp->state == ADC_STOP) {
+ /* Enables the peripheral.*/
+ adcp->regs->ctl[0] = ADC12ON | ADC12MSC;
+ adcp->regs->ctl[1] =
+ MSP430X_ADC1_PDIV | MSP430X_ADC1_DIV | MSP430X_ADC1_SSEL | ADC12SHP;
+ adcp->regs->ctl[3] = ADC12ICH3MAP | ADC12ICH2MAP | ADC12ICH1MAP |
+ ADC12ICH0MAP | ADC12TCMAP | ADC12BATMAP;
+ adcp->regs->ier[2] = ADC12TOVIE | ADC12OVIE;
+ adcp->req.trigger = DMA_TRIGGER_MNEM(ADC12IFG);
+#if MSP430X_ADC_COMPACT_SAMPLES == TRUE
+ adcp->req.data_mode = MSP430X_DMA_SRCWORD | MSP430X_DMA_DSTBYTE;
+#else
+ adcp->req.data_mode = MSP430X_DMA_SRCWORD | MSP430X_DMA_DSTWORD;
+#endif
+ adcp->req.addr_mode = MSP430X_DMA_SRCINCR | MSP430X_DMA_DSTINCR;
+ adcp->req.transfer_mode = MSP430X_DMA_SINGLE;
+ adcp->req.callback.callback = dma_callback;
+ adcp->req.callback.args = adcp;
+
+#if MSP430X_ADC_EXCLUSIVE_DMA == TRUE
+ bool b;
+ if (adcp->config->dma_index < MSP430X_DMA_CHANNELS) {
+ b = dmaAcquireI(&adcp->dma, adcp->config->dma_index);
+ osalDbgAssert(!b, "stream already allocated");
+ }
+ else {
+#endif
+ adcp->dma.registers = NULL;
+#if MSP430X_ADC_EXCLUSIVE_DMA == TRUE
+ }
+#endif
+ }
+ /* Configures the peripheral.*/
+}
+
+/**
+ * @brief Deactivates the ADC peripheral.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_stop(ADCDriver * adcp) {
+
+ if (adcp->state == ADC_READY) {
+/* Resets the peripheral.*/
+
+/* Disables the peripheral.*/
+#if MSP430X_ADC_EXCLUSIVE_DMA == TRUE
+ if (adcp->config->dma_index < MSP430X_DMA_CHANNELS) {
+ dmaRelease(&(adcp->dma));
+ }
+#endif
+ adcp->regs->ctl[0] = 0;
+ }
+}
+
+/**
+ * @brief Starts an ADC conversion.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_start_conversion(ADCDriver * adcp) {
+
+ /* always use sequential transfer mode - this is fine */
+ adcp->regs->ctl[1] |= ADC12CONSEQ0;
+
+ /* set resolution */
+ adcp->regs->ctl[2] |= adcp->grpp->res;
+ /* start from MEM0 */
+ adcp->regs->ctl[3] &= ~(ADC12CSTARTADD_31);
+
+ /* Configure voltage reference */
+ while (REFCTL0 & REFGENBUSY)
+ ;
+ REFCTL0 = adcp->grpp->vref_src;
+
+ for (int i = 0; i < adcp->grpp->num_channels; i++) {
+ osalDbgAssert(adcp->grpp->channels[i] < 32, "invalid channel number");
+ adcp->regs->mctl[i] = adcp->grpp->ref | adcp->grpp->channels[i];
+ }
+
+ adcp->regs->mctl[adcp->grpp->num_channels - 1] |= ADC12EOS;
+
+ adcp->req.source_addr = adcp->regs->mem;
+ adcp->req.dest_addr = adcp->samples;
+ adcp->req.size = adcp->grpp->num_channels;
+ adcp->count = 0;
+
+/* TODO timeouts? */
+#if MSP430X_ADC_EXCLUSIVE_DMA == TRUE
+ if (adcp->config->dma_index >= MSP430X_DMA_CHANNELS) {
+ adcp->dma.index = dmaRequestS(&(adcp->req), TIME_INFINITE);
+ }
+ else {
+ dmaTransfer(&(adcp->dma), &(adcp->req));
+ }
+#else
+ adcp->dma.index = dmaRequestS(&(adcp->req), TIME_INFINITE);
+#endif
+
+ adcp->regs->ctl[0] |= adcp->grpp->rate | ADC12MSC | ADC12ENC | ADC12SC;
+}
+
+/**
+ * @brief Stops an ongoing conversion.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_stop_conversion(ADCDriver * adcp) {
+
+ /* TODO stop DMA transfers here */
+ adcp->regs->ctl[0] &= ~(ADC12ENC | ADC12SC);
+
+#if MSP430X_ADC_EXCLUSIVE_DMA == TRUE
+ if (adcp->config->dma_index >= MSP430X_DMA_CHANNELS) {
+#endif
+ if (adcp->dma.registers != NULL) {
+ dmaRelease(&(adcp->dma));
+ adcp->dma.registers = NULL;
+ }
+#if MSP430X_ADC_EXCLUSIVE_DMA == TRUE
+ }
+#endif
+}
+
+adcsample_t adcMSP430XAdjustResult(ADCConversionGroup * grpp,
+ adcsample_t sample) {
+ uint32_t tmp;
+ uint16_t fact;
+ if (grpp->ref == MSP430X_ADC_VSS_VREF_BUF ||
+ grpp->ref == MSP430X_ADC_VEREF_P_VREF_BUF ||
+ grpp->ref == MSP430X_ADC_VREF_BUF_VCC ||
+ grpp->ref == MSP430X_ADC_VREF_BUF_VEREF_P ||
+ grpp->ref == MSP430X_ADC_VEREF_N_VREF_BUF) {
+ /* Retrieve proper reference correction factor from TLV */
+ fact = (&(ADCD1.ref_cal->CAL_ADC_12VREF_FACTOR))[grpp->vref_src >> 4];
+ /* Calculate corrected value */
+ tmp = (uint32_t)(sample << 1) * (uint32_t)fact;
+ sample = tmp >> 16;
+ }
+
+ /* Gain correction */
+ fact = ADCD1.adc_cal->CAL_ADC_GAIN_FACTOR;
+ tmp = (uint32_t)(sample << 1) * (uint32_t)fact;
+ sample = tmp >> 16;
+
+ /* Offset correction */
+ sample += ADCD1.adc_cal->CAL_ADC_OFFSET;
+
+ return sample;
+}
+
+adcsample_t adcMSP430XAdjustTemp(ADCConversionGroup * grpp,
+ adcsample_t sample) {
+ uint16_t t30;
+ uint16_t t85;
+
+ /* Retrieve proper T = 30 correction value from TLV */
+ t30 = (&(ADCD1.adc_cal->CAL_ADC_12T30))[grpp->vref_src >> 3];
+ /* Retrieve proper T = 85 correction value from TLV */
+ t85 = (&(ADCD1.adc_cal->CAL_ADC_12T30))[(grpp->vref_src >> 3) + 1];
+
+ return ((((int32_t)sample - (int32_t)t30) * (85 - 30)) / (t85 - t30)) + 30;
+}
+
+#endif /* HAL_USE_ADC == TRUE */
+
+/** @} */
diff --git a/os/hal/ports/MSP430X/hal_adc_lld.h b/os/hal/ports/MSP430X/hal_adc_lld.h
new file mode 100644
index 0000000..1cca36b
--- /dev/null
+++ b/os/hal/ports/MSP430X/hal_adc_lld.h
@@ -0,0 +1,516 @@
+/*
+ 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 hal_adc_lld.h
+ * @brief MSP430X ADC subsystem low level driver header.
+ *
+ * @addtogroup ADC
+ * @{
+ */
+
+#ifndef HAL_ADC_LLD_H
+#define HAL_ADC_LLD_H
+
+#if (HAL_USE_ADC == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Sampling rates
+ * @{
+ */
+typedef enum {
+ MSP430X_ADC_SHT_4 = 0x0000,
+ MSP430X_ADC_SHT_8 = 0x1100,
+ MSP430X_ADC_SHT_16 = 0x2200,
+ MSP430X_ADC_SHT_32 = 0x3300,
+ MSP430X_ADC_SHT_64 = 0x4400,
+ MSP430X_ADC_SHT_96 = 0x5500,
+ MSP430X_ADC_SHT_128 = 0x6600,
+ MSP430X_ADC_SHT_192 = 0x7700,
+ MSP430X_ADC_SHT_256 = 0x8800,
+ MSP430X_ADC_SHT_384 = 0x9900,
+ MSP430X_ADC_SHT_512 = 0xAA00
+} MSP430XADCSampleRates;
+/** @} */
+
+/**
+ * @name Resolution
+ * @{
+ */
+typedef enum {
+ MSP430X_ADC_RES_8BIT = 0x0000,
+ MSP430X_ADC_RES_10BIT = 0x0010,
+ MSP430X_ADC_RES_12BIT = 0x0020
+} MSP430XADCResolution;
+/** @} */
+
+/**
+ * @name References
+ * @{
+ */
+typedef enum {
+ MSP430X_ADC_VSS_VCC = 0x0000,
+ MSP430X_ADC_VSS_VREF_BUF = 0x0100,
+ MSP430X_ADC_VSS_VEREF_N = 0x0200,
+ MSP430X_ADC_VSS_VEREF_P_BUF = 0x0300,
+ MSP430X_ADC_VSS_VEREF_P = 0x0400,
+ MSP430X_ADC_VEREF_P_BUF_VCC = 0x0500,
+ MSP430X_ADC_VEREF_P_VCC = 0x0600,
+ MSP430X_ADC_VEREF_P_VREF_BUF = 0x0700,
+ MSP430X_ADC_VREF_BUF_VCC = 0x0900,
+ MSP430X_ADC_VREF_BUF_VEREF_P = 0x0B00,
+ MSP430X_ADC_VEREF_N_VCC = 0x0C00,
+ MSP430X_ADC_VEREF_N_VREF_BUF = 0x0D00,
+ MSP430X_ADC_VEREF_N_VEREF_P = 0x0E00,
+ MSP430X_ADC_VEREF_N_VEREF_P_BUF = 0x0F00
+} MSP430XADCReferences;
+
+typedef enum {
+ MSP430X_REF_1V2 = 0x0000,
+ MSP430X_REF_2V0 = 0x0010,
+ MSP430X_REF_2V5 = 0x0020,
+ MSP430X_REF_1V2_EXT = 0x0002,
+ MSP430X_REF_2V0_EXT = 0x0012,
+ MSP430X_REF_2V5_EXT = 0x0022
+} MSP430XREFSources;
+
+#define MSP430X_REF_NONE MSP430X_REF_1V2
+
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name MSP430X configuration options
+ * @{
+ */
+/**
+ * @brief Stores ADC samples in an 8 bit integer.
+ * @note 10 and 12 bit sampling modes must not be used when this option is
+ * enabled.
+ */
+#if !defined(MSP430X_ADC_COMPACT_SAMPLES) || defined(__DOXYGEN__)
+#define MSP430X_ADC_COMPACT_SAMPLES FALSE
+#endif
+
+/**
+ * @brief ADC1 driver enable switch.
+ * @details If set to @p TRUE the support for ADC1 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(MSP430X_ADC_USE_ADC1) || defined(__DOXYGEN__)
+#define MSP430X_ADC_USE_ADC1 TRUE
+#endif
+
+/**]
+ * @brief Exclusive DMA enable switch.
+ * @details If set to @p TRUE the support for exclusive DMA is included.
+ * @note This increases the size of the compiled executable somewhat.
+ * @note The default is @p FALSE.
+ */
+#if !defined(MSP430X_ADC_EXCLUSIVE_DMA) || defined(__DOXYGEN__)
+#define MSP430X_ADC_EXCLUSIVE_DMA FALSE
+#endif
+
+#if MSP430X_ADC_USE_ADC1
+
+/**
+ * @brief ADC1 clock source configuration
+ */
+#if !defined(MSP430X_ADC1_CLK_SRC)
+#define MSP430X_ADC1_CLK_SRC MSP430X_MODCLK
+#endif
+
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if MSP430X_ADC_USE_ADC1
+
+#if !defined(__MSP430_HAS_ADC12_B__)
+#error "No ADC present or ADC version not supported"
+#endif
+
+#if (MSP430X_ADC1_CLK_SRC == MSP430X_MODCLK)
+#define MSP430X_ADC1_CLK_FREQ MSP430X_MODCLK_FREQ
+#define MSP430X_ADC1_SSEL ADC12SSEL_0
+#elif (MSP430X_ADC1_CLK_SRC == MSP430X_ACLK)
+#define MSP430X_ADC1_CLK_FREQ MSP430X_ACLK_FREQ
+#define MSP430X_ADC1_SSEL ADC12SSEL_1
+#elif (MSP430X_ADC1_CLK_SRC == MSP430X_MCLK)
+#define MSP$30X_ADC1_CLK_FREQ MSP430X_MCLK_FREQ
+#define MSP430X_ADC1_SSEL ADC12SSEL_2
+#elif (MSP430X_ADC1_CLK_SRC == MSP430SMCLK)
+#define MSP430X_ADC1_CLK_FREQ MSP430X_SMCLK_FREQ
+#define MSP430X_ADC1_SSEL ADC12SSEL_3
+#else
+#error "Invalid ADC1 clock source requested!"
+#endif
+
+#if !defined(MSP430X_ADC1_FREQ)
+#warning "ADC clock frequency not defined - assuming 1 for all dividers"
+#define MSP430X_ADC1_DIV_CALC(x) (x == 1)
+#else
+#define MSP430X_ADC1_DIV_CALC(x) \
+ ((MSP430X_ADC1_CLK_FREQ / x) == MSP430X_ADC1_FREQ)
+#endif
+
+/**
+ * @brief ADC1 prescaler calculations
+ */
+#if MSP430X_ADC1_DIV_CALC(1)
+#define MSP430X_ADC1_PDIV ADC12PDIV__1
+#define MSP430X_ADC1_DIV ADC12DIV_0
+#elif MSP430X_ADC1_DIV_CALC(2)
+#define MSP430X_ADC1_PDIV ADC12PDIV__1
+#define MSP430X_ADC1_DIV ADC12DIV_1
+#elif MSP430X_ADC1_DIV_CALC(3)
+#define MSP430X_ADC1_PDIV ADC12PDIV__1
+#define MSP430X_ADC1_DIV ADC12DIV_2
+#elif MSP430X_ADC1_DIV_CALC(4)
+#define MSP430X_ADC1_PDIV ADC12PDIV__4
+#define MSP430X_ADC1_DIV ADC12DIV_0
+#elif MSP430X_ADC1_DIV_CALC(5)
+#define MSP430X_ADC1_PDIV ADC12PDIV__1
+#define MSP430X_ADC1_DIV ADC12DIV_4
+#elif MSP430X_ADC1_DIV_CALC(6)
+#define MSP430X_ADC1_PDIV ADC12PDIV__1
+#define MSP430X_ADC1_DIV ADC12DIV_5
+#elif MSP430X_ADC1_DIV_CALC(7)
+#define MSP430X_ADC1_PDIV ADC12PDIV__1
+#define MSP430X_ADC1_DIV ADC12DIV_6
+#elif MSP430X_ADC1_DIV_CALC(8)
+#define MSP430X_ADC1_PDIV ADC12PDIV__4
+#define MSP430X_ADC1_DIV ADC12DIV_2
+#elif MSP430X_ADC1_DIV_CALC(12)
+#define MSP430X_ADC1_PDIV ADC12PDIV__4
+#define MSP430X_ADC1_DIV ADC12DIV_2
+#elif MSP430X_ADC1_DIV_CALC(16)
+#define MSP430X_ADC1_PDIV ADC12PDIV__4
+#define MSP430X_ADC1_DIV ADC12DIV_3
+#elif MSP430X_ADC1_DIV_CALC(20)
+#define MSP430X_ADC1_PDIV ADC12PDIV__4
+#define MSP430X_ADC1_DIV ADC12DIV_4
+#elif MSP430X_ADC1_DIV_CALC(24)
+#define MSP430X_ADC1_PDIV ADC12PDIV__4
+#define MSP430X_ADC1_DIV ADC12DIV_5
+#elif MSP430X_ADC1_DIV_CALC(28)
+#define MSP430X_ADC1_PDIV ADC12PDIV__4
+#define MSP430X_ADC1_DIV ADC12DIV_6
+#elif MSP430X_ADC1_DIV_CALC(32)
+#define MSP430X_ADC1_PDIV ADC12PDIV__32
+#define MSP430X_ADC1_DIV ADC12DIV_0
+#elif MSP430X_ADC1_DIV_CALC(64)
+#define MSP430X_ADC1_PDIV ADC12PDIV__64
+#define MSP430X_ADC1_DIV ADC12DIV_0
+#elif MSP430X_ADC1_DIV_CALC(96)
+#define MSP430X_ADC1_PDIV ADC12PDIV__32
+#define MSP430X_ADC1_DIV ADC12DIV_2
+#elif MSP430X_ADC1_DIV_CALC(128)
+#define MSP430X_ADC1_PDIV ADC12PDIV__64
+#define MSP430X_ADC1_DIV ADC12DIV_1
+#elif MSP430X_ADC1_DIV_CALC(160)
+#define MSP430X_ADC1_PDIV ADC12PDIV__32
+#define MSP430X_ADC1_DIV ADC12DIV_4
+#elif MSP430X_ADC1_DIV_CALC(192)
+#define MSP430X_ADC1_PDIV ADC12PDIV__64
+#define MSP430X_ADC1_DIV ADC12DIV_2
+#elif MSP430X_ADC1_DIV_CALC(224)
+#define MSP430X_ADC1_PDIV ADC12PDIV__32
+#define MSP430X_ADC1_DIV ADC12DIV_6
+#elif MSP430X_ADC1_DIV_CALC(256)
+#define MSP430X_ADC1_PDIV ADC12PDIV__64
+#define MSP430X_ADC1_DIV ADC12DIV_3
+#elif MSP430X_ADC1_DIV_CALC(320)
+#define MSP430X_ADC1_PDIV ADC12PDIV__64
+#define MSP430X_ADC1_DIV ADC12DIV_4
+#elif MSP430X_ADC1_DIV_CALC(384)
+#define MSP430X_ADC1_PDIV ADC12PDIV__64
+#define MSP430X_ADC1_DIV ADC12DIV_5
+#elif MSP430X_ADC1_DIV_CALC(448)
+#define MSP430X_ADC1_PDIV ADC12PDIV__64
+#define MSP430X_ADC1_DIV ADC12DIV_6
+#elif MSP430X_ADC1_DIV_CALC(512)
+#define MSP430X_ADC1_PDIV ADC12PDIV__64
+#define MSP430X_ADC1_DIV ADC12DIV_7
+#else
+#error "MSP430X_ADC1_FREQ not achievable with MSP430X_ADC1_CLK_SRC"
+#endif
+
+#endif /* MSP430X_ADC_USE_ADC1 */
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief ADC sample data type.
+ */
+#if !MSP430X_ADC_COMPACT_SAMPLES || defined(__DOXYGEN__)
+typedef uint16_t adcsample_t;
+#else
+typedef uint8_t adcsample_t;
+#endif
+
+/**
+ * @brief Channels number in a conversion group.
+ */
+typedef uint8_t adc_channels_num_t;
+
+/**
+ * @brief Possible ADC failure causes.
+ * @note Error codes are architecture dependent and should not relied
+ * upon.
+ */
+typedef enum {
+ ADC_ERR_UNKNOWN = 0, /**< Unknown error has occurred */
+ ADC_ERR_OVERFLOW = 1, /**< ADC overflow condition. */
+ ADC_ERR_AWD = 2 /**< Analog watchdog triggered. */
+} adcerror_t;
+
+/**
+ * @brief Type of a structure representing an ADC driver.
+ */
+typedef struct ADCDriver ADCDriver;
+
+/**
+ * @brief ADC notification callback type.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object triggering the
+ * callback
+ * @param[in] buffer pointer to the most recent samples data
+ * @param[in] n number of buffer rows available starting from @p buffer
+ */
+typedef void (*adccallback_t)(ADCDriver * adcp, adcsample_t * buffer, size_t n);
+
+/**
+ * @brief ADC error callback type.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object triggering the
+ * callback
+ * @param[in] err ADC error code
+ */
+typedef void (*adcerrorcallback_t)(ADCDriver * adcp, adcerror_t err);
+
+/**
+ * @brief MSP430X ADC register structure.
+ */
+typedef struct {
+ uint16_t ctl[4];
+ uint16_t lo;
+ uint16_t hi;
+ uint16_t ifgr[3];
+ uint16_t ier[3];
+ uint16_t iv;
+ uint16_t padding[3];
+ uint16_t mctl[32];
+ uint16_t mem[32];
+} msp430x_adc_reg_t;
+
+/**
+ * @brief MSP430X ADC calibration structure.
+ */
+typedef struct {
+ uint16_t CAL_ADC_GAIN_FACTOR;
+ uint16_t CAL_ADC_OFFSET;
+ uint16_t CAL_ADC_12T30;
+ uint16_t CAL_ADC_12T85;
+ uint16_t CAL_ADC_20T30;
+ uint16_t CAL_ADC_20T85;
+ uint16_t CAL_ADC_25T30;
+ uint16_t CAL_ADC_25T85;
+} msp430x_adc_cal_t;
+
+/**
+ * @brief MSP430X REF calibration structure.
+ */
+typedef struct {
+ uint16_t CAL_ADC_12VREF_FACTOR;
+ uint16_t CAL_ADC_20VREF_FACTOR;
+ uint16_t CAL_ADC_25VREF_FACTOR;
+} msp430x_ref_cal_t;
+
+/**
+ * @brief Conversion group configuration structure.
+ * @details This implementation-dependent structure describes a conversion
+ * operation.
+ * @note The use of this configuration structure requires knowledge of
+ * MSP430X ADC cell registers interface, please refer to the MSP430X
+ * reference manual for details.
+ */
+typedef struct {
+ /**
+ * @brief Enables the circular buffer mode for the group.
+ */
+ bool circular;
+ /**
+ * @brief Number of the analog channels belonging to the conversion group.
+ */
+ adc_channels_num_t num_channels;
+ /**
+ * @brief Callback function associated to the group or @p NULL.
+ */
+ adccallback_t end_cb;
+ /**
+ * @brief Error callback or @p NULL.
+ */
+ adcerrorcallback_t error_cb;
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Sequence of analog channels belonging to the conversion group.
+ * @note Only the first num_channels are valid.
+ */
+ uint8_t channels[32];
+ /**
+ * @brief Sample resolution
+ */
+ MSP430XADCResolution res;
+ /**
+ * @brief Sampling time in clock cycles
+ */
+ MSP430XADCSampleRates rate;
+ /**
+ * @brief Voltage references to use
+ */
+ MSP430XADCReferences ref;
+ /**
+ * @brief VREF source
+ */
+ MSP430XREFSources vref_src;
+} ADCConversionGroup;
+
+/**
+ * @brief Driver configuration structure.
+ * @note It could be empty on some architectures.
+ */
+typedef struct {
+#if MSP430X_ADC_EXCLUSIVE_DMA == TRUE || defined(__DOXYGEN__)
+ /**
+ * @brief The index of the DMA channel.
+ * @note This may be >MSP430X_DMA_CHANNELS to indicate that exclusive DMA
+ * is not used.
+ */
+ uint8_t dma_index;
+#endif
+} ADCConfig;
+
+/**
+ * @brief Structure representing an ADC driver.
+ */
+struct ADCDriver {
+ /**
+ * @brief Driver state.
+ */
+ adcstate_t state;
+ /**
+ * @brief Current configuration data.
+ */
+ const ADCConfig * config;
+ /**
+ * @brief Current samples buffer pointer or @p NULL.
+ */
+ adcsample_t * samples;
+ /**
+ * @brief Current samples buffer depth or @p 0.
+ */
+ size_t depth;
+ /**
+ * @brief Current conversion group pointer or @p NULL.
+ */
+ const ADCConversionGroup * grpp;
+#if (ADC_USE_WAIT == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Waiting thread.
+ */
+ thread_reference_t thread;
+#endif
+#if (ADC_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Mutex protecting the peripheral.
+ */
+ mutex_t mutex;
+#endif
+#if defined(ADC_DRIVER_EXT_FIELDS)
+ ADC_DRIVER_EXT_FIELDS
+#endif
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Base address of ADC12_B registers
+ */
+ msp430x_adc_reg_t * regs;
+ /**
+ * @brief DMA request structure
+ */
+ msp430x_dma_req_t req;
+ /**
+ * @brief ADC calibration structure from TLV
+ */
+ msp430x_adc_cal_t * adc_cal;
+ /**
+ * @brief REF calibration structure from TLV
+ */
+ msp430x_ref_cal_t * ref_cal;
+ /**
+ * @brief Count of times DMA callback has been called
+ */
+ uint8_t count;
+ /**
+ * @brief DMA stream
+ */
+ msp430x_dma_ch_t dma;
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if (MSP430X_ADC_USE_ADC1 == TRUE) && !defined(__DOXYGEN__)
+extern ADCDriver ADCD1;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+void adc_lld_init(void);
+void adc_lld_start(ADCDriver * adcp);
+void adc_lld_stop(ADCDriver * adcp);
+void adc_lld_start_conversion(ADCDriver * adcp);
+void adc_lld_stop_conversion(ADCDriver * adcp);
+adcsample_t adcMSP430XAdjustResult(ADCConversionGroup * grpp,
+ adcsample_t sample);
+adcsample_t adcMSP430XAdjustTemp(ADCConversionGroup * grpp, adcsample_t sample);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_ADC == TRUE */
+
+#endif /* HAL_ADC_LLD_H */
+
+/** @} */
diff --git a/os/hal/ports/MSP430X/hal_dma_lld.c b/os/hal/ports/MSP430X/hal_dma_lld.c
index 2e17afa..82bf39f 100644
--- a/os/hal/ports/MSP430X/hal_dma_lld.c
+++ b/os/hal/ports/MSP430X/hal_dma_lld.c
@@ -44,9 +44,8 @@ static msp430x_dma_ch_reg_t * const dma_channels =
(msp430x_dma_ch_reg_t *)&DMA0CTL;
static msp430x_dma_cb_t callbacks[MSP430X_DMA_CHANNELS];
-#if CH_CFG_USE_SEMAPHORES
-static semaphore_t dma_lock;
-#endif
+static threads_queue_t dma_queue;
+static unsigned int queue_length;
/*===========================================================================*/
/* Driver local functions. */
@@ -88,11 +87,9 @@ PORT_IRQ_HANDLER(DMA_VECTOR) {
index = (DMAIV >> 1) - 1;
if (index < MSP430X_DMA_CHANNELS) {
-#if CH_CFG_USE_SEMAPHORES
- chSysLockFromISR();
- chSemSignalI(&dma_lock);
- chSysUnlockFromISR();
-#endif
+ osalSysLockFromISR();
+ osalThreadDequeueNextI(&dma_queue, MSG_OK);
+ osalSysUnlockFromISR();
msp430x_dma_cb_t * cb = &callbacks[index];
@@ -115,9 +112,7 @@ PORT_IRQ_HANDLER(DMA_VECTOR) {
* @init
*/
void dmaInit(void) {
-#if CH_CFG_USE_SEMAPHORES
- chSemObjectInit(&dma_lock, MSP430X_DMA_CHANNELS);
-#endif
+ osalThreadQueueObjectInit(&dma_queue);
}
/**
@@ -127,134 +122,124 @@ void dmaInit(void) {
* 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.
+ *
+ * @sclass
*/
-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 = chSemWaitTimeoutS(&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;
+int dmaRequestS(msp430x_dma_req_t * request, systime_t timeout) {
+
+ osalDbgCheckClassS();
+
+ /* Check if a DMA channel is available */
+ if (queue_length >= MSP430X_DMA_CHANNELS) {
+ msg_t queueresult = osalThreadEnqueueTimeoutS(&dma_queue, timeout);
+ if (queueresult != MSG_OK)
+ return -1;
+ }
+
+ /* 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;
}
-#endif
+ }
+
+ /* Make the request */
+ init_request(request, i);
+
+ return i;
+}
- /* Make the request */
- init_request(request, i);
+/**
+ * @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.
+ *
+ * @iclass
+ */
+bool dmaAcquireI(msp430x_dma_ch_t * channel, uint8_t index) {
+
+ osalDbgCheckClassI();
- return false;
+ /* Is the channel already acquired? */
+ osalDbgAssert(index < MSP430X_DMA_CHANNELS, "invalid channel index");
+ if (dma_channels[index].ctl & DMADT_4) {
+ return true;
}
- /**
- * @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 */
+ queue_length++;
-/* 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)
+ ;
- while (dma_channels[index].ctl & DMAEN)
- ;
+ /* Acquire the channel in an idle mode */
+ dma_trigger_set(index, DMA_TRIGGER_MNEM(DMAREQ));
+ dma_channels[index].sz = 0;
+ dma_channels[index].ctl = DMAEN | DMAABORT | DMADT_4;
- dma_trigger_set(index, DMA_TRIGGER_MNEM(DMAREQ));
- dma_channels[index].sz = 0;
- dma_channels[index].ctl = DMAEN | DMAABORT | DMADT_4;
+ channel->registers = dma_channels + index;
+ channel->index = index;
+ channel->cb = callbacks + index;
+
+ return false;
+}
- channel->registers = dma_channels + index;
- channel->index = index;
- channel->cb = callbacks + index;
+/**
+ * @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) {
- return false;
- }
+ dma_trigger_set(channel->index, request->trigger);
+ /**(channel->ctl) = request->trigger;*/
- /**
- * @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) {
-
- dma_trigger_set(channel->index, request->trigger);
- /**(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();
- }
+ channel->cb->callback = request->callback.callback;
+ channel->cb->args = request->callback.args;
- /**
- * @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);
-
- /* Release the channel in an idle mode */
- channel->registers->ctl = DMAABORT;
-
-/* release the DMA counter */
-#if CH_CFG_USE_SEMAPHORES
- chSemSignal(&dma_lock);
-#endif
- }
+ 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 */
+}
+
+/**
+ * @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) {
+ syssts_t sts;
+
+ sts = osalSysGetStatusAndLockX();
+ osalDbgCheck(channel != NULL);
+
+ /* Release the channel in an idle mode */
+ channel->registers->ctl = DMAABORT;
+
+ /* release the DMA counter */
+ osalThreadDequeueAllI(&dma_queue, MSG_RESET);
+ queue_length = 0;
+ osalSysRestoreStatusX(sts);
+}
#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
index d1495d2..f558e78 100644
--- a/os/hal/ports/MSP430X/hal_dma_lld.h
+++ b/os/hal/ports/MSP430X/hal_dma_lld.h
@@ -159,8 +159,8 @@ typedef struct {
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);
+int dmaRequestS(msp430x_dma_req_t * request, systime_t timeout);
+bool dmaAcquireI(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);
diff --git a/os/hal/ports/MSP430X/hal_lld.c b/os/hal/ports/MSP430X/hal_lld.c
index 872fe97..812a0cf 100644
--- a/os/hal/ports/MSP430X/hal_lld.c
+++ b/os/hal/ports/MSP430X/hal_lld.c
@@ -82,6 +82,10 @@ void hal_lld_init(void) {
} while (SFRIFG1 & OFIFG);
#endif
CSCTL0_H = 0xFF; /* Lock clock system */
+
+#if (HAL_USE_DMA == TRUE)
+ dmaInit();
+#endif
}
/** @} */
diff --git a/os/hal/ports/MSP430X/hal_lld.h b/os/hal/ports/MSP430X/hal_lld.h
index 9549453..62f07e9 100644
--- a/os/hal/ports/MSP430X/hal_lld.h
+++ b/os/hal/ports/MSP430X/hal_lld.h
@@ -25,6 +25,8 @@
#ifndef _HAL_LLD_H_
#define _HAL_LLD_H_
+#include "hal_dma_lld.h"
+
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
diff --git a/os/hal/ports/MSP430X/hal_serial_lld.c b/os/hal/ports/MSP430X/hal_serial_lld.c
index 8f22650..feb00ac 100644
--- a/os/hal/ports/MSP430X/hal_serial_lld.c
+++ b/os/hal/ports/MSP430X/hal_serial_lld.c
@@ -378,8 +378,7 @@ PORT_IRQ_HANDLER(USCI_A0_VECTOR) {
break;
default: /* other interrupts */
- while (1)
- ;
+ osalDbgAssert(false, "unhandled serial interrupt");
break;
}
@@ -433,11 +432,11 @@ PORT_IRQ_HANDLER(USCI_A1_VECTOR) {
if (oqIsEmptyI(&SD1.oqueue))
chnAddFlagsI(&SD1, CHN_TRANSMISSION_END);
UCA1IE &= ~UCTXCPTIE;
+ osalSysUnlockFromISR();
break;
default: /* other interrupts */
- while (1)
- ;
+ osalDbgAssert(false, "unhandled serial interrupt");
break;
}
@@ -491,11 +490,11 @@ PORT_IRQ_HANDLER(USCI_A2_VECTOR) {
if (oqIsEmptyI(&SD2.oqueue))
chnAddFlagsI(&SD2, CHN_TRANSMISSION_END);
UCA2IE &= ~UCTXCPTIE;
+ osalSysUnlockFromISR();
break;
default: /* other interrupts */
- while (1)
- ;
+ osalDbgAssert(false, "unhandled serial interrupt");
break;
}
@@ -549,11 +548,11 @@ PORT_IRQ_HANDLER(USCI_A3_VECTOR) {
if (oqIsEmptyI(&SD3.oqueue))
chnAddFlagsI(&SD3, CHN_TRANSMISSION_END);
UCA3IE &= ~UCTXCPTIE;
+ osalSysUnlockFromISR();
break;
default: /* other interrupts */
- while (1)
- ;
+ osalDbgAssert(false, "unhandled serial interrupt");
break;
}
diff --git a/os/hal/ports/MSP430X/hal_spi_lld.c b/os/hal/ports/MSP430X/hal_spi_lld.c
index 3768487..3a54b1e 100644
--- a/os/hal/ports/MSP430X/hal_spi_lld.c
+++ b/os/hal/ports/MSP430X/hal_spi_lld.c
@@ -104,21 +104,21 @@ static uint16_t dummyrx;
static void init_transfer(SPIDriver * spip) {
#if MSP430X_SPI_EXCLUSIVE_DMA == TRUE || defined(__DOXYGEN__)
- if (spip->config->dmarx_index > MSP430X_DMA_CHANNELS) {
- dmaRequest(&(spip->rx_req), TIME_INFINITE);
+ if (spip->config->dmarx_index >= MSP430X_DMA_CHANNELS) {
+ dmaRequestS(&(spip->rx_req), TIME_INFINITE);
}
else {
dmaTransfer(&(spip->dmarx), &(spip->rx_req));
}
- if (spip->config->dmatx_index > MSP430X_DMA_CHANNELS) {
- dmaRequest(&(spip->tx_req), TIME_INFINITE);
+ if (spip->config->dmatx_index >= MSP430X_DMA_CHANNELS) {
+ dmaRequestS(&(spip->tx_req), TIME_INFINITE);
}
else {
dmaTransfer(&(spip->dmatx), &(spip->tx_req));
}
#else
- dmaRequest(&(spip->rx_req), TIME_INFINITE);
- dmaRequest(&(spip->tx_req), TIME_INFINITE);
+ dmaRequestS(&(spip->rx_req), TIME_INFINITE);
+ dmaRequestS(&(spip->tx_req), TIME_INFINITE);
#endif
*(spip->ifg) |= UCTXIFG;
@@ -325,11 +325,11 @@ void spi_lld_start(SPIDriver * spip) {
/* Claim DMA streams here */
bool b;
if (spip->config->dmatx_index < MSP430X_DMA_CHANNELS) {
- b = dmaAcquire(&(spip->dmatx), spip->config->dmatx_index);
+ b = dmaAcquireI(&(spip->dmatx), spip->config->dmatx_index);
osalDbgAssert(!b, "stream already allocated");
}
if (spip->config->dmarx_index < MSP430X_DMA_CHANNELS) {
- b = dmaAcquire(&(spip->dmarx), spip->config->dmarx_index);
+ b = dmaAcquireI(&(spip->dmarx), spip->config->dmarx_index);
osalDbgAssert(!b, "stream already allocated");
}
#endif /* MSP430X_SPI_EXCLUSIVE_DMA */
@@ -407,8 +407,12 @@ void spi_lld_stop(SPIDriver * spip) {
if (spip->state == SPI_READY) {
/* Disables the peripheral.*/
#if MSP430X_SPI_EXCLUSIVE_DMA == TRUE
- dmaRelease(&(spip->dmatx));
- dmaRelease(&(spip->dmarx));
+ if (spip->config->dmatx_index < MSP430X_DMA_CHANNELS) {
+ dmaRelease(&(spip->dmatx));
+ }
+ if (spip->config->dmarx_index < MSP430X_DMA_CHANNELS) {
+ dmaRelease(&(spip->dmarx));
+ }
#endif
spip->regs->ctlw0 = UCSWRST;
}
diff --git a/os/hal/ports/MSP430X/hal_spi_lld.h b/os/hal/ports/MSP430X/hal_spi_lld.h
index 0ca4c67..949a8a0 100644
--- a/os/hal/ports/MSP430X/hal_spi_lld.h
+++ b/os/hal/ports/MSP430X/hal_spi_lld.h
@@ -118,7 +118,7 @@
* @note This increases the size of the compiled executable somewhat.
* @note The default is @p FALSE.
*/
-#if !defined(MSP430X_SPI_EXCLUSIVE_DMA) | defined(__DOXYGEN__)
+#if !defined(MSP430X_SPI_EXCLUSIVE_DMA) || defined(__DOXYGEN__)
#define MSP430X_SPI_EXCLUSIVE_DMA FALSE
#endif
diff --git a/os/hal/ports/MSP430X/platform.mk b/os/hal/ports/MSP430X/platform.mk
index 832814b..627a2f0 100644
--- a/os/hal/ports/MSP430X/platform.mk
+++ b/os/hal/ports/MSP430X/platform.mk
@@ -4,7 +4,8 @@ PLATFORMSRC = ${CHIBIOS_CONTRIB}/os/hal/ports/MSP430X/hal_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_dma_lld.c \
- ${CHIBIOS_CONTRIB}/os/hal/ports/MSP430X/hal_spi_lld.c
+ ${CHIBIOS_CONTRIB}/os/hal/ports/MSP430X/hal_spi_lld.c \
+ ${CHIBIOS_CONTRIB}/os/hal/ports/MSP430X/hal_adc_lld.c
# Required include directories
PLATFORMINC = ${CHIBIOS_CONTRIB}/os/hal/ports/MSP430X
diff --git a/testhal/MSP430X/EXP430FR5969/ADC/Makefile b/testhal/MSP430X/EXP430FR5969/ADC/Makefile
new file mode 100644
index 0000000..cf81f18
--- /dev/null
+++ b/testhal/MSP430X/EXP430FR5969/ADC/Makefile
@@ -0,0 +1,206 @@
+##############################################################################
+# Build global options
+# NOTE: Can be overridden externally.
+#
+
+# Optimization level, can be [0, 1, 2, 3, s].
+# 0 = turn off optimization. s = optimize for size.
+# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
+OPTIMIZE = 0
+
+# Debugging format.
+DEBUG =
+#DEBUG = stabs
+
+# Memory/data model
+MODEL = small
+
+# Object files directory
+# To put object files in current directory, use a dot (.), do NOT make
+# this an empty or blank macro!
+OBJDIR = .
+
+# Compiler flag to set the C Standard level.
+# c89 = "ANSI" C
+# gnu89 = c89 plus GCC extensions
+# c99 = ISO C99 standard (not yet fully implemented)
+# gnu99 = c99 plus GCC extensions
+CSTANDARD = -std=gnu11
+
+# Compiler options here.
+ifeq ($(USE_OPT),)
+ USE_OPT = -O$(OPTIMIZE) -g$(DEBUG)
+ USE_OPT += -funsigned-char -fshort-enums
+endif
+
+# C specific options here (added to USE_OPT).
+ifeq ($(USE_COPT),)
+ USE_COPT =
+endif
+
+# C++ specific options here (added to USE_OPT).
+ifeq ($(USE_CPPOPT),)
+ USE_CPPOPT = -fno-rtti
+endif
+
+# Enable this if you want the linker to remove unused code and data
+ifeq ($(USE_LINK_GC),)
+ USE_LINK_GC = yes
+endif
+
+# Linker extra options here.
+ifeq ($(USE_LDOPT),)
+ USE_LDOPT =
+endif
+
+# Enable this if you want link time optimizations (LTO)
+ifeq ($(USE_LTO),)
+ USE_LTO = no
+endif
+
+# Enable the selected hardware multiplier
+ifeq ($(USE_HWMULT),)
+ USE_HWMULT = f5series
+endif
+
+# Enable this if you want to see the full log while compiling.
+ifeq ($(USE_VERBOSE_COMPILE),)
+ USE_VERBOSE_COMPILE = yes
+endif
+
+# If enabled, this option makes the build process faster by not compiling
+# modules not used in the current configuration.
+ifeq ($(USE_SMART_BUILD),)
+ USE_SMART_BUILD = yes
+endif
+
+#
+# Build global options
+##############################################################################
+
+##############################################################################
+# Architecture or project specific options
+#
+
+# Stack size to be allocated to the idle thread stack. This stack is
+# the stack used by the main() thread.
+ifeq ($(USE_IDLE_STACKSIZE),)
+ USE_IDLE_STACKSIZE = 0xC00
+endif
+
+#
+# Architecture or project specific options
+##############################################################################
+
+##############################################################################
+# Project, sources and paths
+#
+
+# Define project name here
+PROJECT = nil
+
+# Imported source files and paths
+CHIBIOS = ../../../../../ChibiOS-RT
+CHIBIOS_CONTRIB = ../../../..
+# Startup files.
+include $(CHIBIOS_CONTRIB)/os/common/startup/MSP430X/compilers/GCC/mk/startup_msp430fr5xxx.mk
+# HAL-OSAL files (optional).
+include $(CHIBIOS)/os/hal/hal.mk
+include $(CHIBIOS_CONTRIB)/os/hal/boards/EXP430FR5969/board.mk
+include $(CHIBIOS_CONTRIB)/os/hal/ports/MSP430X/platform.mk
+include $(CHIBIOS)/os/hal/osal/nil/osal.mk
+# RTOS files (optional).
+include $(CHIBIOS)/os/nil/nil.mk
+include $(CHIBIOS_CONTRIB)/os/common/ports/MSP430X/compilers/GCC/mk/port.mk
+# Other files (optional).
+
+# Define linker script file here
+LDSCRIPT = $(STARTUPLD)/msp430fr5969.ld
+
+# C sources
+CSRC = $(STARTUPSRC) \
+ $(KERNSRC) \
+ $(PORTSRC) \
+ $(OSALSRC) \
+ $(HALSRC) \
+ $(PLATFORMSRC) \
+ $(BOARDSRC) \
+ $(TESTSRC) \
+ msp_vectors.c \
+ main.c
+
+# C++ sources
+CPPSRC =
+
+# List ASM source files here
+ASMSRC = $(STARTUPASM) $(PORTASM) $(OSALASM)
+
+INCDIR = $(CHIBIOS)/os/license \
+ $(STARTUPINC) $(KERNINC) $(PORTINC) $(OSALINC) \
+ $(HALINC) $(PLATFORMINC) $(BOARDINC) $(TESTINC) \
+ $(CHIBIOS)/os/various
+
+#
+# Project, sources and paths
+##############################################################################
+
+##############################################################################
+# Compiler settings
+#
+
+MCU = msp430fr5969
+
+TRGT = msp430-elf-
+CC = $(TRGT)gcc
+CPPC = $(TRGT)g++
+# Enable loading with g++ only if you need C++ runtime support.
+# NOTE: You can use C++ even without C++ support if you are careful. C++
+# runtime support makes code size explode.
+LD = $(TRGT)gcc
+#LD = $(TRGT)g++
+CP = $(TRGT)objcopy
+AS = $(TRGT)gcc -x assembler-with-cpp
+AR = $(TRGT)ar
+OD = $(TRGT)objdump
+SZ = $(TRGT)size
+HEX = $(CP) -O ihex
+BIN = $(CP) -O binary
+
+# MSP430-specific options here
+MOPT = -m$(MODEL)
+
+# Define C warning options here
+CWARN = -Wall -Wextra -Wundef -Wstrict-prototypes
+
+# Define C++ warning options here
+CPPWARN = -Wall -Wextra -Wundef
+
+#
+# Compiler settings
+##############################################################################
+
+##############################################################################
+# Start of user section
+#
+
+# List all user C define here, like -D_DEBUG=1
+UDEFS =
+
+# Define ASM defines here
+UADEFS =
+
+# List all user directories here
+UINCDIR =
+
+# List the user directory to look for the libraries here
+ULIBDIR =
+
+# List all user libraries here
+ULIBS =
+
+#
+# End of user defines
+##############################################################################
+
+RULESPATH = $(CHIBIOS_CONTRIB)/os/common/startup/MSP430X/compilers/GCC
+include $(RULESPATH)/rules.mk
diff --git a/testhal/MSP430X/EXP430FR5969/ADC/chconf.h b/testhal/MSP430X/EXP430FR5969/ADC/chconf.h
new file mode 100644
index 0000000..3b7a8e1
--- /dev/null
+++ b/testhal/MSP430X/EXP430FR5969/ADC/chconf.h
@@ -0,0 +1,274 @@
+/*
+ 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 nilconf.h
+ * @brief Configuration file template.
+ * @details A copy of this file must be placed in each project directory, it
+ * contains the application specific kernel settings.
+ *
+ * @addtogroup config
+ * @details Kernel related settings and hooks.
+ * @{
+ */
+
+#ifndef CHCONF_H
+#define CHCONF_H
+
+#define _CHIBIOS_NIL_CONF_
+
+/*===========================================================================*/
+/**
+ * @name Kernel parameters and options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Number of user threads in the application.
+ * @note This number is not inclusive of the idle thread which is
+ * Implicitly handled.
+ */
+#define CH_CFG_NUM_THREADS 1
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name System timer settings
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief System time counter resolution.
+ * @note Allowed values are 16 or 32 bits.
+ */
+#define CH_CFG_ST_RESOLUTION 16
+
+/**
+ * @brief System tick frequency.
+ * @note This value together with the @p CH_CFG_ST_RESOLUTION
+ * option defines the maximum amount of time allowed for
+ * timeouts.
+ */
+#define CH_CFG_ST_FREQUENCY 1000
+
+/**
+ * @brief Time delta constant for the tick-less mode.
+ * @note If this value is zero then the system uses the classic
+ * periodic tick. This value represents the minimum number
+ * of ticks that is safe to specify in a timeout directive.
+ * The value one is not valid, timeouts are rounded up to
+ * this value.
+ */
+#define CH_CFG_ST_TIMEDELTA 0
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Subsystem options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Semaphores APIs.
+ * @details If enabled then the Semaphores APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_SEMAPHORES TRUE
+
+/**
+ * @brief Mutexes APIs.
+ * @details If enabled then the mutexes APIs are included in the kernel.
+ *
+ * @note Feature not currently implemented.
+ * @note The default is @p FALSE.
+ */
+#define CH_CFG_USE_MUTEXES FALSE
+
+/**
+ * @brief Events Flags APIs.
+ * @details If enabled then the event flags APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_EVENTS TRUE
+
+/**
+ * @brief Mailboxes APIs.
+ * @details If enabled then the asynchronous messages (mailboxes) APIs are
+ * included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_SEMAPHORES.
+ */
+#define CH_CFG_USE_MAILBOXES TRUE
+
+/**
+ * @brief Core Memory Manager APIs.
+ * @details If enabled then the core memory manager APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MEMCORE TRUE
+
+/**
+ * @brief Heap Allocator APIs.
+ * @details If enabled then the memory heap allocator APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_HEAP TRUE
+
+/**
+ * @brief Memory Pools Allocator APIs.
+ * @details If enabled then the memory pools allocator APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MEMPOOLS TRUE
+
+/**
+ * @brief Managed RAM size.
+ * @details Size of the RAM area to be managed by the OS. If set to zero
+ * then the whole available RAM is used. The core memory is made
+ * available to the heap allocator and/or can be used directly through
+ * the simplified core memory allocator.
+ *
+ * @note In order to let the OS manage the whole RAM the linker script must
+ * provide the @p __heap_base__ and @p __heap_end__ symbols.
+ * @note Requires @p CH_CFG_USE_MEMCORE.
+ */
+#define CH_CFG_MEMCORE_SIZE 0
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Debug options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Debug option, kernel statistics.
+ *
+ * @note Feature not currently implemented.
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_STATISTICS FALSE
+
+/**
+ * @brief Debug option, system state check.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_SYSTEM_STATE_CHECK TRUE
+
+/**
+ * @brief Debug option, parameters checks.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_ENABLE_CHECKS TRUE
+
+/**
+ * @brief System assertions.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_ENABLE_ASSERTS TRUE
+
+/**
+ * @brief Stack check.
+ *
+ *@note The default is @p FALSE.
+ */
+#define CH_DBG_ENABLE_STACK_CHECK TRUE
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Kernel hooks
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief System initialization hook.
+ */
+#if !defined(CH_CFG_SYSTEM_INIT_HOOK) || defined(__DOXYGEN__)
+#define CH_CFG_SYSTEM_INIT_HOOK() { \
+}
+#endif
+
+/**
+ * @brief Threads descriptor structure extension.
+ * @details User fields added to the end of the @p thread_t structure.
+ */
+#define CH_CFG_THREAD_EXT_FIELDS \
+ /* Add threads custom fields here.*/
+
+/**
+ * @brief Threads initialization hook.
+ */
+#define CH_CFG_THREAD_EXT_INIT_HOOK(tr) { \
+ /* Add custom threads initialization code here.*/ \
+}
+
+/**
+ * @brief Idle thread enter hook.
+ * @note This hook is invoked within a critical zone, no OS functions
+ * should be invoked from here.
+ * @note This macro can be used to activate a power saving mode.
+ */
+#define CH_CFG_IDLE_ENTER_HOOK() { \
+}
+
+/**
+ * @brief Idle thread leave hook.
+ * @note This hook is invoked within a critical zone, no OS functions
+ * should be invoked from here.
+ * @note This macro can be used to deactivate a power saving mode.
+ */
+#define CH_CFG_IDLE_LEAVE_HOOK() { \
+}
+
+/**
+ * @brief System halt hook.
+ */
+#if !defined(CH_CFG_SYSTEM_HALT_HOOK) || defined(__DOXYGEN__)
+#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \
+}
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/* Port-specific settings (override port settings defaulted in nilcore.h). */
+/*===========================================================================*/
+
+#endif /* _CHCONF_H_ */
+
+/** @} */
diff --git a/testhal/MSP430X/EXP430FR5969/ADC/halconf.h b/testhal/MSP430X/EXP430FR5969/ADC/halconf.h
new file mode 100644
index 0000000..2982a63
--- /dev/null
+++ b/testhal/MSP430X/EXP430FR5969/ADC/halconf.h
@@ -0,0 +1,388 @@
+/*
+ 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 templates/halconf.h
+ * @brief HAL configuration header.
+ * @details HAL configuration file, this file allows to enable or disable the
+ * various device drivers from your application. You may also use
+ * this file in order to override the device drivers default settings.
+ *
+ * @addtogroup HAL_CONF
+ * @{
+ */
+
+#ifndef HALCONF_H
+#define HALCONF_H
+
+#include "mcuconf.h"
+
+/**
+ * @brief Enables the PAL subsystem.
+ */
+#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__)
+#define HAL_USE_PAL TRUE
+#endif
+
+/**
+ * @brief Enables the DMA subsystem.
+ */
+#if !defined(HAL_USE_DMA) || defined(__DOXYGEN__)
+#define HAL_USE_DMA TRUE
+#endif
+
+/**
+ * @brief Enables the ADC subsystem.
+ */
+#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__)
+#define HAL_USE_ADC TRUE
+#endif
+
+/**
+ * @brief Enables the DAC subsystem.
+ */
+#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__)
+#define HAL_USE_DAC FALSE
+#endif
+
+/**
+ * @brief Enables the CAN subsystem.
+ */
+#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__)
+#define HAL_USE_CAN FALSE
+#endif
+
+/**
+ * @brief Enables the EXT subsystem.
+ */
+#if !defined(HAL_USE_EXT) || defined(__DOXYGEN__)
+#define HAL_USE_EXT FALSE
+#endif
+
+/**
+ * @brief Enables the GPT subsystem.
+ */
+#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__)
+#define HAL_USE_GPT FALSE
+#endif
+
+/**
+ * @brief Enables the I2C subsystem.
+ */
+#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__)
+#define HAL_USE_I2C FALSE
+#endif
+
+/**
+ * @brief Enables the I2S subsystem.
+ */
+#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__)
+#define HAL_USE_I2S FALSE
+#endif
+
+/**
+ * @brief Enables the ICU subsystem.
+ */
+#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__)
+#define HAL_USE_ICU FALSE
+#endif
+
+/**
+ * @brief Enables the MAC subsystem.
+ */
+#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__)
+#define HAL_USE_MAC FALSE
+#endif
+
+/**
+ * @brief Enables the MMC_SPI subsystem.
+ */
+#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__)
+#define HAL_USE_MMC_SPI FALSE
+#endif
+
+/**
+ * @brief Enables the PWM subsystem.
+ */
+#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__)
+#define HAL_USE_PWM FALSE
+#endif
+
+/**
+ * @brief Enables the RTC subsystem.
+ */
+#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__)
+#define HAL_USE_RTC FALSE
+#endif
+
+/**
+ * @brief Enables the SDC subsystem.
+ */
+#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__)
+#define HAL_USE_SDC FALSE
+#endif
+
+/**
+ * @brief Enables the SERIAL subsystem.
+ */
+#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__)
+#define HAL_USE_SERIAL TRUE
+#endif
+
+/**
+ * @brief Enables the SERIAL over USB subsystem.
+ */
+#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__)
+#define HAL_USE_SERIAL_USB FALSE
+#endif
+
+/**
+ * @brief Enables the SPI subsystem.
+ */
+#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__)
+#define HAL_USE_SPI FALSE
+#endif
+
+/**
+ * @brief Enables the UART subsystem.
+ */
+#if !defined(HAL_USE_UART) || defined(__DOXYGEN__)
+#define HAL_USE_UART FALSE
+#endif
+
+/**
+ * @brief Enables the USB subsystem.
+ */
+#if !defined(HAL_USE_USB) || defined(__DOXYGEN__)
+#define HAL_USE_USB FALSE
+#endif
+
+/**
+ * @brief Enables the WDG subsystem.
+ */
+#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__)
+#define HAL_USE_WDG FALSE
+#endif
+
+/*===========================================================================*/
+/* ADC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__)
+#define ADC_USE_WAIT TRUE
+#endif
+
+/**
+ * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define ADC_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/*===========================================================================*/
+/* CAN driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Sleep mode related APIs inclusion switch.
+ */
+#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__)
+#define CAN_USE_SLEEP_MODE FALSE
+#endif
+
+/*===========================================================================*/
+/* I2C driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables the mutual exclusion APIs on the I2C bus.
+ */
+#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define I2C_USE_MUTUAL_EXCLUSION FALSE
+#endif
+
+/*===========================================================================*/
+/* MAC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables an event sources for incoming packets.
+ */
+#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__)
+#define MAC_USE_ZERO_COPY FALSE
+#endif
+
+/**
+ * @brief Enables an event sources for incoming packets.
+ */
+#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__)
+#define MAC_USE_EVENTS FALSE
+#endif
+
+/*===========================================================================*/
+/* MMC_SPI driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Delays insertions.
+ * @details If enabled this options inserts delays into the MMC waiting
+ * routines releasing some extra CPU time for the threads with
+ * lower priority, this may slow down the driver a bit however.
+ * This option is recommended also if the SPI driver does not
+ * use a DMA channel and heavily loads the CPU.
+ */
+#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__)
+#define MMC_NICE_WAITING FALSE
+#endif
+
+/*===========================================================================*/
+/* SDC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Number of initialization attempts before rejecting the card.
+ * @note Attempts are performed at 10mS intervals.
+ */
+#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__)
+#define SDC_INIT_RETRY 100
+#endif
+
+/**
+ * @brief Include support for MMC cards.
+ * @note MMC support is not yet implemented so this option must be kept
+ * at @p FALSE.
+ */
+#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__)
+#define SDC_MMC_SUPPORT FALSE
+#endif
+
+/**
+ * @brief Delays insertions.
+ * @details If enabled this options inserts delays into the MMC waiting
+ * routines releasing some extra CPU time for the threads with
+ * lower priority, this may slow down the driver a bit however.
+ */
+#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__)
+#define SDC_NICE_WAITING FALSE
+#endif
+
+/*===========================================================================*/
+/* SERIAL driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Default bit rate.
+ * @details Configuration parameter, this is the baud rate selected for the
+ * default configuration.
+ */
+#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__)
+#define SERIAL_DEFAULT_BITRATE 38400
+#endif
+
+/**
+ * @brief Serial buffers size.
+ * @details Configuration parameter, you can change the depth of the queue
+ * buffers depending on the requirements of your application.
+ * @note The default is 16 bytes for both the transmission and receive
+ * buffers.
+ */
+#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__)
+#define SERIAL_BUFFERS_SIZE 16
+#endif
+
+/*===========================================================================*/
+/* SERIAL_USB driver related setting. */
+/*===========================================================================*/
+
+/**
+ * @brief Serial over USB buffers size.
+ * @details Configuration parameter, the buffer size must be a multiple of
+ * the USB data endpoint maximum packet size.
+ * @note The default is 256 bytes for both the transmission and receive
+ * buffers.
+ */
+#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__)
+#define SERIAL_USB_BUFFERS_SIZE 256
+#endif
+
+/**
+ * @brief Serial over USB number of buffers.
+ * @note The default is 2 buffers.
+ */
+#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__)
+#define SERIAL_USB_BUFFERS_NUMBER 2
+#endif
+
+/*===========================================================================*/
+/* SPI driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__)
+#define SPI_USE_WAIT TRUE
+#endif
+
+/**
+ * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define SPI_USE_MUTUAL_EXCLUSION FALSE
+#endif
+
+/*===========================================================================*/
+/* UART driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__)
+#define UART_USE_WAIT FALSE
+#endif
+
+/**
+ * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define UART_USE_MUTUAL_EXCLUSION FALSE
+#endif
+
+/*===========================================================================*/
+/* USB driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__)
+#define USB_USE_WAIT FALSE
+#endif
+
+#endif /* _HALCONF_H_ */
+
+/** @} */
diff --git a/testhal/MSP430X/EXP430FR5969/ADC/main.c b/testhal/MSP430X/EXP430FR5969/ADC/main.c
new file mode 100644
index 0000000..8a530ec
--- /dev/null
+++ b/testhal/MSP430X/EXP430FR5969/ADC/main.c
@@ -0,0 +1,270 @@
+/*
+ ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
+
+ 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 "ch.h"
+#include "hal.h"
+#include "string.h"
+#include "stdio.h" /* eesh */
+
+/* Disable watchdog because of lousy startup code in newlib */
+static void __attribute__((naked, section(".crt_0042disable_watchdog"), used))
+disable_watchdog(void) {
+ WDTCTL = WDTPW | WDTHOLD;
+}
+
+const char * start_msg = "\r\n\r\nExecuting ADC test suite...\r\n";
+const char * test_1_msg = "\r\nTEST 1: 1 channel, depth 1, no circular\r\n";
+const char * test_2_msg = "\r\nTEST 2: 1 channel, depth 8, no circular\r\n";
+const char * test_3_msg = "\r\nTEST 3: 4 channels, depth 1, no circular\r\n";
+const char * test_4_msg = "\r\nTEST 4: 4 channels, depth 8, no circular\r\n";
+const char * test_5_msg = "\r\nTEST 5: 1 channel, depth 1, circular\r\n";
+const char * test_6_msg = "\r\nTEST 6: 1 channel, depth 8, circular\r\n";
+const char * test_7_msg = "\r\nTEST 7: 4 channel, depth 1, circular\r\n";
+const char * test_8_msg = "\r\nTEST 8: 4 channel, depth 8, circular\r\n";
+const char * test_9_msg = "\r\nTEST 9: 1 channel, depth 1, synchronous\r\n";
+const char * test_10_msg = "\r\nTEST 9: 1 channel, depth 1, exclusive\r\n";
+
+const char * success_string = "\r\nSUCCESS\r\n";
+const char * fail_string = "\r\nFAILURE\r\n";
+
+char out_string[128];
+const char * raw_fmt_string = "Raw Value: %d\r\n";
+const char * cooked_fmt_string = "Cooked Value: %d\r\n";
+const char * chn_fmt_string = "\r\nCHANNEL %d\r\n";
+
+uint16_t buffer_margin[72];
+uint16_t * buffer = buffer_margin + 4;
+uint8_t depth;
+uint8_t cb_arg = 0;
+uint16_t cb_expect;
+
+static const int test = 0;
+
+ADCConfig config = {
+ 255 /* dma_index */
+};
+
+ADCConversionGroup group = {
+ false, /* circular */
+ 1, /* num_channels */
+ NULL, /* end_cb */
+ NULL, /* error_cb */
+ {
+ 30, 31, 30, 31, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+ }, /* channels */
+ MSP430X_ADC_RES_12BIT, /* res */
+ MSP430X_ADC_SHT_32, /* rate */
+ MSP430X_ADC_VSS_VREF_BUF, /* ref */
+ MSP430X_REF_2V5 /* vref_src */
+};
+
+void print(const char * msg) {
+
+ if (!test) {
+ chnWrite(&SD0, (const uint8_t *)msg, strlen(msg));
+ }
+}
+
+void adc_callback(ADCDriver * adcp, adcsample_t *buffer, size_t n) {
+ (void)adcp;
+ (void)buffer;
+ (void)n;
+
+ cb_arg++;
+
+ if (adcp->grpp->circular && cb_arg == cb_expect) {
+ osalSysLockFromISR();
+ adcStopConversionI(adcp);
+ osalSysUnlockFromISR();
+ }
+}
+
+void run_test(const char * test_msg, uint8_t num_channels, uint8_t depth,
+ bool circular) {
+ print(test_msg);
+
+ cb_arg = 0;
+
+ group.num_channels = num_channels;
+ group.circular = circular;
+ group.end_cb = adc_callback;
+
+ if (depth > 1) cb_expect = 2;
+ else cb_expect = 1;
+ if (circular) cb_expect *= 3;
+
+ adcStartConversion(&ADCD1, &group, buffer, depth);
+
+ while (ADCD1.state == ADC_ACTIVE) ;
+
+
+ int index = 0;
+ for (int j = 0; j < depth; j++) {
+ for (int i = 0; i < group.num_channels; i++) {
+ index = i + (j * group.num_channels);
+ sniprintf(out_string, 128, chn_fmt_string, group.channels[i]);
+ print(out_string);
+
+ sniprintf(out_string, 128, raw_fmt_string, buffer[index]);
+ print(out_string);
+
+ if (group.channels[i] == 30) { /* internal temp sensor */
+ buffer[index] = adcMSP430XAdjustTemp(&group, buffer[index]);
+ }
+ else {
+ buffer[index] = adcMSP430XAdjustResult(&group, buffer[index]);
+ }
+
+ sniprintf(out_string, 128, cooked_fmt_string, buffer[index]);
+ print(out_string);
+ }
+ }
+
+ if (cb_arg == cb_expect) {
+ print(success_string);
+ }
+ else {
+ print(fail_string);
+ }
+}
+
+/*
+ * Thread 2.
+ */
+THD_WORKING_AREA(waThread1, 4096);
+THD_FUNCTION(Thread1, arg) {
+
+ (void)arg;
+
+ /*
+ * Activate the serial driver 0 using the driver default configuration.
+ */
+ sdStart(&SD0, NULL);
+
+
+ while (chnGetTimeout(&SD0, TIME_INFINITE)) {
+ print(start_msg);
+ chThdSleepMilliseconds(2000);
+
+ /* Activate the ADC driver 1 using its config */
+ adcStart(&ADCD1, &config);
+
+ /* Test 1 - 1ch1d, no circular */
+ run_test(test_1_msg, 1, 1, false);
+
+ /* Test 2 - 1ch8d, no circular */
+ run_test(test_2_msg, 1, 8, false);
+
+ /* Test 3 - 4chd1, no circular */
+ run_test(test_3_msg, 4, 1, false);
+
+ /* Test 4 - 4ch8d, no circular */
+ run_test(test_4_msg, 4, 8, false);
+
+ /* Test 5 - 1ch1d, circular */
+ run_test(test_5_msg, 1, 1, true);
+
+ /* Test 6 - 1ch8d, circular */
+ run_test(test_6_msg, 1, 8, true);
+
+ /* Test 7 - 4ch1d, circular */
+ run_test(test_7_msg, 4, 1, true);
+
+ /* Test 8 - 4ch8d, circular */
+ run_test(test_8_msg, 4, 8, true);
+
+ /* Test 9 - 1ch1d, synchronous */
+ print(test_9_msg);
+ cb_arg = 0;
+
+ group.num_channels = 1;
+ group.circular = false;
+ group.end_cb = adc_callback;
+
+ cb_expect = 1;
+
+ adcConvert(&ADCD1, &group, buffer, 1);
+
+ while (ADCD1.state == ADC_ACTIVE) ;
+
+ sniprintf(out_string, 128, chn_fmt_string, group.channels[0]);
+ print(out_string);
+
+ sniprintf(out_string, 128, raw_fmt_string, buffer[0]);
+ print(out_string);
+
+ buffer[0] = adcMSP430XAdjustTemp(&group, buffer[0]);
+
+ sniprintf(out_string, 128, cooked_fmt_string, buffer[0]);
+ print(out_string);
+
+ if (cb_arg == cb_expect) {
+ print(success_string);
+ }
+ else {
+ print(fail_string);
+ }
+
+ /* Test 10 - 1ch1d, exclusive */
+ adcStop(&ADCD1);
+
+ config.dma_index = 0;
+
+ adcStart(&ADCD1, &config);
+
+ run_test(test_10_msg, 1, 1, false);
+
+ adcStop(&ADCD1);
+
+ config.dma_index = 255;
+ }
+}
+
+/*
+ * Threads static table, one entry per thread. The number of entries must
+ * match NIL_CFG_NUM_THREADS.
+ */
+THD_TABLE_BEGIN
+ THD_TABLE_ENTRY(waThread1, "adc_test", Thread1, NULL)
+THD_TABLE_END
+
+/*
+ * Application entry point.
+ */
+int main(void) {
+
+ /*
+ * System initializations.
+ * - HAL initialization, this also initializes the configured device drivers
+ * and performs the board-specific initializations.
+ * - Kernel initialization, the main() function becomes a thread and the
+ * RTOS is active.
+ */
+ WDTCTL = WDTPW | WDTHOLD;
+
+ halInit();
+ chSysInit();
+
+ /* This is now the idle thread loop, you may perform here a low priority
+ task but you must never try to sleep or wait in this loop. Note that
+ this tasks runs at the lowest priority level so any instruction added
+ here will be executed after all other tasks have been started.*/
+ while (true) {
+ }
+}
diff --git a/testhal/MSP430X/EXP430FR5969/ADC/mcuconf.h b/testhal/MSP430X/EXP430FR5969/ADC/mcuconf.h
new file mode 100644
index 0000000..70e29ff
--- /dev/null
+++ b/testhal/MSP430X/EXP430FR5969/ADC/mcuconf.h
@@ -0,0 +1,68 @@
+/*
+ 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 MCUCONF_H
+#define MCUCONF_H
+
+/*
+ * MSP430X drivers configuration.
+ * The following settings override the default settings present in
+ * the various device driver implementation headers.
+ * Note that the settings for each driver only have effect if the driver
+ * is enabled in halconf.h.
+ *
+ */
+
+#define MSP430X_MCUCONF
+
+/* HAL driver system settings */
+#define MSP430X_ACLK_SRC MSP430X_VLOCLK
+#define MSP430X_LFXTCLK_FREQ 0
+#define MSP430X_HFXTCLK_FREQ 0
+#define MSP430X_DCOCLK_FREQ 8000000
+#define MSP430X_MCLK_DIV 1
+#define MSP430X_SMCLK_DIV 32
+
+/*
+ * SERIAL driver system settings.
+ */
+#define MSP430X_SERIAL_USE_USART0 TRUE
+#define MSP430X_USART0_CLK_SRC MSP430X_SMCLK_SRC
+#define MSP430X_SERIAL_USE_USART1 FALSE
+#define MSP430X_SERIAL_USE_USART2 FALSE
+#define MSP430X_SERIAL_USE_USART3 FALSE
+
+/*
+ * ST driver system settings.
+ */
+#define MSP430X_ST_CLK_SRC MSP430X_SMCLK_SRC
+#define MSP430X_ST_TIMER_TYPE B
+#define MSP430X_ST_TIMER_INDEX 0
+
+/*
+ * SPI driver system settings.
+ */
+#define MSP430X_SPI_USE_SPIA1 FALSE
+#define MSP430X_SPI_USE_SPIB0 FALSE
+#define MSP430X_SPI_EXCLUSIVE_DMA TRUE
+
+/*
+ * ADC driver system settings
+ */
+#define MSP430X_ADC_EXCLUSIVE_DMA TRUE
+#define MSP430X_ADC1_FREQ 5000000 / 256
+
+#endif /* _MCUCONF_H_ */
diff --git a/testhal/MSP430X/EXP430FR5969/ADC/msp_vectors.c b/testhal/MSP430X/EXP430FR5969/ADC/msp_vectors.c
new file mode 100644
index 0000000..d12ed53
--- /dev/null
+++ b/testhal/MSP430X/EXP430FR5969/ADC/msp_vectors.c
@@ -0,0 +1,286 @@
+#include <msp430.h>
+
+__attribute__((interrupt(1)))
+void Vector1(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(2)))
+void Vector2(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(3)))
+void Vector3(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(4)))
+void Vector4(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(5)))
+void Vector5(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(6)))
+void Vector6(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(7)))
+void Vector7(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(8)))
+void Vector8(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(9)))
+void Vector9(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(10)))
+void Vector10(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(11)))
+void Vector11(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(12)))
+void Vector12(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(13)))
+void Vector13(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(14)))
+void Vector14(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(15)))
+void Vector15(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(16)))
+void Vector16(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(17)))
+void Vector17(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(18)))
+void Vector18(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(19)))
+void Vector19(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(20)))
+void Vector20(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(21)))
+void Vector21(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(22)))
+void Vector22(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(23)))
+void Vector23(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(24)))
+void Vector24(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(25)))
+void Vector25(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(26)))
+void Vector26(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(27)))
+void Vector27(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(28)))
+void Vector28(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(29)))
+void Vector29(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(30)))
+void Vector30(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(31)))
+void Vector31(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(32)))
+void Vector32(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(35)))
+void Vector35(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(36)))
+void Vector36(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(38)))
+void Vector38(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(39)))
+void Vector39(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(41)))
+void Vector41(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(42)))
+void Vector42(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(44)))
+void Vector44(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(45)))
+void Vector45(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(46)))
+void Vector46(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(48)))
+void Vector48(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(50)))
+void Vector50(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(51)))
+void Vector51(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(53)))
+void Vector53(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(54)))
+void Vector54(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(55)))
+void Vector55(void) {
+
+ while (1) {
+ }
+}
+
+
diff --git a/testhal/MSP430X/EXP430FR5969/DMA/main.c b/testhal/MSP430X/EXP430FR5969/DMA/main.c
index 1929af1..757eedc 100644
--- a/testhal/MSP430X/EXP430FR5969/DMA/main.c
+++ b/testhal/MSP430X/EXP430FR5969/DMA/main.c
@@ -35,6 +35,8 @@ const char * test_6_msg = "TEST 6: Attempt to claim already claimed DMA "
"and succeed.\r\n";
const char * test_7_msg = "TEST 7: Claim DMA channel 1, perform a Word-to-word "
"memcpy, and release it\r\n";
+const char * test_8_msg = "TEST 8: Claim all three DMA channels, try to issue dmaRequest, "
+ "fail\r\n";
const char * succeed_string = "SUCCESS\r\n\r\n";
const char * fail_string = "FAILURE\r\n\r\n";
@@ -43,6 +45,8 @@ char instring[256];
char outstring[256];
msp430x_dma_req_t * request;
uint8_t cb_arg = 1;
+bool result;
+int result_i;
void dma_callback_test(void * args) {
@@ -120,6 +124,8 @@ msp430x_dma_req_t test_5_req = {
};
msp430x_dma_ch_t ch = { NULL, 0, NULL };
+msp430x_dma_ch_t ch1 = { NULL, 0, NULL };
+msp430x_dma_ch_t ch2 = { NULL, 0, NULL };
/*
* Thread 2.
@@ -146,7 +152,9 @@ THD_FUNCTION(Thread1, arg) {
chnWrite(&SD0, (const uint8_t *)fail_string, strlen(fail_string));
}
request = &test_1_req;
- dmaRequest(request, TIME_INFINITE);
+ chSysLock();
+ dmaRequestS(request, TIME_INFINITE);
+ chSysUnlock();
if (strcmp("After DMA test \r\n", outstring)) {
chnWrite(&SD0, (const uint8_t *)fail_string, strlen(fail_string));
}
@@ -162,7 +170,9 @@ THD_FUNCTION(Thread1, arg) {
chnWrite(&SD0, (const uint8_t *)fail_string, strlen(fail_string));
}
request = &test_2_req;
- dmaRequest(request, TIME_INFINITE);
+ chSysLock();
+ dmaRequestS(request, TIME_INFINITE);
+ chSysUnlock();
if (strcmp("After DMA test \r\n", outstring)) {
chnWrite(&SD0, (const uint8_t *)fail_string, strlen(fail_string));
}
@@ -178,7 +188,9 @@ THD_FUNCTION(Thread1, arg) {
chnWrite(&SD0, (const uint8_t *)fail_string, strlen(fail_string));
}
request = &test_3_req;
- dmaRequest(request, TIME_INFINITE);
+ chSysLock();
+ dmaRequestS(request, TIME_INFINITE);
+ chSysUnlock();
if (strcmp("AAAAAAAAAAAAAAAA\r\n", outstring)) {
chnWrite(&SD0, (const uint8_t *)fail_string, strlen(fail_string));
}
@@ -196,7 +208,9 @@ THD_FUNCTION(Thread1, arg) {
chnWrite(&SD0, (const uint8_t *)fail_string, strlen(fail_string));
}
request = &test_4_req;
- dmaRequest(request, TIME_INFINITE);
+ chSysLock();
+ dmaRequestS(request, TIME_INFINITE);
+ chSysUnlock();
if (strcmp("After DMA test \r\n", outstring) || cb_arg) {
chnWrite(&SD0, (const uint8_t *)fail_string, strlen(fail_string));
}
@@ -213,7 +227,9 @@ THD_FUNCTION(Thread1, arg) {
chnWrite(&SD0, (const uint8_t *)fail_string, strlen(fail_string));
}
request = &test_5_req;
- dmaAcquire(&ch, 0);
+ chSysLock();
+ dmaAcquireI(&ch, 0);
+ chSysUnlock();
dmaTransfer(&ch, request);
if (strcmp("After DMA test \r\n", outstring)) {
chnWrite(&SD0, (const uint8_t *)fail_string, strlen(fail_string));
@@ -225,11 +241,17 @@ THD_FUNCTION(Thread1, arg) {
/* Test 6 - Attempt to claim DMA channel 0, fail, release it, attempt to
* claim it again */
chnWrite(&SD0, (const uint8_t *)test_6_msg, strlen(test_6_msg));
- if (!dmaAcquire(&ch, 0)) {
+ chSysLock();
+ result = dmaAcquireI(&ch, 0);
+ chSysUnlock();
+ if (!result) {
chnWrite(&SD0, (const uint8_t *)fail_string, strlen(fail_string));
}
dmaRelease(&ch);
- if (dmaAcquire(&ch, 0)) {
+ chSysLock();
+ result = dmaAcquireI(&ch, 0);
+ chSysUnlock();
+ if (result) {
chnWrite(&SD0, (const uint8_t *)fail_string, strlen(fail_string));
}
else {
@@ -246,7 +268,9 @@ THD_FUNCTION(Thread1, arg) {
chnWrite(&SD0, (const uint8_t *)fail_string, strlen(fail_string));
}
request = &test_5_req;
- dmaAcquire(&ch, 1);
+ chSysLock();
+ dmaAcquireI(&ch, 1);
+ chSysUnlock();
dmaTransfer(&ch, request);
if (strcmp("After DMA test \r\n", outstring)) {
chnWrite(&SD0, (const uint8_t *)fail_string, strlen(fail_string));
@@ -255,6 +279,40 @@ THD_FUNCTION(Thread1, arg) {
chnWrite(&SD0, (const uint8_t *)succeed_string, strlen(succeed_string));
}
dmaRelease(&ch);
+
+ /* Test 8 - Claim all 3 DMA channels, attempt dmaRequest, fail */
+ chnWrite(&SD0, (const uint8_t *)test_8_msg, strlen(test_8_msg));
+ chSysLock();
+ result = dmaAcquireI(&ch, 0);
+ chSysUnlock();
+ if (result) {
+ chnWrite(&SD0, (const uint8_t *)fail_string, strlen(fail_string));
+ }
+ chSysLock();
+ result = dmaAcquireI(&ch1, 1);
+ chSysUnlock();
+ if (result) {
+ chnWrite(&SD0, (const uint8_t *)fail_string, strlen(fail_string));
+ }
+ chSysLock();
+ result = dmaAcquireI(&ch2, 2);
+ chSysUnlock();
+ if (result) {
+ chnWrite(&SD0, (const uint8_t *)fail_string, strlen(fail_string));
+ }
+ chSysLock();
+ result_i = dmaRequestS(request, TIME_IMMEDIATE);
+ chSysUnlock();
+ if (result_i > 0) {
+ chnWrite(&SD0, (const uint8_t *)fail_string, strlen(fail_string));
+ }
+ else {
+ chnWrite(&SD0, (const uint8_t *)succeed_string, strlen(succeed_string));
+ }
+ dmaRelease(&ch);
+ dmaRelease(&ch1);
+ dmaRelease(&ch2);
+
}
}
diff --git a/testhal/MSP430X/EXP430FR5969/DMA/msp_vectors.c b/testhal/MSP430X/EXP430FR5969/DMA/msp_vectors.c
index 8968fb9..f5ad4b6 100644
--- a/testhal/MSP430X/EXP430FR5969/DMA/msp_vectors.c
+++ b/testhal/MSP430X/EXP430FR5969/DMA/msp_vectors.c
@@ -192,18 +192,6 @@ void Vector32(void) {
while (1) {
}
}
-__attribute__((interrupt(33)))
-void Vector33(void) {
-
- while (1) {
- }
-}
-__attribute__((interrupt(34)))
-void Vector34(void) {
-
- while (1) {
- }
-}
__attribute__((interrupt(35)))
void Vector35(void) {
@@ -216,12 +204,7 @@ void Vector36(void) {
while (1) {
}
}
-__attribute__((interrupt(37)))
-void Vector37(void) {
- while (1) {
- }
-}
__attribute__((interrupt(38)))
void Vector38(void) {
@@ -234,12 +217,7 @@ void Vector39(void) {
while (1) {
}
}
-__attribute__((interrupt(40)))
-void Vector40(void) {
- while (1) {
- }
-}
__attribute__((interrupt(41)))
void Vector41(void) {
diff --git a/testhal/MSP430X/EXP430FR5969/SPI/msp_vectors.c b/testhal/MSP430X/EXP430FR5969/SPI/msp_vectors.c
index 8968fb9..c23cbc8 100644
--- a/testhal/MSP430X/EXP430FR5969/SPI/msp_vectors.c
+++ b/testhal/MSP430X/EXP430FR5969/SPI/msp_vectors.c
@@ -192,18 +192,6 @@ void Vector32(void) {
while (1) {
}
}
-__attribute__((interrupt(33)))
-void Vector33(void) {
-
- while (1) {
- }
-}
-__attribute__((interrupt(34)))
-void Vector34(void) {
-
- while (1) {
- }
-}
__attribute__((interrupt(35)))
void Vector35(void) {
@@ -216,12 +204,6 @@ void Vector36(void) {
while (1) {
}
}
-__attribute__((interrupt(37)))
-void Vector37(void) {
-
- while (1) {
- }
-}
__attribute__((interrupt(38)))
void Vector38(void) {
@@ -234,12 +216,6 @@ void Vector39(void) {
while (1) {
}
}
-__attribute__((interrupt(40)))
-void Vector40(void) {
-
- while (1) {
- }
-}
__attribute__((interrupt(41)))
void Vector41(void) {
diff --git a/testhal/MSP430X/EXP430FR6989/ADC/Makefile b/testhal/MSP430X/EXP430FR6989/ADC/Makefile
new file mode 100644
index 0000000..b86021e
--- /dev/null
+++ b/testhal/MSP430X/EXP430FR6989/ADC/Makefile
@@ -0,0 +1,206 @@
+##############################################################################
+# Build global options
+# NOTE: Can be overridden externally.
+#
+
+# Optimization level, can be [0, 1, 2, 3, s].
+# 0 = turn off optimization. s = optimize for size.
+# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
+OPTIMIZE = 0
+
+# Debugging format.
+DEBUG =
+#DEBUG = stabs
+
+# Memory/data model
+MODEL = small
+
+# Object files directory
+# To put object files in current directory, use a dot (.), do NOT make
+# this an empty or blank macro!
+OBJDIR = .
+
+# Compiler flag to set the C Standard level.
+# c89 = "ANSI" C
+# gnu89 = c89 plus GCC extensions
+# c99 = ISO C99 standard (not yet fully implemented)
+# gnu99 = c99 plus GCC extensions
+CSTANDARD = -std=gnu11
+
+# Compiler options here.
+ifeq ($(USE_OPT),)
+ USE_OPT = -O$(OPTIMIZE) -g$(DEBUG)
+ USE_OPT += -funsigned-char -fshort-enums
+endif
+
+# C specific options here (added to USE_OPT).
+ifeq ($(USE_COPT),)
+ USE_COPT =
+endif
+
+# C++ specific options here (added to USE_OPT).
+ifeq ($(USE_CPPOPT),)
+ USE_CPPOPT = -fno-rtti
+endif
+
+# Enable this if you want the linker to remove unused code and data
+ifeq ($(USE_LINK_GC),)
+ USE_LINK_GC = yes
+endif
+
+# Linker extra options here.
+ifeq ($(USE_LDOPT),)
+ USE_LDOPT =
+endif
+
+# Enable this if you want link time optimizations (LTO)
+ifeq ($(USE_LTO),)
+ USE_LTO = no
+endif
+
+# Enable the selected hardware multiplier
+ifeq ($(USE_HWMULT),)
+ USE_HWMULT = f5series
+endif
+
+# Enable this if you want to see the full log while compiling.
+ifeq ($(USE_VERBOSE_COMPILE),)
+ USE_VERBOSE_COMPILE = yes
+endif
+
+# If enabled, this option makes the build process faster by not compiling
+# modules not used in the current configuration.
+ifeq ($(USE_SMART_BUILD),)
+ USE_SMART_BUILD = yes
+endif
+
+#
+# Build global options
+##############################################################################
+
+##############################################################################
+# Architecture or project specific options
+#
+
+# Stack size to be allocated to the idle thread stack. This stack is
+# the stack used by the main() thread.
+ifeq ($(USE_IDLE_STACKSIZE),)
+ USE_IDLE_STACKSIZE = 0xC00
+endif
+
+#
+# Architecture or project specific options
+##############################################################################
+
+##############################################################################
+# Project, sources and paths
+#
+
+# Define project name here
+PROJECT = nil
+
+# Imported source files and paths
+CHIBIOS = ../../../../../ChibiOS-RT
+CHIBIOS_CONTRIB = ../../../..
+# Startup files.
+include $(CHIBIOS_CONTRIB)/os/common/startup/MSP430X/compilers/GCC/mk/startup_msp430fr5xxx.mk
+# HAL-OSAL files (optional).
+include $(CHIBIOS)/os/hal/hal.mk
+include $(CHIBIOS_CONTRIB)/os/hal/boards/EXP430FR6989/board.mk
+include $(CHIBIOS_CONTRIB)/os/hal/ports/MSP430X/platform.mk
+include $(CHIBIOS)/os/hal/osal/nil/osal.mk
+# RTOS files (optional).
+include $(CHIBIOS)/os/nil/nil.mk
+include $(CHIBIOS_CONTRIB)/os/common/ports/MSP430X/compilers/GCC/mk/port.mk
+# Other files (optional).
+
+# Define linker script file here
+LDSCRIPT = $(STARTUPLD)/msp430fr6989.ld
+
+# C sources
+CSRC = $(STARTUPSRC) \
+ $(KERNSRC) \
+ $(PORTSRC) \
+ $(OSALSRC) \
+ $(HALSRC) \
+ $(PLATFORMSRC) \
+ $(BOARDSRC) \
+ $(TESTSRC) \
+ msp_vectors.c \
+ main.c
+
+# C++ sources
+CPPSRC =
+
+# List ASM source files here
+ASMSRC = $(STARTUPASM) $(PORTASM) $(OSALASM)
+
+INCDIR = $(CHIBIOS)/os/license \
+ $(STARTUPINC) $(KERNINC) $(PORTINC) $(OSALINC) \
+ $(HALINC) $(PLATFORMINC) $(BOARDINC) $(TESTINC) \
+ $(CHIBIOS)/os/various
+
+#
+# Project, sources and paths
+##############################################################################
+
+##############################################################################
+# Compiler settings
+#
+
+MCU = msp430fr6989
+
+TRGT = msp430-elf-
+CC = $(TRGT)gcc
+CPPC = $(TRGT)g++
+# Enable loading with g++ only if you need C++ runtime support.
+# NOTE: You can use C++ even without C++ support if you are careful. C++
+# runtime support makes code size explode.
+LD = $(TRGT)gcc
+#LD = $(TRGT)g++
+CP = $(TRGT)objcopy
+AS = $(TRGT)gcc -x assembler-with-cpp
+AR = $(TRGT)ar
+OD = $(TRGT)objdump
+SZ = $(TRGT)size
+HEX = $(CP) -O ihex
+BIN = $(CP) -O binary
+
+# MSP430-specific options here
+MOPT = -m$(MODEL)
+
+# Define C warning options here
+CWARN = -Wall -Wextra -Wundef -Wstrict-prototypes
+
+# Define C++ warning options here
+CPPWARN = -Wall -Wextra -Wundef
+
+#
+# Compiler settings
+##############################################################################
+
+##############################################################################
+# Start of user section
+#
+
+# List all user C define here, like -D_DEBUG=1
+UDEFS =
+
+# Define ASM defines here
+UADEFS =
+
+# List all user directories here
+UINCDIR =
+
+# List the user directory to look for the libraries here
+ULIBDIR =
+
+# List all user libraries here
+ULIBS =
+
+#
+# End of user defines
+##############################################################################
+
+RULESPATH = $(CHIBIOS_CONTRIB)/os/common/startup/MSP430X/compilers/GCC
+include $(RULESPATH)/rules.mk
diff --git a/testhal/MSP430X/EXP430FR6989/ADC/chconf.h b/testhal/MSP430X/EXP430FR6989/ADC/chconf.h
new file mode 100644
index 0000000..3b7a8e1
--- /dev/null
+++ b/testhal/MSP430X/EXP430FR6989/ADC/chconf.h
@@ -0,0 +1,274 @@
+/*
+ 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 nilconf.h
+ * @brief Configuration file template.
+ * @details A copy of this file must be placed in each project directory, it
+ * contains the application specific kernel settings.
+ *
+ * @addtogroup config
+ * @details Kernel related settings and hooks.
+ * @{
+ */
+
+#ifndef CHCONF_H
+#define CHCONF_H
+
+#define _CHIBIOS_NIL_CONF_
+
+/*===========================================================================*/
+/**
+ * @name Kernel parameters and options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Number of user threads in the application.
+ * @note This number is not inclusive of the idle thread which is
+ * Implicitly handled.
+ */
+#define CH_CFG_NUM_THREADS 1
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name System timer settings
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief System time counter resolution.
+ * @note Allowed values are 16 or 32 bits.
+ */
+#define CH_CFG_ST_RESOLUTION 16
+
+/**
+ * @brief System tick frequency.
+ * @note This value together with the @p CH_CFG_ST_RESOLUTION
+ * option defines the maximum amount of time allowed for
+ * timeouts.
+ */
+#define CH_CFG_ST_FREQUENCY 1000
+
+/**
+ * @brief Time delta constant for the tick-less mode.
+ * @note If this value is zero then the system uses the classic
+ * periodic tick. This value represents the minimum number
+ * of ticks that is safe to specify in a timeout directive.
+ * The value one is not valid, timeouts are rounded up to
+ * this value.
+ */
+#define CH_CFG_ST_TIMEDELTA 0
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Subsystem options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Semaphores APIs.
+ * @details If enabled then the Semaphores APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_SEMAPHORES TRUE
+
+/**
+ * @brief Mutexes APIs.
+ * @details If enabled then the mutexes APIs are included in the kernel.
+ *
+ * @note Feature not currently implemented.
+ * @note The default is @p FALSE.
+ */
+#define CH_CFG_USE_MUTEXES FALSE
+
+/**
+ * @brief Events Flags APIs.
+ * @details If enabled then the event flags APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_EVENTS TRUE
+
+/**
+ * @brief Mailboxes APIs.
+ * @details If enabled then the asynchronous messages (mailboxes) APIs are
+ * included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_SEMAPHORES.
+ */
+#define CH_CFG_USE_MAILBOXES TRUE
+
+/**
+ * @brief Core Memory Manager APIs.
+ * @details If enabled then the core memory manager APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MEMCORE TRUE
+
+/**
+ * @brief Heap Allocator APIs.
+ * @details If enabled then the memory heap allocator APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_HEAP TRUE
+
+/**
+ * @brief Memory Pools Allocator APIs.
+ * @details If enabled then the memory pools allocator APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MEMPOOLS TRUE
+
+/**
+ * @brief Managed RAM size.
+ * @details Size of the RAM area to be managed by the OS. If set to zero
+ * then the whole available RAM is used. The core memory is made
+ * available to the heap allocator and/or can be used directly through
+ * the simplified core memory allocator.
+ *
+ * @note In order to let the OS manage the whole RAM the linker script must
+ * provide the @p __heap_base__ and @p __heap_end__ symbols.
+ * @note Requires @p CH_CFG_USE_MEMCORE.
+ */
+#define CH_CFG_MEMCORE_SIZE 0
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Debug options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Debug option, kernel statistics.
+ *
+ * @note Feature not currently implemented.
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_STATISTICS FALSE
+
+/**
+ * @brief Debug option, system state check.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_SYSTEM_STATE_CHECK TRUE
+
+/**
+ * @brief Debug option, parameters checks.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_ENABLE_CHECKS TRUE
+
+/**
+ * @brief System assertions.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_ENABLE_ASSERTS TRUE
+
+/**
+ * @brief Stack check.
+ *
+ *@note The default is @p FALSE.
+ */
+#define CH_DBG_ENABLE_STACK_CHECK TRUE
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Kernel hooks
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief System initialization hook.
+ */
+#if !defined(CH_CFG_SYSTEM_INIT_HOOK) || defined(__DOXYGEN__)
+#define CH_CFG_SYSTEM_INIT_HOOK() { \
+}
+#endif
+
+/**
+ * @brief Threads descriptor structure extension.
+ * @details User fields added to the end of the @p thread_t structure.
+ */
+#define CH_CFG_THREAD_EXT_FIELDS \
+ /* Add threads custom fields here.*/
+
+/**
+ * @brief Threads initialization hook.
+ */
+#define CH_CFG_THREAD_EXT_INIT_HOOK(tr) { \
+ /* Add custom threads initialization code here.*/ \
+}
+
+/**
+ * @brief Idle thread enter hook.
+ * @note This hook is invoked within a critical zone, no OS functions
+ * should be invoked from here.
+ * @note This macro can be used to activate a power saving mode.
+ */
+#define CH_CFG_IDLE_ENTER_HOOK() { \
+}
+
+/**
+ * @brief Idle thread leave hook.
+ * @note This hook is invoked within a critical zone, no OS functions
+ * should be invoked from here.
+ * @note This macro can be used to deactivate a power saving mode.
+ */
+#define CH_CFG_IDLE_LEAVE_HOOK() { \
+}
+
+/**
+ * @brief System halt hook.
+ */
+#if !defined(CH_CFG_SYSTEM_HALT_HOOK) || defined(__DOXYGEN__)
+#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \
+}
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/* Port-specific settings (override port settings defaulted in nilcore.h). */
+/*===========================================================================*/
+
+#endif /* _CHCONF_H_ */
+
+/** @} */
diff --git a/testhal/MSP430X/EXP430FR6989/ADC/halconf.h b/testhal/MSP430X/EXP430FR6989/ADC/halconf.h
new file mode 100644
index 0000000..2982a63
--- /dev/null
+++ b/testhal/MSP430X/EXP430FR6989/ADC/halconf.h
@@ -0,0 +1,388 @@
+/*
+ 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 templates/halconf.h
+ * @brief HAL configuration header.
+ * @details HAL configuration file, this file allows to enable or disable the
+ * various device drivers from your application. You may also use
+ * this file in order to override the device drivers default settings.
+ *
+ * @addtogroup HAL_CONF
+ * @{
+ */
+
+#ifndef HALCONF_H
+#define HALCONF_H
+
+#include "mcuconf.h"
+
+/**
+ * @brief Enables the PAL subsystem.
+ */
+#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__)
+#define HAL_USE_PAL TRUE
+#endif
+
+/**
+ * @brief Enables the DMA subsystem.
+ */
+#if !defined(HAL_USE_DMA) || defined(__DOXYGEN__)
+#define HAL_USE_DMA TRUE
+#endif
+
+/**
+ * @brief Enables the ADC subsystem.
+ */
+#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__)
+#define HAL_USE_ADC TRUE
+#endif
+
+/**
+ * @brief Enables the DAC subsystem.
+ */
+#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__)
+#define HAL_USE_DAC FALSE
+#endif
+
+/**
+ * @brief Enables the CAN subsystem.
+ */
+#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__)
+#define HAL_USE_CAN FALSE
+#endif
+
+/**
+ * @brief Enables the EXT subsystem.
+ */
+#if !defined(HAL_USE_EXT) || defined(__DOXYGEN__)
+#define HAL_USE_EXT FALSE
+#endif
+
+/**
+ * @brief Enables the GPT subsystem.
+ */
+#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__)
+#define HAL_USE_GPT FALSE
+#endif
+
+/**
+ * @brief Enables the I2C subsystem.
+ */
+#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__)
+#define HAL_USE_I2C FALSE
+#endif
+
+/**
+ * @brief Enables the I2S subsystem.
+ */
+#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__)
+#define HAL_USE_I2S FALSE
+#endif
+
+/**
+ * @brief Enables the ICU subsystem.
+ */
+#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__)
+#define HAL_USE_ICU FALSE
+#endif
+
+/**
+ * @brief Enables the MAC subsystem.
+ */
+#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__)
+#define HAL_USE_MAC FALSE
+#endif
+
+/**
+ * @brief Enables the MMC_SPI subsystem.
+ */
+#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__)
+#define HAL_USE_MMC_SPI FALSE
+#endif
+
+/**
+ * @brief Enables the PWM subsystem.
+ */
+#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__)
+#define HAL_USE_PWM FALSE
+#endif
+
+/**
+ * @brief Enables the RTC subsystem.
+ */
+#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__)
+#define HAL_USE_RTC FALSE
+#endif
+
+/**
+ * @brief Enables the SDC subsystem.
+ */
+#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__)
+#define HAL_USE_SDC FALSE
+#endif
+
+/**
+ * @brief Enables the SERIAL subsystem.
+ */
+#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__)
+#define HAL_USE_SERIAL TRUE
+#endif
+
+/**
+ * @brief Enables the SERIAL over USB subsystem.
+ */
+#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__)
+#define HAL_USE_SERIAL_USB FALSE
+#endif
+
+/**
+ * @brief Enables the SPI subsystem.
+ */
+#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__)
+#define HAL_USE_SPI FALSE
+#endif
+
+/**
+ * @brief Enables the UART subsystem.
+ */
+#if !defined(HAL_USE_UART) || defined(__DOXYGEN__)
+#define HAL_USE_UART FALSE
+#endif
+
+/**
+ * @brief Enables the USB subsystem.
+ */
+#if !defined(HAL_USE_USB) || defined(__DOXYGEN__)
+#define HAL_USE_USB FALSE
+#endif
+
+/**
+ * @brief Enables the WDG subsystem.
+ */
+#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__)
+#define HAL_USE_WDG FALSE
+#endif
+
+/*===========================================================================*/
+/* ADC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__)
+#define ADC_USE_WAIT TRUE
+#endif
+
+/**
+ * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define ADC_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/*===========================================================================*/
+/* CAN driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Sleep mode related APIs inclusion switch.
+ */
+#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__)
+#define CAN_USE_SLEEP_MODE FALSE
+#endif
+
+/*===========================================================================*/
+/* I2C driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables the mutual exclusion APIs on the I2C bus.
+ */
+#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define I2C_USE_MUTUAL_EXCLUSION FALSE
+#endif
+
+/*===========================================================================*/
+/* MAC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables an event sources for incoming packets.
+ */
+#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__)
+#define MAC_USE_ZERO_COPY FALSE
+#endif
+
+/**
+ * @brief Enables an event sources for incoming packets.
+ */
+#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__)
+#define MAC_USE_EVENTS FALSE
+#endif
+
+/*===========================================================================*/
+/* MMC_SPI driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Delays insertions.
+ * @details If enabled this options inserts delays into the MMC waiting
+ * routines releasing some extra CPU time for the threads with
+ * lower priority, this may slow down the driver a bit however.
+ * This option is recommended also if the SPI driver does not
+ * use a DMA channel and heavily loads the CPU.
+ */
+#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__)
+#define MMC_NICE_WAITING FALSE
+#endif
+
+/*===========================================================================*/
+/* SDC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Number of initialization attempts before rejecting the card.
+ * @note Attempts are performed at 10mS intervals.
+ */
+#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__)
+#define SDC_INIT_RETRY 100
+#endif
+
+/**
+ * @brief Include support for MMC cards.
+ * @note MMC support is not yet implemented so this option must be kept
+ * at @p FALSE.
+ */
+#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__)
+#define SDC_MMC_SUPPORT FALSE
+#endif
+
+/**
+ * @brief Delays insertions.
+ * @details If enabled this options inserts delays into the MMC waiting
+ * routines releasing some extra CPU time for the threads with
+ * lower priority, this may slow down the driver a bit however.
+ */
+#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__)
+#define SDC_NICE_WAITING FALSE
+#endif
+
+/*===========================================================================*/
+/* SERIAL driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Default bit rate.
+ * @details Configuration parameter, this is the baud rate selected for the
+ * default configuration.
+ */
+#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__)
+#define SERIAL_DEFAULT_BITRATE 38400
+#endif
+
+/**
+ * @brief Serial buffers size.
+ * @details Configuration parameter, you can change the depth of the queue
+ * buffers depending on the requirements of your application.
+ * @note The default is 16 bytes for both the transmission and receive
+ * buffers.
+ */
+#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__)
+#define SERIAL_BUFFERS_SIZE 16
+#endif
+
+/*===========================================================================*/
+/* SERIAL_USB driver related setting. */
+/*===========================================================================*/
+
+/**
+ * @brief Serial over USB buffers size.
+ * @details Configuration parameter, the buffer size must be a multiple of
+ * the USB data endpoint maximum packet size.
+ * @note The default is 256 bytes for both the transmission and receive
+ * buffers.
+ */
+#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__)
+#define SERIAL_USB_BUFFERS_SIZE 256
+#endif
+
+/**
+ * @brief Serial over USB number of buffers.
+ * @note The default is 2 buffers.
+ */
+#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__)
+#define SERIAL_USB_BUFFERS_NUMBER 2
+#endif
+
+/*===========================================================================*/
+/* SPI driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__)
+#define SPI_USE_WAIT TRUE
+#endif
+
+/**
+ * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define SPI_USE_MUTUAL_EXCLUSION FALSE
+#endif
+
+/*===========================================================================*/
+/* UART driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__)
+#define UART_USE_WAIT FALSE
+#endif
+
+/**
+ * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define UART_USE_MUTUAL_EXCLUSION FALSE
+#endif
+
+/*===========================================================================*/
+/* USB driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__)
+#define USB_USE_WAIT FALSE
+#endif
+
+#endif /* _HALCONF_H_ */
+
+/** @} */
diff --git a/testhal/MSP430X/EXP430FR6989/ADC/main.c b/testhal/MSP430X/EXP430FR6989/ADC/main.c
new file mode 100644
index 0000000..06f9a9c
--- /dev/null
+++ b/testhal/MSP430X/EXP430FR6989/ADC/main.c
@@ -0,0 +1,254 @@
+/*
+ ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
+
+ 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 "ch.h"
+#include "hal.h"
+#include "string.h"
+#include "stdio.h" /* eesh */
+
+/* Disable watchdog because of lousy startup code in newlib */
+static void __attribute__((naked, section(".crt_0042disable_watchdog"), used))
+disable_watchdog(void) {
+ WDTCTL = WDTPW | WDTHOLD;
+}
+
+const char * start_msg = "\r\n\r\nExecuting ADC test suite...\r\n";
+const char * test_1_msg = "\r\nTEST 1: 1 channel, depth 1, no circular\r\n";
+const char * test_2_msg = "\r\nTEST 2: 1 channel, depth 8, no circular\r\n";
+const char * test_3_msg = "\r\nTEST 3: 4 channels, depth 1, no circular\r\n";
+const char * test_4_msg = "\r\nTEST 4: 4 channels, depth 8, no circular\r\n";
+const char * test_5_msg = "\r\nTEST 5: 1 channel, depth 1, circular\r\n";
+const char * test_6_msg = "\r\nTEST 6: 1 channel, depth 8, circular\r\n";
+const char * test_7_msg = "\r\nTEST 7: 4 channel, depth 1, circular\r\n";
+const char * test_8_msg = "\r\nTEST 8: 4 channel, depth 8, circular\r\n";
+const char * test_9_msg = "\r\nTEST 9: 1 channel, depth 1, synchronous\r\n";
+
+const char * success_string = "\r\nSUCCESS\r\n";
+const char * fail_string = "\r\nFAILURE\r\n";
+
+char out_string[128];
+const char * raw_fmt_string = "Raw Value: %d\r\n";
+const char * cooked_fmt_string = "Cooked Value: %d\r\n";
+const char * chn_fmt_string = "\r\nCHANNEL %d\r\n";
+
+uint16_t buffer_margin[72];
+uint16_t * buffer = buffer_margin + 4;
+uint8_t depth;
+uint8_t cb_arg = 0;
+uint16_t cb_expect;
+
+static const int test = 0;
+
+ADCConfig config = {
+};
+
+ADCConversionGroup group = {
+ false, /* circular */
+ 1, /* num_channels */
+ NULL, /* end_cb */
+ NULL, /* error_cb */
+ {
+ 30, 31, 30, 31, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+ }, /* channels */
+ MSP430X_ADC_RES_12BIT, /* res */
+ MSP430X_ADC_SHT_32, /* rate */
+ MSP430X_ADC_VSS_VREF_BUF, /* ref */
+ MSP430X_REF_2V5 /* vref_src */
+};
+
+void print(const char * msg) {
+
+ if (!test) {
+ chnWrite(&SD1, (const uint8_t *)msg, strlen(msg));
+ }
+}
+
+void adc_callback(ADCDriver * adcp, adcsample_t *buffer, size_t n) {
+ (void)adcp;
+ (void)buffer;
+ (void)n;
+
+ cb_arg++;
+
+ if (adcp->grpp->circular && cb_arg == cb_expect) {
+ osalSysLockFromISR();
+ adcStopConversionI(adcp);
+ osalSysUnlockFromISR();
+ }
+}
+
+void run_test(const char * test_msg, uint8_t num_channels, uint8_t depth,
+ bool circular) {
+ print(test_msg);
+
+ cb_arg = 0;
+
+ group.num_channels = num_channels;
+ group.circular = circular;
+ group.end_cb = adc_callback;
+
+ if (depth > 1) cb_expect = 2;
+ else cb_expect = 1;
+ if (circular) cb_expect *= 3;
+
+ adcStartConversion(&ADCD1, &group, buffer, depth);
+
+ while (ADCD1.state == ADC_ACTIVE) ;
+
+
+ int index = 0;
+ for (int j = 0; j < depth; j++) {
+ for (int i = 0; i < group.num_channels; i++) {
+ index = i + (j * group.num_channels);
+ sniprintf(out_string, 128, chn_fmt_string, group.channels[i]);
+ print(out_string);
+
+ sniprintf(out_string, 128, raw_fmt_string, buffer[index]);
+ print(out_string);
+
+ if (group.channels[i] == 30) { /* internal temp sensor */
+ buffer[index] = adcMSP430XAdjustTemp(&group, buffer[index]);
+ }
+ else {
+ buffer[index] = adcMSP430XAdjustResult(&group, buffer[index]);
+ }
+
+ sniprintf(out_string, 128, cooked_fmt_string, buffer[index]);
+ print(out_string);
+ }
+ }
+
+ if (cb_arg == cb_expect) {
+ print(success_string);
+ }
+ else {
+ print(fail_string);
+ }
+}
+
+/*
+ * Thread 2.
+ */
+THD_WORKING_AREA(waThread1, 4096);
+THD_FUNCTION(Thread1, arg) {
+
+ (void)arg;
+
+ /*
+ * Activate the serial driver 0 using the driver default configuration.
+ */
+ sdStart(&SD1, NULL);
+
+ /* Activate the ADC driver 1 using its config */
+ adcStart(&ADCD1, &config);
+
+ while (chnGetTimeout(&SD1, TIME_INFINITE)) {
+ print(start_msg);
+ chThdSleepMilliseconds(2000);
+
+ /* Test 1 - 1ch1d, no circular */
+ run_test(test_1_msg, 1, 1, false);
+
+ /* Test 2 - 1ch8d, no circular */
+ run_test(test_2_msg, 1, 8, false);
+
+ /* Test 3 - 4chd1, no circular */
+ run_test(test_3_msg, 4, 1, false);
+
+ /* Test 4 - 4ch8d, no circular */
+ run_test(test_4_msg, 4, 8, false);
+
+ /* Test 5 - 1ch1d, circular */
+ run_test(test_5_msg, 1, 1, true);
+
+ /* Test 6 - 1ch8d, circular */
+ run_test(test_6_msg, 1, 8, true);
+
+ /* Test 7 - 4ch1d, circular */
+ run_test(test_7_msg, 4, 1, true);
+
+ /* Test 8 - 4ch8d, circular */
+ run_test(test_8_msg, 4, 8, true);
+
+ /* Test 9 - 1ch1d, synchronous */
+ print(test_9_msg);
+ cb_arg = 0;
+
+ group.num_channels = 1;
+ group.circular = false;
+ group.end_cb = adc_callback;
+
+ cb_expect = 1;
+
+ adcConvert(&ADCD1, &group, buffer, 1);
+
+ while (ADCD1.state == ADC_ACTIVE) ;
+
+ sniprintf(out_string, 128, chn_fmt_string, group.channels[0]);
+ print(out_string);
+
+ sniprintf(out_string, 128, raw_fmt_string, buffer[0]);
+ print(out_string);
+
+ buffer[0] = adcMSP430XAdjustTemp(&group, buffer[0]);
+
+ sniprintf(out_string, 128, cooked_fmt_string, buffer[0]);
+ print(out_string);
+
+ if (cb_arg == cb_expect) {
+ print(success_string);
+ }
+ else {
+ print(fail_string);
+ }
+ }
+}
+
+/*
+ * Threads static table, one entry per thread. The number of entries must
+ * match NIL_CFG_NUM_THREADS.
+ */
+THD_TABLE_BEGIN
+ THD_TABLE_ENTRY(waThread1, "adc_test", Thread1, NULL)
+THD_TABLE_END
+
+/*
+ * Application entry point.
+ */
+int main(void) {
+
+ /*
+ * System initializations.
+ * - HAL initialization, this also initializes the configured device drivers
+ * and performs the board-specific initializations.
+ * - Kernel initialization, the main() function becomes a thread and the
+ * RTOS is active.
+ */
+ WDTCTL = WDTPW | WDTHOLD;
+
+ halInit();
+ chSysInit();
+
+ /* This is now the idle thread loop, you may perform here a low priority
+ task but you must never try to sleep or wait in this loop. Note that
+ this tasks runs at the lowest priority level so any instruction added
+ here will be executed after all other tasks have been started.*/
+ while (true) {
+ }
+}
diff --git a/testhal/MSP430X/EXP430FR6989/ADC/mcuconf.h b/testhal/MSP430X/EXP430FR6989/ADC/mcuconf.h
new file mode 100644
index 0000000..bcb0c69
--- /dev/null
+++ b/testhal/MSP430X/EXP430FR6989/ADC/mcuconf.h
@@ -0,0 +1,68 @@
+/*
+ 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 MCUCONF_H
+#define MCUCONF_H
+
+/*
+ * MSP430X drivers configuration.
+ * The following settings override the default settings present in
+ * the various device driver implementation headers.
+ * Note that the settings for each driver only have effect if the driver
+ * is enabled in halconf.h.
+ *
+ */
+
+#define MSP430X_MCUCONF
+
+/* HAL driver system settings */
+#define MSP430X_ACLK_SRC MSP430X_VLOCLK
+#define MSP430X_LFXTCLK_FREQ 0
+#define MSP430X_HFXTCLK_FREQ 0
+#define MSP430X_DCOCLK_FREQ 8000000
+#define MSP430X_MCLK_DIV 1
+#define MSP430X_SMCLK_DIV 32
+
+/*
+ * SERIAL driver system settings.
+ */
+#define MSP430X_SERIAL_USE_USART1 TRUE
+#define MSP430X_USART1_CLK_SRC MSP430X_SMCLK_SRC
+#define MSP430X_SERIAL_USE_USART0 FALSE
+#define MSP430X_SERIAL_USE_USART2 FALSE
+#define MSP430X_SERIAL_USE_USART3 FALSE
+
+/*
+ * ST driver system settings.
+ */
+#define MSP430X_ST_CLK_SRC MSP430X_SMCLK_SRC
+#define MSP430X_ST_TIMER_TYPE B
+#define MSP430X_ST_TIMER_INDEX 0
+
+/*
+ * SPI driver system settings.
+ */
+#define MSP430X_SPI_USE_SPIA1 FALSE
+#define MSP430X_SPI_USE_SPIB0 FALSE
+#define MSP430X_SPI_EXCLUSIVE_DMA FALSE
+
+/*
+ * ADC driver system settings
+ */
+#define MSP430X_ADC_EXCLUSIVE_DMA FALSE
+#define MSP430X_ADC1_FREQ 5000000 / 256
+
+#endif /* _MCUCONF_H_ */
diff --git a/testhal/MSP430X/EXP430FR6989/ADC/msp_vectors.c b/testhal/MSP430X/EXP430FR6989/ADC/msp_vectors.c
new file mode 100644
index 0000000..24e2a11
--- /dev/null
+++ b/testhal/MSP430X/EXP430FR6989/ADC/msp_vectors.c
@@ -0,0 +1,286 @@
+#include <msp430.h>
+
+__attribute__((interrupt(1)))
+void Vector1(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(2)))
+void Vector2(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(3)))
+void Vector3(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(4)))
+void Vector4(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(5)))
+void Vector5(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(6)))
+void Vector6(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(7)))
+void Vector7(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(8)))
+void Vector8(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(9)))
+void Vector9(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(10)))
+void Vector10(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(11)))
+void Vector11(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(12)))
+void Vector12(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(13)))
+void Vector13(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(14)))
+void Vector14(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(15)))
+void Vector15(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(16)))
+void Vector16(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(17)))
+void Vector17(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(18)))
+void Vector18(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(19)))
+void Vector19(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(20)))
+void Vector20(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(21)))
+void Vector21(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(22)))
+void Vector22(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(23)))
+void Vector23(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(24)))
+void Vector24(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(25)))
+void Vector25(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(26)))
+void Vector26(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(27)))
+void Vector27(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(28)))
+void Vector28(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(29)))
+void Vector29(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(30)))
+void Vector30(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(33)))
+void Vector33(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(34)))
+void Vector34(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(36)))
+void Vector36(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(37)))
+void Vector37(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(39)))
+void Vector39(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(40)))
+void Vector40(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(42)))
+void Vector42(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(44)))
+void Vector44(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(45)))
+void Vector45(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(47)))
+void Vector47(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(48)))
+void Vector48(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(49)))
+void Vector49(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(50)))
+void Vector50(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(51)))
+void Vector51(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(53)))
+void Vector53(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(54)))
+void Vector54(void) {
+
+ while (1) {
+ }
+}
+__attribute__((interrupt(55)))
+void Vector55(void) {
+
+ while (1) {
+ }
+}
+
+