Contiki-NG
udma.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013, Texas Instruments Incorporated - http://www.ti.com/
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  *
14  * 3. Neither the name of the copyright holder nor the names of its
15  * contributors may be used to endorse or promote products derived
16  * from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
29  * OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 /**
32  * \addtogroup cc2538-udma
33  * @{
34  *
35  * \file
36  * Implementation of the cc2538 micro-DMA driver
37  */
38 #include "contiki.h"
39 #include "dev/udma.h"
40 #include "dev/nvic.h"
41 #include "reg.h"
42 
43 #include <stdint.h>
44 #include <string.h>
45 /*---------------------------------------------------------------------------*/
46 struct channel_ctrl {
47  uint32_t src_end_ptr;
48  uint32_t dst_end_ptr;
49  uint32_t ctrl_word;
50  uint32_t unused;
51 };
52 
53 static volatile struct channel_ctrl channel_config[UDMA_CONF_MAX_CHANNEL + 1]
54  __attribute__ ((section(".udma_channel_control_table")));
55 /*---------------------------------------------------------------------------*/
56 void
58 {
59  memset((void *)&channel_config, 0, sizeof(channel_config));
60 
62 
63  REG(UDMA_CTLBASE) = (uint32_t)(&channel_config);
64 
65  NVIC_EnableIRQ(UDMA_SW_IRQn);
66  NVIC_EnableIRQ(UDMA_ERR_IRQn);
67 }
68 /*---------------------------------------------------------------------------*/
69 void
70 udma_set_channel_src(uint8_t channel, uint32_t src_end)
71 {
72  if(channel > UDMA_CONF_MAX_CHANNEL) {
73  return;
74  }
75 
76  channel_config[channel].src_end_ptr = src_end;
77 }
78 /*---------------------------------------------------------------------------*/
79 void
80 udma_set_channel_dst(uint8_t channel, uint32_t dst_end)
81 {
82  if(channel > UDMA_CONF_MAX_CHANNEL) {
83  return;
84  }
85 
86  channel_config[channel].dst_end_ptr = dst_end;
87 }
88 /*---------------------------------------------------------------------------*/
89 void
90 udma_set_channel_control_word(uint8_t channel, uint32_t ctrl)
91 {
92  if(channel > UDMA_CONF_MAX_CHANNEL) {
93  return;
94  }
95 
96  channel_config[channel].ctrl_word = ctrl;
97 }
98 /*---------------------------------------------------------------------------*/
99 void
100 udma_set_channel_assignment(uint8_t channel, uint8_t enc)
101 {
102  uint32_t base_chmap = UDMA_CHMAP0;
103  uint8_t shift;
104 
105  if(channel > UDMA_CONF_MAX_CHANNEL) {
106  return;
107  }
108 
109  /* Calculate the address of the relevant CHMAP register */
110  base_chmap += (channel >> 3) * 4;
111 
112  /* Calculate the shift value for the correct CHMAP register bits */
113  shift = (channel & 0x07);
114 
115  /* Read CHMAPx value, zero out channel's bits and write the new value */
116  REG(base_chmap) = (REG(base_chmap) & ~(0x0F << shift)) | (enc << shift);
117 }
118 /*---------------------------------------------------------------------------*/
119 void
120 udma_channel_enable(uint8_t channel)
121 {
122  if(channel > UDMA_CONF_MAX_CHANNEL) {
123  return;
124  }
125 
126  REG(UDMA_ENASET) |= 1 << channel;
127 }
128 /*---------------------------------------------------------------------------*/
129 void
130 udma_channel_disable(uint8_t channel)
131 {
132  if(channel > UDMA_CONF_MAX_CHANNEL) {
133  return;
134  }
135 
136  /* Writes of 0 have no effect, this no need for RMW */
137  REG(UDMA_ENACLR) = 1 << channel;
138 }
139 /*---------------------------------------------------------------------------*/
140 void
142 {
143  if(channel > UDMA_CONF_MAX_CHANNEL) {
144  return;
145  }
146 
147  REG(UDMA_ALTSET) |= 1 << channel;
148 }
149 /*---------------------------------------------------------------------------*/
150 void
151 udma_channel_use_primary(uint8_t channel)
152 {
153  if(channel > UDMA_CONF_MAX_CHANNEL) {
154  return;
155  }
156 
157  /* Writes of 0 have no effect, this no need for RMW */
158  REG(UDMA_ALTCLR) = 1 << channel;
159 }
160 /*---------------------------------------------------------------------------*/
161 void
163 {
164  if(channel > UDMA_CONF_MAX_CHANNEL) {
165  return;
166  }
167 
168  REG(UDMA_PRIOSET) |= 1 << channel;
169 }
170 /*---------------------------------------------------------------------------*/
171 void
173 {
174  if(channel > UDMA_CONF_MAX_CHANNEL) {
175  return;
176  }
177 
178  /* Writes of 0 have no effect, this no need for RMW */
179  REG(UDMA_PRIOCLR) = 1 << channel;
180 }
181 /*---------------------------------------------------------------------------*/
182 void
183 udma_channel_use_burst(uint8_t channel)
184 {
185  if(channel > UDMA_CONF_MAX_CHANNEL) {
186  return;
187  }
188 
189  REG(UDMA_USEBURSTSET) |= 1 << channel;
190 }
191 /*---------------------------------------------------------------------------*/
192 void
193 udma_channel_use_single(uint8_t channel)
194 {
195  if(channel > UDMA_CONF_MAX_CHANNEL) {
196  return;
197  }
198 
199  /* Writes of 0 have no effect, this no need for RMW */
200  REG(UDMA_USEBURSTCLR) = 1 << channel;
201 }
202 /*---------------------------------------------------------------------------*/
203 void
204 udma_channel_mask_set(uint8_t channel)
205 {
206  if(channel > UDMA_CONF_MAX_CHANNEL) {
207  return;
208  }
209 
210  REG(UDMA_REQMASKSET) |= 1 << channel;
211 }
212 /*---------------------------------------------------------------------------*/
213 void
214 udma_channel_mask_clr(uint8_t channel)
215 {
216  if(channel > UDMA_CONF_MAX_CHANNEL) {
217  return;
218  }
219 
220  /* Writes of 0 have no effect, this no need for RMW */
221  REG(UDMA_REQMASKCLR) = 1 << channel;
222 }
223 /*---------------------------------------------------------------------------*/
224 void
225 udma_channel_sw_request(uint8_t channel)
226 {
227  if(channel > UDMA_CONF_MAX_CHANNEL) {
228  return;
229  }
230 
231  REG(UDMA_SWREQ) |= 1 << channel;
232 }
233 /*---------------------------------------------------------------------------*/
234 uint8_t
235 udma_channel_get_mode(uint8_t channel)
236 {
237  if(channel > UDMA_CONF_MAX_CHANNEL) {
238  return 0;
239  }
240 
241  return (channel_config[channel].ctrl_word & 0x07);
242 }
243 /*---------------------------------------------------------------------------*/
244 void
245 udma_isr()
246 {
247  /* Simply clear Channel interrupt status for now */
248  REG(UDMA_CHIS) = UDMA_CHIS_CHIS;
249 }
250 /*---------------------------------------------------------------------------*/
251 void
252 udma_err_isr()
253 {
254  /* Stub Implementation, just clear the error flag */
255  REG(UDMA_ERRCLR) = 1;
256 }
257 /*---------------------------------------------------------------------------*/
258 
259 /** @} */
Header file for the ARM Nested Vectored Interrupt Controller.
void udma_channel_mask_clr(uint8_t channel)
Enable peripheral triggers for a uDMA channel.
Definition: udma.c:214
void udma_set_channel_dst(uint8_t channel, uint32_t dst_end)
Sets the channel&#39;s destination address.
Definition: udma.c:80
#define UDMA_CHIS
DMA channel interrupt status.
Definition: udma.h:81
#define UDMA_PRIOCLR
DMA channel priority clear.
Definition: udma.h:78
Header file with register manipulation macro definitions.
#define UDMA_REQMASKSET
DMA channel request mask set.
Definition: udma.h:71
#define UDMA_CFG_MASTEN
Controller master enable.
Definition: udma.h:101
void udma_channel_use_alternate(uint8_t channel)
Use the alternate control data structure for a channel.
Definition: udma.c:141
#define UDMA_CHIS_CHIS
Channel [n] interrupt status.
Definition: udma.h:220
void udma_channel_use_primary(uint8_t channel)
Use the primary control data structure for a channel.
Definition: udma.c:151
#define UDMA_SWREQ
DMA channel software request.
Definition: udma.h:68
void udma_channel_prio_set_high(uint8_t channel)
Set a uDMA channel to high priority.
Definition: udma.c:162
Header file with register, macro and function declarations for the cc2538 micro-DMA controller module...
void udma_channel_mask_set(uint8_t channel)
Disable peripheral triggers for a uDMA channel.
Definition: udma.c:204
void udma_set_channel_src(uint8_t channel, uint32_t src_end)
Sets the channels source address.
Definition: udma.c:70
#define UDMA_ENASET
DMA channel enable set.
Definition: udma.h:73
#define UDMA_ENACLR
DMA channel enable clear.
Definition: udma.h:74
#define UDMA_USEBURSTCLR
DMA channel useburst clear.
Definition: udma.h:70
void udma_channel_enable(uint8_t channel)
Enables a uDMA channel.
Definition: udma.c:120
void udma_set_channel_assignment(uint8_t channel, uint8_t enc)
Choose an encoding for a uDMA channel.
Definition: udma.c:100
#define UDMA_CTLBASE
DMA channel control base pointer.
Definition: udma.h:65
void udma_channel_sw_request(uint8_t channel)
Generate a software trigger to start a transfer.
Definition: udma.c:225
#define UDMA_ALTCLR
DMA channel primary alternate clear.
Definition: udma.h:76
#define UDMA_ERRCLR
DMA bus error clear.
Definition: udma.h:79
void udma_channel_disable(uint8_t channel)
Disables a uDMA channel.
Definition: udma.c:130
#define UDMA_CFG
DMA configuration.
Definition: udma.h:64
void udma_channel_use_burst(uint8_t channel)
Configure a channel to only use burst transfers.
Definition: udma.c:183
#define UDMA_PRIOSET
DMA channel priority set.
Definition: udma.h:77
#define UDMA_CHMAP0
DMA channel map select 0.
Definition: udma.h:82
void udma_init()
Initialise the uDMA driver.
Definition: udma.c:57
┬ÁDMA Error Interrupt.
Definition: cc2538_cm3.h:107
#define UDMA_ALTSET
DMA channel primary alternate set.
Definition: udma.h:75
#define UDMA_USEBURSTSET
DMA channel useburst set.
Definition: udma.h:69
void udma_channel_prio_set_default(uint8_t channel)
Set a uDMA channel to default priority.
Definition: udma.c:172
void udma_set_channel_control_word(uint8_t channel, uint32_t ctrl)
Configure the channel&#39;s control word.
Definition: udma.c:90
uint8_t udma_channel_get_mode(uint8_t channel)
Retrieve the current mode for a channel.
Definition: udma.c:235
void udma_channel_use_single(uint8_t channel)
Configure a channel to use single as well as burst requests.
Definition: udma.c:193
┬ÁDMA Software Interrupt.
Definition: cc2538_cm3.h:106
#define UDMA_REQMASKCLR
DMA channel request mask clear.
Definition: udma.h:72