Contiki-NG
Loading...
Searching...
No Matches
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#include "dev/cc2538-dev.h"
43
44#include <stdint.h>
45#include <string.h>
46/*---------------------------------------------------------------------------*/
47struct channel_ctrl {
48 uint32_t src_end_ptr;
49 uint32_t dst_end_ptr;
50 uint32_t ctrl_word;
51 uint32_t unused;
52};
53
54static volatile struct channel_ctrl channel_config[UDMA_CONF_MAX_CHANNEL + 1]
55 __attribute__ ((section(".udma_channel_control_table")));
56
57/*---------------------------------------------------------------------------*/
58bool
59udma_is_valid_source_address(uintptr_t source_address)
60{
61 return source_address >= CC2538_DEV_RLSRAM_ADDR;
62}
63/*---------------------------------------------------------------------------*/
64void
66{
67 memset((void *)&channel_config, 0, sizeof(channel_config));
68
70
71 REG(UDMA_CTLBASE) = (uint32_t)(&channel_config);
72
73 NVIC_EnableIRQ(UDMA_SW_IRQn);
74 NVIC_EnableIRQ(UDMA_ERR_IRQn);
75}
76/*---------------------------------------------------------------------------*/
77void
78udma_set_channel_src(uint8_t channel, uint32_t src_end)
79{
80 if(channel > UDMA_CONF_MAX_CHANNEL) {
81 return;
82 }
83
84 channel_config[channel].src_end_ptr = src_end;
85}
86/*---------------------------------------------------------------------------*/
87void
88udma_set_channel_dst(uint8_t channel, uint32_t dst_end)
89{
90 if(channel > UDMA_CONF_MAX_CHANNEL) {
91 return;
92 }
93
94 channel_config[channel].dst_end_ptr = dst_end;
95}
96/*---------------------------------------------------------------------------*/
97void
98udma_set_channel_control_word(uint8_t channel, uint32_t ctrl)
99{
100 if(channel > UDMA_CONF_MAX_CHANNEL) {
101 return;
102 }
103
104 channel_config[channel].ctrl_word = ctrl;
105}
106/*---------------------------------------------------------------------------*/
107void
108udma_set_channel_assignment(uint8_t channel, uint8_t enc)
109{
110 uint32_t base_chmap = UDMA_CHMAP0;
111 uint8_t shift;
112
113 if(channel > UDMA_CONF_MAX_CHANNEL) {
114 return;
115 }
116
117 /* Calculate the address of the relevant CHMAP register */
118 base_chmap += (channel >> 3) * 4;
119
120 /* Calculate the shift value for the correct CHMAP register bits */
121 shift = (channel & 0x07);
122
123 /* Read CHMAPx value, zero out channel's bits and write the new value */
124 REG(base_chmap) = (REG(base_chmap) & ~(0x0F << shift)) | (enc << shift);
125}
126/*---------------------------------------------------------------------------*/
127void
128udma_channel_enable(uint8_t channel)
129{
130 if(channel > UDMA_CONF_MAX_CHANNEL) {
131 return;
132 }
133
134 REG(UDMA_ENASET) |= 1 << channel;
135}
136/*---------------------------------------------------------------------------*/
137void
138udma_channel_disable(uint8_t channel)
139{
140 if(channel > UDMA_CONF_MAX_CHANNEL) {
141 return;
142 }
143
144 /* Writes of 0 have no effect, this no need for RMW */
145 REG(UDMA_ENACLR) = 1 << channel;
146}
147/*---------------------------------------------------------------------------*/
148void
150{
151 if(channel > UDMA_CONF_MAX_CHANNEL) {
152 return;
153 }
154
155 REG(UDMA_ALTSET) |= 1 << channel;
156}
157/*---------------------------------------------------------------------------*/
158void
160{
161 if(channel > UDMA_CONF_MAX_CHANNEL) {
162 return;
163 }
164
165 /* Writes of 0 have no effect, this no need for RMW */
166 REG(UDMA_ALTCLR) = 1 << channel;
167}
168/*---------------------------------------------------------------------------*/
169void
171{
172 if(channel > UDMA_CONF_MAX_CHANNEL) {
173 return;
174 }
175
176 REG(UDMA_PRIOSET) |= 1 << channel;
177}
178/*---------------------------------------------------------------------------*/
179void
181{
182 if(channel > UDMA_CONF_MAX_CHANNEL) {
183 return;
184 }
185
186 /* Writes of 0 have no effect, this no need for RMW */
187 REG(UDMA_PRIOCLR) = 1 << channel;
188}
189/*---------------------------------------------------------------------------*/
190void
192{
193 if(channel > UDMA_CONF_MAX_CHANNEL) {
194 return;
195 }
196
197 REG(UDMA_USEBURSTSET) |= 1 << channel;
198}
199/*---------------------------------------------------------------------------*/
200void
202{
203 if(channel > UDMA_CONF_MAX_CHANNEL) {
204 return;
205 }
206
207 /* Writes of 0 have no effect, this no need for RMW */
208 REG(UDMA_USEBURSTCLR) = 1 << channel;
209}
210/*---------------------------------------------------------------------------*/
211void
212udma_channel_mask_set(uint8_t channel)
213{
214 if(channel > UDMA_CONF_MAX_CHANNEL) {
215 return;
216 }
217
218 REG(UDMA_REQMASKSET) |= 1 << channel;
219}
220/*---------------------------------------------------------------------------*/
221void
222udma_channel_mask_clr(uint8_t channel)
223{
224 if(channel > UDMA_CONF_MAX_CHANNEL) {
225 return;
226 }
227
228 /* Writes of 0 have no effect, this no need for RMW */
229 REG(UDMA_REQMASKCLR) = 1 << channel;
230}
231/*---------------------------------------------------------------------------*/
232void
234{
235 if(channel > UDMA_CONF_MAX_CHANNEL) {
236 return;
237 }
238
239 REG(UDMA_SWREQ) |= 1 << channel;
240}
241/*---------------------------------------------------------------------------*/
242uint8_t
243udma_channel_get_mode(uint8_t channel)
244{
245 if(channel > UDMA_CONF_MAX_CHANNEL) {
246 return 0;
247 }
248
249 return (channel_config[channel].ctrl_word & 0x07);
250}
251/*---------------------------------------------------------------------------*/
252void
253udma_isr()
254{
255 /* Simply clear Channel interrupt status for now */
257}
258/*---------------------------------------------------------------------------*/
259void
260udma_err_isr()
261{
262 /* Stub Implementation, just clear the error flag */
263 REG(UDMA_ERRCLR) = 1;
264}
265/*---------------------------------------------------------------------------*/
266
267/** @} */
Header file for the cc2538 devices definitions.
@ UDMA_ERR_IRQn
µDMA Error Interrupt
Definition cc2538_cm3.h:107
@ UDMA_SW_IRQn
µDMA Software Interrupt
Definition cc2538_cm3.h:106
#define CC2538_DEV_RLSRAM_ADDR
Regular-leakage SRAM address.
Definition cc2538-dev.h:108
bool udma_is_valid_source_address(uintptr_t source_address)
Checks if data can be DMAed from the given address.
Definition udma.c:59
void udma_set_channel_dst(uint8_t channel, uint32_t dst_end)
Sets the channel's destination address.
Definition udma.c:88
void udma_init()
Initialise the uDMA driver.
Definition udma.c:65
void udma_channel_mask_set(uint8_t channel)
Disable peripheral triggers for a uDMA channel.
Definition udma.c:212
#define UDMA_ERRCLR
DMA bus error clear.
Definition udma.h:80
void udma_channel_enable(uint8_t channel)
Enables a uDMA channel.
Definition udma.c:128
#define UDMA_ALTCLR
DMA channel primary alternate clear.
Definition udma.h:77
uint8_t udma_channel_get_mode(uint8_t channel)
Retrieve the current mode for a channel.
Definition udma.c:243
void udma_channel_sw_request(uint8_t channel)
Generate a software trigger to start a transfer.
Definition udma.c:233
void udma_channel_use_burst(uint8_t channel)
Configure a channel to only use burst transfers.
Definition udma.c:191
#define UDMA_CFG
DMA configuration.
Definition udma.h:65
#define UDMA_PRIOCLR
DMA channel priority clear.
Definition udma.h:79
#define UDMA_USEBURSTCLR
DMA channel useburst clear.
Definition udma.h:71
#define UDMA_PRIOSET
DMA channel priority set.
Definition udma.h:78
void udma_channel_disable(uint8_t channel)
Disables a uDMA channel.
Definition udma.c:138
#define UDMA_SWREQ
DMA channel software request.
Definition udma.h:69
void udma_channel_prio_set_high(uint8_t channel)
Set a uDMA channel to high priority.
Definition udma.c:170
void udma_channel_mask_clr(uint8_t channel)
Enable peripheral triggers for a uDMA channel.
Definition udma.c:222
void udma_set_channel_control_word(uint8_t channel, uint32_t ctrl)
Configure the channel's control word.
Definition udma.c:98
#define UDMA_ENASET
DMA channel enable set.
Definition udma.h:74
#define UDMA_USEBURSTSET
DMA channel useburst set.
Definition udma.h:70
#define UDMA_REQMASKCLR
DMA channel request mask clear.
Definition udma.h:73
#define UDMA_CHIS_CHIS
Channel [n] interrupt status.
Definition udma.h:221
#define UDMA_CHIS
DMA channel interrupt status.
Definition udma.h:82
#define UDMA_ALTSET
DMA channel primary alternate set.
Definition udma.h:76
void udma_set_channel_assignment(uint8_t channel, uint8_t enc)
Choose an encoding for a uDMA channel.
Definition udma.c:108
#define UDMA_CHMAP0
DMA channel map select 0.
Definition udma.h:83
#define UDMA_REQMASKSET
DMA channel request mask set.
Definition udma.h:72
void udma_channel_use_single(uint8_t channel)
Configure a channel to use single as well as burst requests.
Definition udma.c:201
#define UDMA_ENACLR
DMA channel enable clear.
Definition udma.h:75
#define UDMA_CTLBASE
DMA channel control base pointer.
Definition udma.h:66
void udma_channel_use_primary(uint8_t channel)
Use the primary control data structure for a channel.
Definition udma.c:159
void udma_channel_prio_set_default(uint8_t channel)
Set a uDMA channel to default priority.
Definition udma.c:180
void udma_set_channel_src(uint8_t channel, uint32_t src_end)
Sets the channels source address.
Definition udma.c:78
void udma_channel_use_alternate(uint8_t channel)
Use the alternate control data structure for a channel.
Definition udma.c:149
#define UDMA_CFG_MASTEN
Controller master enable.
Definition udma.h:102
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...