From eabaa0c8e402e1e5c0ee9a56218f2a0d22b824cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20R=C3=A9tornaz?= Date: Fri, 3 Aug 2012 16:08:07 +0200 Subject: [PATCH] cc253x: DMA Changes - Fixed DMA irq flag clearing - Added a dma_reset helper See Pull Request #18 --- cpu/cc253x/dev/dma.c | 25 +++++++++++++++++++++++++ cpu/cc253x/dev/dma.h | 4 +++- cpu/cc253x/dev/dma_intr.c | 6 +++--- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/cpu/cc253x/dev/dma.c b/cpu/cc253x/dev/dma.c index 8d07e83cf..9a4c5db01 100644 --- a/cpu/cc253x/dev/dma.c +++ b/cpu/cc253x/dev/dma.c @@ -67,4 +67,29 @@ dma_associate_process(struct process * p, uint8_t c) dma_callback[c] = p; } /*---------------------------------------------------------------------------*/ +/* + * Reset a channel to idle state. As per cc253x datasheet section 8.1, + * we must reconfigure the channel to trigger source 0 between each + * reconfiguration. + */ +void +dma_reset(uint8_t c) +{ + static __xdata uint8_t dummy; + if(c >= DMA_CHANNEL_COUNT) { + return; + } + DMA_ABORT(c); + dma_conf[c].src_h = (uint16_t) &dummy >> 8; + dma_conf[c].src_l = (uint16_t) &dummy; + dma_conf[c].dst_h = (uint16_t) &dummy >> 8; + dma_conf[c].dst_l = (uint16_t) &dummy; + dma_conf[c].len_h = 0; + dma_conf[c].len_l = 1; + dma_conf[c].wtt = DMA_BLOCK; + dma_conf[c].inc_prio = DMA_PRIO_GUARANTEED; + DMA_TRIGGER(c); // The operation order is important + DMA_ARM(c); + while(DMAARM & (1 << c)); +} #endif diff --git a/cpu/cc253x/dev/dma.h b/cpu/cc253x/dev/dma.h index 83e283a7a..7f767bc68 100644 --- a/cpu/cc253x/dev/dma.h +++ b/cpu/cc253x/dev/dma.h @@ -12,6 +12,7 @@ #ifndef __DMA_H #define __DMA_H #include "cc253x.h" +#include "sfr-bits.h" /* DMA triggers */ #define DMA_T_NONE 0 /* None, DMAREQ.DMAREQx bits start transfer */ @@ -133,12 +134,13 @@ extern dma_config_t dma_conf[DMA_CHANNEL_COUNT]; */ #define DMA_STATUS(c) (DMAIRQ &(1 << c)) /* Abort Ongoing DMA Transfers on Channel C */ -#define DMA_ABORT(c) (DMAARM = ABORT | (1 << c)) +#define DMA_ABORT(c) (DMAARM = DMAARM_ABORT | (1 << c)) #define DMA_ABORT_ALL() (DMAARM = 0x9F) /* Abort ALL Ongoing DMA Transfers */ /* Functions Declarations */ void dma_init(void); void dma_associate_process (struct process * p, uint8_t c); +void dma_reset(uint8_t c); /* Only link the ISR when DMA_ON is .... on */ #if DMA_ON diff --git a/cpu/cc253x/dev/dma_intr.c b/cpu/cc253x/dev/dma_intr.c index 222a9f3ae..633fb3cda 100644 --- a/cpu/cc253x/dev/dma_intr.c +++ b/cpu/cc253x/dev/dma_intr.c @@ -47,21 +47,21 @@ dma_isr(void) __interrupt (DMA_VECTOR) DMAIF = 0; #ifdef HAVE_RF_DMA if((DMAIRQ & 1) != 0) { - DMAIRQ &= ~1; + DMAIRQ = ~1; DMAARM=0x81; rf_dma_callback_isr(); } #endif #ifdef SPI_DMA_RX if((DMAIRQ & 0x08) != 0) { - DMAIRQ &= ~(1 << 3); + DMAIRQ = ~(1 << 3); spi_rx_dma_callback(); } #endif #if DMA_ON for(i = 0; i < DMA_CHANNEL_COUNT; i++) { if((DMAIRQ & (1 << i)) != 0) { - DMAIRQ &= ~(1 << i); + DMAIRQ = ~(1 << i); if(dma_callback[i] != 0) { process_poll(dma_callback[i]); }