1 | /**
|
2 | * @file hal_dma.h
|
3 | *
|
4 | * Created: 28.10.2019 07:49:08
|
5 | * Author: A.Patzak
|
6 | *
|
7 | * Erklärung:
|
8 | * - Diese HAL ist für Menschen die wissen was sie tun!
|
9 | * + Zur Sicherheit sind die definierten Konstanten zu verwenden
|
10 | * - Die DMA besteht aus dem Hauptmodul und den max. 12 Kanälen
|
11 | * - Je Kanal gibt es mind. einen (Block-)Descriptor (oder mehr verlinkte)...
|
12 | * ...der Quelle, Ziel und die Übertragungsweise eines Blockes festlegt
|
13 | * - Ist ein Descriptor abgearbeitet wird der nächste verlinkte Descriptor abgearbeitet
|
14 | * - Nach dem letzten Descriptor wird die Übertragung des Kanales beendet
|
15 | * - DMA-Transfers sind folgendermaßen zusammengesetzt:
|
16 | * + Beatsize: (Bytes) ist ein Buszugriff (fetch) <== Peripherie-Reg-Size
|
17 | * + Blocksize: Anzahl der Beats pro Block (= ein Descriptor!) <-- "beatcnt"
|
18 | * + Transaction: Alle Blöcke (aller verlinkten Descriptoren)
|
19 | * - Um die Übertragung anzustoßen gibt es verschiedene DMA-Triggerquellen:
|
20 | * + Software-Command
|
21 | * + Events
|
22 | * + direkte Verbindungen zu Peripherie-Modulen (ählich zu INT-Flags)
|
23 | * - Pro DMA-Trigger kann entweder ein Beat oder ein Block oder Transfer angestoßen werden.
|
24 | * + Für Peripheriemodule verwendet man den Beat-Trigger
|
25 | * - Die DMA kann auch selbst Interupts und Events generieren / ausgeben
|
26 | *
|
27 | * Benutzung:
|
28 | * 0.) Anpassung des DMA-Konfigurationsbereiches in hal_dma.h
|
29 | * 1.) SetupDma()
|
30 | * 2.) SetupDmaChannel()
|
31 | * 3.) AddDmaDescriptor()
|
32 | * ?.) Evtl. zusätzliche Konfigurierungen
|
33 | * 4.) EnableDmaChannel()
|
34 | * 5.) für weitere Kanäle 2.) -> 4.)
|
35 | *
|
36 | * \defgroup HAL: Funktionen für die DMA
|
37 | * @{*/
|
38 | #ifndef HAL_DMA_H_
|
39 | #define HAL_DMA_H_
|
40 | /******************************************************************************/
|
41 | /************************** HAL: DMA-Konstante ****************************/
|
42 | /******************************************************************************/
|
43 | // !!!!!!!!!!!!!!!!!!!!!!!! DMA-Konfigurationsbereich !!!!!!!!!!!!!!!!!!!!!!!!!
|
44 | // !! Hier muss die maximal benutzte Anzahl an DMA-Kanälen eingestellt werden
|
45 | #define DMA_MAX_CHANNELS 2
|
46 | #define DMA_MORE_DESCRIPTORS 1 // maximale Anzahl aller zusätzlicher Descriptoren aller Kanäle
|
47 | #define DMA_PRI_LEVELS_ENABLE (0xF) // Level 0..3 enabled
|
48 | #define DMA_MEMACCESS_PRI_MED 0x2 // mittlerer Speicherzugriffslevel für Fetch, Transaktion und Writeback
|
49 | /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
|
50 | typedef enum dma_channel_id{
|
51 | DMA_CHID_CHANNEL0= 0,
|
52 | DMA_CHID_CHANNEL1,
|
53 | DMA_CHID_CHANNEL2,
|
54 | DMA_CHID_CHANNEL3,
|
55 | DMA_CHID_CHANNEL4,
|
56 | DMA_CHID_CHANNEL5,
|
57 | DMA_CHID_CHANNEL6,
|
58 | DMA_CHID_CHANNEL7,
|
59 | } dma_channel_id_t;
|
60 |
|
61 | typedef enum dma_transfer_trigger_action{
|
62 | DMA_TRIGGER_ACTON_BLOCK = DMAC_CHCTRLB_TRIGACT_BLOCK_Val,
|
63 | DMA_TRIGGER_ACTON_BEAT = DMAC_CHCTRLB_TRIGACT_BEAT_Val,
|
64 | DMA_TRIGGER_ACTON_TRANSACTION = DMAC_CHCTRLB_TRIGACT_TRANSACTION_Val,
|
65 | } dma_transfer_trigger_action_t;
|
66 |
|
67 | typedef enum dma_callback_type {
|
68 | // First item here is for any transfer errors. A transfer error is
|
69 | // flagged if a bus error is detected during an AHB access or when
|
70 | // the DMAC fetches an invalid descriptor
|
71 | DMA_CALLBACK_TRANSFER_ERROR,
|
72 | DMA_CALLBACK_TRANSFER_DONE,
|
73 | DMA_CALLBACK_CHANNEL_SUSPEND,
|
74 | DMA_CALLBACK_N, // Number of available callbacks
|
75 | } dma_callback_type_t;
|
76 |
|
77 | typedef enum dma_beat_size {
|
78 | DMA_BEAT_SIZE_8B = 0, // 8-bit
|
79 | DMA_BEAT_SIZE_16B, // 16-bit
|
80 | DMA_BEAT_SIZE_32B, // 32-bit
|
81 | } dma_beat_size_t;
|
82 |
|
83 | typedef enum dma_event_output_selection {
|
84 | DMA_EVENT_OUTPUT_DISABLE = 0, // Disable event generation
|
85 | DMA_EVENT_OUTPUT_BLOCK, // Event strobe when block xfer complete
|
86 | DMA_EVENT_OUTPUT_RESERVED,
|
87 | DMA_EVENT_OUTPUT_BEAT, // Event strobe when beat xfer complete
|
88 | } dma_evo_sel_t;
|
89 |
|
90 | // DMA step selection. This bit determines whether the step size setting
|
91 | // is applied to source or destination address.
|
92 | typedef enum dma_step_selection {
|
93 | DMA_STEPSEL_DST = 0,
|
94 | DMA_STEPSEL_SRC,
|
95 | } dma_step_selection_t;
|
96 |
|
97 | // Address increment step size. These bits select the address increment step
|
98 | // size. The setting apply to source or destination address, depending on
|
99 | // STEPSEL setting.
|
100 | typedef enum dma_address_increment_stepsize {
|
101 | DMA_ADDR_INC_NONE = -1, // kein Adress-Increment
|
102 | DMA_ADDR_INC_1 = 0, // beat size * 1
|
103 | DMA_ADDR_INC_2, // beat size * 2
|
104 | DMA_ADDR_INC_4, // beat size * 4
|
105 | DMA_ADDR_INC_8, // etc...
|
106 | DMA_ADDR_INC_16,
|
107 | DMA_ADDR_INC_32,
|
108 | DMA_ADDR_INC_64,
|
109 | DMA_ADDR_INC_128,
|
110 | } dma_addr_inc_t;
|
111 |
|
112 | // higher numbers are higher priority
|
113 | typedef enum dma_priority {
|
114 | DMA_PRIORITY_0, // lowest (default)
|
115 | DMA_PRIORITY_1,
|
116 | DMA_PRIORITY_2,
|
117 | DMA_PRIORITY_3, // highest
|
118 | } dma_priority_t;
|
119 |
|
120 | typedef enum dma_block_action {
|
121 | DMA_BLOCK_ACTION_NOACT = 0,
|
122 | // Channel in normal operation and sets transfer complete interrupt
|
123 | // flag after block transfer
|
124 | DMA_BLOCK_ACTION_INT,
|
125 | // Trigger channel suspend after block transfer and sets channel
|
126 | // suspend interrupt flag once the channel is suspended
|
127 | DMA_BLOCK_ACTION_SUSPEND,
|
128 | // Sets transfer complete interrupt flag after a block transfer and
|
129 | // trigger channel suspend. The channel suspend interrupt flag will
|
130 | // be set once the channel is suspended.
|
131 | DMA_BLOCK_ACTION_BOTH
|
132 | } dma_block_action_t;
|
133 |
|
134 | //
|
135 | typedef enum dma_trigact {
|
136 | DMA_TRIGACT_BLOCK, //
|
137 | DMA_TRIGACT_RESERVED, //
|
138 | DMA_TRIGACT_BEAT, //
|
139 | DMA_TRIGACT_TRANSACTION //
|
140 | } dma_trigact_t;
|
141 |
|
142 | //
|
143 | typedef enum dma_trigsource {
|
144 | DMA_TRIGSRC_SW_EVENT, //
|
145 | DMA_TRIGSRC_SERCOM0_RX, //
|
146 | DMA_TRIGSRC_SERCOM0_TX, //
|
147 | DMA_TRIGSRC_SERCOM1_RX, //
|
148 | DMA_TRIGSRC_SERCOM1_TX, //
|
149 | DMA_TRIGSRC_SERCOM2_RX, //
|
150 | DMA_TRIGSRC_SERCOM2_TX, //
|
151 | DMA_TRIGSRC_SERCOM3_RX, //
|
152 | DMA_TRIGSRC_SERCOM3_TX, //
|
153 | DMA_TRIGSRC_SERCOM4_RX, //
|
154 | DMA_TRIGSRC_SERCOM4_TX, //
|
155 | DMA_TRIGSRC_SERCOM5_RX, //
|
156 | DMA_TRIGSRC_SERCOM5_TX, //
|
157 | DMA_TRIGSRC_TCC0_OVF, //
|
158 | DMA_TRIGSRC_TCC0_MC0, //
|
159 | DMA_TRIGSRC_TCC0_MC1, //
|
160 | DMA_TRIGSRC_TCC0_MC2, //
|
161 | DMA_TRIGSRC_TCC0_MC3, //
|
162 | DMA_TRIGSRC_TCC1_OVF, //
|
163 | DMA_TRIGSRC_TCC1_MC0, //
|
164 | DMA_TRIGSRC_TCC1_MC1, //
|
165 | DMA_TRIGSRC_TCC2_OVF, //
|
166 | DMA_TRIGSRC_TCC2_MC0, //
|
167 | DMA_TRIGSRC_TCC2_MC1, //
|
168 | DMA_TRIGSRC_TC3_OVF, //
|
169 | DMA_TRIGSRC_TC3_MC0, //
|
170 | DMA_TRIGSRC_TC3_MC1, //
|
171 | DMA_TRIGSRC_TC4_OVF, //
|
172 | DMA_TRIGSRC_TC4_MC0, //
|
173 | DMA_TRIGSRC_TC4_MC1, //
|
174 | DMA_TRIGSRC_TC5_OVF, //
|
175 | DMA_TRIGSRC_TC5_MC0, //
|
176 | DMA_TRIGSRC_TC5_MC1, //
|
177 | DMA_TRIGSRC_TC6_OVF, //
|
178 | DMA_TRIGSRC_TC6_MC0, //
|
179 | DMA_TRIGSRC_TC6_MC1, //
|
180 | DMA_TRIGSRC_TC7_OVF, //
|
181 | DMA_TRIGSRC_TC7_MC0, //
|
182 | DMA_TRIGSRC_TC7_MC1, //
|
183 | DMA_TRIGSRC_ADCRDY, //
|
184 | DMA_TRIGSRC_DACEMPTY, //
|
185 | DMA_TRIGSRC_I2SRX0, //
|
186 | DMA_TRIGSRC_I2SRX1, //
|
187 | DMA_TRIGSRC_I2STX0, //
|
188 | DMA_TRIGSRC_I2STX1, //
|
189 | DMA_TRIGSRC_TCC3_OVF, //
|
190 | DMA_TRIGSRC_TCC3_MC0, //
|
191 | DMA_TRIGSRC_TCC3_MC1, //
|
192 | DMA_TRIGSRC_TCC3_MC2, //
|
193 | DMA_TRIGSRC_TCC3_MC3 //
|
194 | } dma_trigsource_t;
|
195 |
|
196 | //
|
197 | typedef enum dma_eventact {
|
198 | DMA_EVACT_NONE, // keine Reaktion auf Events
|
199 | DMA_EVACT_TRIG, // Event triggert normal
|
200 | DMA_EVACT_CONTRANS, // conditional Transfer-Trigger
|
201 | DMA_EVACT_CONBLOCK, // conditional Block-Trigger
|
202 | DMA_EVACT_SUSPEND, // Suspend-Aktion
|
203 | DMA_EVACT_RESUME, // Resume-Aktion
|
204 | DMA_EVACT_SSKIP, // Skip-Aktion
|
205 | } dma_eventact_t;
|
206 | /******************************************************************************/
|
207 | /*************************** HAL: DMA-Routinen ****************************/
|
208 | /******************************************************************************/
|
209 | /** @brief setzt das CRC-Modul der DMA zurück */
|
210 | void DmaCrcReset(void);
|
211 |
|
212 | /** @brief setzt alle DMA-Descriptor-Sections und more_desriptors im RAM zurück */
|
213 | void ResetDmaDescriptorSections(void);
|
214 |
|
215 | /** @brief setzt / fügt an (dem angegebenen Kanal), einen DMA-Link-Descriptor & liefert Pointer auf neuen Descriptor zurück
|
216 | * @param[in] chann: DMA-Kanal, eine der dma_channel_id_t-Konstanten;
|
217 | * @param[in] srcendaddr: Die !!letzte!! Adresse des Source-Bereiches
|
218 | * @param[in] srcinc: Bestimmt das Adressincrement für Source; eine der dma_addr_inc_t-Konstanten
|
219 | * @param[in] dstendaddr: Die !!letzte!! Adresse des Destination-Bereiches
|
220 | * @param[in] dstinc: Bestimmt das Adressincrement für Destination; eine der dma_addr_inc_t-Konstanten
|
221 | * @param[in] beatsize: Datenformat der Source in Byte (kleinste Einheit für Trigger); eine der dma_beat_size_t-Konstanten
|
222 | * @param[in] beatcnt: Anzahl der Beat-Transfers pro Block-Transfer
|
223 | * @param[in] evosel: Auswahl, wann ein Event erzeugt wird; eine der dma_evo_sel_t-Konstanten
|
224 | * @return: OK: Pointer auf neuen Descriptor (damit kann man noch händisch nachkonfigurieren!); Fehler: Null */
|
225 | DmacDescriptor* AddDmaDescriptor(const dma_channel_id_t chann, void* const srcendaddr, const dma_addr_inc_t srcinc,
|
226 | void* const dstendaddr, const dma_addr_inc_t dstinc,
|
227 | const dma_beat_size_t beatsize, const uint16_t beatcnt, const dma_evo_sel_t evosel);
|
228 |
|
229 | /** @brief löscht alle Descriptoren eines Kanals
|
230 | * @param[in] chann: DMA-Kanal, eine der dma_channel_id_t-Konstanten */
|
231 | void ResetDmaChannelDescriptors(const dma_channel_id_t chann);
|
232 |
|
233 | /** @brief resettet einen kompletten DMA-Kanal und disabled ihn
|
234 | * @param[in] chann: DMA-Kanal, eine der dma_channel_id_t-Konstanten */
|
235 | void ResetDmaChannel(const dma_channel_id_t chann);
|
236 |
|
237 | /** @brief enabled den angegebenen DMA-Kanal
|
238 | * @param[in] chann: DMA-Kanal, eine der dma_channel_id_t-Konstanten */
|
239 | void EnableDmaChannel(const dma_channel_id_t chann);
|
240 |
|
241 | /** @brief disabled den angegebenen DMA-Kanal
|
242 | * @param[in] chann: DMA-Kanal, eine der dma_channel_id_t-Konstanten */
|
243 | void DisableDmaChannel(const dma_channel_id_t chann);
|
244 |
|
245 | /** @brief Konfiguriert einen DMA-Kanal ohne ihn zu enablen und ohne Descriptor(en)!
|
246 | * Hinweis:
|
247 | * - Zur vollen Funktionsfähigkeit des Kanals muss danach noch folgendes erfolgen...
|
248 | * - mind. ein Aufruf AddDmaDescriptor(....)
|
249 | * - danach müssen evtl. noch weitere Konfigurationen manuell erledigt werden
|
250 | * - Aufruf von EnableDmaChannel(...)
|
251 | * @param[in] chann: DMA-Kanal, eine der dma_channel_id_t-Konstanten
|
252 | * @param[in] channprio: Priorität des Kanals; eine der dma_priority_t-Konstanten
|
253 | * @param[in] trigact: Auswahl, was getriggert wird; eine der dma_trigact_t-Konstanten
|
254 | * @param[in] trigsrc: Auswahl der Hardware- / Peripherie-Triggerquellen
|
255 | * @param[in] evact: Ausahl der Event-Trigger-Aktion; eine der dma_eventact_t-Konstanten */
|
256 | void SetupDmaChannel(const dma_channel_id_t chann, const dma_priority_t channprio, const dma_trigact_t trigact,
|
257 | const dma_trigsource_t trigsrc, const dma_eventact_t evact);
|
258 |
|
259 | /** @brief initialisiert die DMA mit den grundlegenden Einstellungen und enabled sie
|
260 | * Hinweis:
|
261 | * - Zur vollen Funktionsfähigkeit muss danach noch ein/die Kanäle konfiguriert werden:
|
262 | * -> SetupDmaChannel() + n x AddDmaDescriptor() + ?config? + EnableDmaChannel() */
|
263 | void SetupDma(void);
|
264 | /******************************************************************************/
|
265 | /******************************************************************************/
|
266 | /**@}*/
|
267 | #endif /* HAL_DMA_H_ */
|