Skip to content

Commit

Permalink
chips/samd21: Improve DMAC code a bit
Browse files Browse the repository at this point in the history
This still doesn't quite work right, but it's closer.

Signed-off-by: Keith Packard <keithp@keithp.com>
  • Loading branch information
keith-packard committed Jun 12, 2020
1 parent 9be4706 commit e97370d
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 35 deletions.
48 changes: 22 additions & 26 deletions chips/samd21/ao-dma-samd21.c
Expand Up @@ -19,14 +19,17 @@
#include <ao.h>
#include <ao-dma-samd21.h>

uint8_t ao_dma_done[SAMD21_DMAC_NCHAN];

static struct samd21_dmac_desc samd21_dmac_desc[SAMD21_DMAC_NCHAN] __attribute__((aligned(16)));
static struct samd21_dmac_desc samd21_dmac_wrb[SAMD21_DMAC_NCHAN] __attribute__((aligned(16)));

static volatile uint16_t saved_intpend;
static volatile int interrupts;

static struct {
void (*callback)(uint8_t id, void *closure);
void *closure;
} dmac_callback[SAMD21_DMAC_NCHAN];

void
samd21_dmac_isr(void)
{
Expand All @@ -38,14 +41,14 @@ samd21_dmac_isr(void)
uint8_t id = (intpend >> SAMD21_DMAC_INTPEND_ID) & SAMD21_DMAC_INTPEND_ID_MASK;
samd21_dmac.intpend = intpend;
if (intpend & (1 << SAMD21_DMAC_INTPEND_TCMPL)) {
ao_dma_done[id] = 1;
ao_wakeup(&ao_dma_done[id]);
if (dmac_callback[id].callback)
(*dmac_callback[id].callback)(id, dmac_callback[id].closure);
}
}
}

static void
dump_dma(char *where)
void
ao_dma_dump(char *where)
{
printf("DMA %s ctrl %04x intpend %04x intstatus %04x\n",
where,
Expand All @@ -72,48 +75,41 @@ dump_dma(char *where)
samd21_dmac_desc[0].descaddr);
fflush(stdout);
printf("intpend %04x interrupts %d\n", saved_intpend, interrupts);
ao_delay(AO_SEC_TO_TICKS(1));
}

void
ao_dma_start_transfer(uint8_t id,
void *src,
void *dst,
uint16_t count,
uint32_t chctrlb,
uint16_t btctrl)
_ao_dma_start_transfer(uint8_t id,
void *src,
void *dst,
uint16_t count,
uint32_t chctrlb,
uint16_t btctrl,
void (*callback)(uint8_t id, void *closure),
void *closure)
{
/* Set up the callback */
dmac_callback[id].closure = closure;
dmac_callback[id].callback = callback;

/* Set up the descriptor */
samd21_dmac_desc[id].btctrl = btctrl;
samd21_dmac_desc[id].btcnt = count;
samd21_dmac_desc[id].srcaddr = (uint32_t) src;
samd21_dmac_desc[id].dstaddr = (uint32_t) dst;
samd21_dmac_desc[id].descaddr = 0;

dump_dma("start");

/* Configure the channel and enable it */
ao_arch_block_interrupts();
samd21_dmac.chid = id;
samd21_dmac.chctrlb = chctrlb;
samd21_dmac.chctrla = (1 << SAMD21_DMAC_CHCTRLA_ENABLE);
ao_arch_release_interrupts();
}

void
ao_dma_done_transfer(uint8_t id)
_ao_dma_done_transfer(uint8_t id)
{
printf("done[%d] = %d\n", id, ao_dma_done[id]);
dump_dma("done");

/* Disable channel */
ao_arch_block_interrupts();
samd21_dmac.chid = id;
samd21_dmac.chctrla = 0;
ao_arch_release_interrupts();

/* Reset done flag */
ao_dma_done[id] = 0;
}

void
Expand Down
21 changes: 12 additions & 9 deletions chips/samd21/ao-dma-samd21.h
Expand Up @@ -19,20 +19,23 @@
#ifndef _AO_DMA_SAM21_H_
#define _AO_DMA_SAM21_H_

extern uint8_t ao_dma_done[SAMD21_DMAC_NCHAN];

void
ao_dma_init(void);

void
ao_dma_start_transfer(uint8_t id,
void *src,
void *dst,
uint16_t count,
uint32_t chctrlb,
uint16_t btctrl);
_ao_dma_start_transfer(uint8_t id,
void *src,
void *dst,
uint16_t count,
uint32_t chctrlb,
uint16_t btctrl,
void (*callback)(uint8_t id, void *closure),
void *closure);

void
_ao_dma_done_transfer(uint8_t id);

void
ao_dma_done_transfer(uint8_t id);
ao_dma_dump(char *where);

#endif /* _AO_DMA_SAM21_H_ */
55 changes: 55 additions & 0 deletions chips/samd21/samd21.h
Expand Up @@ -538,6 +538,9 @@ struct samd21_dmac_desc {
#define SAMD21_DMAC_DESC_BTCTRL_EVOSEL 1
#define SAMD21_DMAC_DESC_BTCTRL_BLOCKACT 3
#define SAMD21_DMAC_DESC_BTCTRL_BEATSIZE 8
#define SAMD21_DMAC_DESC_BTCTRL_BEATSIZE_BYTE 0
#define SAMD21_DMAC_DESC_BTCTRL_BEATSIZE_HWORD 1
#define SAMD21_DMAC_DESC_BTCTRL_BEATSIZE_WORD 2
#define SAMD21_DMAC_DESC_BTCTRL_SRCINC 10
#define SAMD21_DMAC_DESC_BTCTRL_DSTINC 11
#define SAMD21_DMAC_DESC_BTCTRL_STEPSEL 12
Expand Down Expand Up @@ -800,6 +803,58 @@ extern struct samd21_adc samd21_adc;

#define samd21_adc (*(struct samd21_adc *) 0x42004000)

struct samd21_dac {
vuint8_t ctrla;
vuint8_t ctrlb;
vuint8_t evctrl;
uint8_t reserved_03;

vuint8_t intenclr;
vuint8_t intenset;
vuint8_t intflag;
vuint8_t status;

vuint16_t data;
uint16_t reserved_0a;

vuint16_t databuf;
};

#define SAMD21_DAC_CTRLA_SWRST 0
#define SAMD21_DAC_CTRLA_ENABLE 1
#define SAMD21_DAC_CTRLA_RUNSTDBY 2

#define SAMD21_DAC_CTRLB_EOEN 0
#define SAMD21_DAC_CTRLB_IOEN 1
#define SAMD21_DAC_CTRLB_LEFTADJ 2
#define SAMD21_DAC_CTRLB_VPD 3
#define SAMD21_DAC_CTRLB_BDWP 4
#define SAMD21_DAC_CTRLB_REFSEL 6
#define SAMD21_DAC_CTRLB_REFSEL_INTREF 0
#define SAMD21_DAC_CTRLB_REFSEL_VDDANA 1
#define SAMD21_DAC_CTRLB_REFSEL_VREFA 2
#define SAMD21_DAC_CTRLB_REFSEL_MASK 3

#define SAMD21_DAC_EVCTRL_STARTEI 0
#define SAMD21_DAC_EVCTRL_EMPTYEO 1

#define SAMD21_DAC_INTENCLR_UNDERRUN 0
#define SAMD21_DAC_INTENCLR_EMPTY 1
#define SAMD21_DAC_INTENCLR_SYNCRDY 2

#define SAMD21_DAC_INTENSET_UNDERRUN 0
#define SAMD21_DAC_INTENSET_EMPTY 1
#define SAMD21_DAC_INTENSET_SYNCRDY 2

#define SAMD21_DAC_INTFLAG_UNDERRUN 0
#define SAMD21_DAC_INTFLAG_EMPTY 1
#define SAMD21_DAC_INTFLAG_SYNCRDY 2

#define SAMD21_DAC_STATUS_SYNCBUSY 7

extern struct samd21_dac samd21_dac;
#define samd21_dac (*(struct samd21_dac *) 0x42004800)

/* TC */
struct samd21_tc {
vuint16_t ctrla;
Expand Down

0 comments on commit e97370d

Please sign in to comment.