dma.c

Go to the documentation of this file.
00001 /**
00002  * \file
00003  *         DMA driver
00004  * \author
00005  *         Original: Martti Huttunen <martti@sensinode.com>
00006  *         Port: Zach Shelby <zach@sensinode.com>
00007  *
00008  *         bankable DMA functions
00009  */
00010 
00011 #include <stdio.h>
00012 
00013 #include "contiki.h"
00014 #include "banked.h"
00015 
00016 #include "dev/dma.h"
00017 #include "cc2430_sfr.h"
00018 
00019 dma_config_t dma_conf[4];
00020 struct process * dma_callback[4];
00021 
00022 /*---------------------------------------------------------------------------*/
00023 void
00024 dma_init(void) __banked
00025 {
00026   uint16_t tmp_ptr;
00027   memset(dma_conf, 0, 4*sizeof(dma_config_t));
00028   for(tmp_ptr = 0; tmp_ptr < 4; tmp_ptr++) {
00029     dma_callback[tmp_ptr] = 0;
00030   }
00031   tmp_ptr = (uint16_t) &(dma_conf[0]);
00032 
00033   DMA1CFGH = tmp_ptr >> 8;
00034   DMA1CFGL = tmp_ptr;
00035   IEN1_DMAIE = 1;       /*enable DMA interrupts*/
00036 }
00037 /*---------------------------------------------------------------------------*/
00038 #ifdef HAVE_DMA
00039 /**
00040  * Configure a DMA channel except word mode.
00041  *
00042  * \param channel channel ID;
00043  * \param src source address;
00044  * \param src_inc source increment mode;
00045  * \param dst dest address;
00046  * \param dst_inc dest increment mode;
00047  * \param length maximum length;
00048  * \param vlen_mode variable length mode;
00049  * \param t_mode DMA transfer mode;
00050  * \param trigger DMA trigger;
00051  * \param proc process that is upon interrupt;
00052  *
00053  * \return Handle to DMA channel
00054  * \return 0 invalid channel
00055  */
00056 /*  IMPLEMENTED dma_config as macro to reduce stack/code space
00057 xDMAHandle
00058 dma_config(uint8_t channel, void *src, dma_inc_t src_inc, void *dst, dma_inc_t dst_inc,
00059            uint16_t length, dma_vlen_t vlen_mode, dma_type_t t_mode, dma_trigger_t trigger,
00060            struct process * proc) __banked
00061 {
00062   return dma_config2(channel,src,src_inc, dst, dst_inc, length, 0, vlen_mode, t_mode, trigger, proc);
00063 }
00064 */
00065 /*---------------------------------------------------------------------------*/
00066 /**
00067  * Configure a DMA channel.
00068  *
00069  * \param channel channel ID;
00070  * \param src source address;
00071  * \param src_inc source increment mode;
00072  * \param dst dest address;
00073  * \param dst_inc dest increment mode;
00074  * \param length maximum length;
00075  * \param word_mode set to 1 for 16-bits per transfer;
00076  * \param vlen_mode variable length mode;
00077  * \param t_mode DMA transfer mode;
00078  * \param trigger DMA trigger;
00079  * \param proc process that is upon interrupt;
00080  *
00081  * \return Handle to DMA channel
00082  * \return 0 invalid channel
00083  */
00084 xDMAHandle
00085 dma_config2(uint8_t channel, void *src, dma_inc_t src_inc, void *dst, dma_inc_t dst_inc,
00086            uint16_t length, uint8_t word_mode, dma_vlen_t vlen_mode, dma_type_t t_mode, dma_trigger_t trigger,
00087            struct process * proc) __banked
00088 {
00089   unsigned char jj;
00090   if((!channel) || (channel > 4)) {
00091     return 0;
00092   }
00093 
00094   DMAIRQ &= ~(1 << channel);
00095   
00096   channel--;
00097   
00098   dma_conf[channel].src_h = ((uint16_t) src) >> 8;
00099   dma_conf[channel].src_l = ((uint16_t) src);
00100   dma_conf[channel].dst_h = ((uint16_t) dst) >> 8;
00101   dma_conf[channel].dst_l = ((uint16_t) dst);
00102   dma_conf[channel].len_h = vlen_mode + (length >> 8);
00103   dma_conf[channel].len_l = length;
00104   dma_conf[channel].t_mode = ((word_mode&0x1)<<7) | (t_mode << 5) | trigger;
00105   dma_conf[channel].addr_mode = (src_inc << 6) + (dst_inc << 4) + 2; /*DMA has priority*/
00106   
00107   /*Callback is defined*/
00108   if(proc) {
00109     dma_conf[channel].addr_mode |= 8;   /*set IRQMASK*/
00110     IEN1_DMAIE = 1;     /*enable DMA interrupts*/
00111   }
00112   dma_callback[channel] = proc;
00113   
00114   return (xDMAHandle)channel + 1;
00115 }
00116 /*---------------------------------------------------------------------------*/
00117 /**
00118  * Arm a DMA channel.
00119  *
00120  * \param channel channel handle;
00121  *
00122  * \return pdTRUE
00123  * \return pdFALSE      semaphore creation failed
00124  */
00125 uint8_t
00126 dma_arm(xDMAHandle channel) __banked
00127 {
00128   uint8_t ch_id = ((uint8_t)channel);
00129   if(!ch_id || (ch_id > 4)) {
00130     return 0;
00131   }
00132   DMAARM |= (1 << ch_id);
00133   return 1;
00134 }
00135 /*---------------------------------------------------------------------------*/
00136 /**
00137  * Stop a DMA channel.
00138  *
00139  * \param channel channel handle;
00140  *
00141  * \return pdTRUE
00142  * \return pdFALSE      semaphore creation failed
00143  */
00144 uint8_t
00145 dma_abort(xDMAHandle channel) __banked
00146 {
00147   uint8_t ch_id = ((uint8_t) channel);
00148   if(!ch_id || (ch_id > 4)) {
00149     return 0;
00150   }
00151   DMAARM = 0x80 + (1 << ch_id); /*ABORT + channel bit*/
00152   return 1;
00153 }
00154 /*---------------------------------------------------------------------------*/
00155 /**
00156  * Trigger a DMA channel.
00157  *
00158  * \param channel channel handle;
00159  *
00160  * \return pdTRUE
00161  * \return pdFALSE      semaphore creation failed
00162  */
00163 uint8_t
00164 dma_trigger(xDMAHandle channel) __banked
00165 {
00166   uint8_t ch_id = ((uint8_t) channel);
00167   if(!ch_id || (ch_id > 4)) {
00168     return 0;
00169   }
00170   DMAREQ |= (1 << ch_id);
00171   return 1;
00172 }
00173 /*---------------------------------------------------------------------------*/
00174 /**
00175  * Get DMA state.
00176  *
00177  * \param channel channel handle;
00178  *
00179  * \return pdTRUE       active
00180  * \return pdFALSE      not active
00181  */
00182 uint8_t
00183 dma_state(xDMAHandle channel) __banked
00184 {
00185   uint8_t ch_id = ((uint8_t)channel);
00186   if(!ch_id || (ch_id > 4)) {
00187     return 0;
00188   }
00189   if((DMAIRQ &(1 << ch_id)) == 0) {
00190     return 1;
00191   }
00192   return 0;
00193 }
00194 /*---------------------------------------------------------------------------*/
00195 void
00196 dma_config_print(xDMAHandle channel) __banked
00197 {
00198   uint8_t ch_id = channel - 1;
00199   
00200   if(ch_id > 4) {
00201     return;
00202   }
00203   
00204   printf("DMA channel %d @ %x %x ", ch_id, (uint16_t) &(dma_conf[ch_id]) >> 8, (uint16_t) &(dma_conf[ch_id]) & 0xFF);
00205   {
00206     uint8_t i;
00207     uint8_t *ptr = (uint8_t *)&(dma_conf[ch_id]);
00208     for(i = 0; i< 8; i++) {
00209       if(i != 0) {
00210         printf(":%02x", *ptr++);
00211       }
00212     }
00213     printf("\n");
00214   }
00215 }
00216 #endif

Generated on Mon Apr 11 14:23:38 2011 for Contiki 2.5 by  doxygen 1.6.1