Added SPI driver and test code to MSP430X port
A DMA-driven SPI driver and fairly comprehensive test code for SPI on the MSP430X port. Required some cleanup to the DMA and Serial drivers as well. Includes some reformatting to be more in line with ChibiOS coding standards.
This commit is contained in:
parent
cf02c79b5a
commit
dfd93d512b
|
@ -40,9 +40,8 @@
|
|||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/* TODO make sure this is right... */
|
||||
static msp430x_dma_ch_reg_t * const dma_channels = (msp430x_dma_ch_reg_t *)&DMA0CTL;
|
||||
static uint8_t * const dma_ctls = (uint8_t *)&DMACTL0;
|
||||
static msp430x_dma_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
|
||||
|
@ -53,16 +52,29 @@ static semaphore_t dma_lock;
|
|||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Set a DMA trigger using an index.
|
||||
*
|
||||
* @param[in] index The index of the DMA channel whose trigger is set.
|
||||
* @param[in] trigger The trigger to use.
|
||||
* @note This is all to get around weird MSP behavior when writing to memory-
|
||||
* mapped registers using bytewise instructions.
|
||||
*/
|
||||
static void dma_trigger_set(uint8_t index, uint8_t trigger) {
|
||||
uint16_t * ctl = ((uint16_t *)((uintptr_t)(&DMACTL0)) + (index / 2));
|
||||
*ctl &= 0xFF00 >> (8 * (index % 2));
|
||||
*ctl |= trigger << (8 * (index % 2));
|
||||
}
|
||||
static void init_request(const msp430x_dma_req_t * request, uint8_t index) {
|
||||
|
||||
dma_ctls[index] = request->trigger;
|
||||
dma_trigger_set(index, request->trigger);
|
||||
callbacks[index] = request->callback;
|
||||
msp430x_dma_ch_reg_t * ch = &dma_channels[index];
|
||||
ch->sa = (uintptr_t)request->source_addr;
|
||||
ch->da = (uintptr_t)request->dest_addr;
|
||||
ch->sz = request->size;
|
||||
ch->ctl = DMAREQ | DMAIE | DMAEN | request->data_mode | request->addr_mode
|
||||
| request->transfer_mode;
|
||||
ch->ctl = DMAREQ | DMAIE | DMAEN | request->data_mode | request->addr_mode |
|
||||
request->transfer_mode;
|
||||
}
|
||||
|
||||
/*===========================================================================*/
|
||||
|
@ -76,13 +88,16 @@ PORT_IRQ_HANDLER(DMA_VECTOR) {
|
|||
index = (DMAIV >> 1) - 1;
|
||||
|
||||
if (index < MSP430X_DMA_CHANNELS) {
|
||||
#if CH_CFG_USE_SEMAPHORES
|
||||
chSemSignalI(&dma_lock);
|
||||
#endif
|
||||
|
||||
msp430x_dma_cb_t * cb = &callbacks[index];
|
||||
|
||||
/* WARNING: CALLBACKS ARE CALLED IN AN ISR CONTEXT! */
|
||||
if (cb->callback != NULL) {
|
||||
cb->callback(cb->args);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
OSAL_IRQ_EPILOGUE();
|
||||
|
@ -132,7 +147,8 @@ bool dmaRequest(msp430x_dma_req_t * request, systime_t timeout) {
|
|||
}
|
||||
}
|
||||
#if !(CH_CFG_USE_SEMAPHORES)
|
||||
while (chVTTimeElapsedSinceX(start) < timeout);
|
||||
while (chVTTimeElapsedSinceX(start) < timeout)
|
||||
;
|
||||
#endif
|
||||
|
||||
#if !(CH_CFG_USE_SEMAPHORES)
|
||||
|
@ -144,10 +160,6 @@ bool dmaRequest(msp430x_dma_req_t * request, systime_t timeout) {
|
|||
/* Make the request */
|
||||
init_request(request, i);
|
||||
|
||||
#if CH_CFG_USE_SEMAPHORES
|
||||
chSemSignal(&dma_lock);
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -180,14 +192,15 @@ bool dmaAcquire(msp430x_dma_ch_t * channel, uint8_t index) {
|
|||
return true;
|
||||
#endif
|
||||
|
||||
while (dma_channels[index].ctl & DMAEN) ;
|
||||
while (dma_channels[index].ctl & DMAEN)
|
||||
;
|
||||
|
||||
dma_ctls[index] = DMA_TRIGGER_MNEM(DMAREQ);
|
||||
dma_trigger_set(index, DMA_TRIGGER_MNEM(DMAREQ));
|
||||
dma_channels[index].sz = 0;
|
||||
dma_channels[index].ctl = DMAEN | DMAABORT | DMADT_4;
|
||||
|
||||
channel->registers = dma_channels + index;
|
||||
channel->ctl = dma_ctls + index;
|
||||
channel->index = index;
|
||||
channel->cb = callbacks + index;
|
||||
|
||||
return false;
|
||||
|
@ -202,7 +215,8 @@ bool dmaAcquire(msp430x_dma_ch_t * channel, uint8_t index) {
|
|||
*/
|
||||
void dmaTransfer(msp430x_dma_ch_t * channel, msp430x_dma_req_t * request) {
|
||||
|
||||
*(channel->ctl) = request->trigger;
|
||||
dma_trigger_set(channel->index, request->trigger);
|
||||
/**(channel->ctl) = request->trigger;*/
|
||||
|
||||
channel->cb->callback = request->callback.callback;
|
||||
channel->cb->args = request->callback.args;
|
||||
|
@ -212,14 +226,16 @@ void dmaTransfer(msp430x_dma_ch_t * channel, msp430x_dma_req_t * request) {
|
|||
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 */
|
||||
channel->registers->ctl = DMAIE | request->data_mode | request->addr_mode |
|
||||
request->transfer_mode | DMADT_4 | DMAEN |
|
||||
DMAREQ; /* repeated transfers */
|
||||
chSysUnlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Releases exclusive control of a DMA channel.
|
||||
* @details The channel is released from control and returned to the DMA engine
|
||||
* @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().
|
||||
|
@ -228,7 +244,6 @@ void dmaTransfer(msp430x_dma_ch_t * channel, msp430x_dma_req_t * request) {
|
|||
void dmaRelease(msp430x_dma_ch_t * channel) {
|
||||
|
||||
osalDbgCheck(channel != NULL);
|
||||
osalDbgAssert(channel->registers->ctl & DMADT_4, "not acquired");
|
||||
|
||||
/* Release the channel in an idle mode */
|
||||
channel->registers->ctl = DMAABORT;
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
|
||||
#if !defined(DMA_BASE) && !defined(MSP430X_DMA_SOFTWARE)
|
||||
#error "The MSP430 device in use does not support DMA. Explicitly enable"
|
||||
#error "software support by defining MSP430X_DMA_SOFTWARE."
|
||||
#error "software emulation by defining MSP430X_DMA_SOFTWARE."
|
||||
#endif
|
||||
|
||||
#if defined(__MSP430_HAS_DMAX_1__) || defined(__MSP430X_HAS_DMA_1__)
|
||||
|
@ -91,7 +91,7 @@ typedef struct {
|
|||
* @brief MSP430X DMA request structure.
|
||||
*/
|
||||
typedef struct {
|
||||
void * source_addr; /**< @brief Source address */
|
||||
const void * source_addr; /**< @brief Source address */
|
||||
void * dest_addr; /**< @brief Destination address */
|
||||
uint16_t size; /**< @brief Number of values to transfer */
|
||||
uint16_t addr_mode; /**< @brief Address manipulation mode */
|
||||
|
@ -133,7 +133,7 @@ typedef struct {
|
|||
*/
|
||||
typedef struct {
|
||||
msp430x_dma_ch_reg_t * registers; /**< @brief Pointer to channel registers */
|
||||
volatile uint8_t * ctl; /**< @brief Pointer to channel control register */
|
||||
uint8_t index; /**< @brief Index of channel trigger control register */
|
||||
msp430x_dma_cb_t * cb; /**< @brief Pointer to callback function and args */
|
||||
} msp430x_dma_ch_t;
|
||||
|
||||
|
@ -171,4 +171,3 @@ extern "C" {
|
|||
#endif /* HAL_USE_DMA == true */
|
||||
|
||||
#endif /* HAL_MSP430X_DMA_H */
|
||||
|
||||
|
|
|
@ -85,7 +85,6 @@
|
|||
|
||||
/** @} */
|
||||
|
||||
|
||||
/**
|
||||
* @name Line handling macros
|
||||
* @{
|
||||
|
@ -109,8 +108,7 @@
|
|||
/**
|
||||
* @brief Decodes a pad identifier from a line identifier.
|
||||
*/
|
||||
#define PAL_PAD(line) \
|
||||
((uint16_t)((uint16_t)(line) >> 12))
|
||||
#define PAL_PAD(line) ((uint16_t)((uint16_t)(line) >> 12))
|
||||
|
||||
/**
|
||||
* @brief Value identifying an invalid line.
|
||||
|
@ -309,7 +307,6 @@ typedef msp430x_gpio_registers_t * ioportid_t;
|
|||
*/
|
||||
#define pal_lld_writeport(port, bits) ((port)->out = (bits))
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sets a bits mask on a I/O port.
|
||||
*
|
||||
|
@ -366,7 +363,7 @@ typedef msp430x_gpio_registers_t * ioportid_t;
|
|||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_clearpad(port, pad) ((port)->out &= ~(BIT ## pad))
|
||||
#define pal_lld_clearpad(port, pad) ((port)->out &= ~(1 << pad))
|
||||
|
||||
#if !defined(__DOXYGEN__)
|
||||
extern const PALConfig pal_default_config;
|
||||
|
@ -376,9 +373,7 @@ extern const PALConfig pal_default_config;
|
|||
extern "C" {
|
||||
#endif
|
||||
void _pal_lld_init(const PALConfig * config);
|
||||
void _pal_lld_setgroupmode(ioportid_t port,
|
||||
ioportmask_t mask,
|
||||
iomode_t mode);
|
||||
void _pal_lld_setgroupmode(ioportid_t port, ioportmask_t mask, iomode_t mode);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -39,7 +39,11 @@
|
|||
#ifndef __MSP430_HAS_EUSCI_A0__
|
||||
#error "Cannot find USCI module to use for SD0"
|
||||
#endif
|
||||
#ifdef MSP430X_USCI_A0_USED
|
||||
#error "USCI module A0 already in use - USART0 not available"
|
||||
#endif
|
||||
SerialDriver SD0;
|
||||
#define MSP430X_USCI_A0_USED
|
||||
#endif
|
||||
|
||||
/** @brief USART1 serial driver identifier.*/
|
||||
|
@ -47,7 +51,11 @@ SerialDriver SD0;
|
|||
#ifndef __MSP430_HAS_EUSCI_A1__
|
||||
#error "Cannot find USCI module to use for SD1"
|
||||
#endif
|
||||
#ifdef MSP430X_USCI_A1_USED
|
||||
#error "USCI module A1 already in use - USART1 not available"
|
||||
#endif
|
||||
SerialDriver SD1;
|
||||
#define MSP430X_USCI_A1_USED
|
||||
#endif
|
||||
|
||||
/** @brief USART2 serial driver identifier.*/
|
||||
|
@ -55,7 +63,11 @@ SerialDriver SD1;
|
|||
#ifndef __MSP430_HAS_EUSCI_A2__
|
||||
#error "Cannot find USCI module to use for SD2"
|
||||
#endif
|
||||
#ifdef MSP430X_USCI_A2_USED
|
||||
#error "USCI module A2 already in use - USART2 not available"
|
||||
#endif
|
||||
SerialDriver SD2;
|
||||
#define MSP430X_USCI_A2_USED
|
||||
#endif
|
||||
|
||||
/** @brief USART3 serial driver identifier.*/
|
||||
|
@ -63,7 +75,11 @@ SerialDriver SD2;
|
|||
#ifndef __MSP430_HAS_EUSCI_A3__
|
||||
#error "Cannot find USCI module to use for SD3"
|
||||
#endif
|
||||
#ifdef MSP430X_USCI_A3_USED
|
||||
#error "USCI module A3 already in use - USART3 not available"
|
||||
#endif
|
||||
SerialDriver SD3;
|
||||
#define MSP430X_USCI_A3_USED
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
|
@ -73,9 +89,7 @@ SerialDriver SD3;
|
|||
/**
|
||||
* @brief Driver default configuration.
|
||||
*/
|
||||
static const SerialConfig default_config = {
|
||||
SERIAL_DEFAULT_BITRATE
|
||||
};
|
||||
static const SerialConfig default_config = { SERIAL_DEFAULT_BITRATE };
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
|
@ -209,8 +223,8 @@ static void usart0_init(const SerialConfig *config) {
|
|||
UCA0STATW = 0;
|
||||
UCA0ABCTL = 0;
|
||||
UCA0IRCTL = 0;
|
||||
UCA0CTLW0 = (MSP430X_USART0_PARITY << 14) | (MSP430X_USART0_ORDER << 13) | \
|
||||
(MSP430X_USART0_SIZE << 12) | (MSP430X_USART0_STOP << 11) | \
|
||||
UCA0CTLW0 = (MSP430X_USART0_PARITY << 14) | (MSP430X_USART0_ORDER << 13) |
|
||||
(MSP430X_USART0_SIZE << 12) | (MSP430X_USART0_STOP << 11) |
|
||||
(MSP430X_USART0_UCSSEL);
|
||||
UCA0IE = UCRXIE;
|
||||
}
|
||||
|
@ -223,8 +237,8 @@ static void usart1_init(const SerialConfig *config) {
|
|||
UCA1STATW = 0;
|
||||
UCA1ABCTL = 0;
|
||||
UCA1IRCTL = 0;
|
||||
UCA1CTLW0 = (MSP430X_USART1_PARITY << 14) | (MSP430X_USART1_ORDER << 13) | \
|
||||
(MSP430X_USART1_SIZE << 12) | (MSP430X_USART1_STOP << 11) | \
|
||||
UCA1CTLW0 = (MSP430X_USART1_PARITY << 14) | (MSP430X_USART1_ORDER << 13) |
|
||||
(MSP430X_USART1_SIZE << 12) | (MSP430X_USART1_STOP << 11) |
|
||||
(MSP430X_USART1_UCSSEL);
|
||||
UCA1IE = UCRXIE;
|
||||
}
|
||||
|
@ -237,8 +251,8 @@ static void usart2_init(const SerialConfig *config) {
|
|||
UCA2STATW = 0;
|
||||
UCA2ABCTL = 0;
|
||||
UCA2IRCTL = 0;
|
||||
UCA2CTLW0 = (MSP430X_USART2_PARITY << 14) | (MSP430X_USART2_ORDER << 13) | \
|
||||
(MSP430X_USART2_SIZE << 12) | (MSP430X_USART2_STOP << 11) | \
|
||||
UCA2CTLW0 = (MSP430X_USART2_PARITY << 14) | (MSP430X_USART2_ORDER << 13) |
|
||||
(MSP430X_USART2_SIZE << 12) | (MSP430X_USART2_STOP << 11) |
|
||||
(MSP430X_USART2_UCSSEL);
|
||||
UCA2IE = UCRXIE;
|
||||
}
|
||||
|
@ -251,8 +265,8 @@ static void usart3_init(const SerialConfig *config) {
|
|||
UCA3STATW = 0;
|
||||
UCA3ABCTL = 0;
|
||||
UCA3IRCTL = 0;
|
||||
UCA3CTLW0 = (MSP430X_USART3_PARITY << 14) | (MSP430X_USART3_ORDER << 13) | \
|
||||
(MSP430X_USART3_SIZE << 12) | (MSP430X_USART3_STOP << 11) | \
|
||||
UCA3CTLW0 = (MSP430X_USART3_PARITY << 14) | (MSP430X_USART3_ORDER << 13) |
|
||||
(MSP430X_USART3_SIZE << 12) | (MSP430X_USART3_STOP << 11) |
|
||||
(MSP430X_USART3_UCSSEL);
|
||||
UCA3IE = UCRXIE;
|
||||
}
|
||||
|
@ -310,7 +324,6 @@ static void set_error(uint16_t sra, SerialDriver *sdp) {
|
|||
osalSysUnlockFromISR();
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver interrupt handlers. */
|
||||
/*===========================================================================*/
|
||||
|
@ -364,12 +377,12 @@ PORT_IRQ_HANDLER(USCI_A0_VECTOR) {
|
|||
break;
|
||||
|
||||
default: /* other interrupts */
|
||||
while (1);
|
||||
while (1)
|
||||
;
|
||||
break;
|
||||
}
|
||||
|
||||
OSAL_IRQ_EPILOGUE();
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -422,12 +435,12 @@ PORT_IRQ_HANDLER(USCI_A1_VECTOR) {
|
|||
break;
|
||||
|
||||
default: /* other interrupts */
|
||||
while (1);
|
||||
while (1)
|
||||
;
|
||||
break;
|
||||
}
|
||||
|
||||
OSAL_IRQ_EPILOGUE();
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -480,12 +493,12 @@ PORT_IRQ_HANDLER(USCI_A2_VECTOR) {
|
|||
break;
|
||||
|
||||
default: /* other interrupts */
|
||||
while (1);
|
||||
while (1)
|
||||
;
|
||||
break;
|
||||
}
|
||||
|
||||
OSAL_IRQ_EPILOGUE();
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -538,16 +551,15 @@ PORT_IRQ_HANDLER(USCI_A3_VECTOR) {
|
|||
break;
|
||||
|
||||
default: /* other interrupts */
|
||||
while (1);
|
||||
while (1)
|
||||
;
|
||||
break;
|
||||
}
|
||||
|
||||
OSAL_IRQ_EPILOGUE();
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
@ -592,7 +604,6 @@ void sd_lld_start(SerialDriver *sdp, const SerialConfig *config) {
|
|||
config = &default_config;
|
||||
}
|
||||
|
||||
|
||||
if (sdp->state == SD_STOP) {
|
||||
#if MSP430X_SERIAL_USE_USART0 == TRUE
|
||||
if (&SD0 == sdp) {
|
||||
|
|
|
@ -0,0 +1,578 @@
|
|||
/*
|
||||
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_spi_lld.c
|
||||
* @brief MSP430X SPI subsystem low level driver source.
|
||||
*
|
||||
* @addtogroup SPI
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "hal.h"
|
||||
|
||||
#if (HAL_USE_SPI == TRUE) || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local definitions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief SPIA0 driver identifier.
|
||||
*/
|
||||
#if (MSP430X_SPI_USE_SPIA0 == TRUE) || defined(__DOXYGEN__)
|
||||
SPIDriver SPIDA0;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SPIA1 driver identifier.
|
||||
*/
|
||||
#if (MSP430X_SPI_USE_SPIA1 == TRUE) || defined(__DOXYGEN__)
|
||||
SPIDriver SPIDA1;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SPIA2 driver identifier.
|
||||
*/
|
||||
#if (MSP430X_SPI_USE_SPIA2 == TRUE) || defined(__DOXYGEN__)
|
||||
SPIDriver SPIDA2;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SPIA3 driver identifier.
|
||||
*/
|
||||
#if (MSP430X_SPI_USE_SPIA3 == TRUE) || defined(__DOXYGEN__)
|
||||
SPIDriver SPIDA3;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SPIB0 driver identifier.
|
||||
*/
|
||||
#if (MSP430X_SPI_USE_SPIB0 == TRUE) || defined(__DOXYGEN__)
|
||||
SPIDriver SPIDB0;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SPIB1 driver identifier.
|
||||
*/
|
||||
#if (MSP430X_SPI_USE_SPIB1 == TRUE) || defined(__DOXYGEN__)
|
||||
SPIDriver SPIDB1;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SPIB2 driver identifier.
|
||||
*/
|
||||
#if (MSP430X_SPI_USE_SPIB2 == TRUE) || defined(__DOXYGEN__)
|
||||
SPIDriver SPIDB2;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SPIB3 driver identifier.
|
||||
*/
|
||||
#if (MSP430X_SPI_USE_SPIB3 == TRUE) || defined(__DOXYGEN__)
|
||||
SPIDriver SPIDB3;
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
static const uint16_t dummytx = 0xFFFFU;
|
||||
static uint16_t dummyrx;
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
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);
|
||||
}
|
||||
else {
|
||||
dmaTransfer(&(spip->dmarx), &(spip->rx_req));
|
||||
}
|
||||
if (spip->config->dmatx_index > MSP430X_DMA_CHANNELS) {
|
||||
dmaRequest(&(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);
|
||||
#endif
|
||||
|
||||
*(spip->ifg) |= UCTXIFG;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Shared end-of-transfer callback.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
* @note This function is called in ISR context by the DMA code.
|
||||
*/
|
||||
static void spi_lld_end_of_transfer(void * spip) {
|
||||
|
||||
/* So that future transfers will actually work */
|
||||
*(((SPIDriver *)spip)->ifg) &= ~(UCTXIFG);
|
||||
/* NOTE to future me - this macro sets the driver state and calls the
|
||||
* configured callback end_cb, if applicable. That callback doesn't seem to
|
||||
* be modifiable without reconfiguring the whole driver. */
|
||||
_spi_isr_code((SPIDriver *)spip);
|
||||
}
|
||||
/*===========================================================================*/
|
||||
/* Driver interrupt handlers. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Low level SPI driver initialization.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_init(void) {
|
||||
|
||||
#if MSP430X_SPI_USE_SPIA0 == TRUE
|
||||
/* Driver initialization.*/
|
||||
spiObjectInit(&SPIDA0);
|
||||
SPIDA0.regs = (msp430x_spi_reg_t *)(&UCA0CTLW0);
|
||||
SPIDA0.ifg = (volatile uint16_t *)&UCA0IFG;
|
||||
SPIDA0.tx_req.trigger = DMA_TRIGGER_MNEM(UCA0TXIFG);
|
||||
SPIDA0.rx_req.trigger = DMA_TRIGGER_MNEM(UCA0RXIFG);
|
||||
SPIDA0.tx_req.dest_addr = &(SPIDA0.regs->txbuf);
|
||||
SPIDA0.rx_req.source_addr = &(SPIDA0.regs->rxbuf);
|
||||
SPIDA0.tx_req.data_mode = MSP430X_DMA_SRCBYTE | MSP430X_DMA_DSTBYTE;
|
||||
SPIDA0.rx_req.data_mode = MSP430X_DMA_SRCBYTE | MSP430X_DMA_DSTBYTE;
|
||||
SPIDA0.tx_req.transfer_mode = MSP430X_DMA_SINGLE;
|
||||
SPIDA0.rx_req.transfer_mode = MSP430X_DMA_SINGLE;
|
||||
SPIDA0.tx_req.callback.callback = NULL;
|
||||
SPIDA0.tx_req.callback.args = NULL;
|
||||
SPIDA0.rx_req.callback.callback = spi_lld_end_of_transfer;
|
||||
SPIDA0.rx_req.callback.args = &SPIDA0;
|
||||
/* NOTE to my future self - this must be SINGLE because BLOCK and BURST
|
||||
* don't wait for triggers and would overflow both buffers. Don't worry, it
|
||||
* still works - the transfer isn't complete until SZ bytes are transferred */
|
||||
#endif
|
||||
|
||||
#if MSP430X_SPI_USE_SPIA1 == TRUE
|
||||
/* Driver initialization.*/
|
||||
spiObjectInit(&SPIDA1);
|
||||
SPIDA1.regs = (msp430x_spi_reg_t *)(&UCA1CTLW0);
|
||||
SPIDA1.ifg = (volatile uint16_t *)&UCA1IFG;
|
||||
SPIDA1.tx_req.trigger = DMA_TRIGGER_MNEM(UCA1TXIFG);
|
||||
SPIDA1.rx_req.trigger = DMA_TRIGGER_MNEM(UCA1RXIFG);
|
||||
SPIDA1.tx_req.dest_addr = &(SPIDA1.regs->txbuf);
|
||||
SPIDA1.rx_req.source_addr = &(SPIDA1.regs->rxbuf);
|
||||
SPIDA1.tx_req.data_mode = MSP430X_DMA_SRCBYTE | MSP430X_DMA_DSTBYTE;
|
||||
SPIDA1.rx_req.data_mode = MSP430X_DMA_SRCBYTE | MSP430X_DMA_DSTBYTE;
|
||||
SPIDA1.tx_req.transfer_mode = MSP430X_DMA_SINGLE;
|
||||
SPIDA1.rx_req.transfer_mode = MSP430X_DMA_SINGLE;
|
||||
SPIDA1.tx_req.callback.callback = NULL;
|
||||
SPIDA1.tx_req.callback.args = NULL;
|
||||
SPIDA1.rx_req.callback.callback = spi_lld_end_of_transfer;
|
||||
SPIDA1.rx_req.callback.args = &SPIDA1;
|
||||
#endif
|
||||
|
||||
#if MSP430X_SPI_USE_SPIA2 == TRUE
|
||||
/* Driver initialization.*/
|
||||
spiObjectInit(&SPIDA2);
|
||||
SPIDA2.regs = (msp430x_spi_reg_t *)(&UCA2CTLW0);
|
||||
SPIDA2.ifg = (volatile uint16_t *)&UCA2IFG;
|
||||
SPIDA2.tx_req.trigger = DMA_TRIGGER_MNEM(UCA2TXIFG);
|
||||
SPIDA2.rx_req.trigger = DMA_TRIGGER_MNEM(UCA2RXIFG);
|
||||
SPIDA2.tx_req.dest_addr = &(SPIDA2.regs->txbuf);
|
||||
SPIDA2.rx_req.source_addr = &(SPIDA2.regs->rxbuf);
|
||||
SPIDA2.tx_req.data_mode = MSP430X_DMA_SRCBYTE | MSP430X_DMA_DSTBYTE;
|
||||
SPIDA2.rx_req.data_mode = MSP430X_DMA_SRCBYTE | MSP430X_DMA_DSTBYTE;
|
||||
SPIDA2.tx_req.transfer_mode = MSP430X_DMA_SINGLE;
|
||||
SPIDA2.rx_req.transfer_mode = MSP430X_DMA_SINGLE;
|
||||
SPIDA2.tx_req.callback.callback = NULL;
|
||||
SPIDA2.tx_req.callback.args = NULL;
|
||||
SPIDA2.rx_req.callback.callback = spi_lld_end_of_transfer;
|
||||
SPIDA2.rx_req.callback.args = &SPIDA2;
|
||||
#endif
|
||||
|
||||
#if MSP430X_SPI_USE_SPIA3 == TRUE
|
||||
/* Driver initialization.*/
|
||||
spiObjectInit(&SPIDA3);
|
||||
SPIDA3.regs = (msp430x_spi_reg_t *)(&UCA3CTLW0);
|
||||
SPIDA3.ifg = (volatile uint16_t *)&UCA3IFG;
|
||||
SPIDA3.tx_req.trigger = DMA_TRIGGER_MNEM(UCA3TXIFG);
|
||||
SPIDA3.rx_req.trigger = DMA_TRIGGER_MNEM(UCA3RXIFG);
|
||||
SPIDA3.tx_req.dest_addr = &(SPIDA3.regs->txbuf);
|
||||
SPIDA3.rx_req.source_addr = &(SPIDA3.regs->rxbuf);
|
||||
SPIDA3.tx_req.data_mode = MSP430X_DMA_SRCBYTE | MSP430X_DMA_DSTBYTE;
|
||||
SPIDA3.rx_req.data_mode = MSP430X_DMA_SRCBYTE | MSP430X_DMA_DSTBYTE;
|
||||
SPIDA3.tx_req.transfer_mode = MSP430X_DMA_SINGLE;
|
||||
SPIDA3.rx_req.transfer_mode = MSP430X_DMA_SINGLE;
|
||||
SPIDA3.tx_req.callback.callback = NULL;
|
||||
SPIDA3.tx_req.callback.args = NULL;
|
||||
SPIDA3.rx_req.callback.callback = spi_lld_end_of_transfer;
|
||||
SPIDA3.rx_req.callback.args = &SPIDA3;
|
||||
#endif
|
||||
|
||||
#if MSP430X_SPI_USE_SPIB0 == TRUE
|
||||
/* Driver initialization.*/
|
||||
spiObjectInit(&SPIDB0);
|
||||
SPIDB0.regs = (msp430x_spi_reg_t *)(&UCB0CTLW0);
|
||||
SPIDB0.ifg = (volatile uint16_t *)&UCB0IFG;
|
||||
SPIDB0.tx_req.trigger = DMA_TRIGGER_MNEM(UCB0TXIFG0);
|
||||
SPIDB0.rx_req.trigger = DMA_TRIGGER_MNEM(UCB0RXIFG0);
|
||||
SPIDB0.tx_req.dest_addr = &(SPIDB0.regs->txbuf);
|
||||
SPIDB0.rx_req.source_addr = &(SPIDB0.regs->rxbuf);
|
||||
SPIDB0.tx_req.data_mode = MSP430X_DMA_SRCBYTE | MSP430X_DMA_DSTBYTE;
|
||||
SPIDB0.rx_req.data_mode = MSP430X_DMA_SRCBYTE | MSP430X_DMA_DSTBYTE;
|
||||
SPIDB0.tx_req.transfer_mode = MSP430X_DMA_SINGLE;
|
||||
SPIDB0.rx_req.transfer_mode = MSP430X_DMA_SINGLE;
|
||||
SPIDB0.tx_req.callback.callback = NULL;
|
||||
SPIDB0.tx_req.callback.args = NULL;
|
||||
SPIDB0.rx_req.callback.callback = spi_lld_end_of_transfer;
|
||||
SPIDB0.rx_req.callback.args = &SPIDB0;
|
||||
#endif
|
||||
|
||||
#if MSP430X_SPI_USE_SPIB1 == TRUE
|
||||
/* Driver initialization.*/
|
||||
spiObjectInit(&SPIDB1);
|
||||
SPIDB1.regs = (msp430x_spi_reg_t *)(&UCB1CTLW0);
|
||||
SPIDB1.ifg = (volatile uint16_t *)&UCB1IFG;
|
||||
SPIDB1.tx_req.trigger = DMA_TRIGGER_MNEM(UCB1TXIFG0);
|
||||
SPIDB1.rx_req.trigger = DMA_TRIGGER_MNEM(UCB1RXIFG0);
|
||||
SPIDB1.tx_req.dest_addr = &(SPIDB1.regs->txbuf);
|
||||
SPIDB1.rx_req.source_addr = &(SPIDB1.regs->rxbuf);
|
||||
SPIDB1.tx_req.data_mode = MSP430X_DMA_SRCBYTE | MSP430X_DMA_DSTBYTE;
|
||||
SPIDB1.rx_req.data_mode = MSP430X_DMA_SRCBYTE | MSP430X_DMA_DSTBYTE;
|
||||
SPIDB1.tx_req.transfer_mode = MSP430X_DMA_SINGLE;
|
||||
SPIDB1.rx_req.transfer_mode = MSP430X_DMA_SINGLE;
|
||||
SPIDB1.tx_req.callback.callback = NULL;
|
||||
SPIDB1.tx_req.callback.args = NULL;
|
||||
SPIDB1.rx_req.callback.callback = spi_lld_end_of_transfer;
|
||||
SPIDB1.rx_req.callback.args = &SPIDB1;
|
||||
#endif
|
||||
|
||||
#if MSP430X_SPI_USE_SPIB2 == TRUE
|
||||
/* Driver initialization.*/
|
||||
spiObjectInit(&SPIDB2);
|
||||
SPIDB2.regs = (msp430x_spi_reg_t *)(&UCB2CTLW0);
|
||||
SPIDB2.ifg = (volatile uint16_t *)&UCB2IFG;
|
||||
SPIDB2.tx_req.trigger = DMA_TRIGGER_MNEM(UCB2TXIFG0);
|
||||
SPIDB2.rx_req.trigger = DMA_TRIGGER_MNEM(UCB2RXIFG0);
|
||||
SPIDB2.tx_req.dest_addr = &(SPIDB2.regs->txbuf);
|
||||
SPIDB2.rx_req.source_addr = &(SPIDB2.regs->rxbuf);
|
||||
SPIDB2.tx_req.data_mode = MSP430X_DMA_SRCBYTE | MSP430X_DMA_DSTBYTE;
|
||||
SPIDB2.rx_req.data_mode = MSP430X_DMA_SRCBYTE | MSP430X_DMA_DSTBYTE;
|
||||
SPIDB2.tx_req.transfer_mode = MSP430X_DMA_SINGLE;
|
||||
SPIDB2.rx_req.transfer_mode = MSP430X_DMA_SINGLE;
|
||||
SPIDB2.tx_req.callback.callback = NULL;
|
||||
SPIDB2.tx_req.callback.args = NULL;
|
||||
SPIDB2.rx_req.callback.callback = spi_lld_end_of_transfer;
|
||||
SPIDB2.rx_req.callback.args = &SPIDB2;
|
||||
#endif
|
||||
|
||||
#if MSP430X_SPI_USE_SPIB3 == TRUE
|
||||
/* Driver initialization.*/
|
||||
spiObjectInit(&SPIDB3);
|
||||
SPIDB3.regs = (msp430x_spi_reg_t *)(&UCB3CTLW0);
|
||||
SPIDB3.ifg = (volatile uint16_t *)&UCB3IFG;
|
||||
SPIDB3.tx_req.trigger = DMA_TRIGGER_MNEM(UCB3TXIFG0);
|
||||
SPIDB3.rx_req.trigger = DMA_TRIGGER_MNEM(UCB3RXIFG0);
|
||||
SPIDB3.tx_req.dest_addr = &(SPIDB3.regs->txbuf);
|
||||
SPIDB3.rx_req.source_addr = &(SPIDB3.regs->rxbuf);
|
||||
SPIDB3.tx_req.data_mode = MSP430X_DMA_SRCBYTE | MSP430X_DMA_DSTBYTE;
|
||||
SPIDB3.rx_req.data_mode = MSP430X_DMA_SRCBYTE | MSP430X_DMA_DSTBYTE;
|
||||
SPIDB3.tx_req.transfer_mode = MSP430X_DMA_SINGLE;
|
||||
SPIDB3.rx_req.transfer_mode = MSP430X_DMA_SINGLE;
|
||||
SPIDB3.tx_req.callback.callback = NULL;
|
||||
SPIDB3.tx_req.callback.args = NULL;
|
||||
SPIDB3.rx_req.callback.callback = spi_lld_end_of_transfer;
|
||||
SPIDB3.rx_req.callback.args = &SPIDB3;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures and activates the SPI peripheral.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_start(SPIDriver * spip) {
|
||||
|
||||
if (spip->state == SPI_STOP) {
|
||||
/* Enables the peripheral.*/
|
||||
#if MSP430X_SPI_EXCLUSIVE_DMA == TRUE
|
||||
/* Claim DMA streams here */
|
||||
bool b;
|
||||
if (spip->config->dmatx_index < MSP430X_DMA_CHANNELS) {
|
||||
b = dmaAcquire(&(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);
|
||||
osalDbgAssert(!b, "stream already allocated");
|
||||
}
|
||||
#endif /* MSP430X_SPI_EXCLUSIVE_DMA */
|
||||
}
|
||||
uint16_t brw = 0;
|
||||
uint8_t ssel = 0;
|
||||
#if MSP430X_SPI_USE_SPIA0
|
||||
if (spip == &SPIDA0) {
|
||||
brw = MSP430X_SPIA0_CLK_FREQ / spip->config->bit_rate;
|
||||
ssel = MSP430X_SPIA0_UCSSEL;
|
||||
}
|
||||
#endif
|
||||
#if MSP430X_SPI_USE_SPIA1
|
||||
if (spip == &SPIDA1) {
|
||||
brw = MSP430X_SPIA1_CLK_FREQ / spip->config->bit_rate;
|
||||
ssel = MSP430X_SPIA1_UCSSEL;
|
||||
}
|
||||
#endif
|
||||
#if MSP430X_SPI_USE_SPIA2
|
||||
if (spip == &SPIDA2) {
|
||||
brw = MSP430X_SPIA2_CLK_FREQ / spip->config->bit_rate;
|
||||
ssel = MSP430X_SPIA2_UCSSEL;
|
||||
}
|
||||
#endif
|
||||
#if MSP430X_SPI_USE_SPIA3
|
||||
if (spip == &SPIDA3) {
|
||||
brw = MSP430X_SPIA3_CLK_FREQ / spip->config->bit_rate;
|
||||
ssel = MSP430X_SPIA3_UCSSEL;
|
||||
}
|
||||
#endif
|
||||
#if MSP430X_SPI_USE_SPIB0
|
||||
if (spip == &SPIDB0) {
|
||||
brw = MSP430X_SPIB0_CLK_FREQ / spip->config->bit_rate;
|
||||
ssel = MSP430X_SPIB0_UCSSEL;
|
||||
}
|
||||
#endif
|
||||
#if MSP430X_SPI_USE_SPIB1
|
||||
if (spip == &SPIDB1) {
|
||||
brw = MSP430X_SPIB1_CLK_FREQ / spip->config->bit_rate;
|
||||
ssel = MSP430X_SPIB1_UCSSEL;
|
||||
}
|
||||
#endif
|
||||
#if MSP430X_SPI_USE_SPIB2
|
||||
if (spip == &SPIDB2) {
|
||||
brw = MSP430X_SPIB2_CLK_FREQ / spip->config->bit_rate;
|
||||
ssel = MSP430X_SPIB2_UCSSEL;
|
||||
}
|
||||
#endif
|
||||
#if MSP430X_SPI_USE_SPIB3
|
||||
if (spip == &SPIDB3) {
|
||||
brw = MSP430X_SPIB3_CLK_FREQ / spip->config->bit_rate;
|
||||
ssel = MSP430X_SPIB3_UCSSEL;
|
||||
}
|
||||
#endif
|
||||
/* Configures the peripheral.*/
|
||||
spip->regs->ctlw0 = UCSWRST;
|
||||
spip->regs->brw = brw;
|
||||
spip->regs->ctlw0 =
|
||||
(spip->config->spi_mode << 14) | (spip->config->bit_order << 13) |
|
||||
(spip->config->data_size << 12) | (UCMST) |
|
||||
((spip->config->ss_line ? 0 : 2) << 9) | (UCSYNC) | (ssel) | (UCSTEM);
|
||||
*(spip->ifg) = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deactivates the SPI peripheral.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
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));
|
||||
#endif
|
||||
spip->regs->ctlw0 = UCSWRST;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Asserts the slave select signal and prepares for transfers.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_select(SPIDriver * spip) {
|
||||
|
||||
if (spip->config->ss_line) {
|
||||
palClearLine(spip->config->ss_line);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deasserts the slave select signal.
|
||||
* @details The previously selected peripheral is unselected.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_unselect(SPIDriver * spip) {
|
||||
|
||||
if (spip->config->ss_line) {
|
||||
palSetLine(spip->config->ss_line);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Ignores data on the SPI bus.
|
||||
* @details This asynchronous function starts the transmission of a series of
|
||||
* idle bytes on the SPI bus and ignores the received data.
|
||||
* @post At the end of the operation the configured callback is invoked.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
* @param[in] n number of bytes to be ignored
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_ignore(SPIDriver * spip, size_t n) {
|
||||
|
||||
spip->tx_req.source_addr = &dummytx;
|
||||
spip->tx_req.size = n;
|
||||
spip->tx_req.addr_mode = 0;
|
||||
|
||||
spip->rx_req.dest_addr = &dummyrx;
|
||||
spip->rx_req.size = n;
|
||||
spip->rx_req.addr_mode = 0;
|
||||
|
||||
init_transfer(spip);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Exchanges data on the SPI bus.
|
||||
* @details This asynchronous function starts a simultaneous transmit/receive
|
||||
* operation.
|
||||
* @post At the end of the operation the configured callback is invoked.
|
||||
* @note The buffers are organized as uint8_t arrays for data sizes below or
|
||||
* equal to 8 bits else it is organized as uint16_t arrays.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
* @param[in] n number of words to be exchanged
|
||||
* @param[in] txbuf the pointer to the transmit buffer
|
||||
* @param[out] rxbuf the pointer to the receive buffer
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_exchange(SPIDriver * spip,
|
||||
size_t n,
|
||||
const void * txbuf,
|
||||
void * rxbuf) {
|
||||
|
||||
spip->tx_req.source_addr = txbuf;
|
||||
spip->tx_req.size = n;
|
||||
spip->tx_req.addr_mode = MSP430X_DMA_SRCINCR;
|
||||
|
||||
spip->rx_req.dest_addr = rxbuf;
|
||||
spip->rx_req.size = n;
|
||||
spip->rx_req.addr_mode = MSP430X_DMA_DSTINCR;
|
||||
|
||||
init_transfer(spip);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sends data over the SPI bus.
|
||||
* @details This asynchronous function starts a transmit operation.
|
||||
* @post At the end of the operation the configured callback is invoked.
|
||||
* @note The buffers are organized as uint8_t arrays for data sizes below or
|
||||
* equal to 8 bits else it is organized as uint16_t arrays.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
* @param[in] n number of words to send
|
||||
* @param[in] txbuf the pointer to the transmit buffer
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_send(SPIDriver * spip, size_t n, const void * txbuf) {
|
||||
|
||||
spip->tx_req.source_addr = txbuf;
|
||||
spip->tx_req.size = n;
|
||||
spip->tx_req.addr_mode = MSP430X_DMA_SRCINCR;
|
||||
|
||||
spip->rx_req.dest_addr = &dummyrx;
|
||||
spip->rx_req.size = n;
|
||||
spip->rx_req.addr_mode = 0;
|
||||
|
||||
init_transfer(spip);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receives data from the SPI bus.
|
||||
* @details This asynchronous function starts a receive operation.
|
||||
* @post At the end of the operation the configured callback is invoked.
|
||||
* @note The buffers are organized as uint8_t arrays for data sizes below or
|
||||
* equal to 8 bits else it is organized as uint16_t arrays.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
* @param[in] n number of words to receive
|
||||
* @param[out] rxbuf the pointer to the receive buffer
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_receive(SPIDriver * spip, size_t n, void * rxbuf) {
|
||||
|
||||
spip->tx_req.source_addr = &dummytx;
|
||||
spip->tx_req.size = n;
|
||||
spip->tx_req.addr_mode = 0;
|
||||
|
||||
spip->rx_req.dest_addr = rxbuf;
|
||||
spip->rx_req.size = n;
|
||||
spip->rx_req.addr_mode = MSP430X_DMA_DSTINCR;
|
||||
|
||||
init_transfer(spip);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Exchanges one frame using a polled wait.
|
||||
* @details This synchronous function exchanges one frame using a polled
|
||||
* synchronization method. This function is useful when exchanging
|
||||
* small amount of data on high speed channels, usually in this
|
||||
* situation is much more efficient just wait for completion using
|
||||
* polling than suspending the thread waiting for an interrupt.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
* @param[in] frame the data frame to send over the SPI bus
|
||||
* @return The received data frame from the SPI bus.
|
||||
*/
|
||||
uint16_t spi_lld_polled_exchange(SPIDriver * spip, uint16_t frame) {
|
||||
|
||||
osalDbgAssert(!(frame & 0xFF00U), "16-bit transfers not supported");
|
||||
|
||||
while (!(*(spip->ifg) & UCTXIFG))
|
||||
;
|
||||
spip->regs->txbuf = frame;
|
||||
while (!(*(spip->ifg) & UCRXIFG))
|
||||
;
|
||||
return spip->regs->rxbuf;
|
||||
}
|
||||
|
||||
#endif /* HAL_USE_SPI == TRUE */
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,642 @@
|
|||
/*
|
||||
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_spi_lld.h
|
||||
* @brief MSP430X SPI subsystem low level driver header.
|
||||
*
|
||||
* @addtogroup SPI
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef HAL_SPI_LLD_H
|
||||
#define HAL_SPI_LLD_H
|
||||
|
||||
#if (HAL_USE_SPI == TRUE) || defined(__DOXYGEN__)
|
||||
|
||||
#include "hal_dma_lld.h"
|
||||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @name MSP430X configuration options
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief SPIA0 driver enable switch.
|
||||
* @details If set to @p TRUE the support for SPIA0 is included.
|
||||
* @note The default is @p FALSE.
|
||||
*/
|
||||
#if !defined(MSP430X_SPI_USE_SPIA0) || defined(__DOXYGEN__)
|
||||
#define MSP430X_SPI_USE_SPIA0 FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SPIA1 driver enable switch.
|
||||
* @details If set to @p TRUE the support for SPIA1 is included.
|
||||
* @note The default is @p FALSE.
|
||||
*/
|
||||
#if !defined(MSP430X_SPI_USE_SPIA1) || defined(__DOXYGEN__)
|
||||
#define MSP430X_SPI_USE_SPIA1 FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SPIA2 driver enable switch.
|
||||
* @details If set to @p TRUE the support for SPIA2 is included.
|
||||
* @note The default is @p FALSE.
|
||||
*/
|
||||
#if !defined(MSP430X_SPI_USE_SPIA2) || defined(__DOXYGEN__)
|
||||
#define MSP430X_SPI_USE_SPIA2 FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SPIA3 driver enable switch.
|
||||
* @details If set to @p TRUE the support for SPIA3 is included.
|
||||
* @note The default is @p FALSE.
|
||||
*/
|
||||
#if !defined(MSP430X_SPI_USE_SPIA3) || defined(__DOXYGEN__)
|
||||
#define MSP430X_SPI_USE_SPIA3 FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SPIB0 driver enable switch.
|
||||
* @details If set to @p TRUE the support for SPIB0 is included.
|
||||
* @note The default is @p FALSE.
|
||||
*/
|
||||
#if !defined(MSP430X_SPI_USE_SPIB0) || defined(__DOXYGEN__)
|
||||
#define MSP430X_SPI_USE_SPIB0 FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SPIB1 driver enable switch.
|
||||
* @details If set to @p TRUE the support for SPIB1 is included.
|
||||
* @note The default is @p FALSE.
|
||||
*/
|
||||
#if !defined(MSP430X_SPI_USE_SPIB1) || defined(__DOXYGEN__)
|
||||
#define MSP430X_SPI_USE_SPIB1 FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SPIB2 driver enable switch.
|
||||
* @details If set to @p TRUE the support for SPIB2 is included.
|
||||
* @note The default is @p FALSE.
|
||||
*/
|
||||
#if !defined(MSP430X_SPI_USE_SPIB2) || defined(__DOXYGEN__)
|
||||
#define MSP430X_SPI_USE_SPIB2 FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SPIB3 driver enable switch.
|
||||
* @details If set to @p TRUE the support for SPIB3 is included.
|
||||
* @note The default is @p FALSE.
|
||||
*/
|
||||
#if !defined(MSP430X_SPI_USE_SPIB3) || defined(__DOXYGEN__)
|
||||
#define MSP430X_SPI_USE_SPIB3 FALSE
|
||||
#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_SPI_EXCLUSIVE_DMA) | defined(__DOXYGEN__)
|
||||
#define MSP430X_SPI_EXCLUSIVE_DMA FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SPIA0 clock source switch.
|
||||
* @details Sets the clock source for SPIA0.
|
||||
* @note Legal values are @p MSP430X_SMCLK_SRC or @p MSP430X_ACLK_SRC.
|
||||
* @note The default is @p MSP430X_SMCLK_SRC.
|
||||
*/
|
||||
#if !defined(MSP430X_SPIA0_CLK_SRC)
|
||||
#define MSP430X_SPIA0_CLK_SRC MSP430X_SMCLK_SRC
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SPIA1 clock source switch.
|
||||
* @details Sets the clock source for SPIA1.
|
||||
* @note Legal values are @p MSP430X_SMCLK_SRC or @p MSP430X_ACLK_SRC.
|
||||
* @note The default is @p MSP430X_SMCLK_SRC.
|
||||
*/
|
||||
#if !defined(MSP430X_SPIA1_CLK_SRC)
|
||||
#define MSP430X_SPIA1_CLK_SRC MSP430X_SMCLK_SRC
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SPIA2 clock source switch.
|
||||
* @details Sets the clock source for SPIA2.
|
||||
* @note Legal values are @p MSP430X_SMCLK_SRC or @p MSP430X_ACLK_SRC.
|
||||
* @note The default is @p MSP430X_SMCLK_SRC.
|
||||
*/
|
||||
#if !defined(MSP430X_SPIA2_CLK_SRC)
|
||||
#define MSP430X_SPIA2_CLK_SRC MSP430X_SMCLK_SRC
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SPIA3 clock source switch.
|
||||
* @details Sets the clock source for SPIA3.
|
||||
* @note Legal values are @p MSP430X_SMCLK_SRC or @p MSP430X_ACLK_SRC.
|
||||
* @note The default is @p MSP430X_SMCLK_SRC.
|
||||
*/
|
||||
#if !defined(MSP430X_SPIA3_CLK_SRC)
|
||||
#define MSP430X_SPIA3_CLK_SRC MSP430X_SMCLK_SRC
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SPIB0 clock source switch.
|
||||
* @details Sets the clock source for SPIB0.
|
||||
* @note Legal values are @p MSP430X_SMCLK_SRC or @p MSP430X_ACLK_SRC.
|
||||
* @note The default is @p MSP430X_SMCLK_SRC.
|
||||
*/
|
||||
#if !defined(MSP430X_SPIB0_CLK_SRC)
|
||||
#define MSP430X_SPIB0_CLK_SRC MSP430X_SMCLK_SRC
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SPIB1 clock source switch.
|
||||
* @details Sets the clock source for SPIB1.
|
||||
* @note Legal values are @p MSP430X_SMCLK_SRC or @p MSP430X_ACLK_SRC.
|
||||
* @note The default is @p MSP430X_SMCLK_SRC.
|
||||
*/
|
||||
#if !defined(MSP430X_SPIB1_CLK_SRC)
|
||||
#define MSP430X_SPIB1_CLK_SRC MSP430X_SMCLK_SRC
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SPIB2 clock source switch.
|
||||
* @details Sets the clock source for SPIB2.
|
||||
* @note Legal values are @p MSP430X_SMCLK_SRC or @p MSP430X_ACLK_SRC.
|
||||
* @note The default is @p MSP430X_SMCLK_SRC.
|
||||
*/
|
||||
#if !defined(MSP430X_SPIB2_CLK_SRC)
|
||||
#define MSP430X_SPIB2_CLK_SRC MSP430X_SMCLK_SRC
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SPIB3 clock source switch.
|
||||
* @details Sets the clock source for SPIB3.
|
||||
* @note Legal values are @p MSP430X_SMCLK_SRC or @p MSP430X_ACLK_SRC.
|
||||
* @note The default is @p MSP430X_SMCLK_SRC.
|
||||
*/
|
||||
#if !defined(MSP430X_SPIB3_CLK_SRC)
|
||||
#define MSP430X_SPIB3_CLK_SRC MSP430X_SMCLK_SRC
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if MSP430X_SPI_USE_SPIA0 && !defined(__MSP430_HAS_EUSCI_A0__)
|
||||
#error "Cannot find MSP430X_USCI module to use for SPIA0"
|
||||
#endif
|
||||
|
||||
#if MSP430X_SPI_USE_SPIA1 && !defined(__MSP430_HAS_EUSCI_A1__)
|
||||
#error "Cannot find MSP430X_USCI module to use for SPIA1"
|
||||
#endif
|
||||
|
||||
#if MSP430X_SPI_USE_SPIA2 && !defined(__MSP430_HAS_EUSCI_A2__)
|
||||
#error "Cannot find MSP430X_USCI module to use for SPIA2"
|
||||
#endif
|
||||
|
||||
#if MSP430X_SPI_USE_SPIA3 && !defined(__MSP430_HAS_EUSCI_A3__)
|
||||
#error "Cannot find MSP430X_USCI module to use for SPIA3"
|
||||
#endif
|
||||
|
||||
#if MSP430X_SPI_USE_SPIB0 && !defined(__MSP430_HAS_EUSCI_B0__)
|
||||
#error "Cannot find MSP430X_USCI module to use for SPIB0"
|
||||
#endif
|
||||
|
||||
#if MSP430X_SPI_USE_SPIB1 && !defined(__MSP430_HAS_EUSCI_B1__)
|
||||
#error "Cannot find MSP430X_USCI module to use for SPIB1"
|
||||
#endif
|
||||
|
||||
#if MSP430X_SPI_USE_SPIB2 && !defined(__MSP430_HAS_EUSCI_B2__)
|
||||
#error "Cannot find MSP430X_USCI module to use for SPIB2"
|
||||
#endif
|
||||
|
||||
#if MSP430X_SPI_USE_SPIB3 && !defined(__MSP430_HAS_EUSCI_B3__)
|
||||
#error "Cannot find MSP430X_USCI module to use for SPIB3"
|
||||
#endif
|
||||
|
||||
#if MSP430X_SPI_USE_SPIA0
|
||||
#ifdef MSP430X_USCI_A0_USED
|
||||
#error "USCI module A0 already in use - SPIA0 not available"
|
||||
#else
|
||||
#define MSP430X_USCI_A0_USED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if MSP430X_SPI_USE_SPIA1
|
||||
#ifdef MSP430X_USCI_A1_USED
|
||||
#error "USCI module A1 already in use - SPIA1 not available"
|
||||
#else
|
||||
#define MSP430X_USCI_A1_USED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if MSP430X_SPI_USE_SPIA2
|
||||
#ifdef MSP430X_USCI_A2_USED
|
||||
#error "USCI module A2 already in use - SPIA2 not available"
|
||||
#else
|
||||
#define MSP430X_USCI_A2_USED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if MSP430X_SPI_USE_SPIA3
|
||||
#ifdef MSP430X_USCI_A3_USED
|
||||
#error "USCI module A3 already in use - SPIA3 not available"
|
||||
#else
|
||||
#define MSP430X_USCI_A3_USED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if MSP430X_SPI_USE_SPIB0
|
||||
#ifdef MSP430X_USCI_B0_USED
|
||||
#error "USCI module B0 already in use - SPIB0 not available"
|
||||
#else
|
||||
#define MSP430X_USCI_B0_USED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if MSP430X_SPI_USE_SPIB1
|
||||
#ifdef MSP430X_USCI_B1_USED
|
||||
#error "USCI module B1 already in use - SPIB1 not available"
|
||||
#else
|
||||
#define MSP430X_USCI_B1_USED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if MSP430X_SPI_USE_SPIB2
|
||||
#ifdef MSP430X_USCI_B2_USED
|
||||
#error "USCI module B2 already in use - SPIB2 not available"
|
||||
#else
|
||||
#define MSP430X_USCI_B2_USED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if MSP430X_SPI_USE_SPIB3
|
||||
#ifdef MSP430X_USCI_B3_USED
|
||||
#error "USCI module B3 already in use - SPIB3 not available"
|
||||
#else
|
||||
#define MSP430X_USCI_B3_USED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(MSP430X_SPIA0_TX_DMA) && (MSP430X_SPI_DMA >= MSP430X_DMA_CHANNELS)
|
||||
#error "Requested DMA for SPIA0 TX, but requested index is invalid"
|
||||
#endif
|
||||
#if defined(MSP430X_SPIA0_RX_DMA) && (MSP430X_SPI_DMA >= MSP430X_DMA_CHANNELS)
|
||||
#error "Requested DMA for SPIA0 RX, but requested index is invalid"
|
||||
#endif
|
||||
|
||||
#if defined(MSP430X_SPIA1_TX_DMA) && (MSP430X_SPI_DMA >= MSP430X_DMA_CHANNELS)
|
||||
#error "Requested DMA for SPIA1 TX, but requested index is invalid"
|
||||
#endif
|
||||
#if defined(MSP430X_SPIA1_RX_DMA) && (MSP430X_SPI_DMA >= MSP430X_DMA_CHANNELS)
|
||||
#error "Requested DMA for SPIA1 RX, but requested index is invalid"
|
||||
#endif
|
||||
|
||||
#if defined(MSP430X_SPIA2_TX_DMA) && (MSP430X_SPI_DMA >= MSP430X_DMA_CHANNELS)
|
||||
#error "Requested DMA for SPIA2 TX, but requested index is invalid"
|
||||
#endif
|
||||
#if defined(MSP430X_SPIA2_RX_DMA) && (MSP430X_SPI_DMA >= MSP430X_DMA_CHANNELS)
|
||||
#error "Requested DMA for SPIA2 RX, but requested index is invalid"
|
||||
#endif
|
||||
|
||||
#if defined(MSP430X_SPIA3_TX_DMA) && (MSP430X_SPI_DMA >= MSP430X_DMA_CHANNELS)
|
||||
#error "Requested DMA for SPIA3 TX, but requested index is invalid"
|
||||
#endif
|
||||
#if defined(MSP430X_SPIA3_RX_DMA) && (MSP430X_SPI_DMA >= MSP430X_DMA_CHANNELS)
|
||||
#error "Requested DMA for SPIA3 RX, but requested index is invalid"
|
||||
#endif
|
||||
|
||||
#if defined(MSP430X_SPIB0_TX_DMA) && (MSP430X_SPI_DMA >= MSP430X_DMA_CHANNELS)
|
||||
#error "Requested DMA for SPIB0 TX, but requested index is invalid"
|
||||
#endif
|
||||
#if defined(MSP430X_SPIB0_RX_DMA) && (MSP430X_SPI_DMA >= MSP430X_DMA_CHANNELS)
|
||||
#error "Requested DMA for SPIB0 RX, but requested index is invalid"
|
||||
#endif
|
||||
|
||||
#if defined(MSP430X_SPIB1_TX_DMA) && (MSP430X_SPI_DMA >= MSP430X_DMA_CHANNELS)
|
||||
#error "Requested DMA for SPIB1 TX, but requested index is invalid"
|
||||
#endif
|
||||
#if defined(MSP430X_SPIB1_RX_DMA) && (MSP430X_SPI_DMA >= MSP430X_DMA_CHANNELS)
|
||||
#error "Requested DMA for SPIB1 RX, but requested index is invalid"
|
||||
#endif
|
||||
|
||||
#if defined(MSP430X_SPIB2_TX_DMA) && (MSP430X_SPI_DMA >= MSP430X_DMA_CHANNELS)
|
||||
#error "Requested DMA for SPIB2 TX, but requested index is invalid"
|
||||
#endif
|
||||
#if defined(MSP430X_SPIB2_RX_DMA) && (MSP430X_SPI_DMA >= MSP430X_DMA_CHANNELS)
|
||||
#error "Requested DMA for SPIB2 RX, but requested index is invalid"
|
||||
#endif
|
||||
|
||||
#if defined(MSP430X_SPIB3_TX_DMA) && (MSP430X_SPI_DMA >= MSP430X_DMA_CHANNELS)
|
||||
#error "Requested DMA for SPIB3 TX, but requested index is invalid"
|
||||
#endif
|
||||
#if defined(MSP430X_SPIB3_RX_DMA) && (MSP430X_SPI_DMA >= MSP430X_DMA_CHANNELS)
|
||||
#error "Requested DMA for SPIB3 RX, but requested index is invalid"
|
||||
#endif
|
||||
|
||||
/* TODO figure out a way to check for conflicting DMA channels */
|
||||
|
||||
#if MSP430X_SPIA0_CLK_SRC == MSP430X_ACLK_SRC
|
||||
#define MSP430X_SPIA0_CLK_FREQ MSP430X_ACLK_FREQ
|
||||
#define MSP430X_SPIA0_UCSSEL UCSSEL__ACLK
|
||||
#elif MSP430X_SPIA0_CLK_SRC == MSP430X_SMCLK_SRC
|
||||
#define MSP430X_SPIA0_CLK_FREQ MSP430X_SMCLK_FREQ
|
||||
#define MSP430X_SPIA0_UCSSEL UCSSEL__SMCLK
|
||||
#endif
|
||||
|
||||
#if MSP430X_SPIA1_CLK_SRC == MSP430X_ACLK_SRC
|
||||
#define MSP430X_SPIA1_CLK_FREQ MSP430X_ACLK_FREQ
|
||||
#define MSP430X_SPIA1_UCSSEL UCSSEL__ACLK
|
||||
#elif MSP430X_SPIA1_CLK_SRC == MSP430X_SMCLK_SRC
|
||||
#define MSP430X_SPIA1_CLK_FREQ MSP430X_SMCLK_FREQ
|
||||
#define MSP430X_SPIA1_UCSSEL UCSSEL__SMCLK
|
||||
#endif
|
||||
|
||||
#if MSP430X_SPIA2_CLK_SRC == MSP430X_ACLK_SRC
|
||||
#define MSP430X_SPIA2_CLK_FREQ MSP430X_ACLK_FREQ
|
||||
#define MSP430X_SPIA2_UCSSEL UCSSEL__ACLK
|
||||
#elif MSP430X_SPIA2_CLK_SRC == MSP430X_SMCLK_SRC
|
||||
#define MSP430X_SPIA2_CLK_FREQ MSP430X_SMCLK_FREQ
|
||||
#define MSP430X_SPIA2_UCSSEL UCSSEL__SMCLK
|
||||
#endif
|
||||
|
||||
#if MSP430X_SPIA3_CLK_SRC == MSP430X_ACLK_SRC
|
||||
#define MSP430X_SPIA3_CLK_FREQ MSP430X_ACLK_FREQ
|
||||
#define MSP430X_SPIA3_UCSSEL UCSSEL__ACLK
|
||||
#elif MSP430X_SPIA3_CLK_SRC == MSP430X_SMCLK_SRC
|
||||
#define MSP430X_SPIA3_CLK_FREQ MSP430X_SMCLK_FREQ
|
||||
#define MSP430X_SPIA3_UCSSEL UCSSEL__SMCLK
|
||||
#endif
|
||||
|
||||
#if MSP430X_SPIB0_CLK_SRC == MSP430X_ACLK_SRC
|
||||
#define MSP430X_SPIB0_CLK_FREQ MSP430X_ACLK_FREQ
|
||||
#define MSP430X_SPIB0_UCSSEL UCSSEL__ACLK
|
||||
#elif MSP430X_SPIB0_CLK_SRC == MSP430X_SMCLK_SRC
|
||||
#define MSP430X_SPIB0_CLK_FREQ MSP430X_SMCLK_FREQ
|
||||
#define MSP430X_SPIB0_UCSSEL UCSSEL__SMCLK
|
||||
#endif
|
||||
|
||||
#if MSP430X_SPIB1_CLK_SRC == MSP430X_ACLK_SRC
|
||||
#define MSP430X_SPIB1_CLK_FREQ MSP430X_ACLK_FREQ
|
||||
#define MSP430X_SPIB1_UCSSEL UCSSEL__ACLK
|
||||
#elif MSP430X_SPIB1_CLK_SRC == MSP430X_SMCLK_SRC
|
||||
#define MSP430X_SPIB1_CLK_FREQ MSP430X_SMCLK_FREQ
|
||||
#define MSP430X_SPIB1_UCSSEL UCSSEL__SMCLK
|
||||
#endif
|
||||
|
||||
#if MSP430X_SPIB2_CLK_SRC == MSP430X_ACLK_SRC
|
||||
#define MSP430X_SPIB2_CLK_FREQ MSP430X_ACLK_FREQ
|
||||
#define MSP430X_SPIB2_UCSSEL UCSSEL__ACLK
|
||||
#elif MSP430X_SPIB2_CLK_SRC == MSP430X_SMCLK_SRC
|
||||
#define MSP430X_SPIB2_CLK_FREQ MSP430X_SMCLK_FREQ
|
||||
#define MSP430X_SPIB2_UCSSEL UCSSEL__SMCLK
|
||||
#endif
|
||||
|
||||
#if MSP430X_SPIB3_CLK_SRC == MSP430X_ACLK_SRC
|
||||
#define MSP430X_SPIB3_CLK_FREQ MSP430X_ACLK_FREQ
|
||||
#define MSP430X_SPIB3_UCSSEL UCSSEL__ACLK
|
||||
#elif MSP430X_SPIB3_CLK_SRC == MSP430X_SMCLK_SRC
|
||||
#define MSP430X_SPIB3_CLK_FREQ MSP430X_SMCLK_FREQ
|
||||
#define MSP430X_SPIB3_UCSSEL UCSSEL__SMCLK
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Type of a structure representing an SPI driver.
|
||||
*/
|
||||
typedef struct SPIDriver SPIDriver;
|
||||
|
||||
/**
|
||||
* @brief SPI notification callback type.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object triggering the
|
||||
* callback
|
||||
*/
|
||||
typedef void (*spicallback_t)(SPIDriver *spip);
|
||||
|
||||
/**
|
||||
* @brief Enumerated type for SPI bit order.
|
||||
*/
|
||||
typedef enum {
|
||||
MSP430X_SPI_BO_LSB = 0,
|
||||
MSP430X_SPI_BO_MSB = 1
|
||||
} msp430x_spi_bit_order_t;
|
||||
|
||||
/**
|
||||
* @brief Enumerated type for SPI data size.
|
||||
*/
|
||||
typedef enum {
|
||||
MSP430X_SPI_DS_EIGHT = 0,
|
||||
MSP430X_SPI_DS_SEVEN = 1
|
||||
} msp430x_spi_data_size_t;
|
||||
|
||||
/**
|
||||
* @brief Driver configuration structure.
|
||||
* @note Implementations may extend this structure to contain more,
|
||||
* architecture dependent, fields.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief Operation complete callback or @p NULL.
|
||||
*/
|
||||
spicallback_t end_cb;
|
||||
/* End of the mandatory fields.*/
|
||||
/**
|
||||
* @brief The chip select line.
|
||||
* @note This may be PAL_NOLINE to indicate that hardware chip select is used.
|
||||
*/
|
||||
ioline_t ss_line;
|
||||
/**
|
||||
* @brief The bit rate of the SPI interface.
|
||||
* @note Nearest available rate is used.
|
||||
*/
|
||||
uint32_t bit_rate;
|
||||
/**
|
||||
* @brief The bit order of the peripheral - LSB or MSB first.
|
||||
*/
|
||||
msp430x_spi_bit_order_t bit_order;
|
||||
/**
|
||||
* @brief The data size of the peripheral - 7 or 8 bits.
|
||||
*/
|
||||
msp430x_spi_data_size_t data_size;
|
||||
/**
|
||||
* @brief The SPI mode to use - 0 through 3.
|
||||
*/
|
||||
uint8_t spi_mode;
|
||||
#if MSP430X_SPI_EXCLUSIVE_DMA == TRUE || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief The index of the TX DMA channel.
|
||||
* @note This may be >MSP430X_DMA_CHANNELS to indicate that exclusive DMA is not used.
|
||||
*/
|
||||
uint8_t dmatx_index;
|
||||
/**
|
||||
* @brief The index of the RX DMA channel.
|
||||
* @note This may be >MSP430X_DMA_CHANNELS to indicate that exclusive DMA is not used.
|
||||
*/
|
||||
uint8_t dmarx_index;
|
||||
#endif
|
||||
} SPIConfig;
|
||||
|
||||
/**
|
||||
* @brief MSP430X SPI register structure.
|
||||
*/
|
||||
typedef struct {
|
||||
uint16_t ctlw0;
|
||||
uint16_t _padding0;
|
||||
uint16_t _padding1;
|
||||
uint16_t brw;
|
||||
uint16_t statw_b;
|
||||
uint16_t statw_a;
|
||||
uint16_t rxbuf;
|
||||
uint16_t txbuf;
|
||||
} msp430x_spi_reg_t;
|
||||
|
||||
/**
|
||||
* @brief Structure representing an SPI driver.
|
||||
* @note Implementations may extend this structure to contain more,
|
||||
* architecture dependent, fields.
|
||||
*/
|
||||
struct SPIDriver {
|
||||
/**
|
||||
* @brief Driver state.
|
||||
*/
|
||||
spistate_t state;
|
||||
/**
|
||||
* @brief Current configuration data.
|
||||
*/
|
||||
const SPIConfig *config;
|
||||
#if (SPI_USE_WAIT == TRUE) || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Waiting thread.
|
||||
*/
|
||||
thread_reference_t thread;
|
||||
#endif /* SPI_USE_WAIT */
|
||||
#if (SPI_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Mutex protecting the peripheral.
|
||||
*/
|
||||
mutex_t mutex;
|
||||
#endif
|
||||
#if defined(SPI_DRIVER_EXT_FIELDS)
|
||||
SPI_DRIVER_EXT_FIELDS
|
||||
#endif
|
||||
/* End of the mandatory fields.*/
|
||||
/**
|
||||
* @brief Configuration registers.
|
||||
*/
|
||||
msp430x_spi_reg_t * regs;
|
||||
/**
|
||||
* @brief Interrupt flag register.
|
||||
*/
|
||||
volatile uint16_t * ifg;
|
||||
/**
|
||||
* @brief TX DMA request.
|
||||
*/
|
||||
msp430x_dma_req_t tx_req;
|
||||
/**
|
||||
* @brief RX DMA request.
|
||||
*/
|
||||
msp430x_dma_req_t rx_req;
|
||||
#if MSP430X_SPI_EXCLUSIVE_DMA == TRUE || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief TX DMA stream.
|
||||
*/
|
||||
msp430x_dma_ch_t dmatx;
|
||||
/**
|
||||
* @brief RX DMA stream.
|
||||
*/
|
||||
msp430x_dma_ch_t dmarx;
|
||||
#endif
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if (MSP430X_SPI_USE_SPIA0 == TRUE) && !defined(__DOXYGEN__)
|
||||
extern SPIDriver SPIDA0;
|
||||
#endif
|
||||
|
||||
#if (MSP430X_SPI_USE_SPIA1 == TRUE) && !defined(__DOXYGEN__)
|
||||
extern SPIDriver SPIDA1;
|
||||
#endif
|
||||
|
||||
#if (MSP430X_SPI_USE_SPIA2 == TRUE) && !defined(__DOXYGEN__)
|
||||
extern SPIDriver SPIDA2;
|
||||
#endif
|
||||
|
||||
#if (MSP430X_SPI_USE_SPIA3 == TRUE) && !defined(__DOXYGEN__)
|
||||
extern SPIDriver SPIDA3;
|
||||
#endif
|
||||
|
||||
#if (MSP430X_SPI_USE_SPIB0 == TRUE) && !defined(__DOXYGEN__)
|
||||
extern SPIDriver SPIDB0;
|
||||
#endif
|
||||
|
||||
#if (MSP430X_SPI_USE_SPIB1 == TRUE) && !defined(__DOXYGEN__)
|
||||
extern SPIDriver SPIDB1;
|
||||
#endif
|
||||
|
||||
#if (MSP430X_SPI_USE_SPIB2 == TRUE) && !defined(__DOXYGEN__)
|
||||
extern SPIDriver SPIDB2;
|
||||
#endif
|
||||
|
||||
#if (MSP430X_SPI_USE_SPIB3 == TRUE) && !defined(__DOXYGEN__)
|
||||
extern SPIDriver SPIDB3;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void spi_lld_init(void);
|
||||
void spi_lld_start(SPIDriver *spip);
|
||||
void spi_lld_stop(SPIDriver *spip);
|
||||
void spi_lld_select(SPIDriver *spip);
|
||||
void spi_lld_unselect(SPIDriver *spip);
|
||||
void spi_lld_ignore(SPIDriver *spip, size_t n);
|
||||
void spi_lld_exchange(SPIDriver *spip, size_t n,
|
||||
const void *txbuf, void *rxbuf);
|
||||
void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf);
|
||||
void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf);
|
||||
uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HAL_USE_SPI == TRUE */
|
||||
|
||||
#endif /* HAL_SPI_LLD_H */
|
||||
|
||||
/** @} */
|
|
@ -3,7 +3,8 @@ PLATFORMSRC = ${CHIBIOS_CONTRIB}/os/hal/ports/MSP430X/hal_lld.c \
|
|||
${CHIBIOS_CONTRIB}/os/hal/ports/MSP430X/hal_st_lld.c \
|
||||
${CHIBIOS_CONTRIB}/os/hal/ports/MSP430X/hal_serial_lld.c \
|
||||
${CHIBIOS_CONTRIB}/os/hal/ports/MSP430X/hal_pal_lld.c \
|
||||
${CHIBIOS_CONTRIB}/os/hal/ports/MSP430X/hal_dma_lld.c
|
||||
${CHIBIOS_CONTRIB}/os/hal/ports/MSP430X/hal_dma_lld.c \
|
||||
${CHIBIOS_CONTRIB}/os/hal/ports/MSP430X/hal_spi_lld.c
|
||||
|
||||
# Required include directories
|
||||
PLATFORMINC = ${CHIBIOS_CONTRIB}/os/hal/ports/MSP430X
|
||||
|
|
|
@ -113,7 +113,6 @@ include $(CHIBIOS)/os/hal/osal/nil/osal.mk
|
|||
include $(CHIBIOS)/os/nil/nil.mk
|
||||
include $(CHIBIOS_CONTRIB)/os/common/ports/MSP430X/compilers/GCC/mk/port.mk
|
||||
# Other files (optional).
|
||||
include $(CHIBIOS)/test/nil/test.mk
|
||||
|
||||
# Define linker script file here
|
||||
LDSCRIPT = $(STARTUPLD)/msp430fr5969.ld
|
||||
|
|
|
@ -14,19 +14,27 @@
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
#include "hal.h"
|
||||
#include "ch.h"
|
||||
#include "string.h"
|
||||
#include "hal.h"
|
||||
#include "hal_dma_lld.h"
|
||||
#include "string.h"
|
||||
|
||||
const char * start_msg = "\r\n\r\nExecuting DMA test suite...\r\n";
|
||||
const char * test_1_msg = "TEST 1: Word-to-word memcpy with DMA engine, no callbacks\r\n";
|
||||
const char * test_2_msg = "TEST 2: Byte-to-byte memcpy with DMA engine, no callbacks\r\n";
|
||||
const char * test_3_msg = "TEST 3: Byte-to-byte memset with DMA engine, no callbacks\r\n";
|
||||
const char * test_4_msg = "TEST 4: Word-to-word memcpy with DMA engine, with callback\r\n";
|
||||
const char * test_5_msg = "TEST 5: Claim DMA channel 0, perform a Word-to-word memcpy\r\n";
|
||||
const char * test_6_msg = "TEST 6: Attempt to claim already claimed DMA channel, fail. Release it, try to claim it again, 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_1_msg =
|
||||
"TEST 1: Word-to-word memcpy with DMA engine, no callbacks\r\n";
|
||||
const char * test_2_msg =
|
||||
"TEST 2: Byte-to-byte memcpy with DMA engine, no callbacks\r\n";
|
||||
const char * test_3_msg =
|
||||
"TEST 3: Byte-to-byte memset with DMA engine, no callbacks\r\n";
|
||||
const char * test_4_msg =
|
||||
"TEST 4: Word-to-word memcpy with DMA engine, with callback\r\n";
|
||||
const char * test_5_msg =
|
||||
"TEST 5: Claim DMA channel 0, perform a Word-to-word memcpy\r\n";
|
||||
const char * test_6_msg = "TEST 6: Attempt to claim already claimed DMA "
|
||||
"channel, fail. Release it, try to claim it again, "
|
||||
"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 * succeed_string = "SUCCESS\r\n\r\n";
|
||||
const char * fail_string = "FAILURE\r\n\r\n";
|
||||
|
@ -111,11 +119,7 @@ msp430x_dma_req_t test_5_req = {
|
|||
}
|
||||
};
|
||||
|
||||
msp430x_dma_ch_t ch = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
msp430x_dma_ch_t ch = { NULL, 0, NULL };
|
||||
|
||||
/*
|
||||
* Thread 2.
|
||||
|
@ -187,6 +191,7 @@ THD_FUNCTION(Thread1, arg) {
|
|||
chnWrite(&SD0, (const uint8_t *)test_4_msg, strlen(test_4_msg));
|
||||
strcpy(instring, "After DMA test \r\n");
|
||||
strcpy(outstring, "Before DMA test \r\n");
|
||||
cb_arg = 1;
|
||||
if (strcmp("Before DMA test \r\n", outstring) || (cb_arg != 1)) {
|
||||
chnWrite(&SD0, (const uint8_t *)fail_string, strlen(fail_string));
|
||||
}
|
||||
|
@ -199,7 +204,8 @@ THD_FUNCTION(Thread1, arg) {
|
|||
chnWrite(&SD0, (const uint8_t *)succeed_string, strlen(succeed_string));
|
||||
}
|
||||
|
||||
/* Test 5 - use exclusive DMA channel 0 to execute a word-wise memory-to-memory copy. */
|
||||
/* Test 5 - use exclusive DMA channel 0 to execute a word-wise
|
||||
* memory-to-memory copy. */
|
||||
chnWrite(&SD0, (const uint8_t *)test_5_msg, strlen(test_5_msg));
|
||||
strcpy(instring, "After DMA test \r\n");
|
||||
strcpy(outstring, "Before DMA test \r\n");
|
||||
|
@ -216,7 +222,8 @@ THD_FUNCTION(Thread1, arg) {
|
|||
chnWrite(&SD0, (const uint8_t *)succeed_string, strlen(succeed_string));
|
||||
}
|
||||
|
||||
/* Test 6 - Attempt to claim DMA channel 0, fail, release it, attempt to claim it again */
|
||||
/* 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)) {
|
||||
chnWrite(&SD0, (const uint8_t *)fail_string, strlen(fail_string));
|
||||
|
@ -230,7 +237,8 @@ THD_FUNCTION(Thread1, arg) {
|
|||
}
|
||||
dmaRelease(&ch);
|
||||
|
||||
/* Test 7 - use exclusive DMA channel 1 to execute a word-wise memory-to-memory copy. */
|
||||
/* Test 7 - use exclusive DMA channel 1 to execute a word-wise
|
||||
* memory-to-memory copy. */
|
||||
chnWrite(&SD0, (const uint8_t *)test_7_msg, strlen(test_7_msg));
|
||||
strcpy(instring, "After DMA test \r\n");
|
||||
strcpy(outstring, "Before DMA test \r\n");
|
||||
|
@ -250,7 +258,6 @@ THD_FUNCTION(Thread1, arg) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Threads static table, one entry per thread. The number of entries must
|
||||
* match NIL_CFG_NUM_THREADS.
|
||||
|
@ -273,7 +280,6 @@ int main(void) {
|
|||
*/
|
||||
WDTCTL = WDTPW | WDTHOLD;
|
||||
|
||||
|
||||
halInit();
|
||||
chSysInit();
|
||||
dmaInit();
|
||||
|
|
|
@ -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
|
|
@ -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 FALSE
|
||||
|
||||
/**
|
||||
* @brief Debug option, parameters checks.
|
||||
*
|
||||
* @note The default is @p FALSE.
|
||||
*/
|
||||
#define CH_DBG_ENABLE_CHECKS FALSE
|
||||
|
||||
/**
|
||||
* @brief System assertions.
|
||||
*
|
||||
* @note The default is @p FALSE.
|
||||
*/
|
||||
#define CH_DBG_ENABLE_ASSERTS FALSE
|
||||
|
||||
/**
|
||||
* @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_ */
|
||||
|
||||
/** @} */
|
|
@ -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 FALSE
|
||||
#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 TRUE
|
||||
#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 FALSE
|
||||
#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 FALSE
|
||||
#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_ */
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,395 @@
|
|||
/*
|
||||
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 "hal_dma_lld.h"
|
||||
#include "string.h"
|
||||
|
||||
/* 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 SPI test suite...\r\n";
|
||||
const char * test_1_msg = "TEST 1: spiStartIgnore, with callback\r\n";
|
||||
const char * test_2_msg = "TEST 2: spiStartExchange, with callback\r\n";
|
||||
const char * test_3_msg = "TEST 3: spiStartSend, with callback\r\n";
|
||||
const char * test_4_msg = "TEST 4: spiStartReceive, with callback\r\n";
|
||||
const char * test_5_msg = "TEST 5: spiIgnore\r\n";
|
||||
const char * test_6_msg = "TEST 6: spiExchange\r\n";
|
||||
const char * test_7_msg = "TEST 7: spiSend\r\n";
|
||||
const char * test_8_msg = "TEST 8: spiReceive\r\n";
|
||||
const char * test_9_msg = "TEST 9: spiStartExchange with exclusive DMA\r\n";
|
||||
const char * test_10_msg =
|
||||
"TEST 10: spiStartExchange with exclusive DMA for TX\r\n";
|
||||
const char * test_11_msg =
|
||||
"TEST 11: spiStartExchange with exclusive DMA for RX\r\n";
|
||||
|
||||
const char * succeed_string = "SUCCESS\r\n\r\n";
|
||||
const char * fail_string = "FAILURE\r\n\r\n";
|
||||
|
||||
char instring[256];
|
||||
char outstring[256];
|
||||
uint8_t cb_arg = 1;
|
||||
|
||||
void spi_callback(SPIDriver * spip) {
|
||||
(void)spip;
|
||||
cb_arg = 0;
|
||||
}
|
||||
|
||||
SPIConfig SPIDA1_config = {
|
||||
spi_callback, /* callback */
|
||||
PAL_NOLINE, /* hardware slave select line */
|
||||
250000, /* data rate */
|
||||
MSP430X_SPI_BO_LSB, /* bit order */
|
||||
MSP430X_SPI_DS_EIGHT, /* data size */
|
||||
0, /* SPI mode */
|
||||
0xFFU, /* no exclusive TX DMA */
|
||||
0xFFU /* no exclusive RX DMA */
|
||||
};
|
||||
|
||||
SPIConfig SPIDB0_config = {
|
||||
NULL, /* callback */
|
||||
LINE_LED_G, /* GPIO slave select line */
|
||||
1000, /* data rate */
|
||||
MSP430X_SPI_BO_MSB, /* bit order */
|
||||
MSP430X_SPI_DS_SEVEN, /* data size */
|
||||
3, /* SPI mode */
|
||||
0xFF, /* no exclusive TX DMA */
|
||||
0xFF /* no exclusive RX DMA */
|
||||
};
|
||||
|
||||
/*
|
||||
* Thread 2.
|
||||
*/
|
||||
THD_WORKING_AREA(waThread1, 4096);
|
||||
THD_FUNCTION(Thread1, arg) {
|
||||
|
||||
(void)arg;
|
||||
|
||||
/* Set up loopback mode for testing */
|
||||
SPIDA1.regs->statw_a |= UCLISTEN;
|
||||
SPIDB0.regs->statw_b |= UCLISTEN;
|
||||
|
||||
/*
|
||||
* Activate the serial driver 0 using the driver default configuration.
|
||||
*/
|
||||
sdStart(&SD0, NULL);
|
||||
|
||||
/* Activate the SPI driver A1 using its config */
|
||||
spiStart(&SPIDA1, &SPIDA1_config);
|
||||
/* Activate the SPI driver B0 using its config */
|
||||
spiStart(&SPIDB0, &SPIDB0_config);
|
||||
|
||||
while (chnGetTimeout(&SD0, TIME_INFINITE)) {
|
||||
chnWrite(&SD0, (const uint8_t *)start_msg, strlen(start_msg));
|
||||
chThdSleepMilliseconds(2000);
|
||||
|
||||
/* Test 1 - spiStartIgnore with callback */
|
||||
chnWrite(&SD0, (const uint8_t *)test_1_msg, strlen(test_1_msg));
|
||||
strcpy(outstring, "After SPI test \r\n");
|
||||
strcpy(instring, "Before SPI test \r\n");
|
||||
cb_arg = 1;
|
||||
if (strcmp("Before SPI test \r\n", instring) ||
|
||||
strcmp("After SPI test \r\n", outstring) || cb_arg != 1) {
|
||||
chnWrite(&SD0, (const uint8_t *)fail_string, strlen(fail_string));
|
||||
}
|
||||
spiSelect(&SPIDA1);
|
||||
spiStartIgnore(&SPIDA1, strlen(outstring));
|
||||
while (SPIDA1.state != SPI_READY)
|
||||
; /* wait for transaction to finish */
|
||||
spiUnselect(&SPIDA1);
|
||||
if (strcmp("Before SPI test \r\n", instring) ||
|
||||
strcmp("After SPI test \r\n", outstring) || cb_arg != 0) {
|
||||
chnWrite(&SD0, (const uint8_t *)fail_string, strlen(fail_string));
|
||||
}
|
||||
else {
|
||||
chnWrite(&SD0, (const uint8_t *)succeed_string, strlen(succeed_string));
|
||||
}
|
||||
|
||||
/* Test 2 - spiStartExchange with callback */
|
||||
chnWrite(&SD0, (const uint8_t *)test_2_msg, strlen(test_2_msg));
|
||||
strcpy(outstring, "After SPI test \r\n");
|
||||
strcpy(instring, "Before SPI test \r\n");
|
||||
cb_arg = 1;
|
||||
if (strcmp("Before SPI test \r\n", instring) ||
|
||||
strcmp("After SPI test \r\n", outstring) || cb_arg != 1) {
|
||||
chnWrite(&SD0, (const uint8_t *)fail_string, strlen(fail_string));
|
||||
}
|
||||
spiSelect(&SPIDA1);
|
||||
spiStartExchange(&SPIDA1, strlen(instring), outstring, instring);
|
||||
while (SPIDA1.state != SPI_READY)
|
||||
; /* wait for transaction to finish */
|
||||
spiUnselect(&SPIDA1);
|
||||
if (strcmp("After SPI test \r\n", instring) ||
|
||||
strcmp("After SPI test \r\n", outstring) || cb_arg != 0) {
|
||||
chnWrite(&SD0, (const uint8_t *)fail_string, strlen(fail_string));
|
||||
}
|
||||
else {
|
||||
chnWrite(&SD0, (const uint8_t *)succeed_string, strlen(succeed_string));
|
||||
}
|
||||
|
||||
/* Test 3 - spiStartSend with callback */
|
||||
chnWrite(&SD0, (const uint8_t *)test_3_msg, strlen(test_3_msg));
|
||||
strcpy(outstring, "After SPI test \r\n");
|
||||
strcpy(instring, "Before SPI test \r\n");
|
||||
cb_arg = 1;
|
||||
if (strcmp("Before SPI test \r\n", instring) ||
|
||||
strcmp("After SPI test \r\n", outstring) || cb_arg != 1) {
|
||||
chnWrite(&SD0, (const uint8_t *)fail_string, strlen(fail_string));
|
||||
}
|
||||
spiSelect(&SPIDA1);
|
||||
spiStartSend(&SPIDA1, strlen(outstring), outstring);
|
||||
while (SPIDA1.state != SPI_READY)
|
||||
; /* wait for transaction to finish */
|
||||
spiUnselect(&SPIDA1);
|
||||
if (strcmp("Before SPI test \r\n", instring) ||
|
||||
strcmp("After SPI test \r\n", outstring) || cb_arg != 0) {
|
||||
chnWrite(&SD0, (const uint8_t *)fail_string, strlen(fail_string));
|
||||
}
|
||||
else {
|
||||
chnWrite(&SD0, (const uint8_t *)succeed_string, strlen(succeed_string));
|
||||
}
|
||||
|
||||
/* Test 4 - spiStartReceive with callback */
|
||||
chnWrite(&SD0, (const uint8_t *)test_4_msg, strlen(test_4_msg));
|
||||
strcpy(outstring, "After SPI test \r\n");
|
||||
strcpy(instring, "Before SPI test \r\n");
|
||||
cb_arg = 1;
|
||||
if (strcmp("Before SPI test \r\n", instring) ||
|
||||
strcmp("After SPI test \r\n", outstring) || cb_arg != 1) {
|
||||
chnWrite(&SD0, (const uint8_t *)fail_string, strlen(fail_string));
|
||||
}
|
||||
spiSelect(&SPIDA1);
|
||||
chThdSleepMilliseconds(2000);
|
||||
spiStartReceive(&SPIDA1, strlen(instring), instring);
|
||||
while (SPIDA1.state != SPI_READY)
|
||||
; /* wait for transaction to finish */
|
||||
spiUnselect(&SPIDA1);
|
||||
if (strcmp("After SPI test \r\n", outstring) ||
|
||||
strcmp("\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
|
||||
"\xff\xff\xff",
|
||||
instring) ||
|
||||
cb_arg != 0) {
|
||||
chnWrite(&SD0, (const uint8_t *)fail_string, strlen(fail_string));
|
||||
}
|
||||
else {
|
||||
chnWrite(&SD0, (const uint8_t *)succeed_string, strlen(succeed_string));
|
||||
}
|
||||
|
||||
/* Test 5 - spiIgnore */
|
||||
chnWrite(&SD0, (const uint8_t *)test_5_msg, strlen(test_5_msg));
|
||||
strcpy(instring, "After SPI test \r\n");
|
||||
strcpy(outstring, "Before SPI test \r\n");
|
||||
if (strcmp("Before SPI test \r\n", outstring) ||
|
||||
strcmp("After SPI test \r\n", instring)) {
|
||||
chnWrite(&SD0, (const uint8_t *)fail_string, strlen(fail_string));
|
||||
}
|
||||
spiSelect(&SPIDB0);
|
||||
chThdSleepMilliseconds(2000);
|
||||
spiIgnore(&SPIDB0, strlen(outstring));
|
||||
spiUnselect(&SPIDB0);
|
||||
if (strcmp("After SPI test \r\n", instring) ||
|
||||
strcmp("Before SPI test \r\n", outstring)) {
|
||||
chnWrite(&SD0, (const uint8_t *)fail_string, strlen(fail_string));
|
||||
}
|
||||
else {
|
||||
chnWrite(&SD0, (const uint8_t *)succeed_string, strlen(succeed_string));
|
||||
}
|
||||
|
||||
/* Test 6 - spiExchange */
|
||||
chnWrite(&SD0, (const uint8_t *)test_6_msg, strlen(test_6_msg));
|
||||
strcpy(outstring, "After SPI test \r\n");
|
||||
strcpy(instring, "Before SPI test \r\n");
|
||||
if (strcmp("Before SPI test \r\n", instring) ||
|
||||
strcmp("After SPI test \r\n", outstring)) {
|
||||
chnWrite(&SD0, (const uint8_t *)fail_string, strlen(fail_string));
|
||||
}
|
||||
spiSelect(&SPIDB0);
|
||||
spiExchange(&SPIDB0, strlen(outstring), outstring, instring);
|
||||
spiUnselect(&SPIDB0);
|
||||
if (strcmp("After SPI test \r\n", instring) ||
|
||||
strcmp("After SPI test \r\n", outstring)) {
|
||||
chnWrite(&SD0, (const uint8_t *)fail_string, strlen(fail_string));
|
||||
}
|
||||
else {
|
||||
chnWrite(&SD0, (const uint8_t *)succeed_string, strlen(succeed_string));
|
||||
}
|
||||
|
||||
/* Test 7 - spiSend */
|
||||
chnWrite(&SD0, (const uint8_t *)test_7_msg, strlen(test_7_msg));
|
||||
strcpy(outstring, "After SPI test \r\n");
|
||||
strcpy(instring, "Before SPI test \r\n");
|
||||
if (strcmp("Before SPI test \r\n", instring) ||
|
||||
strcmp("After SPI test \r\n", outstring)) {
|
||||
chnWrite(&SD0, (const uint8_t *)fail_string, strlen(fail_string));
|
||||
}
|
||||
spiSelect(&SPIDB0);
|
||||
spiSend(&SPIDB0, strlen(outstring), outstring);
|
||||
spiUnselect(&SPIDB0);
|
||||
if (strcmp("After SPI test \r\n", outstring) ||
|
||||
strcmp("Before SPI test \r\n", instring)) {
|
||||
chnWrite(&SD0, (const uint8_t *)fail_string, strlen(fail_string));
|
||||
}
|
||||
else {
|
||||
chnWrite(&SD0, (const uint8_t *)succeed_string, strlen(succeed_string));
|
||||
}
|
||||
|
||||
/* Test 8 - spiReceive */
|
||||
chnWrite(&SD0, (const uint8_t *)test_8_msg, strlen(test_8_msg));
|
||||
strcpy(outstring, "After SPI test \r\n");
|
||||
strcpy(instring, "Before SPI test \r\n");
|
||||
if (strcmp("Before SPI test \r\n", instring) ||
|
||||
strcmp("After SPI test \r\n", outstring)) {
|
||||
chnWrite(&SD0, (const uint8_t *)fail_string, strlen(fail_string));
|
||||
}
|
||||
spiSelect(&SPIDB0);
|
||||
spiReceive(&SPIDB0, strlen(instring), instring);
|
||||
spiUnselect(&SPIDB0);
|
||||
if (strcmp("After SPI test \r\n", outstring) ||
|
||||
strcmp("\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f"
|
||||
"\x7f\x7f\x7f",
|
||||
instring)) {
|
||||
chnWrite(&SD0, (const uint8_t *)fail_string, strlen(fail_string));
|
||||
}
|
||||
else {
|
||||
chnWrite(&SD0, (const uint8_t *)succeed_string, strlen(succeed_string));
|
||||
}
|
||||
|
||||
/* Reconfigure SPIDA1 to use exclusive DMA for both */
|
||||
spiStop(&SPIDA1);
|
||||
SPIDA1_config.dmatx_index = 0;
|
||||
SPIDA1_config.dmarx_index = 1;
|
||||
SPIDA1_config.spi_mode = 1; /* because why not get coverage */
|
||||
spiStart(&SPIDA1, &SPIDA1_config);
|
||||
|
||||
/* Test 9 - spiStartExchange with exclusive DMA */
|
||||
chnWrite(&SD0, (const uint8_t *)test_9_msg, strlen(test_9_msg));
|
||||
strcpy(outstring, "After SPI test \r\n");
|
||||
strcpy(instring, "Before SPI test \r\n");
|
||||
cb_arg = 1;
|
||||
if (strcmp("Before SPI test \r\n", instring) ||
|
||||
strcmp("After SPI test \r\n", outstring) || cb_arg != 1) {
|
||||
chnWrite(&SD0, (const uint8_t *)fail_string, strlen(fail_string));
|
||||
}
|
||||
spiSelect(&SPIDA1);
|
||||
spiStartExchange(&SPIDA1, strlen(outstring), outstring, instring);
|
||||
while (SPIDA1.state != SPI_READY)
|
||||
; /* wait for transaction to finish */
|
||||
spiUnselect(&SPIDA1);
|
||||
if (strcmp("After SPI test \r\n", instring) ||
|
||||
strcmp("After SPI test \r\n", outstring) || cb_arg != 0) {
|
||||
chnWrite(&SD0, (const uint8_t *)fail_string, strlen(fail_string));
|
||||
}
|
||||
else {
|
||||
chnWrite(&SD0, (const uint8_t *)succeed_string, strlen(succeed_string));
|
||||
}
|
||||
|
||||
/* Reconfigure SPIDA1 to use exclusive DMA for TX only */
|
||||
spiStop(&SPIDA1);
|
||||
SPIDA1_config.dmatx_index = 0;
|
||||
SPIDA1_config.dmarx_index = 0xFFU;
|
||||
SPIDA1_config.spi_mode = 2; /* because why not get coverage */
|
||||
spiStart(&SPIDA1, &SPIDA1_config);
|
||||
|
||||
/* Test 10 - spiStartExchange with exclusive DMA for TX */
|
||||
chnWrite(&SD0, (const uint8_t *)test_10_msg, strlen(test_10_msg));
|
||||
strcpy(outstring, "After SPI test \r\n");
|
||||
strcpy(instring, "Before SPI test \r\n");
|
||||
cb_arg = 1;
|
||||
if (strcmp("Before SPI test \r\n", instring) ||
|
||||
strcmp("After SPI test \r\n", outstring) || cb_arg != 1) {
|
||||
chnWrite(&SD0, (const uint8_t *)fail_string, strlen(fail_string));
|
||||
}
|
||||
spiSelect(&SPIDA1);
|
||||
spiStartExchange(&SPIDA1, strlen(outstring), outstring, instring);
|
||||
while (SPIDA1.state != SPI_READY)
|
||||
; /* wait for transaction to finish */
|
||||
spiUnselect(&SPIDA1);
|
||||
if (strcmp("After SPI test \r\n", instring) ||
|
||||
strcmp("After SPI test \r\n", outstring) || cb_arg != 0) {
|
||||
chnWrite(&SD0, (const uint8_t *)fail_string, strlen(fail_string));
|
||||
}
|
||||
else {
|
||||
chnWrite(&SD0, (const uint8_t *)succeed_string, strlen(succeed_string));
|
||||
}
|
||||
|
||||
/* Reconfigure SPIDA1 to use exclusive DMA for TX only */
|
||||
spiStop(&SPIDA1);
|
||||
SPIDA1_config.dmatx_index = 0xFFU;
|
||||
SPIDA1_config.dmarx_index = 1;
|
||||
SPIDA1_config.spi_mode = 3; /* because why not get coverage */
|
||||
spiStart(&SPIDA1, &SPIDA1_config);
|
||||
|
||||
/* Test 11 - spiStartExchange with exclusive DMA for RX */
|
||||
chnWrite(&SD0, (const uint8_t *)test_11_msg, strlen(test_11_msg));
|
||||
strcpy(outstring, "After SPI test \r\n");
|
||||
strcpy(instring, "Before SPI test \r\n");
|
||||
cb_arg = 1;
|
||||
if (strcmp("Before SPI test \r\n", instring) ||
|
||||
strcmp("After SPI test \r\n", outstring) || cb_arg != 1) {
|
||||
chnWrite(&SD0, (const uint8_t *)fail_string, strlen(fail_string));
|
||||
}
|
||||
spiSelect(&SPIDA1);
|
||||
spiStartExchange(&SPIDA1, strlen(outstring), outstring, instring);
|
||||
while (SPIDA1.state != SPI_READY)
|
||||
; /* wait for transaction to finish */
|
||||
spiUnselect(&SPIDA1);
|
||||
if (strcmp("After SPI test \r\n", instring) ||
|
||||
strcmp("After SPI test \r\n", outstring) || cb_arg != 0) {
|
||||
chnWrite(&SD0, (const uint8_t *)fail_string, strlen(fail_string));
|
||||
}
|
||||
else {
|
||||
chnWrite(&SD0, (const uint8_t *)succeed_string, strlen(succeed_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, "spi_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();
|
||||
dmaInit();
|
||||
|
||||
/* 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) {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
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 TRUE
|
||||
#define MSP430X_SPI_USE_SPIB0 TRUE
|
||||
#define MSP430X_SPI_EXCLUSIVE_DMA TRUE
|
||||
|
||||
#endif /* _MCUCONF_H_ */
|
|
@ -0,0 +1,316 @@
|
|||
#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(33)))
|
||||
void Vector33(void) {
|
||||
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
__attribute__((interrupt(34)))
|
||||
void Vector34(void) {
|
||||
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
__attribute__((interrupt(35)))
|
||||
void Vector35(void) {
|
||||
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
__attribute__((interrupt(36)))
|
||||
void Vector36(void) {
|
||||
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
__attribute__((interrupt(37)))
|
||||
void Vector37(void) {
|
||||
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
__attribute__((interrupt(38)))
|
||||
void Vector38(void) {
|
||||
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
__attribute__((interrupt(39)))
|
||||
void Vector39(void) {
|
||||
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
__attribute__((interrupt(40)))
|
||||
void Vector40(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(47)))
|
||||
void Vector47(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) {
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue