PIC24 Support Libraries
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ecan_example_fifo.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 #include <stdio.h>
31 
32 /** \file
33 Illustrate CAN transmit, receive. Uses a FIFO for RX receive, and
34 uses a standard data frame.
35 */
36 
37 /**
38 Clock config taken from the PIC24H FRM ECAN datasheet (DS70226B, Example 21-9),
39 Produces data rate of 1 Mbps assuming FCY = 40 MHz, quanta = 20, Prescale = 2.
40 **/
41 
42 void configBaudECAN1(void) { //set baud rate
43 #if FCY == 40000000L
44 // FCAN = FCY = 40 MHz. TQ = 20. Prescale = 2, Data Rate = FCAN/(TQ * pre) = 40MHz/40 = 1 MHz.
45  C1CTRL1bits.CANCKS = ECAN_FCAN_IS_FCY; // CANCKS = 1, sets FCAN = FCY = 40 MHz
46 //20 TQ for a bit time. 20 = Sync(1) + Seg1 (8) + Seg2 (6) + Prop seg (5)
47  C1CFG2 = ECAN_NO_WAKEUP |
48  ECAN_SAMPLE_3TIMES | //sample three times at sample point
49  ECAN_SEG1PH_8TQ | //seg1 = 8 TQ
50  ECAN_SEG2_PROGRAMMABLE | //seg2 is programmable
51  ECAN_SEG2PH_6TQ | //seg2 = 6 TQ
52  ECAN_PRSEG_5TQ; //propagation delay segment = 5 TQ
53 
54  C1CFG1 = ECAN_SYNC_JUMP_4 | //use maximum sync jump width
55  ECAN_PRE_2x1; //prescalers to 2x1
56 #else
57 #warning ECAN module not configured! Edit function configECAN1()
58 #endif
59 }
60 
61 #define NUM_TX_BUFS 1 //reserve 1 for TX
62 #define NUM_BUFS 8 //make this a power of 2 for the alignment to work or enter alignment manually
63 ECANMSG msgBuf[NUM_BUFS] __attribute__((space(dma),aligned(NUM_BUFS*16)));
64 
65 //base message ID
66 #define MSG_ID 0x7A0 //arbitrary choice for 11-bit messsage ID
67 
68 //configure DMA transmit buffer
69 void configDMA0(void) {
70  DMACS0 = 0;
71  _DMA0IF = 0;
72  DMA0PAD = (unsigned int) &C1TXD;
73  DMA0REQ = DMA_IRQ_ECAN1TX;
74  DMA0STA = __builtin_dmaoffset(msgBuf);
75  DMA0CNT = 7; //8 words in ECANMSG
76  DMA0CON = //configure and enable the module Module
77  (DMA_MODULE_ON |
78  DMA_SIZE_WORD |
79  DMA_DIR_WRITE_PERIPHERAL |
80  DMA_INTERRUPT_FULL |
81  DMA_NULLW_OFF |
82  DMA_AMODE_PERIPHERAL_INDIRECT |
83  DMA_MODE_CONTINUOUS);
84 }
85 
86 //configure DMA receive buffer
87 void configDMA1(void) {
88  _DMA1IF = 0;
89  DMA1PAD = (unsigned int) &C1RXD;
90  DMA1REQ = DMA_IRQ_ECAN1RX;
91  DMA1STA = __builtin_dmaoffset(msgBuf);
92  DMA1CNT = 7; //8 words in ECANMSG
93  DMA1CON = //configure and enable the module Module
94  (DMA_MODULE_ON |
95  DMA_SIZE_WORD |
96  DMA_DIR_READ_PERIPHERAL |
97  DMA_INTERRUPT_FULL |
98  DMA_NULLW_OFF |
99  DMA_AMODE_PERIPHERAL_INDIRECT |
100  DMA_MODE_CONTINUOUS);
101 
102 }
103 
104 #define RX_BUFFER_ID 15 //a value of 15 means to use a FIFO for RX
105 
106 void configECAN1() {
107  uint8_t u8_i;
108  CHANGE_MODE_ECAN1(ECAN_MODE_CONFIGURE);
109  configBaudECAN1();
110  C1FCTRL = ECAN_FIFO_START_AREA_1 | ECAN_DMA_BUF_SIZE_8 ;
111 //use Filter 0 with Mask 0
112  configRxFilterECAN1(0, MSG_ID, ECAN_MATCH_SID, RX_BUFFER_ID, 0);
113  configRxMaskECAN1(0, 0x7FC, 0, 0); //check all but last two bits
114  clrRxFullOvfFlagsECAN1(); //clear all RX full, overflow flags.
115 
116 //first 8 buffs must be configured as either TX or TX
117  for (u8_i = 0; u8_i<8; u8_i++) {
118  if (u8_i < NUM_TX_BUFS)
119  configTxRxBufferECAN1(u8_i,ECAN_TX_BUFF,3);
120  else
121  configTxRxBufferECAN1(u8_i,ECAN_RX_BUFF,3);
122  }
123  configDMA0(); //do DMA config after ECAN has been initialized
124  configDMA1();
125  CHANGE_MODE_ECAN1(ECAN_MODE_NORMAL);
126 }
127 
128 uint32_t rrot32(uint32_t u32_x) {
129  if (u32_x & 0x1) {
130  u32_x = u32_x >> 1;
131  u32_x = u32_x | 0x8000;
132  } else u32_x = u32_x >> 1;
133  return u32_x;
134 }
135 
136 int main (void) {
137  uint32_t u32_out0, u32_out1, u32_in0, u32_in1;
138  uint8_t rx_buff_id, u8_cnt;
139 
140  configBasic(HELLO_MSG);
141  configECAN1();
142  CHANGE_MODE_ECAN1(ECAN_MODE_LOOPBACK); //loopback to ourself for a test.
143  u32_out0 = 0xFEDCBA98;
144  u32_out1 = 0x76543210;
145  u8_cnt = 0;
146  while (1) {
147  DELAY_MS(500);
148  msgBuf[0].data.u32[0] = u32_out0; //save in CAN message
149  msgBuf[0].data.u32[1] = u32_out1;
150  //format Buffer 0 for TX with SID=MSG_ID, data length = 8 bytes
151  formatStandardDataFrameECAN(&msgBuf[0], MSG_ID+u8_cnt, 8);
152  startTxECAN1(0); //start transmission of buffer 0
153  while (getTxInProgressECAN1(0)) {
154  doHeartbeat(); //wait for transmission to end.
155  }
156  _DMA0IF = 1;
157  DELAY_MS(10); //delay for reception
158  if (!_DMA1IF) {
159  printf("Message ID 0x%X rejected by acceptance filter.\n",MSG_ID+u8_cnt);
160  } else {
161  _DMA1IF = 0; //RX message accepted
162  rx_buff_id = GET_FIFO_READBUFFER_ECAN1();
163  u32_in0 = msgBuf[rx_buff_id].data.u32[0];
164  u32_in1 = msgBuf[rx_buff_id].data.u32[1];
165  printf("Rx Buff: %d. Msg ID: 0x%X, Out: 0x%lx%lx, In: 0x%lx%lx\n",
166  rx_buff_id, msgBuf[rx_buff_id].w0.SID,u32_out0, u32_out1, u32_in0, u32_in1 );
167  clrRxFullFlagECAN1(rx_buff_id);
168  }
169  u32_out0 = rrot32(u32_out0);
170  u32_out1 = rrot32(u32_out1);
171  u8_cnt++;
172  if (u8_cnt == 8) u8_cnt = 0;
173  }//end while
174 }//end main