X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=bertos%2Fcpu%2Fcortex-m3%2Fdrv%2Fdmac_sam3.c;h=06dba6ea9d558b158454a80a8d89b2e567d7c34a;hb=6970f4233dd70293d45f2df4406c581128e887dc;hp=202b4f37259b5ce08df04dab6a714a2ee9d54934;hpb=b42a8bd9e19d221e7ede7455c2f6979595307d89;p=bertos.git diff --git a/bertos/cpu/cortex-m3/drv/dmac_sam3.c b/bertos/cpu/cortex-m3/drv/dmac_sam3.c index 202b4f37..06dba6ea 100644 --- a/bertos/cpu/cortex-m3/drv/dmac_sam3.c +++ b/bertos/cpu/cortex-m3/drv/dmac_sam3.c @@ -42,6 +42,8 @@ #include +#include + #include struct DmacCh @@ -54,7 +56,7 @@ struct DmacCh reg32_t *ctrlb; }; -#define DMAC_CHANNEL_CNT 5 +#define DMAC_CHANNEL_CNT 6 struct DmacCh dmac_ch[] = { { @@ -107,113 +109,104 @@ struct DmacCh dmac_ch[] = }, }; -void dmac_setSourcesLLI(Dmac *dmac, DmacDesc *lli, uint32_t src, uint32_t dst, uint32_t desc) -{ - ASSERT(lli); - DMAC_CHDR = BV(dmac->ch); - - lli->src_addr = src; - lli->dst_addr = dst; - lli->dsc_addr = desc; -} +/* We use event to signal the end of conversion */ +static Dmac dmac[DMAC_CHANNEL_CNT]; +static uint8_t dmac_ch_enabled; -void dmac_configureDmacLLI(Dmac *dmac, DmacDesc *lli, size_t transfer_size, uint32_t cfg, uint32_t ctrla, uint32_t ctrlb) +void dmac_setLLITransfer(int ch, DmacDesc *lli, uint32_t cfg) { - DMAC_CHDR = BV(dmac->ch); + DMAC_CHDR = BV(ch); + reg32_t reg = DMAC_EBCISR; + (void)reg; - *dmac_ch[dmac->ch].cfg = cfg | DMAC_CFG_FIFOCFG_ALAP_CFG | (0x1 << DMAC_CFG_AHB_PROT_SHIFT); - lli->ctrla = ctrla | (transfer_size & DMAC_CTRLA_BTSIZE_MASK); - lli->ctrlb = ctrlb | BV(DMAC_CTRLB_IEN); - *dmac_ch[dmac->ch].desc = (uint32_t)lli; + *dmac_ch[ch].cfg = cfg | DMAC_CFG_FIFOCFG_ALAP_CFG | (0x1 << DMAC_CFG_AHB_PROT_SHIFT); + *dmac_ch[ch].desc = (uint32_t)lli; } -void dmac_setSources(Dmac *dmac, uint32_t src, uint32_t dst) +void dmac_setSources(int ch, uint32_t src, uint32_t dst) { - DMAC_CHDR = BV(dmac->ch); + DMAC_CHDR = BV(ch); - *dmac_ch[dmac->ch].src = src; - *dmac_ch[dmac->ch].dst = dst; - *dmac_ch[dmac->ch].desc = 0; + *dmac_ch[ch].src = src; + *dmac_ch[ch].dst = dst; + *dmac_ch[ch].desc = 0; } -void dmac_configureDmac(Dmac *dmac, size_t transfer_size, uint32_t cfg, uint32_t ctrla, uint32_t ctrlb) +void dmac_configureDmac(int ch, size_t transfer_size, uint32_t cfg, uint32_t ctrla, uint32_t ctrlb) { - DMAC_CHDR = BV(dmac->ch); + DMAC_CHDR = BV(ch); - *dmac_ch[dmac->ch].cfg = cfg | DMAC_CFG_FIFOCFG_ALAP_CFG | (0x1 << DMAC_CFG_AHB_PROT_SHIFT); - *dmac_ch[dmac->ch].ctrla = ctrla | (transfer_size & DMAC_CTRLA_BTSIZE_MASK); - *dmac_ch[dmac->ch].ctrlb = ctrlb | BV(DMAC_CTRLB_IEN); + *dmac_ch[ch].cfg = cfg | DMAC_CFG_FIFOCFG_ALAP_CFG | (0x1 << DMAC_CFG_AHB_PROT_SHIFT); + *dmac_ch[ch].ctrla = ctrla | (transfer_size & DMAC_CTRLA_BTSIZE_MASK); + *dmac_ch[ch].ctrlb = ctrlb & ~BV(DMAC_CTRLB_IEN); } -int dmac_start(Dmac *dmac) +int dmac_start(int ch) { - if (DMAC_CHSR & BV(dmac->ch)) + if (DMAC_CHSR & BV(ch)) { - dmac->errors |= DMAC_ERR_CH_ALREDY_ON; + dmac[ch].errors |= DMAC_ERR_CH_ALREDY_ON; return -1; } - DMAC_CHER = BV(dmac->ch); + DMAC_CHER = BV(ch); + dmac_ch_enabled |= BV(ch); return 0; } - -bool dmac_isLLIDone(Dmac *dmac) -{ - return (DMAC_EBCIMR |= (BV(dmac->ch) << DMAC_EBCISR_CBTC0)); -} - -bool dmac_waitLLIDone(Dmac *dmac) +void dmac_stop(int ch) { - while(!(DMAC_EBCIMR |= (BV(dmac->ch) << DMAC_EBCISR_CBTC0))) - cpu_relax(); - - DMAC_CHDR = BV(dmac->ch); - return true; + DMAC_CHDR = BV(ch); + dmac_ch_enabled &= ~BV(ch); } -bool dmac_isDone(Dmac *dmac) +int dmac_error(int ch) { - return (DMAC_EBCIMR |= BV(dmac->ch)); + uint32_t err = ((DMAC_EBCISR & 0x3F0000) | dmac[ch].errors); + dmac[ch].errors = 0; + return err; } -bool dmac_waitDone(Dmac *dmac) +static DECLARE_ISR(dmac_irq) { - while(!(DMAC_EBCIMR |= BV(dmac->ch))) - cpu_relax(); - - DMAC_CHDR = BV(dmac->ch); - return true; + uint32_t status = DMAC_EBCISR; + uint32_t irq_ch = (status & (((dmac_ch_enabled | + (dmac_ch_enabled << DMAC_EBCIDR_ERR0) >> DMAC_EBCIDR_ERR0) | + (dmac_ch_enabled << DMAC_EBCIDR_CBTC0) >> DMAC_EBCIDR_CBTC0) & 0xFF)); + if (irq_ch) + for(int i = 0; i < 6; i++) + { + if (BV(i) & irq_ch) + if(dmac[i].handler) + dmac[i].handler(status); + } } -int dmac_error(Dmac *dmac) +bool dmac_enableCh(int ch, dmac_handler_t handler) { - uint32_t err = ((DMAC_EBCISR & 0x3F0000) | dmac->errors); - dmac->errors = 0; - return err; -} + ASSERT(ch <= DMAC_CHANNEL_CNT); -static DECLARE_ISR(dmac_irq) -{ - uint32_t status = DMAC_EBCISR; - if(status & 0x3f3f) + dmac_ch_enabled |= BV(ch); + if (handler) { - kputs("Ends\n"); + dmac[ch].handler = handler; + DMAC_EBCIER |= (BV(ch) << DMAC_EBCIER_BTC0) | (BV(ch) << DMAC_EBCIDR_CBTC0) | (BV(ch) << DMAC_EBCIDR_ERR0); + kprintf("Init dmac ch[%08lx]\n", DMAC_EBCIMR); } + return true; } -void dmac_init(Dmac *dmac, int channel) +void dmac_init(void) { - ASSERT(channel <= DMAC_CHANNEL_CNT); - memset(dmac, 0, sizeof(dmac)); - dmac->ch = channel; + dmac_ch_enabled = 0; + memset(&dmac, 0, sizeof(dmac)); + //init DMAC DMAC_EBCIDR = 0x3FFFFF; DMAC_CHDR = 0x1F; pmc_periphEnable(DMAC_ID); DMAC_EN = BV(DMAC_EN_ENABLE); - sysirq_setHandler(INT_DMAC, dmac_irq); - DMAC_EBCIER = (BV(dmac->ch) << DMAC_EBCIER_BTC0) | (BV(dmac->ch) << DMAC_EBCIDR_BTC0); + sysirq_setHandler(INT_DMAC, dmac_irq); }