From 0c12ae82a5256ba40fef3e48b82d8adacee9ccf2 Mon Sep 17 00:00:00 2001 From: patacongo Date: Tue, 30 Mar 2010 01:39:30 +0000 Subject: [PATCH] More DMA logic git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@2567 42af7a65-404d-4744-a932-0658087f49c3 --- arch/arm/src/sam3u/sam3u_dmac.c | 145 +++++++++++++++++++++++++--- arch/arm/src/sam3u/sam3u_dmac.h | 4 + arch/arm/src/sam3u/sam3u_hsmci.c | 9 +- arch/arm/src/sam3u/sam3u_internal.h | 18 ++-- 4 files changed, 152 insertions(+), 24 deletions(-) diff --git a/arch/arm/src/sam3u/sam3u_dmac.c b/arch/arm/src/sam3u/sam3u_dmac.c index 7680f93db7..b5ed3e8878 100755 --- a/arch/arm/src/sam3u/sam3u_dmac.c +++ b/arch/arm/src/sam3u/sam3u_dmac.c @@ -207,70 +207,185 @@ static inline boolean sam3u_flowcontrol(uint8_t dmach_flags) } /************************************************************************************ - * Name: sam3u_settxctrla + * Name: sam3u_txctrlabits * * Description: * Decode the the flags to get the correct CTRLA register bit settings for a transmit - * (memory to peripheral) transfer. + * (memory to peripheral) transfer. These are only the "fixed" CTRLA values and + * need to be updated with the actual transfer size before being written to CTRLA + * sam3u_txctrla). * ************************************************************************************/ -static inline void -sam3u_settxctrla(struct sam3u_dma_s *dmach, uint32_t dmasize, uint32_t otherbits) +static inline uint32_t +sam3u_txctrlabits(struct sam3u_dma_s *dmach, uint32_t otherbits) { uint32_t regval; unsigned int ndx; - DEBUGASSERT(dmach && dmasize <= DMACHAN_CTRLA_BTSIZE_MAX); - regval = (dmasize << DMACHAN_CTRLA_BTSIZE_SHIFT) | otherbits; + DEBUGASSERT(dmach); + regval = otherbits; - /* Since this is a transmit, the source is described by the memeory selections */ + /* Since this is a transmit, the source is described by the memory selections. + * Set the source width (memory width). + */ ndx = (dmach->flags & DMACH_FLAG_MEMWIDTH_MASK) >> DMACH_FLAG_MEMWIDTH_SHIFT; DEBUGASSERT(ndx < 3); regval |= g_srcwidth[ndx]; - return regval; - /* Since this is a transmit, the destination is described by the peripheral selections */ + /* Set the source chuck size (memory chunk size) */ + + if ((dmach->flags & DMACH_FLAG_MEMCHUNKSIZE) == DMACH_FLAG_MEMCHUNKSIZE_4) + { + regval |= DMACHAN_CTRLA_SCSIZE_4; + } +#if 0 /* DMACHAN_CTRLA_SCSIZE_1 is zero */ + else + { + regval |= DMACHAN_CTRLA_SCSIZE_1; + } +#endif + + /* Since this is a transmit, the destination is described by the peripheral selections. + * Set the destination width (peripheral width). + */ ndx = (dmach->flags & DMACH_FLAG_PERIPHWIDTH_MASK) >> DMACH_FLAG_PERIPHWIDTH_SHIFT; DEBUGASSERT(ndx < 3); regval |= g_destwidth[ndx]; + + /* Set the destination chuck size (peripheral chunk size) */ + + if ((dmach->flags & DMACH_FLAG_PERIPHCHUNKSIZE) == DMACH_FLAG_PERIPHCHUNKSIZE_4) + { + regval |= DMACHAN_CTRLA_DCSIZE_4; + } +#if 0 /* DMACHAN_CTRLA_DCSIZE_1 is zero */ + else + { + regval |= DMACHAN_CTRLA_DCSIZE_1; + } +#endif + return regval; } +/************************************************************************************ + * Name: sam3u_txctrla + * + * Description: + * Or in the variable CTRLA bits + * + ************************************************************************************/ + +static inline uint32_t sam3u_txctrla(uint32_t dmasize, uint32_t txctrlabits) +{ + /* Set the buffer transfer size field. This is the number of transfers to be + * performed, that is, the number of source width transfers to perform. + */ + + /* Adjust the the source transfer size for the source chunk size (memory chunk size) */ + + if ((dmach->flags & DMACH_FLAG_MEMCHUNKSIZE) == DMACH_FLAG_MEMCHUNKSIZE_4) + { + dmasize >>= 2; + } + + DEBUGASSERT(dmasize <= DMACHAN_CTRLA_BTSIZE_MAX); + return (txctrlabits & ~DMACHAN_CTRLA_BTSIZE_MASK) | (dmasize << DMACHAN_CTRLA_BTSIZE_SHIFT); +} + /************************************************************************************ * Name: sam3u_setrxctrla * * Description: * Decode the the flags to get the correct CTRLA register bit settings for a read - * (peripheral to memory) transfer. + * (peripheral to memory) transfer. These are only the "fixed" CTRLA values and + * need to be updated with the actual transfer size before being written to CTRLA + * sam3u_rxctrla). * ************************************************************************************/ -static inline void -sam3u_setrxctrla(struct sam3u_dma_s *dmach, uint32_t dmasize, uint32_t otherbits) +static inline uint32_t +sam3u_setrxctrla(struct sam3u_dma_s *dmach, uint32_t otherbits) { uint32_t regval; unsigned int ndx; DEBUGASSERT(dmach && dmasize <= DMACHAN_CTRLA_BTSIZE_MAX); - regval = (dmasize << DMACHAN_CTRLA_BTSIZE_SHIFT) | otherbits; + regval = otherbits; - /* Since this is a receive, the source is described by the peripheral selections */ + /* Since this is a receive, the source is described by the peripheral selections. + * Set the source width (peripheral width). + */ ndx = (dmach->flags & DMACH_FLAG_PERIPHWIDTH_MASK) >> DMACH_FLAG_PERIPHWIDTH_SHIFT; DEBUGASSERT(ndx < 3); regval |= g_srcwidth[ndx]; - /* Since this is a receive, the destination is described by the memory selections */ + /* Set the source chuck size (peripheral chunk size) */ + + if ((dmach->flags & DMACH_FLAG_PERIPHCHUNKSIZE) == DMACH_FLAG_PERIPHCHUNKSIZE_4) + { + regval |= DMACHAN_CTRLA_SCSIZE_4; + } +#if 0 /* DMACHAN_CTRLA_SCSIZE_1 is zero */ + else + { + regval |= DMACHAN_CTRLA_SCSIZE_1; + } +#endif + + /* Since this is a receive, the destination is described by the memory selections. + * Set the destination width (memory width). + */ ndx = (dmach->flags & DMACH_FLAG_MEMWIDTH_MASK) >> DMACH_FLAG_MEMWIDTH_SHIFT; DEBUGASSERT(ndx < 3); regval |= g_destwidth[ndx]; + + /* Set the destination chuck size (memory chunk size) */ + + if ((dmach->flags & DMACH_FLAG_MEMCHUNKSIZE) == DMACH_FLAG_MEMCHUNKSIZE_4) + { + regval |= DMACHAN_CTRLA_DCSIZE_4; + } +#if 0 /* DMACHAN_CTRLA_DCSIZE_1 is zero */ + else + { + regval |= DMACHAN_CTRLA_DCSIZE_1; + } +#endif + return regval; } +/************************************************************************************ + * Name: sam3u_rxctrla + * + * Description: + * Or in the variable CTRLA bits + * + ************************************************************************************/ + +static inline uint32_t sam3u_rxctrla(uint32_t dmasize, uint32_t txctrlabits) +{ + /* Set the buffer transfer size field. This is the number of transfers to be + * performed, that is, the number of source width transfers to perform. + */ + + /* Adjust the the source transfer size for the source chunk size (peripheral chunk size) */ + + if ((dmach->flags & DMACH_FLAG_PERIPHCHUNKSIZE) == DMACH_FLAG_PERIPHCHUNKSIZE_4) + { + dmasize >>= 2; + } + + DEBUGASSERT(dmasize <= DMACHAN_CTRLA_BTSIZE_MAX); + return (txctrlabits & ~DMACHAN_CTRLA_BTSIZE_MASK) | (dmasize << DMACHAN_CTRLA_BTSIZE_SHIFT); +} + /************************************************************************************ * Name: sam3u_srcctrlb * diff --git a/arch/arm/src/sam3u/sam3u_dmac.h b/arch/arm/src/sam3u/sam3u_dmac.h index c92c45edf3..736e689b0d 100755 --- a/arch/arm/src/sam3u/sam3u_dmac.h +++ b/arch/arm/src/sam3u/sam3u_dmac.h @@ -345,7 +345,11 @@ #define DMACHAN_CTRLA_BTSIZE_SHIFT (0) /* Bits 0-11: Buffer Transfer Size */ #define DMACHAN_CTRLA_BTSIZE_MASK (DMACHAN_CTRLA_BTSIZE_MAX << DMACHAN_CTRLA_BTSIZE_SHIFT) #define DMACHAN_CTRLA_SCSIZE (1 << 16) /* Bit 16: Source Chunk Transfer Size */ +# define DMACHAN_CTRLA_SCSIZE_1 (0) +# define DMACHAN_CTRLA_SCSIZE_4 DMACHAN_CTRLA_SCSIZE #define DMACHAN_CTRLA_DCSIZE (1 << 20) /* Bit 20: Destination Chunk Transfer size */ +# define DMACHAN_CTRLA_DCSIZE_1 (0) +# define DMACHAN_CTRLA_DCSIZE_4 DMACHAN_CTRLA_DCSIZE #define DMACHAN_CTRLA_SRCWIDTH_SHIFT (24) /* Bits 24-25 */ #define DMACHAN_CTRLA_SRCWIDTH_MASK (3 << DMACHAN_CTRLA_SRCWIDTH_SHIFT) # define DMACHAN_CTRLA_SRCWIDTH_BYTE (0 << DMACHAN_CTRLA_SRCWIDTH_SHIFT) diff --git a/arch/arm/src/sam3u/sam3u_hsmci.c b/arch/arm/src/sam3u/sam3u_hsmci.c index 795cac9542..552d554c75 100755 --- a/arch/arm/src/sam3u/sam3u_hsmci.c +++ b/arch/arm/src/sam3u/sam3u_hsmci.c @@ -120,9 +120,12 @@ /* DMA configuration flags */ #define DMA_FLAGS \ - (DMACH_FLAG_FIFO_8BYTES | DMACH_FLAG_FIFOCFG_LARGEST | (DMACHAN_PID_MCI0 << DMACH_FLAG_PERIPHPID_SHIFT) | \ - DMACH_FLAG_PERIPHH2SEL | DMACH_FLAG_PERIPHLLIMODE | DMACH_FLAG_PERIPHWIDTH_32BITS | \ - DMACH_FLAG_MEMLLIMODE | DMACH_FLAG_MEMWIDTH_32BITS | DMACH_FLAG_MEMINCREMENT) + (DMACH_FLAG_FIFO_8BYTES | DMACH_FLAG_FIFOCFG_LARGEST | \ + (DMACHAN_PID_MCI0 << DMACH_FLAG_PERIPHPID_SHIFT) | \ + DMACH_FLAG_PERIPHH2SEL | DMACH_FLAG_PERIPHLLIMODE | \ + DMACH_FLAG_PERIPHWIDTH_32BITS | DMACH_FLAG_PERIPHCHUNKSIZE_1 | \ + DMACH_FLAG_MEMLLIMODE | DMACH_FLAG_MEMWIDTH_32BITS | \ + DMACH_FLAG_MEMINCREMENT | DMACH_FLAG_MEMCHUNKSIZE_4) /* FIFO sizes */ diff --git a/arch/arm/src/sam3u/sam3u_internal.h b/arch/arm/src/sam3u/sam3u_internal.h index a6ff75ba62..91cfc7fa15 100755 --- a/arch/arm/src/sam3u/sam3u_internal.h +++ b/arch/arm/src/sam3u/sam3u_internal.h @@ -313,7 +313,7 @@ #define DMACH_FLAG_FIFOCFG_SHIFT (2) /* Bits 2-3: FIFO configuration */ #define DMACH_FLAG_FIFOCFG_MASK (3 << DMACH_FLAG_FIFOCFG_SHIFT) -# define DMACH_FLAG_FIFOCFG_LARGEST (DMACH_FLAG_BURST_LARGEST << DMACH_FLAG_FIFOCFG_SHIFT +# define DMACH_FLAG_FIFOCFG_LARGEST (DMACH_FLAG_BURST_LARGEST << DMACH_FLAG_FIFOCFG_SHIFT) # define DMACH_FLAG_FIFOCFG_HALF (DMACH_FLAG_BURST_HALF << DMACH_FLAG_FIFOCFG_SHIFT) # define DMACH_FLAG_FIFOCFG_SINGLE (DMACH_FLAG_BURST_SINGLE << DMACH_FLAG_FIFOCFG_SHIFT) @@ -329,19 +329,25 @@ # define DMACH_FLAG_PERIPHWIDTH_32BITS (2 << DMACH_FLAG_PERIPHWIDTH_SHIFT) /* 32 bits */ #define DMACH_FLAG_PERIPHINCREMENT (1 << 11) /* Bit 11: Autoincrement peripheral address */ #define DMACH_FLAG_PERIPHLLIMODE (1 << 12) /* Bit 12: Use link list descriptors */ +#define DMACH_FLAG_PERIPHCHUNKSIZE (1 << 13) /* Bit 13: Peripheral chunk size */ +# define DMACH_FLAG_PERIPHCHUNKSIZE_1 (0) /* Peripheral chunksize = 1 */ +# define DMACH_FLAG_PERIPHCHUNKSIZE_4 DMACH_FLAG_PERIPHCHUNKSIZE /* Peripheral chunksize = 4 */ /* Memory endpoint characteristics */ -#define DMACH_FLAG_MEMPID_SHIFT (13) /* Bits 13-16: Memory PID */ +#define DMACH_FLAG_MEMPID_SHIFT (14) /* Bits 14-17: Memory PID */ #define DMACH_FLAG_MEMPID_MASK (15 << DMACH_FLAG_PERIPHPID_SHIFT) -#define DMACH_FLAG_MEMH2SEL (1 << 17) /* Bits 17: HW handshaking */ -#define DMACH_FLAG_MEMWIDTH_SHIFT (18) /* Bits 18-19: Memory width */ +#define DMACH_FLAG_MEMH2SEL (1 << 18) /* Bits 18: HW handshaking */ +#define DMACH_FLAG_MEMWIDTH_SHIFT (19) /* Bits 19-20: Memory width */ #define DMACH_FLAG_MEMWIDTH_MASK (3 << DMACH_FLAG_MEMWIDTH_SHIFT) # define DMACH_FLAG_MEMWIDTH_8BITS (0 << DMACH_FLAG_MEMWIDTH_SHIFT) /* 8 bits */ # define DMACH_FLAG_MEMWIDTH_16BITS (1 << DMACH_FLAG_MEMWIDTH_SHIFT) /* 16 bits */ # define DMACH_FLAG_MEMWIDTH_32BITS (2 << DMACH_FLAG_MEMWIDTH_SHIFT) /* 32 bits */ -#define DMACH_FLAG_MEMINCREMENT (1 << 20) /* Bit 20: Autoincrement memory address */ -#define DMACH_FLAG_MEMLLIMODE (1 << 21) /* Bit 21: Use link list descriptors */ +#define DMACH_FLAG_MEMINCREMENT (1 << 21) /* Bit 21: Autoincrement memory address */ +#define DMACH_FLAG_MEMLLIMODE (1 << 22) /* Bit 22: Use link list descriptors */ +#define DMACH_FLAG_MEMCHUNKSIZE (1 << 23) /* Bit 23: Memory chunk size */ +# define DMACH_FLAG_MEMCHUNKSIZE_1 (0) /* Memory chunksize = 1 */ +# define DMACH_FLAG_MEMCHUNKSIZE_4 DMACH_FLAG_MEMCHUNKSIZE /* Memory chunksize = 4 */ /************************************************************************************ * Public Types