Contiki 2.5
dma.c
Go to the documentation of this file.
1 /**
2  * \file
3  * DMA driver
4  * \author
5  * Original: Martti Huttunen <martti@sensinode.com>
6  * Port: Zach Shelby <zach@sensinode.com>
7  *
8  * bankable DMA functions
9  */
10 
11 #include <stdio.h>
12 
13 #include "contiki.h"
14 #include "banked.h"
15 
16 #include "dev/dma.h"
17 #include "cc2430_sfr.h"
18 
19 dma_config_t dma_conf[4];
20 struct process * dma_callback[4];
21 
22 /*---------------------------------------------------------------------------*/
23 void
24 dma_init(void) __banked
25 {
26  uint16_t tmp_ptr;
27  memset(dma_conf, 0, 4*sizeof(dma_config_t));
28  for(tmp_ptr = 0; tmp_ptr < 4; tmp_ptr++) {
29  dma_callback[tmp_ptr] = 0;
30  }
31  tmp_ptr = (uint16_t) &(dma_conf[0]);
32 
33  DMA1CFGH = tmp_ptr >> 8;
34  DMA1CFGL = tmp_ptr;
35  IEN1_DMAIE = 1; /*enable DMA interrupts*/
36 }
37 /*---------------------------------------------------------------------------*/
38 #ifdef HAVE_DMA
39 /**
40  * Configure a DMA channel except word mode.
41  *
42  * \param channel channel ID;
43  * \param src source address;
44  * \param src_inc source increment mode;
45  * \param dst dest address;
46  * \param dst_inc dest increment mode;
47  * \param length maximum length;
48  * \param vlen_mode variable length mode;
49  * \param t_mode DMA transfer mode;
50  * \param trigger DMA trigger;
51  * \param proc process that is upon interrupt;
52  *
53  * \return Handle to DMA channel
54  * \return 0 invalid channel
55  */
56 /* IMPLEMENTED dma_config as macro to reduce stack/code space
57 xDMAHandle
58 dma_config(uint8_t channel, void *src, dma_inc_t src_inc, void *dst, dma_inc_t dst_inc,
59  uint16_t length, dma_vlen_t vlen_mode, dma_type_t t_mode, dma_trigger_t trigger,
60  struct process * proc) __banked
61 {
62  return dma_config2(channel,src,src_inc, dst, dst_inc, length, 0, vlen_mode, t_mode, trigger, proc);
63 }
64 */
65 /*---------------------------------------------------------------------------*/
66 /**
67  * Configure a DMA channel.
68  *
69  * \param channel channel ID;
70  * \param src source address;
71  * \param src_inc source increment mode;
72  * \param dst dest address;
73  * \param dst_inc dest increment mode;
74  * \param length maximum length;
75  * \param word_mode set to 1 for 16-bits per transfer;
76  * \param vlen_mode variable length mode;
77  * \param t_mode DMA transfer mode;
78  * \param trigger DMA trigger;
79  * \param proc process that is upon interrupt;
80  *
81  * \return Handle to DMA channel
82  * \return 0 invalid channel
83  */
84 xDMAHandle
85 dma_config2(uint8_t channel, void *src, dma_inc_t src_inc, void *dst, dma_inc_t dst_inc,
86  uint16_t length, uint8_t word_mode, dma_vlen_t vlen_mode, dma_type_t t_mode, dma_trigger_t trigger,
87  struct process * proc) __banked
88 {
89  unsigned char jj;
90  if((!channel) || (channel > 4)) {
91  return 0;
92  }
93 
94  DMAIRQ &= ~(1 << channel);
95 
96  channel--;
97 
98  dma_conf[channel].src_h = ((uint16_t) src) >> 8;
99  dma_conf[channel].src_l = ((uint16_t) src);
100  dma_conf[channel].dst_h = ((uint16_t) dst) >> 8;
101  dma_conf[channel].dst_l = ((uint16_t) dst);
102  dma_conf[channel].len_h = vlen_mode + (length >> 8);
103  dma_conf[channel].len_l = length;
104  dma_conf[channel].t_mode = ((word_mode&0x1)<<7) | (t_mode << 5) | trigger;
105  dma_conf[channel].addr_mode = (src_inc << 6) + (dst_inc << 4) + 2; /*DMA has priority*/
106 
107  /*Callback is defined*/
108  if(proc) {
109  dma_conf[channel].addr_mode |= 8; /*set IRQMASK*/
110  IEN1_DMAIE = 1; /*enable DMA interrupts*/
111  }
112  dma_callback[channel] = proc;
113 
114  return (xDMAHandle)channel + 1;
115 }
116 /*---------------------------------------------------------------------------*/
117 /**
118  * Arm a DMA channel.
119  *
120  * \param channel channel handle;
121  *
122  * \return pdTRUE
123  * \return pdFALSE semaphore creation failed
124  */
125 uint8_t
126 dma_arm(xDMAHandle channel) __banked
127 {
128  uint8_t ch_id = ((uint8_t)channel);
129  if(!ch_id || (ch_id > 4)) {
130  return 0;
131  }
132  DMAARM |= (1 << ch_id);
133  return 1;
134 }
135 /*---------------------------------------------------------------------------*/
136 /**
137  * Stop a DMA channel.
138  *
139  * \param channel channel handle;
140  *
141  * \return pdTRUE
142  * \return pdFALSE semaphore creation failed
143  */
144 uint8_t
145 dma_abort(xDMAHandle channel) __banked
146 {
147  uint8_t ch_id = ((uint8_t) channel);
148  if(!ch_id || (ch_id > 4)) {
149  return 0;
150  }
151  DMAARM = 0x80 + (1 << ch_id); /*ABORT + channel bit*/
152  return 1;
153 }
154 /*---------------------------------------------------------------------------*/
155 /**
156  * Trigger a DMA channel.
157  *
158  * \param channel channel handle;
159  *
160  * \return pdTRUE
161  * \return pdFALSE semaphore creation failed
162  */
163 uint8_t
164 dma_trigger(xDMAHandle channel) __banked
165 {
166  uint8_t ch_id = ((uint8_t) channel);
167  if(!ch_id || (ch_id > 4)) {
168  return 0;
169  }
170  DMAREQ |= (1 << ch_id);
171  return 1;
172 }
173 /*---------------------------------------------------------------------------*/
174 /**
175  * Get DMA state.
176  *
177  * \param channel channel handle;
178  *
179  * \return pdTRUE active
180  * \return pdFALSE not active
181  */
182 uint8_t
183 dma_state(xDMAHandle channel) __banked
184 {
185  uint8_t ch_id = ((uint8_t)channel);
186  if(!ch_id || (ch_id > 4)) {
187  return 0;
188  }
189  if((DMAIRQ &(1 << ch_id)) == 0) {
190  return 1;
191  }
192  return 0;
193 }
194 /*---------------------------------------------------------------------------*/
195 void
196 dma_config_print(xDMAHandle channel) __banked
197 {
198  uint8_t ch_id = channel - 1;
199 
200  if(ch_id > 4) {
201  return;
202  }
203 
204  printf("DMA channel %d @ %x %x ", ch_id, (uint16_t) &(dma_conf[ch_id]) >> 8, (uint16_t) &(dma_conf[ch_id]) & 0xFF);
205  {
206  uint8_t i;
207  uint8_t *ptr = (uint8_t *)&(dma_conf[ch_id]);
208  for(i = 0; i< 8; i++) {
209  if(i != 0) {
210  printf(":%02x", *ptr++);
211  }
212  }
213  printf("\n");
214  }
215 }
216 #endif