contiki/cpu/cc253x/dev/dma.c

96 lines
2.5 KiB
C
Raw Normal View History

/**
* \file
* Driver for the cc2530 DMA controller. Derived from the cc2430
* equivalent
*
* \author
* Original: Martti Huttunen <martti@sensinode.com>
* Port: Zach Shelby <zach@sensinode.com>
* Further Modifications:
* George Oikonomou <oikonomou@users.sourceforge.net>
*
*/
#include "contiki.h"
#include "dev/dma.h"
#include "cc253x.h"
#if DMA_ON
struct dma_config dma_conf[DMA_CHANNEL_COUNT]; /* DMA Descriptors */
2012-12-16 13:10:28 +00:00
struct process *dma_callback[DMA_CHANNEL_COUNT];
/*---------------------------------------------------------------------------*/
void
dma_init(void)
{
uint16_t tmp_ptr;
memset(dma_conf, 0, 4 * sizeof(dma_config_t));
for(tmp_ptr = 0; tmp_ptr < DMA_CHANNEL_COUNT; tmp_ptr++) {
dma_callback[tmp_ptr] = 0;
}
/* The address of the descriptor for Channel 0 is configured separately */
2012-12-16 13:10:28 +00:00
tmp_ptr = (uint16_t)&(dma_conf[0]);
DMA0CFGH = tmp_ptr >> 8;
DMA0CFGL = tmp_ptr;
/*
* Descriptors for Channels 1-4 must be consecutive in RAM.
* We write the address of the 1st one to the register and the rest are
* derived by the SoC
*/
#if (DMA_CHANNEL_COUNT > 1)
2012-12-16 13:10:28 +00:00
tmp_ptr = (uint16_t)&(dma_conf[1]);
DMA1CFGH = tmp_ptr >> 8;
DMA1CFGL = tmp_ptr;
#endif
2012-08-03 15:04:11 +00:00
DMAIE = 1; /* Enable DMA interrupts */
}
/*---------------------------------------------------------------------------*/
/*
* Associate process p with DMA channel c. When a transfer on that channel
* completes, the ISR will poll this process.
*/
void
2012-12-16 13:10:28 +00:00
dma_associate_process(struct process *p, uint8_t c)
{
if((!c) || (c >= DMA_CHANNEL_COUNT)) {
return;
}
if(p) {
dma_conf[c].inc_prio |= 8; /* Enable interrupt generation */
2012-08-03 15:04:11 +00:00
DMAIE = 1; /* Make sure DMA interrupts are acknowledged */
}
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);
2012-12-16 13:10:28 +00:00
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_ASSURED;
2012-12-16 13:10:28 +00:00
DMA_TRIGGER(c); /** The operation order is important */
DMA_ARM(c);
while(DMAARM & (1 << c));
}
#endif