Add fuction to configure dmac in linked mode. Include dmac channel into context.
authorasterix <asterix@38d2e660-2303-0410-9eaa-f027e97ec537>
Wed, 7 Sep 2011 16:14:59 +0000 (16:14 +0000)
committerasterix <asterix@38d2e660-2303-0410-9eaa-f027e97ec537>
Wed, 7 Sep 2011 16:14:59 +0000 (16:14 +0000)
git-svn-id: https://src.develer.com/svnoss/bertos/trunk@5038 38d2e660-2303-0410-9eaa-f027e97ec537

bertos/cpu/cortex-m3/drv/dmac_sam3.c
bertos/cpu/cortex-m3/drv/dmac_sam3.h

index 21045b7f89e47f3979a216bbe773cd127b632544..202b4f37259b5ce08df04dab6a714a2ee9d54934 100644 (file)
  */
 
 #include "dmac_sam3.h"
-
-#include "hsmci_sam3.h"
-#include "hw/hw_sd.h"
-
-#include <drv/timer.h>
 #include <drv/irq_cm3.h>
 
 #include <cpu/irq.h>
@@ -47,6 +42,8 @@
 
 #include <io/cm3.h>
 
+#include <string.h>
+
 struct DmacCh
 {
        reg32_t *src;
@@ -110,66 +107,106 @@ struct DmacCh dmac_ch[] =
        },
 };
 
-void dmac_setSources(Dmac *dmac, uint8_t ch, uint32_t src, uint32_t dst, size_t transfer_size)
+void dmac_setSourcesLLI(Dmac *dmac, DmacDesc *lli, uint32_t src, uint32_t dst, uint32_t desc)
 {
-       ASSERT(ch <= DMAC_CHANNEL_CNT);
-
-       DMAC_CHDR = BV(ch);
+       ASSERT(lli);
+       DMAC_CHDR = BV(dmac->ch);
 
-       *dmac_ch[ch].src = src;
-       *dmac_ch[ch].dst = dst;
-       *dmac_ch[ch].desc = 0;
-       dmac->transfer_size = transfer_size;
+       lli->src_addr = src;
+       lli->dst_addr = dst;
+       lli->dsc_addr = desc;
 }
 
-void dmac_configureDmac(Dmac *dmac, uint8_t ch, uint32_t cfg, uint32_t ctrla, uint32_t ctrlb)
+void dmac_configureDmacLLI(Dmac *dmac, DmacDesc *lli, size_t transfer_size, uint32_t cfg, uint32_t ctrla, uint32_t ctrlb)
 {
-       ASSERT(ch <= DMAC_CHANNEL_CNT);
+       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);
+       lli->ctrla = ctrla | (transfer_size & DMAC_CTRLA_BTSIZE_MASK);
+       lli->ctrlb = ctrlb | BV(DMAC_CTRLB_IEN);
+       *dmac_ch[dmac->ch].desc = (uint32_t)lli;
+}
+
+void dmac_setSources(Dmac *dmac, uint32_t src, uint32_t dst)
+{
+       DMAC_CHDR = BV(dmac->ch);
 
-       *dmac_ch[ch].cfg = cfg | DMAC_CFG_FIFOCFG_ALAP_CFG | (0x1 << DMAC_CFG_AHB_PROT_SHIFT);
-       *dmac_ch[ch].ctrla = ctrla | (dmac->transfer_size & DMAC_CTRLA_BTSIZE_MASK);
-       *dmac_ch[ch].ctrlb = ctrlb | BV(DMAC_CTRLB_IEN);
+       *dmac_ch[dmac->ch].src = src;
+       *dmac_ch[dmac->ch].dst = dst;
+       *dmac_ch[dmac->ch].desc = 0;
 }
 
-int dmac_start(Dmac *dmac, uint8_t ch)
+void dmac_configureDmac(Dmac *dmac, size_t transfer_size, uint32_t cfg, uint32_t ctrla, uint32_t ctrlb)
 {
-       ASSERT(ch <= DMAC_CHANNEL_CNT);
+       DMAC_CHDR = BV(dmac->ch);
 
-       if (DMAC_CHSR & 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);
+}
+
+int dmac_start(Dmac *dmac)
+{
+       if (DMAC_CHSR & BV(dmac->ch))
        {
                dmac->errors |= DMAC_ERR_CH_ALREDY_ON;
                return -1;
        }
-
-       DMAC_CHER = BV(ch);
+       DMAC_CHER = BV(dmac->ch);
        return 0;
 }
 
-bool dmac_isDone(Dmac *dmac, uint8_t ch)
+
+bool dmac_isLLIDone(Dmac *dmac)
 {
-       (void)dmac;
-       return (DMAC_EBCISR |= BV(ch));
+       return (DMAC_EBCIMR |= (BV(dmac->ch) << DMAC_EBCISR_CBTC0));
 }
 
-bool dmac_waitDone(Dmac *dmac, uint8_t ch)
+bool dmac_waitLLIDone(Dmac *dmac)
 {
-       (void)dmac;
-       while(!(DMAC_EBCISR |= BV(ch)))
+       while(!(DMAC_EBCIMR |= (BV(dmac->ch) << DMAC_EBCISR_CBTC0)))
                cpu_relax();
 
+       DMAC_CHDR = BV(dmac->ch);
        return true;
 }
 
-static DECLARE_ISR(dmac_irq)
+bool dmac_isDone(Dmac *dmac)
 {
+       return (DMAC_EBCIMR |= BV(dmac->ch));
 }
 
-void dmac_init(Dmac *dmac)
+bool dmac_waitDone(Dmac *dmac)
 {
-       (void)dmac;
+       while(!(DMAC_EBCIMR |= BV(dmac->ch)))
+               cpu_relax();
 
+       DMAC_CHDR = BV(dmac->ch);
+       return true;
+}
+
+int dmac_error(Dmac *dmac)
+{
+       uint32_t err = ((DMAC_EBCISR & 0x3F0000) | dmac->errors);
+       dmac->errors = 0;
+       return err;
+}
+
+static DECLARE_ISR(dmac_irq)
+{
+       uint32_t status = DMAC_EBCISR;
+       if(status & 0x3f3f)
+       {
+               kputs("Ends\n");
+       }
+
+}
+
+void dmac_init(Dmac *dmac, int channel)
+{
+       ASSERT(channel <= DMAC_CHANNEL_CNT);
+       memset(dmac, 0, sizeof(dmac));
+       dmac->ch = channel;
        //init DMAC
        DMAC_EBCIDR = 0x3FFFFF;
        DMAC_CHDR = 0x1F;
@@ -177,4 +214,6 @@ void dmac_init(Dmac *dmac)
        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);
 }
index 41aeb80b3c3b166f46c3364df0b293d80c719c34..eb87989c016de100fff67d8e05e215e7c9970f6b 100644 (file)
@@ -49,25 +49,33 @@ typedef struct DmacDesc
 {
     uint32_t src_addr;     ///< Source buffer address
     uint32_t dst_addr;     ///< Destination buffer address
-    uint32_t ctrl_a;       ///< Control A register settings
-    uint32_t ctrl_b;       ///< Control B register settings
+    uint32_t ctrla;       ///< Control A register settings
+    uint32_t ctrlb;       ///< Control B register settings
     uint32_t dsc_addr;     ///< Next descriptor address
 } DmacDesc;
 
 typedef struct Dmac
 {
+       DmacDesc lli;
+       uint8_t ch;
        uint8_t errors;
        size_t transfer_size;
 } Dmac;
 
 #define DMAC_ERR_CH_ALREDY_ON    BV(0)
 
-void dmac_setSources(Dmac *dmac, uint8_t ch, uint32_t src, uint32_t dst, size_t transfer_size);
-void dmac_configureDmac(Dmac *dmac, uint8_t ch, uint32_t cfg, uint32_t ctrla, uint32_t ctrlb);
-int dmac_start(Dmac *dmac, uint8_t ch);
-bool dmac_isDone(Dmac *dmac, uint8_t ch);
-bool dmac_waitDone(Dmac *dmac, uint8_t ch);
+void dmac_setSourcesLLI(Dmac *dmac, DmacDesc *lli, uint32_t src, uint32_t dst, uint32_t desc);
+void dmac_configureDmacLLI(Dmac *dmac, DmacDesc *lli, size_t transfer_size, uint32_t cfg, uint32_t ctrla, uint32_t ctrlb);
+bool dmac_isLLIDone(Dmac *dmac);
+bool dmac_waitLLIDone(Dmac *dmac);
 
-void dmac_init(Dmac *dmac);
+void dmac_setSources(Dmac *dmac, uint32_t src, uint32_t dst);
+void dmac_configureDmac(Dmac *dmac, size_t transfer_size, uint32_t cfg, uint32_t ctrla, uint32_t ctrlb);
+int dmac_start(Dmac *dmac);
+bool dmac_isDone(Dmac *dmac);
+bool dmac_waitDone(Dmac *dmac);
+int dmac_error(Dmac *dmac);
+
+void dmac_init(Dmac *dmac, int channel);
 
 #endif /* DRV_DMAC_SAM3_H */