improved SPI no DMA block read + added SPI DMA
This commit is contained in:
parent
28fa836f4f
commit
59ebf2a818
|
@ -117,33 +117,16 @@ void dma_detach_interrupt(dma_dev *dev, dma_stream stream) {
|
||||||
dev->handlers[stream].handler = NULL;
|
dev->handlers[stream].handler = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const uint8 dma_isr_bits_shift[] = { 0, 6, 16, 22};
|
||||||
|
|
||||||
|
uint8 dma_get_isr_bits(dma_dev *dev, dma_stream stream) {
|
||||||
|
if ( stream&0xFC ) return ((dev->regs->HISR)>>dma_isr_bits_shift[stream&0x03]) & 0x3d;
|
||||||
|
else return ((dev->regs->LISR)>>dma_isr_bits_shift[stream&0x03]) & 0x3d;
|
||||||
|
}
|
||||||
|
|
||||||
void dma_clear_isr_bits(dma_dev *dev, dma_stream stream) {
|
void dma_clear_isr_bits(dma_dev *dev, dma_stream stream) {
|
||||||
switch (stream) {
|
if ( stream&0xFC ) dev->regs->HIFCR = (uint32)0x0000003d << dma_isr_bits_shift[stream&0x03];
|
||||||
case 0:
|
else dev->regs->LIFCR = (uint32)0x0000003d << dma_isr_bits_shift[stream&0x03];
|
||||||
dev->regs->LIFCR|=0x0000003d;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
dev->regs->LIFCR|=0x00000f40;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
dev->regs->LIFCR|=0x003d0000;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
dev->regs->LIFCR|=0x0f400000;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
dev->regs->HIFCR|=0x0000003d;
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
dev->regs->HIFCR|=0x00000f40;
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
dev->regs->HIFCR|=0x003d0000;
|
|
||||||
break;
|
|
||||||
case 7:
|
|
||||||
dev->regs->HIFCR|=0x0f400000;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file dma.h
|
* @file dmaF4.h
|
||||||
*
|
*
|
||||||
* @author Marti Bolivar <mbolivar@leaflabs.com>;
|
* @author Marti Bolivar <mbolivar@leaflabs.com>;
|
||||||
* Original implementation by Michael Hope
|
* Original implementation by Michael Hope
|
||||||
|
@ -84,7 +84,7 @@ typedef struct dma_reg_map {
|
||||||
* Register bit definitions
|
* Register bit definitions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Channel configuration register */
|
/* Stream configuration register */
|
||||||
|
|
||||||
#define DMA_CR_CH0 (0x0 << 25)
|
#define DMA_CR_CH0 (0x0 << 25)
|
||||||
#define DMA_CR_CH1 (0x1 << 25)
|
#define DMA_CR_CH1 (0x1 << 25)
|
||||||
|
@ -136,6 +136,25 @@ typedef struct dma_reg_map {
|
||||||
#define DMA_CR_DMEIE (0x1 << 1)
|
#define DMA_CR_DMEIE (0x1 << 1)
|
||||||
#define DMA_CR_EN (0x1)
|
#define DMA_CR_EN (0x1)
|
||||||
|
|
||||||
|
typedef enum dma_channel {
|
||||||
|
DMA_CH0 = DMA_CR_CH0, /**< Channel 0 */
|
||||||
|
DMA_CH1 = DMA_CR_CH1, /**< Channel 1 */
|
||||||
|
DMA_CH2 = DMA_CR_CH2, /**< Channel 2 */
|
||||||
|
DMA_CH3 = DMA_CR_CH3, /**< Channel 3 */
|
||||||
|
DMA_CH4 = DMA_CR_CH4, /**< Channel 4 */
|
||||||
|
DMA_CH5 = DMA_CR_CH5, /**< Channel 5 */
|
||||||
|
DMA_CH6 = DMA_CR_CH6, /**< Channel 6 */
|
||||||
|
DMA_CH7 = DMA_CR_CH7, /**< Channel 7 */
|
||||||
|
} dma_channel;
|
||||||
|
|
||||||
|
/* Device interrupt status register flags */
|
||||||
|
|
||||||
|
#define DMA_ISR_TCIF (1 << 5)
|
||||||
|
#define DMA_ISR_HTIF (1 << 4)
|
||||||
|
#define DMA_ISR_TEIF (1 << 3)
|
||||||
|
#define DMA_ISR_DMEIF (1 << 2)
|
||||||
|
#define DMA_ISR_FEIF (1 << 0)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Devices
|
* Devices
|
||||||
*/
|
*/
|
||||||
|
@ -166,25 +185,35 @@ extern dma_dev *DMA2;
|
||||||
* Convenience functions
|
* Convenience functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void dma_init(dma_dev *dev);
|
extern void dma_init(dma_dev *dev);
|
||||||
|
|
||||||
/** Flags for DMA transfer configuration. */
|
/** Flags for DMA transfer configuration. */
|
||||||
typedef enum dma_mode_flags {
|
typedef enum dma_mode_flags {
|
||||||
DMA_MEM_2_MEM = 1 << 14, /**< Memory to memory mode */
|
DMA_MEM_BUF_0 = DMA_CR_CT0, /**< Current memory target buffer 0 */
|
||||||
DMA_MINC_MODE = 1 << 7, /**< Auto-increment memory address */
|
DMA_MEM_BUF_1 = DMA_CR_CT1, /**< Current memory target buffer 1 */
|
||||||
DMA_PINC_MODE = 1 << 6, /**< Auto-increment peripheral address */
|
DMA_DBL_BUF_MODE = DMA_CR_DBM, /**< Current memory double buffer mode */
|
||||||
DMA_CIRC_MODE = 1 << 5, /**< Circular mode */
|
DMA_PINC_OFFSET = DMA_CR_PINCOS, /**< Peripheral increment offset size */
|
||||||
DMA_FROM_MEM = 1 << 4, /**< Read from memory to peripheral */
|
DMA_MINC_MODE = DMA_CR_MINC, /**< Memory increment mode */
|
||||||
DMA_TRNS_ERR = 1 << 3, /**< Interrupt on transfer error */
|
DMA_PINC_MODE = DMA_CR_PINC, /**< Peripheral increment mode */
|
||||||
DMA_HALF_TRNS = 1 << 2, /**< Interrupt on half-transfer */
|
DMA_CIRC_MODE = DMA_CR_CIRC, /**< Memory Circular mode */
|
||||||
DMA_TRNS_CMPLT = 1 << 1 /**< Interrupt on transfer completion */
|
DMA_FROM_PER = DMA_CR_DIR_P2M, /**< Read from memory to peripheral */
|
||||||
|
DMA_FROM_MEM = DMA_CR_DIR_M2P, /**< Read from memory to peripheral */
|
||||||
|
DMA_MEM_TO_MEM = DMA_CR_DIR_M2M, /**< Read from memory to memory */
|
||||||
|
DMA_PERIF_CTRL = DMA_CR_PFCTRL, /**< Peripheral flow controller */
|
||||||
|
DMA_PRIO_MEDIUM = DMA_CR_PL_MEDIUM, /**< Medium priority */
|
||||||
|
DMA_PRIO_HIGH = DMA_CR_PL_HIGH, /**< High priority */
|
||||||
|
DMA_PRIO_VERY_HIGH = DMA_CR_PL_VERY_HIGH, /**< Very high priority */
|
||||||
|
DMA_TRNS_CMPLT = DMA_CR_TCIE, /**< Interrupt on transfer completion */
|
||||||
|
DMA_TRNS_HALF = DMA_CR_HTIE, /**< Interrupt on half-transfer */
|
||||||
|
DMA_TRNS_ERR = DMA_CR_TEIE, /**< Interrupt on transfer error */
|
||||||
|
DMA_DIR_MODE_ERR = DMA_CR_DMEIE /**< Interrupt on direct mode error */
|
||||||
} dma_mode_flags;
|
} dma_mode_flags;
|
||||||
|
|
||||||
/** Source and destination transfer sizes. */
|
/** Source and destination transfer sizes. */
|
||||||
typedef enum dma_xfer_size {
|
typedef enum dma_xfer_size {
|
||||||
DMA_SIZE_8BITS = 0, /**< 8-bit transfers */
|
DMA_SIZE_8BITS = ( DMA_CR_MSIZE_8BITS|DMA_CR_PSIZE_8BITS ), /**< 8-bit transfers */
|
||||||
DMA_SIZE_16BITS = 1, /**< 16-bit transfers */
|
DMA_SIZE_16BITS = (DMA_CR_MSIZE_16BITS|DMA_CR_PSIZE_16BITS), /**< 16-bit transfers */
|
||||||
DMA_SIZE_32BITS = 2 /**< 32-bit transfers */
|
DMA_SIZE_32BITS = (DMA_CR_MSIZE_32BITS|DMA_CR_PSIZE_32BITS) /**< 32-bit transfers */
|
||||||
} dma_xfer_size;
|
} dma_xfer_size;
|
||||||
|
|
||||||
/** DMA channel */
|
/** DMA channel */
|
||||||
|
@ -201,17 +230,17 @@ typedef enum dma_stream {
|
||||||
|
|
||||||
static inline void dma_setup_transfer(dma_dev *dev,
|
static inline void dma_setup_transfer(dma_dev *dev,
|
||||||
dma_stream stream,
|
dma_stream stream,
|
||||||
|
dma_channel channel,
|
||||||
|
dma_xfer_size trx_size,
|
||||||
__io void *peripheral_address,
|
__io void *peripheral_address,
|
||||||
__io void *memory_address0,
|
__io void *memory_address0,
|
||||||
__io void *memory_address1,
|
__io void *memory_address1,
|
||||||
uint32 flags,
|
uint32 flags) {
|
||||||
uint32 fifo_flags) {
|
|
||||||
dev->regs->STREAM[stream].CR &= ~DMA_CR_EN; // disable
|
dev->regs->STREAM[stream].CR &= ~DMA_CR_EN; // disable
|
||||||
dev->regs->STREAM[stream].PAR = (uint32)peripheral_address;
|
dev->regs->STREAM[stream].PAR = (uint32)peripheral_address;
|
||||||
dev->regs->STREAM[stream].M0AR = (uint32)memory_address0;
|
dev->regs->STREAM[stream].M0AR = (uint32)memory_address0;
|
||||||
dev->regs->STREAM[stream].M1AR = (uint32)memory_address1;
|
dev->regs->STREAM[stream].M1AR = (uint32)memory_address1;
|
||||||
dev->regs->STREAM[stream].FCR = fifo_flags & 0x87; // mask out reserved bits
|
dev->regs->STREAM[stream].CR = ((flags|channel|trx_size) & 0x0feffffe); // mask out reserved and enable
|
||||||
dev->regs->STREAM[stream].CR = flags & 0x0feffffe; // mask out reserved and enable
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void dma_set_num_transfers(dma_dev *dev,
|
static inline void dma_set_num_transfers(dma_dev *dev,
|
||||||
|
@ -220,6 +249,12 @@ static inline void dma_set_num_transfers(dma_dev *dev,
|
||||||
dev->regs->STREAM[stream].NDTR = num_transfers;
|
dev->regs->STREAM[stream].NDTR = num_transfers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void dma_set_fifo_flags(dma_dev *dev,
|
||||||
|
dma_stream stream,
|
||||||
|
uint8 fifo_flags) {
|
||||||
|
dev->regs->STREAM[stream].FCR = fifo_flags & 0x87; // mask out reserved bits
|
||||||
|
}
|
||||||
|
|
||||||
void dma_attach_interrupt(dma_dev *dev,
|
void dma_attach_interrupt(dma_dev *dev,
|
||||||
dma_stream stream,
|
dma_stream stream,
|
||||||
void (*handler)(void));
|
void (*handler)(void));
|
||||||
|
@ -232,6 +267,7 @@ static inline void dma_enable(dma_dev *dev, dma_stream stream) {
|
||||||
|
|
||||||
static inline void dma_disable(dma_dev *dev, dma_stream stream) {
|
static inline void dma_disable(dma_dev *dev, dma_stream stream) {
|
||||||
dev->regs->STREAM[stream].CR &= ~DMA_CR_EN;
|
dev->regs->STREAM[stream].CR &= ~DMA_CR_EN;
|
||||||
|
while (dev->regs->STREAM[stream].CR & DMA_CR_EN); // wait till EN bit is reset, see AN4031, chapter 4.1
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -56,7 +56,7 @@ extern "C"{
|
||||||
* Devices
|
* Devices
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct dma_reg_map;
|
//struct dma_reg_map;
|
||||||
|
|
||||||
/* Encapsulates state related to user interrupt handlers. You
|
/* Encapsulates state related to user interrupt handlers. You
|
||||||
* shouldn't touch these directly; use dma_attach_interrupt() and
|
* shouldn't touch these directly; use dma_attach_interrupt() and
|
||||||
|
@ -82,16 +82,6 @@ struct dma_reg_map;
|
||||||
*
|
*
|
||||||
* @see dma_tube
|
* @see dma_tube
|
||||||
*/
|
*/
|
||||||
typedef enum dma_channel {
|
|
||||||
DMA_CH0 = 0, /**< Channel 0 */
|
|
||||||
DMA_CH1 = 1, /**< Channel 1 */
|
|
||||||
DMA_CH2 = 2, /**< Channel 2 */
|
|
||||||
DMA_CH3 = 3, /**< Channel 3 */
|
|
||||||
DMA_CH4 = 4, /**< Channel 4 */
|
|
||||||
DMA_CH5 = 5, /**< Channel 5 */
|
|
||||||
DMA_CH6 = 6, /**< Channel 6 */
|
|
||||||
DMA_CH7 = 7, /**< Channel 7 */
|
|
||||||
} dma_channel;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Source and destination transfer sizes.
|
* @brief Source and destination transfer sizes.
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
/**
|
/**
|
||||||
* @file libmaple/stm32f1/spi.c
|
* @file libmaple/stm32f1/spi.c
|
||||||
* @author Marti Bolivar <mbolivar@leaflabs.com>
|
* @author Marti Bolivar <mbolivar@leaflabs.com>
|
||||||
* @brief STM32F1 SPI/I2S.
|
* @brief STM32F4 SPI/I2S.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <libmaple/spi.h>
|
#include <libmaple/spi.h>
|
||||||
|
|
|
@ -42,6 +42,8 @@
|
||||||
#include <libmaple/dma.h>
|
#include <libmaple/dma.h>
|
||||||
#include <wirish.h>
|
#include <wirish.h>
|
||||||
|
|
||||||
|
#define SPI_DMA
|
||||||
|
|
||||||
// SPI_HAS_TRANSACTION means SPI has
|
// SPI_HAS_TRANSACTION means SPI has
|
||||||
// - beginTransaction()
|
// - beginTransaction()
|
||||||
// - endTransaction()
|
// - endTransaction()
|
||||||
|
@ -135,11 +137,12 @@ private:
|
||||||
uint32_t dataSize;
|
uint32_t dataSize;
|
||||||
|
|
||||||
spi_dev *spi_d;
|
spi_dev *spi_d;
|
||||||
//uint8_t _SSPin;
|
|
||||||
uint32_t clockDivider;
|
uint32_t clockDivider;
|
||||||
|
|
||||||
#ifdef SPI_DMA
|
#ifdef SPI_DMA
|
||||||
dma_channel spiRxDmaChannel, spiTxDmaChannel;
|
|
||||||
dma_dev* spiDmaDev;
|
dma_dev* spiDmaDev;
|
||||||
|
dma_channel spiDmaChannel;
|
||||||
|
dma_stream spiRxDmaStream, spiTxDmaStream;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
friend class SPIClass;
|
friend class SPIClass;
|
||||||
|
@ -396,5 +399,6 @@ private:
|
||||||
*/
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern SPIClass SPI;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue