PIC24 Support Libraries
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
dma_example.c
Go to the documentation of this file.
1 /*
2  * "Copyright (c) 2008 Robert B. Reese, Bryan A. Jones, J. W. Bruce ("AUTHORS")"
3  * All rights reserved.
4  * (R. Reese, reese_AT_ece.msstate.edu, Mississippi State University)
5  * (B. A. Jones, bjones_AT_ece.msstate.edu, Mississippi State University)
6  * (J. W. Bruce, jwbruce_AT_ece.msstate.edu, Mississippi State University)
7  *
8  * Permission to use, copy, modify, and distribute this software and its
9  * documentation for any purpose, without fee, and without written agreement is
10  * hereby granted, provided that the above copyright notice, the following
11  * two paragraphs and the authors appear in all copies of this software.
12  *
13  * IN NO EVENT SHALL THE "AUTHORS" BE LIABLE TO ANY PARTY FOR
14  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
15  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE "AUTHORS"
16  * HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
17  *
18  * THE "AUTHORS" SPECIFICALLY DISCLAIMS ANY WARRANTIES,
19  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20  * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
21  * ON AN "AS IS" BASIS, AND THE "AUTHORS" HAS NO OBLIGATION TO
22  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
23  *
24  * Please maintain this header in its entirety when copying/modifying
25  * these files.
26  *
27  *
28  */
29 #include "pic24_all.h"
30 
31 /** \file
32 DMA Example: Uses DMA in ping-pong mode to
33 capture data from the UART, write it to the
34 24LC515 EEPROM.
35 */
36 
37 #define EEPROM 0xA0 //LC515 address assuming both address pins tied low.
38 #define BLKSIZE 64
39 
40 //Assumes WDT is configured for longer than EEPROM write time
41 void waitForWriteCompletion(uint8_t u8_i2cAddr) {
42  uint8_t u8_ack, u8_savedSWDTEN;
43  u8_savedSWDTEN = _SWDTEN;
44  _SWDTEN = 1; //enable WDT so that do not get stuck in infinite loop!
45  u8_i2cAddr = I2C_WADDR(u8_i2cAddr); //write operation, R/W# = 0;
46  do {
47  startI2C1();
48  u8_ack = putNoAckCheckI2C1(u8_i2cAddr);
49  stopI2C1();
50  } while (u8_ack == I2C_NAK);
51  _SWDTEN = u8_savedSWDTEN; //restore WDT to original state
52 }
53 
54 //this version just expects a block of 64 data bytes
55 void memWriteLC515(uint8_t u8_i2cAddr, uint16_t u16_MemAddr, uint8_t *pu8_buf) {
56  uint8_t u8_AddrLo, u8_AddrHi;
57  uint16_t u16_i;
58  u8_AddrLo = u16_MemAddr & 0x00FF;
59  u8_AddrHi = (u16_MemAddr >> 8);
60  if (u16_MemAddr & 0x8000) {
61  // if MSB set , set block select bit
62  u8_i2cAddr = u8_i2cAddr | 0x08;
63  }
64  waitForWriteCompletion(u8_i2cAddr);
65  //write the data to the EEPROM
66  startI2C1();
67  putI2C1(I2C_WADDR(u8_i2cAddr));
68  putI2C1(u8_AddrHi);
69  putI2C1(u8_AddrLo);
70  for (u16_i=0; u16_i < BLKSIZE; u16_i++) {
71  putI2C1(*pu8_buf);
72  pu8_buf++;
73  }
74  stopI2C1();
75 }
76 
77 void memReadLC515(uint8_t u8_i2cAddr, uint16_t u16_MemAddr, uint8_t *pu8_buf) {
78 
79  uint8_t u8_AddrLo, u8_AddrHi;
80 
81  u8_AddrLo = u16_MemAddr & 0x00FF;
82  u8_AddrHi = (u16_MemAddr >> 8);
83 
84  if (u16_MemAddr & 0x8000) {
85  // if MSB set , set block select bit
86  u8_i2cAddr = u8_i2cAddr | 0x08;
87  }
88  waitForWriteCompletion(u8_i2cAddr);
89  //set address counter
90  write2I2C1(u8_i2cAddr,u8_AddrHi, u8_AddrLo);
91  //read data
92  readNI2C1(u8_i2cAddr,pu8_buf, BLKSIZE);
93 }
94 
95 #define DMA_TRANSFER_SIZE BLKSIZE
96 //DMA buffers
97 uint8_t au8_bufferA[DMA_TRANSFER_SIZE] __attribute__((space(dma)));
98 uint8_t au8_bufferB[DMA_TRANSFER_SIZE] __attribute__((space(dma)));
99 //some one-bit flags
100 typedef struct tagFLAGBITS {
101 unsigned u1_activeBuffer:
102  1;
103 unsigned u1_writeFlag:
104  1;
105 } FLAGBITS;
106 volatile FLAGBITS flags;
107 
108 void configDMA0() {
109  DMA0PAD = (unsigned int) &U1RXREG; //peripheral address to read
110  DMA0REQ = DMA_IRQ_U1RX; //source from UART1 RX
111  _U1RXIF = 0; //clear the UART RX IF flag
112 //set up ping pong buffer registers
113  DMA0STA = __builtin_dmaoffset(au8_bufferA);
114  DMA0STB = __builtin_dmaoffset(au8_bufferB);
115 //setup transfer size
116  DMA0CNT = DMA_TRANSFER_SIZE -1;
117  DMA0CON = //configure and enable the module Module
118  (DMA_MODULE_ON |
119  DMA_SIZE_BYTE |
120  DMA_DIR_READ_PERIPHERAL |
121  DMA_INTERRUPT_FULL |
122  DMA_NULLW_OFF |
123  DMA_AMODE_REGISTER_POSTINC |
124  DMA_MODE_CONTINUOUS_PING_PONG);
125 //enable the UART1RX Error interrupt
126  _U1EIF = 0;
127  _U1EIP = 1;
128  _U1EIE = 1;
129 //enable DMA channel 0 interrupt
130  _DMA0IF = 0;
131  _DMA0IP = 2;
132  _DMA0IE = 1;
133 }
134 
135 //UART error interrupt, need this with DMA since DMA does not check for errors.
136 void _ISRFAST _U1ErrInterrupt(void) {
137  _U1EIF = 0; //clear the UART1 Error flag
139 }
140 
141 //interrupted when a ping-pong buffer is full
142 void _ISRFAST _DMA0Interrupt(void) {
143  _DMA0IF = 0;
144  flags.u1_activeBuffer = !flags.u1_activeBuffer;
145  flags.u1_writeFlag = 1;
146 }
147 
148 int main (void) {
149  uint8_t au8_eepromBuf[BLKSIZE]; //holds read data from EEPROM
150  uint16_t u16_MemAddr;
151  uint8_t u8_mode, u8_pause;
152  configBasic(HELLO_MSG);
153  configI2C1(400); //configure I2C for 400 KHz
154  outString("\nEnter 'w' for write mode, anything else reads: ");
155  u8_mode = inCharEcho();
156  outString("\n");
157  u16_MemAddr = 0; //start at location 0 in memory
158  u8_pause = 0;
159  while (1) {
160  uint8_t u8_i;
161  if (u8_mode == 'w') {
162  configDMA0();
163  while (1) {
164  if (flags.u1_writeFlag) reportError("DMA overflow!\n");
165  while (!flags.u1_writeFlag) doHeartbeat();
166  flags.u1_writeFlag = 0;
167  if (flags.u1_activeBuffer)
168  memWriteLC515(EEPROM,u16_MemAddr,au8_bufferA);
169  else
170  memWriteLC515(EEPROM,u16_MemAddr,au8_bufferB);
171  u16_MemAddr = u16_MemAddr +64;
172  outString("*");
173  }//end while(1), press reset to escape
174  } else {
175  while (1) {
176  if (u8_pause) {
177  inChar(); //get a character
178  u8_pause = 0;
179  }
180  memReadLC515(EEPROM,u16_MemAddr,au8_eepromBuf); // do read
181  for (u8_i = 0; u8_i< 64; u8_i++) outChar(au8_eepromBuf[u8_i]);
182  if (isCharReady()) {
183  inChar();
184  u8_pause = 1;
185  }
186  u16_MemAddr = u16_MemAddr + 64;
187  }//end while(1) read mode, press reset to escape
188  }//end else
189  }//end while(1) main
190 }//end main