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/*---------------------------------------------------------------------------*/
46struct 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
53static volatile struct channel_ctrl channel_config[UDMA_CONF_MAX_CHANNEL + 1]
54 __attribute__ ((section(".udma_channel_control_table")));
55/*---------------------------------------------------------------------------*/
56void
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/*---------------------------------------------------------------------------*/
69void
70udma_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/*---------------------------------------------------------------------------*/
79void
80udma_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/*---------------------------------------------------------------------------*/
89void
90udma_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/*---------------------------------------------------------------------------*/
99void
100udma_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/*---------------------------------------------------------------------------*/
119void
120udma_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/*---------------------------------------------------------------------------*/
129void
130udma_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/*---------------------------------------------------------------------------*/
140void
142{
143 if(channel > UDMA_CONF_MAX_CHANNEL) {
144 return;
145 }
146
147 REG(UDMA_ALTSET) |= 1 << channel;
148}
149/*---------------------------------------------------------------------------*/
150void
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/*---------------------------------------------------------------------------*/
161void
163{
164 if(channel > UDMA_CONF_MAX_CHANNEL) {
165 return;
166 }
167
168 REG(UDMA_PRIOSET) |= 1 << channel;
169}
170/*---------------------------------------------------------------------------*/
171void
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/*---------------------------------------------------------------------------*/
182void
184{
185 if(channel > UDMA_CONF_MAX_CHANNEL) {
186 return;
187 }
188
189 REG(UDMA_USEBURSTSET) |= 1 << channel;
190}
191/*---------------------------------------------------------------------------*/
192void
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/*---------------------------------------------------------------------------*/
203void
204udma_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/*---------------------------------------------------------------------------*/
213void
214udma_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/*---------------------------------------------------------------------------*/
224void
226{
227 if(channel > UDMA_CONF_MAX_CHANNEL) {
228 return;
229 }
230
231 REG(UDMA_SWREQ) |= 1 << channel;
232}
233/*---------------------------------------------------------------------------*/
234uint8_t
235udma_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/*---------------------------------------------------------------------------*/
244void
245udma_isr()
246{
247 /* Simply clear Channel interrupt status for now */
249}
250/*---------------------------------------------------------------------------*/
251void
252udma_err_isr()
253{
254 /* Stub Implementation, just clear the error flag */
255 REG(UDMA_ERRCLR) = 1;
256}
257/*---------------------------------------------------------------------------*/
258
259/** @} */
@ UDMA_ERR_IRQn
µDMA Error Interrupt
Definition: cc2538_cm3.h:107
@ UDMA_SW_IRQn
µDMA Software Interrupt
Definition: cc2538_cm3.h:106
void udma_set_channel_dst(uint8_t channel, uint32_t dst_end)
Sets the channel's destination address.
Definition: udma.c:80
void udma_init()
Initialise the uDMA driver.
Definition: udma.c:57
void udma_channel_mask_set(uint8_t channel)
Disable peripheral triggers for a uDMA channel.
Definition: udma.c:204
#define UDMA_ERRCLR
DMA bus error clear.
Definition: udma.h:79
void udma_channel_enable(uint8_t channel)
Enables a uDMA channel.
Definition: udma.c:120
#define UDMA_ALTCLR
DMA channel primary alternate clear.
Definition: udma.h:76
uint8_t udma_channel_get_mode(uint8_t channel)
Retrieve the current mode for a channel.
Definition: udma.c:235
void udma_channel_sw_request(uint8_t channel)
Generate a software trigger to start a transfer.
Definition: udma.c:225
void udma_channel_use_burst(uint8_t channel)
Configure a channel to only use burst transfers.
Definition: udma.c:183
#define UDMA_CFG
DMA configuration.
Definition: udma.h:64
#define UDMA_PRIOCLR
DMA channel priority clear.
Definition: udma.h:78
#define UDMA_USEBURSTCLR
DMA channel useburst clear.
Definition: udma.h:70
#define UDMA_PRIOSET
DMA channel priority set.
Definition: udma.h:77
void udma_channel_disable(uint8_t channel)
Disables a uDMA channel.
Definition: udma.c:130
#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
void udma_channel_mask_clr(uint8_t channel)
Enable peripheral triggers for a uDMA channel.
Definition: udma.c:214
void udma_set_channel_control_word(uint8_t channel, uint32_t ctrl)
Configure the channel's control word.
Definition: udma.c:90
#define UDMA_ENASET
DMA channel enable set.
Definition: udma.h:73
#define UDMA_USEBURSTSET
DMA channel useburst set.
Definition: udma.h:69
#define UDMA_REQMASKCLR
DMA channel request mask clear.
Definition: udma.h:72
#define UDMA_CHIS_CHIS
Channel [n] interrupt status.
Definition: udma.h:220
#define UDMA_CHIS
DMA channel interrupt status.
Definition: udma.h:81
#define UDMA_ALTSET
DMA channel primary alternate set.
Definition: udma.h:75
void udma_set_channel_assignment(uint8_t channel, uint8_t enc)
Choose an encoding for a uDMA channel.
Definition: udma.c:100
#define UDMA_CHMAP0
DMA channel map select 0.
Definition: udma.h:82
#define UDMA_REQMASKSET
DMA channel request mask set.
Definition: udma.h:71
void udma_channel_use_single(uint8_t channel)
Configure a channel to use single as well as burst requests.
Definition: udma.c:193
#define UDMA_ENACLR
DMA channel enable clear.
Definition: udma.h:74
#define UDMA_CTLBASE
DMA channel control base pointer.
Definition: udma.h:65
void udma_channel_use_primary(uint8_t channel)
Use the primary control data structure for a channel.
Definition: udma.c:151
void udma_channel_prio_set_default(uint8_t channel)
Set a uDMA channel to default priority.
Definition: udma.c:172
void udma_set_channel_src(uint8_t channel, uint32_t src_end)
Sets the channels source address.
Definition: udma.c:70
void udma_channel_use_alternate(uint8_t channel)
Use the alternate control data structure for a channel.
Definition: udma.c:141
#define UDMA_CFG_MASTEN
Controller master enable.
Definition: udma.h:101
Header file for the ARM Nested Vectored Interrupt Controller.
Header file with register manipulation macro definitions.
Header file with register, macro and function declarations for the cc2538 micro-DMA controller module...