NetBurner 3.5.6
PDF Version
xdmac.h
1#ifndef __XDMAC_H
2#define __XDMAC_H
3/*NB_REVISION*/
4
5/*NB_COPYRIGHT*/
6#include <same70.h>
7#include <basictypes.h>
8#include <nbrtos.h>
9
10struct dma_descview_0;
11struct dma_descview_1;
12struct dma_descview_2;
13struct dma_descview_3;
14
15struct dma_transfer_desc_t
16{
17 union
18 {
19 dma_transfer_desc_t *pNext;
20 dma_descview_0 *pNext_0;
21 dma_descview_1 *pNext_1;
22 dma_descview_2 *pNext_2;
23 dma_descview_3 *pNext_3;
24 uint32_t nda;
25 };
26 uint32_t ubCtrl;
27};
28struct dma_descview_0 : public dma_transfer_desc_t
29{
30 uint32_t addr;
31};
32
33struct dma_descview_1 : public dma_transfer_desc_t
34{
35 uint32_t src;
36 uint32_t dst;
37};
38
39struct dma_descview_2 : public dma_transfer_desc_t
40{
41 uint32_t src;
42 uint32_t dst;
43 uint32_t cfg;
44};
45
46struct dma_descview_3 : public dma_transfer_desc_t
47{
48 uint32_t src;
49 uint32_t dst;
50 uint32_t cfg;
51 uint32_t blkCtrl;
52 uint32_t stride;
53 uint32_t srcuStride;
54 uint32_t dstuStride;
55};
56
57#include <type_traits>
58struct XdmaCh_t;
59extern "C" XdmaCh_t * xdmacGetFreeCh();
60extern "C" void xdmacReleaseCh(XdmaCh_t *xdmaCh);
61
62
63struct XdmaChCtx_t
64{
65 uint32_t lastISR;
66 uint32_t stickyISR;
67 void (* isr) (XdmaCh_t *);
68 void reset();
69};
70
71struct XdmaCh_t : public XdmacChid
72{
73 private:
74 static XdmaChCtx_t ctx[XDMACCHID_NUMBER];
75 static uint32_t bInUse;
76 public:
77 enum TransType_t
78 {
79 Mem2Mem = XDMAC_CC_TYPE_MEM_TRAN_Val,
80 Periph = XDMAC_CC_TYPE_PER_TRAN_Val
81 };
82 enum MBSiz_t
83 {
84 MBSiz_1 = XDMAC_CC_MBSIZE_SINGLE_Val,
85 MBSiz_4 = XDMAC_CC_MBSIZE_FOUR_Val,
86 MBSiz_8 = XDMAC_CC_MBSIZE_EIGHT_Val,
87 MBSiz_16 = XDMAC_CC_MBSIZE_SIXTEEN_Val
88 };
89 enum DSync_t
90 {
91 Periph2Mem = XDMAC_CC_DSYNC_PER2MEM_Val,
92 Mem2Periph = XDMAC_CC_DSYNC_MEM2PER_Val
93 };
94 enum SWReq_t
95 {
96 Req_HW = XDMAC_CC_SWREQ_HWR_CONNECTED_Val,
97 Req_SW = XDMAC_CC_SWREQ_SWR_CONNECTED_Val
98 };
99 enum ChunkSiz_t
100 {
101 ChunkSiz_1 = XDMAC_CC_CSIZE_CHK_1_Val,
102 ChunkSiz_2 = XDMAC_CC_CSIZE_CHK_2_Val,
103 ChunkSiz_4 = XDMAC_CC_CSIZE_CHK_4_Val,
104 ChunkSiz_8 = XDMAC_CC_CSIZE_CHK_8_Val,
105 ChunkSiz_16 = XDMAC_CC_CSIZE_CHK_16_Val
106 };
107 enum DWidth_t
108 {
109 DWidth_Byte = XDMAC_CC_DWIDTH_BYTE_Val,
110 DWidth_HalfWord = XDMAC_CC_DWIDTH_HALFWORD_Val,
111 DWidth_Word = XDMAC_CC_DWIDTH_WORD_Val
112 };
113 enum AHB_IF_t
114 {
115 AHB_IF_0 = XDMAC_CC_SIF_AHB_IF0_Val,
116 AHB_IF_1 = XDMAC_CC_SIF_AHB_IF1_Val
117 };
118 enum AddrMode_t
119 {
120 AddrMode_Fixed = XDMAC_CC_SAM_FIXED_AM_Val,
121 AddrMode_Inc = XDMAC_CC_SAM_INCREMENTED_AM_Val,
122 AddrMode_uBS = XDMAC_CC_SAM_UBS_AM_Val,
123 AddrMode_uBS_DS = XDMAC_CC_SAM_UBS_DS_AM_Val
124 };
125 // Fetches the status from HW and stores to ctx
126 inline uint32_t readyStatus()
127 {
128 ctx[getID()].stickyISR |= ctx[getID()].lastISR = XDMAC_CIS;
129 return ctx[getID()].lastISR;
130 }
131 // Returns the status as stored in ctx
132 inline uint32_t getStatus() { return ctx[getID()].lastISR;}
133 inline uint32_t getStickyStatus() { return ctx[getID()].stickyISR;}
134 inline void clrStickyStatus(uint32_t mask = 0xFFFFFFFFul)
135 {
136 ctx[getID()].stickyISR &= ~mask;
137 }
138 inline uint32_t getID() { return((XdmacChid *)this) - XDMAC->XDMAC_CHID;}
139
140 inline void enableGIrq() { XDMAC->XDMAC_GIE = 1 << getID();}
141 inline void disableGIrq() { XDMAC->XDMAC_GID = 1 << getID();}
142
143 inline void suspRd() { XDMAC->XDMAC_GRS |= 1 << getID();}
144 inline void suspWr() { XDMAC->XDMAC_GWS |= 1 << getID();}
145 inline void suspRdWr() { XDMAC->XDMAC_GRWS = 1 << getID();}
146 inline void resRd() { XDMAC->XDMAC_GRS &= ~(1 << getID());}
147 inline void resWr() { XDMAC->XDMAC_GWS &= ~(1 << getID());}
148 inline void resRdWr() { XDMAC->XDMAC_GRWR = 1 << getID();}
149 inline void flush() { XDMAC->XDMAC_GSWF = 1 << getID();}
150 inline void disable() { XDMAC->XDMAC_GD = 1 << getID();}
151 inline void enable() { XDMAC->XDMAC_GE = 1 << getID();}
152 inline bool isEnabled() { return(XDMAC->XDMAC_GS) & (1 << getID());}
153 inline void suspRdAndFlush()
154 {
155 /* For some reason the channel cannot flush the transfer FIFO if
156 * it is requesting to fetch the next descriptor and the read
157 * interface is suspended. So, if the channel is suspended *as*
158 * the previous configuration is depleted *and* it is configured to
159 * fetch a new descriptor, we need to renable the read interface,
160 * let the new descriptor be fetched, and *then* we can suspend the
161 * channel for the flush.
162 *
163 * No, this isn't documented in the manual. */
164 suspRd();
165
166 readyStatus();
167 flush();
168 int i = 0;
169 do
170 {
171 if (i < 25)
172 {
173 i++;
174 asm("dsb");
175 continue;
176 }
177 if ((XDMAC_CNDC & XDMAC_CNDC_NDE)
178 && (guBLen() == 0))
179 {
180 resRd();
181 asm("dsb");
182 asm("dsb");
183
184 while (!(readyStatus() & XDMAC_CIS_FIS))
185 {
186 }
187 suspRd();
188 flush();
189 }
190 } while (!(readyStatus() & XDMAC_CIS_FIS));
191 }
192
193 inline void sSrcAddr(uint32_t src) { XDMAC_CSA = src;}
194 inline void sDstAddr(uint32_t dst) { XDMAC_CDA = dst;}
195 inline uint32_t gSrcAddr() { return XDMAC_CSA;}
196 inline uint32_t gDstAddr() { return XDMAC_CDA;}
197 inline void suBLen(uint32_t uBLen) { XDMAC_CUBC = uBLen;}
198 inline void s_BLen(uint32_t BLen) { XDMAC_CBC = BLen;}
199 inline uint32_t guBLen() { return XDMAC_CUBC;}
200 dma_transfer_desc_t * getNextDesc(uint32_t *remDataRet);
201 inline void *gNextDest()
202 {
203 dma_transfer_desc_t *desc = getNextDesc(NULL);
204 if ((XDMAC_CNDA & XDMAC_CNDA_NDA_Msk) == 0)
205 {
206 return NULL;
207 }
208 return(XDMAC_CNDC >> 3)
209 ? (void *)(((dma_descview_1 *)XDMAC_CNDA)->dst)
210 : (void *)(((dma_descview_0 *)XDMAC_CNDA)->addr);
211 }
212 inline uint32_t gNextuBLen()
213 {
214 return((XDMAC_CNDA & XDMAC_CNDA_NDA_Msk) == 0)
215 ? 0
216 : (((dma_descview_0 *)XDMAC_CNDA)->ubCtrl) & 0xFFFFFF;
217 }
218 void sNextDescAddr(dma_transfer_desc_t *pDesc);
219 inline uint32_t gXfrWidth()
220 { return(XDMAC_CC & XDMAC_CC_DWIDTH_Msk) >> (XDMAC_CC_DWIDTH_Pos - 1);}
221
222 inline void sConfig(TransType_t type, MBSiz_t mbsiz, DSync_t dir,
223 SWReq_t reqSrc, ChunkSiz_t chunksiz, DWidth_t dataWidth,
224 AHB_IF_t srcIF, AHB_IF_t dstIF, AddrMode_t srcAddrMode,
225 AddrMode_t dstAddrMode, uint8_t periphID)
226 {
227
228 // The following is a fix for a SAME70 XDMAC errata
229 /***** BEGIN ERRATA FIX *****/
230 if (dataWidth != DWidth_Word)
231 {
232 if (srcAddrMode == AddrMode_Fixed)
233 {
234 srcAddrMode = AddrMode_uBS_DS;
235 // set source data stride stride to -1
236 XDMAC_CDS_MSP |= (0xFFFF);
237 // ERRATA IS WRONG!
238 // We need to set the microstride to -1 as well.
239 XDMAC_CSUS = 0xFFFFFF;
240 }
241 if (dstAddrMode == AddrMode_Fixed)
242 {
243 dstAddrMode = AddrMode_uBS_DS;
244 // set dest data stride stride to -1
245 XDMAC_CDS_MSP |= (0xFFFF << 16);
246 // ERRATA IS WRONG!
247 // We need to set the microstride to -1 as well.
248 XDMAC_CDUS = 0xFFFFFF;
249 }
250 }
251 /***** END ERRATA FIX *****/
252 XDMAC_CC = (type << XDMAC_CC_TYPE_Pos) | (mbsiz << XDMAC_CC_MBSIZE_Pos)
253 | (dir << XDMAC_CC_DSYNC_Pos) | (chunksiz << XDMAC_CC_CSIZE_Pos)
254 | (dataWidth << XDMAC_CC_DWIDTH_Pos)
255 | (srcIF << XDMAC_CC_SIF_Pos) | (dstIF << XDMAC_CC_DIF_Pos)
256 | (srcAddrMode << XDMAC_CC_SAM_Pos)
257 | (dstAddrMode << XDMAC_CC_DAM_Pos)
258 | (periphID << XDMAC_CC_PERID_Pos);
259 }
260
261
262
263 inline void RegisterIsr(void (*isr)(XdmaCh_t *)) { ctx[getID()].isr = isr;}
264 // First Descriptor is only used to declare initial loading conditions
265
266 friend void XDMAC_Handler();
267 friend XdmaCh_t * xdmacGetFreeCh();
268 friend void xdmacReleaseCh(XdmaCh_t *xdmaCh);
269};
270
271XdmaCh_t::AHB_IF_t xdmacGetIntfForAddr(uint32_t addr);
272
273inline void XdmaCh_t::sNextDescAddr(dma_transfer_desc_t *pDesc)
274{
275 XDMAC_CNDA = (((uint32_t)pDesc) & ~0x3)
276 | xdmacGetIntfForAddr((uint32_t)pDesc);
277}
278
279#define XDMA_BD_INUSE (0x1)
280#define XDMA_BD_SWEEP_MARK (0x2)
281#define XDMA_BD_BUFFER_DONE_Msk (XDMA_BD_SWEEP_MARK | XDMA_BD_INUSE)
282#define XDMA_BD_BUFFER_DONE (XDMA_BD_INUSE)
283
284struct Desc0Ring
285{
286 XdmaCh_t *xdmaCh;
287 dma_descview_0 *descs;
288 dma_descview_0 *queueHead;
289 dma_descview_0 *modRelease;
290 uint32_t *BDFlag;
291 uint32_t ringLen;
292 uint32_t spinLength;
293 uint32_t spinBuf;
294 int xfrIncSiz;
295 uint8_t ubCtrlBits;
296 bool spinOnLastNotNext;
297
298 uint32_t nConfigFirst;
299 uint32_t nAddXfr;
300 uint32_t nModNext;
301 uint32_t nBDUsed;
302 uint32_t nBDFreed;
303
304 int GetFreeDesc(dma_descview_0 *next);
305 dma_descview_0 * ModifyNextActive(uint32_t addr, uint32_t unumXfrs, uint32_t suspThresh);
306 void ConfigFirstAndEnableCh(uint32_t addr, uint32_t numXfrs);
307 dma_descview_0 * AddXfr(uint32_t addr, uint32_t numXfrs, uint32_t suspThresh);
308
309 void PrintCounts();
310 void PrintDescChain();
311};
312
313
314
315
316#endif /* ----- #ifndef __XDMAC_H ----- */
NetBurner Real-Time Operating System (NBRTOS) API.
#define XDMAC
(XDMAC ) Base Address
Definition same70q21_sim.h:241