Adds ADC12 support to MSP430X port.

Adds support for the MSP430X's 12-bit ADC peripheral, as well as
reasonably complete testing of same.

Also includes fixes for several bugs and cleanup of the DMA peripheral,
which used ch calls rather than osal calls and was unclear about what
contexts its methods could be called from.
This commit is contained in:
Andrew Wygle 2016-06-04 18:26:39 -07:00
parent 456702ee87
commit d9ee72504f
31 changed files with 4068 additions and 233 deletions

View File

@ -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
}
/** @} */

View File

@ -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;
}
/**

View File

@ -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 */

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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 */
/** @} */

View File

@ -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 */
/** @} */

View File

@ -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)
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;
}
}
/* Make the request */
init_request(request, i);
return 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();
/* Is the channel already acquired? */
osalDbgAssert(index < MSP430X_DMA_CHANNELS, "invalid channel index");
if (dma_channels[index].ctl & DMADT_4) {
return true;
#endif
#if !(CH_CFG_USE_SEMAPHORES)
systime_t start = chVTGetSystemTimeX();
do {
#endif
/* Grab the correct DMA channel to use */
int i = 0;
for (i = 0; i < MSP430X_DMA_CHANNELS; i++) {
if (!(dma_channels[i].ctl & DMAEN)) {
break;
}
}
#if !(CH_CFG_USE_SEMAPHORES)
while (chVTTimeElapsedSinceX(start) < timeout)
;
#endif
#if !(CH_CFG_USE_SEMAPHORES)
if (i == MSP430X_DMA_CHANNELS) {
return true;
}
#endif
/* Make the request */
init_request(request, i);
return false;
}
/**
* @brief Acquires exclusive control of a DMA channel.
* @pre The channel must not be already acquired or an error is returned.
* @note If the channel is in use by the DMA engine, blocks until acquired.
* @post This channel must be interacted with using only the functions
* defined in this module.
*
* @param[out] channel The channel handle. Must be pre-allocated.
* @param[in] index The index of the channel (< MSP430X_DMA_CHANNELS).
* @return The operation status.
* @retval false no error, channel acquired.
* @retval true error, channel already acquired.
*/
bool dmaAcquire(msp430x_dma_ch_t * channel, uint8_t index) {
/* Acquire the channel in an idle mode */
/* Increment the DMA counter */
queue_length++;
/* Is the channel already acquired? */
osalDbgAssert(index < MSP430X_DMA_CHANNELS, "invalid channel index");
if (dma_channels[index].ctl & DMADT_4) {
return true;
}
while (dma_channels[index].ctl & DMAEN)
;
/* Increment the DMA counter */
#if CH_CFG_USE_SEMAPHORES
msg_t semresult = chSemWait(&dma_lock);
if (semresult != MSG_OK)
return true;
#endif
/* 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;
while (dma_channels[index].ctl & DMAEN)
;
channel->registers = dma_channels + index;
channel->index = index;
channel->cb = callbacks + index;
return false;
}
dma_trigger_set(index, DMA_TRIGGER_MNEM(DMAREQ));
dma_channels[index].sz = 0;
dma_channels[index].ctl = DMAEN | DMAABORT | DMADT_4;
/**
* @brief Initiates a DMA transfer operation using an acquired channel.
* @pre The channel must have been acquired using @p dmaAcquire().
*
* @param[in] channel pointer to a DMA channel from @p dmaAcquire().
* @param[in] request pointer to a DMA request object.
*/
void dmaTransfer(msp430x_dma_ch_t * channel, msp430x_dma_req_t * request) {
channel->registers = dma_channels + index;
channel->index = index;
channel->cb = callbacks + index;
dma_trigger_set(channel->index, request->trigger);
/**(channel->ctl) = request->trigger;*/
return false;
}
channel->cb->callback = request->callback.callback;
channel->cb->args = request->callback.args;
/**
* @brief Initiates a DMA transfer operation using an acquired channel.
* @pre The channel must have been acquired using @p dmaAcquire().
*
* @param[in] channel pointer to a DMA channel from @p dmaAcquire().
* @param[in] request pointer to a DMA request object.
*/
void dmaTransfer(msp430x_dma_ch_t * channel, msp430x_dma_req_t * request) {
channel->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 */
}
dma_trigger_set(channel->index, request->trigger);
/**(channel->ctl) = request->trigger;*/
/**
* @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;
channel->cb->callback = request->callback.callback;
channel->cb->args = request->callback.args;
sts = osalSysGetStatusAndLockX();
osalDbgCheck(channel != NULL);
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();
}
/* Release the channel in an idle mode */
channel->registers->ctl = DMAABORT;
/**
* @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
}
/* release the DMA counter */
osalThreadDequeueAllI(&dma_queue, MSG_RESET);
queue_length = 0;
osalSysRestoreStatusX(sts);
}
#endif /* HAL_USE_DMA == TRUE */

View File

@ -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);

View File

@ -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
}
/** @} */

View File

@ -25,6 +25,8 @@
#ifndef _HAL_LLD_H_
#define _HAL_LLD_H_
#include "hal_dma_lld.h"
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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_ */
/** @} */

View File

@ -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_ */
/** @} */

View File

@ -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) {
}
}

View File

@ -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_ */

View File

@ -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) {
}
}

View File

@ -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);
}
}

View File

@ -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) {

View File

@ -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) {

View File

@ -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

View File

@ -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_ */
/** @} */

View File

@ -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_ */
/** @} */

View File

@ -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) {
}
}

View File

@ -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_ */

View File

@ -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) {
}
}