dmac_sam3.c
Go to the documentation of this file.
00001 00037 #include "dmac_sam3.h" 00038 #include <drv/irq_cm3.h> 00039 00040 #include <cpu/irq.h> 00041 #include <cpu/power.h> 00042 00043 #include <io/cm3.h> 00044 00045 #include <mware/event.h> 00046 00047 #include <string.h> 00048 00049 struct DmacCh 00050 { 00051 reg32_t *src; 00052 reg32_t *dst; 00053 reg32_t *desc; 00054 reg32_t *cfg; 00055 reg32_t *ctrla; 00056 reg32_t *ctrlb; 00057 }; 00058 00059 #define DMAC_CHANNEL_CNT 6 00060 struct DmacCh dmac_ch[] = 00061 { 00062 { 00063 .src = &DMAC_SADDR0, 00064 .dst = &DMAC_DADDR0, 00065 .desc = &DMAC_DSCR0, 00066 .cfg = &DMAC_CFG0, 00067 .ctrla = &DMAC_CTRLA0, 00068 .ctrlb = &DMAC_CTRLB0, 00069 }, 00070 { 00071 .src = &DMAC_SADDR1, 00072 .dst = &DMAC_DADDR1, 00073 .desc = &DMAC_DSCR1, 00074 .cfg = &DMAC_CFG1, 00075 .ctrla = &DMAC_CTRLA1, 00076 .ctrlb = &DMAC_CTRLB1, 00077 }, 00078 { 00079 .src = &DMAC_SADDR2, 00080 .dst = &DMAC_DADDR2, 00081 .desc = &DMAC_DSCR2, 00082 .cfg = &DMAC_CFG2, 00083 .ctrla = &DMAC_CTRLA2, 00084 .ctrlb = &DMAC_CTRLB2, 00085 }, 00086 { 00087 .src = &DMAC_SADDR3, 00088 .dst = &DMAC_DADDR3, 00089 .desc = &DMAC_DSCR3, 00090 .cfg = &DMAC_CFG3, 00091 .ctrla = &DMAC_CTRLA3, 00092 .ctrlb = &DMAC_CTRLB3, 00093 }, 00094 { 00095 .src = &DMAC_SADDR4, 00096 .dst = &DMAC_DADDR4, 00097 .desc = &DMAC_DSCR4, 00098 .cfg = &DMAC_CFG4, 00099 .ctrla = &DMAC_CTRLA4, 00100 .ctrlb = &DMAC_CTRLB4, 00101 }, 00102 { 00103 .src = &DMAC_SADDR5, 00104 .dst = &DMAC_DADDR5, 00105 .desc = &DMAC_DSCR5, 00106 .cfg = &DMAC_CFG5, 00107 .ctrla = &DMAC_CTRLA5, 00108 .ctrlb = &DMAC_CTRLB5, 00109 }, 00110 }; 00111 00112 /* We use event to signal the end of conversion */ 00113 static Dmac dmac[DMAC_CHANNEL_CNT]; 00114 static uint8_t dmac_ch_enabled; 00115 00116 void dmac_setLLITransfer(int ch, DmacDesc *lli, uint32_t cfg) 00117 { 00118 DMAC_CHDR = BV(ch); 00119 reg32_t reg = DMAC_EBCISR; 00120 (void)reg; 00121 00122 *dmac_ch[ch].cfg = cfg | DMAC_CFG_FIFOCFG_ALAP_CFG | (0x1 << DMAC_CFG_AHB_PROT_SHIFT); 00123 *dmac_ch[ch].desc = (uint32_t)lli; 00124 } 00125 00126 void dmac_setSources(int ch, uint32_t src, uint32_t dst) 00127 { 00128 DMAC_CHDR = BV(ch); 00129 00130 *dmac_ch[ch].src = src; 00131 *dmac_ch[ch].dst = dst; 00132 *dmac_ch[ch].desc = 0; 00133 } 00134 00135 void dmac_configureDmac(int ch, size_t transfer_size, uint32_t cfg, uint32_t ctrla, uint32_t ctrlb) 00136 { 00137 DMAC_CHDR = BV(ch); 00138 00139 *dmac_ch[ch].cfg = cfg | DMAC_CFG_FIFOCFG_ALAP_CFG | (0x1 << DMAC_CFG_AHB_PROT_SHIFT); 00140 *dmac_ch[ch].ctrla = ctrla | (transfer_size & DMAC_CTRLA_BTSIZE_MASK); 00141 *dmac_ch[ch].ctrlb = ctrlb & ~BV(DMAC_CTRLB_IEN); 00142 } 00143 00144 int dmac_start(int ch) 00145 { 00146 if (DMAC_CHSR & BV(ch)) 00147 { 00148 dmac[ch].errors |= DMAC_ERR_CH_ALREDY_ON; 00149 return -1; 00150 } 00151 DMAC_CHER = BV(ch); 00152 dmac_ch_enabled |= BV(ch); 00153 return 0; 00154 } 00155 00156 void dmac_stop(int ch) 00157 { 00158 DMAC_CHDR = BV(ch); 00159 dmac_ch_enabled &= ~BV(ch); 00160 } 00161 00162 int dmac_error(int ch) 00163 { 00164 uint32_t err = ((DMAC_EBCISR & 0x3F0000) | dmac[ch].errors); 00165 dmac[ch].errors = 0; 00166 return err; 00167 } 00168 00169 static DECLARE_ISR(dmac_irq) 00170 { 00171 uint32_t status = DMAC_EBCISR; 00172 uint32_t irq_ch = (status & (((dmac_ch_enabled | 00173 (dmac_ch_enabled << DMAC_EBCIDR_ERR0) >> DMAC_EBCIDR_ERR0) | 00174 (dmac_ch_enabled << DMAC_EBCIDR_CBTC0) >> DMAC_EBCIDR_CBTC0) & 0xFF)); 00175 if (irq_ch) 00176 for(int i = 0; i < 6; i++) 00177 { 00178 if (BV(i) & irq_ch) 00179 if(dmac[i].handler) 00180 dmac[i].handler(status); 00181 } 00182 } 00183 00184 bool dmac_enableCh(int ch, dmac_handler_t handler) 00185 { 00186 ASSERT(ch <= DMAC_CHANNEL_CNT); 00187 00188 dmac_ch_enabled |= BV(ch); 00189 if (handler) 00190 { 00191 dmac[ch].handler = handler; 00192 DMAC_EBCIER |= (BV(ch) << DMAC_EBCIER_BTC0) | (BV(ch) << DMAC_EBCIDR_CBTC0) | (BV(ch) << DMAC_EBCIDR_ERR0); 00193 kprintf("Init dmac ch[%08lx]\n", DMAC_EBCIMR); 00194 } 00195 00196 return true; 00197 } 00198 00199 void dmac_init(void) 00200 { 00201 dmac_ch_enabled = 0; 00202 memset(&dmac, 0, sizeof(dmac)); 00203 00204 //init DMAC 00205 DMAC_EBCIDR = 0x3FFFFF; 00206 DMAC_CHDR = 0x1F; 00207 00208 pmc_periphEnable(DMAC_ID); 00209 DMAC_EN = BV(DMAC_EN_ENABLE); 00210 00211 sysirq_setHandler(INT_DMAC, dmac_irq); 00212 }
![(please configure the [header_logo] section in trac.ini)](/chrome/site/bertos_logo.png)