]> git.sur5r.net Git - freertos/blob
4aa58653965f6d53a8ca3394c58d9e7f3c57949d
[freertos] /
1 /**********************************************************************\r
2 * $Id$          lpc18xx_can.c           2011-06-02\r
3 *//**\r
4 * @file         lpc18xx_can.c\r
5 * @brief        Contains all functions support for C CAN firmware library\r
6 *                       on LPC18xx\r
7 * @version      1.0\r
8 * @date         02. June. 2011\r
9 * @author       NXP MCU SW Application Team\r
10 *\r
11 * Copyright(C) 2011, NXP Semiconductor\r
12 * All rights reserved.\r
13 *\r
14 ***********************************************************************\r
15 * Software that is described herein is for illustrative purposes only\r
16 * which provides customers with programming information regarding the\r
17 * products. This software is supplied "AS IS" without any warranties.\r
18 * NXP Semiconductors assumes no responsibility or liability for the\r
19 * use of the software, conveys no license or title under any patent,\r
20 * copyright, or mask work right to the product. NXP Semiconductors\r
21 * reserves the right to make changes in the software without\r
22 * notification. NXP Semiconductors also make no representation or\r
23 * warranty that such application will be suitable for the specified\r
24 * use without further testing or modification.\r
25 **********************************************************************/\r
26 \r
27 /* Peripheral group ----------------------------------------------------------- */\r
28 /** @addtogroup C_CAN\r
29  * @{\r
30  */\r
31 \r
32 /* Includes ------------------------------------------------------------------- */\r
33 #include "LPC18xx.h"\r
34 #include "lpc18xx_can.h"\r
35 #include "lpc18xx_cgu.h"\r
36 \r
37 /* If this source file built with example, the LPC18xx FW library configuration\r
38  * file in each example directory ("lpc18xx_libcfg.h") must be included,\r
39  * otherwise the default FW library configuration file must be included instead\r
40  */\r
41 #ifdef __BUILD_WITH_EXAMPLE__\r
42 #include "lpc18xx_libcfg.h"\r
43 #else\r
44 #include "lpc18xx_libcfg_default.h"\r
45 #endif /* __BUILD_WITH_EXAMPLE__ */\r
46 \r
47 #ifdef _C_CAN\r
48 \r
49 /* Private Macros ---------------------------------------------------------- */\r
50 #ifndef __GNUC__\r
51 /* Macro for reading and writing to CCAN IF registers */\r
52 #define CAN_IF_Read(reg, IFsel) (LPC_C_CAN0->##IFsel##_##reg)\r
53 #define CAN_IF_Write(reg, IFsel, val) (LPC_C_CAN0->##IFsel##_##reg=val)\r
54 \r
55 /* Macro for writing IF to specific RAM message object */\r
56 #define CAN_IF_readBuf(IFsel,msg) \\r
57   LPC_C_CAN0->##IFsel##_##CMDMSK_W=RD|MASK|ARB|CTRL|CLRINTPND|DATAA|DATAB; \\r
58   LPC_C_CAN0->##IFsel##_##CMDREQ=msg; \\r
59   while (LPC_C_CAN0->##IFsel##_##CMDREQ & IFCREQ_BUSY );\r
60 \r
61 /* Macro for reading specific RAM message object to IF */\r
62 #define CAN_IF_writeBuf(IFsel,msg) \\r
63   LPC_C_CAN0->##IFsel##_##CMDMSK_W=WR|MASK|ARB|CTRL|CLRINTPND|DATAA|DATAB; \\r
64   LPC_C_CAN0->##IFsel##_##CMDREQ=msg; \\r
65   while (LPC_C_CAN0->##IFsel##_##CMDREQ & IFCREQ_BUSY );\r
66 #else\r
67 #define CAN_IF_Read(reg, IFsel) (LPC_C_CAN0->IFsel##_##reg)\r
68 #define CAN_IF_Write(reg, IFsel, val) (LPC_C_CAN0->IFsel ## _ ## reg = val)\r
69 \r
70 /* Macro for writing IF to specific RAM message object */\r
71 #define CAN_IF_readBuf(IFsel,msg) \\r
72   LPC_C_CAN0->IFsel##_##CMDMSK_W=RD|MASK|ARB|CTRL|CLRINTPND|DATAA|DATAB; \\r
73   LPC_C_CAN0->IFsel##_##CMDREQ=msg; \\r
74   while (LPC_C_CAN0->IFsel##_##CMDREQ & IFCREQ_BUSY );\r
75 \r
76 /* Macro for reading specific RAM message object to IF */\r
77 #define CAN_IF_writeBuf(IFsel,msg) \\r
78   LPC_C_CAN0->IFsel##_##CMDMSK_W=WR|MASK|ARB|CTRL|CLRINTPND|DATAA|DATAB; \\r
79   LPC_C_CAN0->IFsel##_##CMDREQ=msg; \\r
80   while (LPC_C_CAN0->IFsel##_##CMDREQ & IFCREQ_BUSY );\r
81 #endif\r
82 \r
83 #define IF1     0\r
84 #define IF2     1\r
85 \r
86 #define CAN_STATUS_INTERRUPT      0x8000    /* 0x0001-0x0020 are the # of the message\r
87                                                                                     object */\r
88                                             /* 0x8000 is the status interrupt */\r
89 \r
90 /* CAN Message interface register definitions */\r
91 /* bit field of IF command request n register */\r
92 #define IFCREQ_BUSY               0x8000    /* 1 is writing is progress, cleared when\r
93                                             RD/WR done */\r
94 /* CAN CTRL register */\r
95 #define CTRL_INIT               (1 << 0)\r
96 #define CTRL_IE                 (1 << 1)\r
97 #define CTRL_SIE                (1 << 2)\r
98 #define CTRL_EIE                (1 << 3)\r
99 #define CTRL_DAR                (1 << 5)\r
100 #define CTRL_CCE                (1 << 6)\r
101 #define CTRL_TEST               (1 << 7)\r
102 \r
103 /* CAN Test register */\r
104 #define TEST_BASIC              (1 << 2)\r
105 #define TEST_SILENT             (1 << 3)\r
106 #define TEST_LBACK              (1 << 4)\r
107 \r
108 /* CAN Status register */\r
109 #define STAT_LEC                (0x7 << 0)\r
110 #define STAT_TXOK               (1 << 3)\r
111 #define STAT_RXOK               (1 << 4)\r
112 #define STAT_EPASS              (1 << 5)\r
113 #define STAT_EWARN              (1 << 6)\r
114 #define STAT_BOFF               (1 << 7)\r
115 \r
116 #define NO_ERR          0       // No Error\r
117 #define STUFF_ERR       1       // Stuff Error : More than 5 equal bits in a sequence have occurred in a part\r
118                                                 // of a received message where this is not allowed.\r
119 #define FORM_ERR        2       // Form Error : A fixed format part of a received frame has the wrong format.\r
120 #define ACK_ERR         3       // AckError : The message this CAN Core transmitted was not acknowledged\r
121                                                 // by another node.\r
122 #define BIT1_ERR        4       // Bit1Error : During the transmission of a message (with the exception of\r
123                                                 // the arbitration field), the device wanted to send a recessive level (bit of\r
124                                                 // logical value �1�), but the monitored bus value was dominant.\r
125 #define BIT0_ERR        5       // Bit0Error : During the transmission of a message (or acknowledge bit,\r
126                                                 // or active error flag, or overload flag), the device wanted to send a\r
127                                                 // LOW/dominant level (data or identifier bit logical value �0�), but the\r
128                                                 // monitored Bus value was HIGH/recessive. During busoff recovery this\r
129                                                 // status is set each time a\r
130                                                 // sequence of 11 HIGH/recessive bits has been monitored. This enables\r
131                                                 // the CPU to monitor the proceeding of the busoff recovery sequence\r
132                                                 // (indicating the bus is not stuck at LOW/dominant or continuously\r
133                                                 // disturbed).\r
134 #define CRC_ERR         6       // CRCError: The CRC checksum was incorrect in the message received.\r
135 \r
136 \r
137 /* bit field of IF command mask register */\r
138 #define DATAB           (1 << 0)   /* 1 is transfer data byte 4-7 to message object, 0 is not */\r
139 #define DATAA           (1 << 1)   /* 1 is transfer data byte 0-3 to message object, 0 is not */\r
140 #define NEWDAT          (1 << 2)   /* Clear NEWDAT bit in the message object */\r
141 #define CLRINTPND       (1 << 3)\r
142 #define CTRL            (1 << 4)   /* 1 is transfer the CTRL bit to the message object, 0 is not */\r
143 #define ARB                     (1 << 5)   /* 1 is transfer the ARB bits to the message object, 0 is not */\r
144 #define MASK            (1 << 6)   /* 1 is transfer the MASK bit to the message object, 0 is not */\r
145 #define WR                      (1 << 7)   /* 0 is READ, 1 is WRITE */\r
146 #define RD              0x0000\r
147 \r
148 /* bit field of IF mask 2 register */\r
149 #define MASK_MXTD       (1 << 15)     /* 1 extended identifier bit is used in the RX filter unit, 0 is not */\r
150 #define MASK_MDIR       (1 << 14)     /* 1 direction bit is used in the RX filter unit, 0 is not */\r
151 \r
152 /* bit field of IF identifier 2 register */\r
153 #define ID_MVAL         (1 << 15)     /* Message valid bit, 1 is valid in the MO handler, 0 is ignored */\r
154 #define ID_MTD          (1 << 14)     /* 1 extended identifier bit is used in the RX filter unit, 0 is not */\r
155 #define ID_DIR          (1 << 13)     /* 1 direction bit is used in the RX filter unit, 0 is not */\r
156 \r
157 /* bit field of IF message control register */\r
158 #define NEWD            (1 << 15)     /* 1 indicates new data is in the message buffer.  */\r
159 #define MLST            (1 << 14)     /* 1 indicates a message loss. */\r
160 #define INTP            (1 << 13)     /* 1 indicates message object is an interrupt source */\r
161 #define UMSK            (1 << 12)     /* 1 is to use the mask for the receive filter mask. */\r
162 #define TXIE            (1 << 11)     /* 1 is TX interrupt enabled */\r
163 #define RXIE            (1 << 10)     /* 1 is RX interrupt enabled */\r
164 \r
165 #if REMOTE_ENABLE\r
166         #define RMTEN           (1 << 9)  /* 1 is remote frame enabled */\r
167 #else\r
168         #define RMTEN           0\r
169 #endif\r
170 \r
171 #define TXRQ            (1 << 8)      /* 1 is TxRqst enabled */\r
172 #define EOB                     (1 << 7)      /* End of buffer, always write to 1 */\r
173 #define DLC                     0x000F        /* bit mask for DLC */\r
174 \r
175 #define ID_STD_MASK             0x07FF\r
176 #define ID_EXT_MASK             0x1FFFFFFF\r
177 #define DLC_MASK                0x0F\r
178 \r
179 /* Private Variables ---------------------------------------------------------- */\r
180 /* Statistics of all the interrupts */\r
181 /* Buss off status counter */\r
182 volatile uint32_t BOffCnt = 0;\r
183 /* Warning status counter.      At least one of the error counters\r
184  in the EML has reached the error warning limit of 96 */\r
185 volatile uint32_t EWarnCnt = 0;\r
186 /* More than 5 equal bits in a sequence in received message */\r
187 volatile uint32_t StuffErrCnt = 0;\r
188 /* Wrong format of fixed format part of a received frame */\r
189 volatile uint32_t FormErrCnt = 0;\r
190 /* Transmitted message not acknowledged. */\r
191 volatile uint32_t AckErrCnt = 0;\r
192 /* Send a HIGH/recessive level, but monitored LOW/dominant */\r
193 volatile uint32_t Bit1ErrCnt = 0;\r
194 /* Send a LOW/dominant level, but monitored HIGH/recessive */\r
195 volatile uint32_t Bit0ErrCnt = 0;\r
196 /* The CRC checksum was incorrect in the message received */\r
197 volatile uint32_t CRCErrCnt = 0;\r
198 /* Message object new data error counter */\r
199 volatile uint32_t ND1ErrCnt = 0;\r
200 \r
201 MSG_CB TX_cb, RX_cb;\r
202 \r
203 message_object can_buff[CAN_MSG_OBJ_MAX];\r
204 message_object recv_buff;\r
205 \r
206 #if CAN_DEBUG\r
207 uint32_t CANStatusLog[100];\r
208 uint32_t CANStatusLogCount = 0;\r
209 #endif\r
210 \r
211 //#ifdef __GNUC__\r
212 //uint32_t CAN_IF_Read(uint32_t reg,uint32_t IFsel){\r
213 //      if(IFsel == IF1){\r
214 //              return (LPC_C_CAN0->IF1_reg);\r
215 //      }else{\r
216 //              return (LPC_C_CAN0->IF2_reg);\r
217 //      }\r
218 //}\r
219 //void CAN_IF_Write(uint32_t reg, uint32_t IFsel,uint32_t val){\r
220 //      if(IFsel == IF1){\r
221 //      (LPC_C_CAN0->IF1_reg=val);\r
222 //      }else{\r
223 //              (LPC_C_CAN0->IF2_reg=val);\r
224 //      }\r
225 //}\r
226 //\r
227 ///* Macro for writing IF to specific RAM message object */\r
228 //void CAN_IF_readBuf(uint32_t IFsel,uint32_t msg){\r
229 //      if(IFsel == IF1){\r
230 //      LPC_C_CAN0->IF1_CMDMSK_W=RD|MASK|ARB|CTRL|CLRINTPND|DATAA|DATAB;\r
231 //      LPC_C_CAN0->IF1_CMDREQ=msg;\r
232 //      while (LPC_C_CAN0->IF1_CMDREQ & IFCREQ_BUSY );\r
233 //      }else{\r
234 //        LPC_C_CAN0->IF2_CMDMSK_W=RD|MASK|ARB|CTRL|CLRINTPND|DATAA|DATAB;\r
235 //        LPC_C_CAN0->IF2_CMDREQ=msg;\r
236 //        while (LPC_C_CAN0->IF2_CMDREQ & IFCREQ_BUSY );\r
237 //  }\r
238 //\r
239 //}\r
240 //\r
241 ///* Macro for reading specific RAM message object to IF */\r
242 //void CAN_IF_writeBuf(uint32_t IFsel,uint32_t msg){\r
243 //      if(IFsel == IF1){\r
244 //  LPC_C_CAN0->IF1_CMDMSK_W=WR|MASK|ARB|CTRL|CLRINTPND|DATAA|DATAB;\r
245 //  LPC_C_CAN0->IF1_CMDREQ=msg;\r
246 //  while (LPC_C_CAN0->IF1_CMDREQ & IFCREQ_BUSY );\r
247 //      }else{\r
248 //                LPC_C_CAN0->IF2_CMDMSK_W=WR|MASK|ARB|CTRL|CLRINTPND|DATAA|DATAB;\r
249 //                LPC_C_CAN0->IF2_CMDREQ=msg;\r
250 //                while (LPC_C_CAN0->IF2_CMDREQ & IFCREQ_BUSY );\r
251 //      }\r
252 //}\r
253 //#endif\r
254 \r
255 /*********************************************************************//**\r
256  * @brief               Handle valid received message\r
257  * @param[in]   msg_no Message Object number\r
258  * @return              None\r
259  **********************************************************************/\r
260 void CAN_RxInt_MessageProcess( uint8_t msg_no )\r
261 {\r
262         uint32_t msg_id;\r
263         uint32_t *p_add;\r
264         uint32_t reg1, reg2;\r
265 \r
266         /* Import message object to IF2 */\r
267         CAN_IF_readBuf(IF2, msg_no);                                    /* Read the message into the IF registers */\r
268 \r
269         p_add = (uint32_t *)&recv_buff;\r
270 \r
271         if( CAN_IF_Read(ARB2, IF2) & ID_MTD )                   /* bit 28-0 is 29 bit extended frame */\r
272         {\r
273                 /* mask off MsgVal and Dir */\r
274                 reg1 = CAN_IF_Read(ARB1, IF2);\r
275                 reg2 = CAN_IF_Read(ARB2, IF2);\r
276                 msg_id = (reg1|(reg2<<16));\r
277         }\r
278         else\r
279         {\r
280                 /* bit 28-18 is 11-bit standard frame */\r
281                 msg_id = (CAN_IF_Read(ARB2, IF2) &0x1FFF) >> 2;\r
282         }\r
283 \r
284         p_add[0] = msg_id;\r
285         p_add[1] = CAN_IF_Read(MCTRL, IF2) & 0x000F;    /* Get Msg Obj Data length */\r
286         p_add[2] = (CAN_IF_Read(DA2, IF2)<<16) | CAN_IF_Read(DA1, IF2);\r
287         p_add[3] = (CAN_IF_Read(DB2, IF2)<<16) | CAN_IF_Read(DB1, IF2);\r
288 \r
289         /* Clear interrupt pending bit */\r
290         CAN_IF_Write(MCTRL, IF2, UMSK|RXIE|EOB|CAN_DLC_MAX);\r
291         /* Save changes to message RAM */\r
292         CAN_IF_writeBuf(IF2, msg_no);\r
293 \r
294         return;\r
295 }\r
296 /*********************************************************************//**\r
297  * @brief               Handle valid transmit message\r
298  * @param[in]   msg_no Message Object number\r
299  * @return              None\r
300  **********************************************************************/\r
301 void CAN_TxInt_MessageProcess( uint8_t msg_no )\r
302 {\r
303         /* Clear interrupt pending bit */\r
304         CAN_IF_Write(MCTRL, IF2, UMSK|RXIE|EOB|CAN_DLC_MAX);\r
305         /* Save changes to message RAM */\r
306         CAN_IF_writeBuf(IF2,msg_no);\r
307         return;\r
308 }\r
309 \r
310 /*********************************************************************//**\r
311  * @brief               CAN interrupt handler\r
312  * @param[in]   None\r
313  * @return              None\r
314  **********************************************************************/\r
315 volatile uint32_t nd_tmp;\r
316 void CAN_IRQHandler(void)\r
317 {\r
318         uint32_t canstat = 0;\r
319         uint32_t can_int, msg_no;\r
320 \r
321         while ( (can_int = LPC_C_CAN0->INT) != 0 )      /* While interrupt is pending */\r
322         {\r
323                 canstat = LPC_C_CAN0->STAT;                             /* Read CAN status register */\r
324 \r
325                 if ( can_int & CAN_STATUS_INTERRUPT )\r
326                 {\r
327                         /* Passive state monitored frequently in main. */\r
328 \r
329                         if ( canstat & STAT_EWARN )\r
330                         {\r
331                                 EWarnCnt++;\r
332                                 return;\r
333                         }\r
334                         if ( canstat & STAT_BOFF )\r
335                         {\r
336                                 BOffCnt++;\r
337                                 return;\r
338                         }\r
339 \r
340                         switch (canstat&STAT_LEC)       /* LEC Last Error Code (Type of the last error to occur on the CAN bus) */\r
341                         {\r
342                                 case NO_ERR:\r
343                                         break;\r
344                                 case STUFF_ERR:\r
345                                         StuffErrCnt++;\r
346                                         break;\r
347                                 case FORM_ERR:\r
348                                         FormErrCnt++;\r
349                                         break;\r
350                                 case ACK_ERR:\r
351                                         AckErrCnt++;\r
352                                         break;\r
353                                 case BIT1_ERR:\r
354                                         Bit1ErrCnt++;\r
355                                         break;\r
356                                 case BIT0_ERR:\r
357                                         Bit0ErrCnt++;\r
358                                         break;\r
359                                 case CRC_ERR:\r
360                                         CRCErrCnt++;\r
361                                         break;\r
362                                 default:\r
363                                         break;\r
364                         }\r
365 \r
366                         /* Clear all warning/error states except RXOK/TXOK */\r
367                         LPC_C_CAN0->STAT &= STAT_RXOK|STAT_TXOK;\r
368                 }\r
369                 else\r
370                 {\r
371                         if ( (canstat & STAT_LEC) == 0 )        /* NO ERROR */\r
372                         {\r
373                                 msg_no = can_int & 0x7FFF;\r
374                                 if((msg_no >= 1 ) && (msg_no <= 16))\r
375                                 {\r
376                                         LPC_C_CAN0->STAT &= ~STAT_RXOK;\r
377                                         /* Check if message number is correct by reading NEWDAT registers.\r
378                                          By reading out the NEWDAT bits, the CPU can check for which Message\r
379                                          Object the data portion was updated\r
380                                          Only first 16 message object used for receive : only use ND1 */\r
381                                         if((1<<(msg_no-1)) != LPC_C_CAN0->ND1)\r
382                                         {\r
383                                                 /* message object does not contain new data! */\r
384                                                 ND1ErrCnt++;\r
385                                                 break;\r
386                                         }\r
387                                         CAN_RxInt_MessageProcess(msg_no);\r
388                                         RX_cb(msg_no);\r
389                                 }\r
390                                 else\r
391                                 {\r
392                                         LPC_C_CAN0->STAT &= ~STAT_TXOK;\r
393                                         CAN_TxInt_MessageProcess(msg_no);\r
394                                         TX_cb(msg_no);\r
395                                 }\r
396                         }\r
397                 }\r
398         }\r
399         return;\r
400 }\r
401 \r
402 /*********************************************************************//**\r
403  * @brief               Initialize CAN peripheral\r
404  * @param[in]   BitClk CAN bit clock setting\r
405  * @param[in]   ClkDiv CAN bit clock setting\r
406  * @param[in]   Tx_cb point to call-back function when transmitted\r
407  * @param[in]   Rx_cb point to call-back function when received\r
408  * @return              None\r
409  **********************************************************************/\r
410 void CAN_Init( uint32_t BitClk, CCAN_CLKDIV_Type ClkDiv , MSG_CB Tx_cb, MSG_CB Rx_cb)\r
411 {\r
412 \r
413         RX_cb = Rx_cb;\r
414         TX_cb = Tx_cb;\r
415         if ( !(LPC_C_CAN0->CNTL & CTRL_INIT) )\r
416         {\r
417                 /* If it's in normal operation already, stop it, reconfigure\r
418                  everything first, then restart.  */\r
419                 LPC_C_CAN0->CNTL |= CTRL_INIT;  /* Default state */\r
420         }\r
421 \r
422         LPC_C_CAN0->CLKDIV = ClkDiv;                    /* Divider for CAN VPB3 clock */\r
423         LPC_C_CAN0->CNTL |= CTRL_CCE;           /* Start configuring bit timing */\r
424         LPC_C_CAN0->BT = BitClk;\r
425         LPC_C_CAN0->BRPE = 0x0000;\r
426         LPC_C_CAN0->CNTL &= ~CTRL_CCE;          /* Stop configuring bit timing */\r
427 \r
428         LPC_C_CAN0->CNTL &= ~CTRL_INIT;         /* Initialization finished, normal operation now. */\r
429         while ( LPC_C_CAN0->CNTL & CTRL_INIT );\r
430 \r
431         /* By default, auto TX is enabled, enable all related interrupts */\r
432         LPC_C_CAN0->CNTL |= (CTRL_IE|CTRL_SIE|CTRL_EIE);\r
433         return;\r
434 }\r
435 \r
436 /*********************************************************************//**\r
437  * @brief               Send a message to the CAN port\r
438  * @param[in]   msg_no message object number\r
439  * @param[in]   msg_ptr msg buffer pointer\r
440  * @return              None\r
441  **********************************************************************/\r
442 void CAN_Send(uint8_t msg_no, uint32_t *msg_ptr )\r
443 {\r
444         uint32_t tx_id, Length;\r
445 \r
446         if(msg_ptr == NULL) return;\r
447 \r
448         /* first is the ID, second is length, the next four are data */\r
449         tx_id = *msg_ptr++;\r
450         Length = *msg_ptr++;\r
451 \r
452         if(Length>CAN_DLC_MAX)Length = CAN_DLC_MAX;\r
453         CAN_IF_Write(MCTRL, IF1, UMSK|TXIE|TXRQ|EOB|RMTEN|(Length & DLC_MASK));\r
454         CAN_IF_Write(DA1, IF1, *msg_ptr);                       /* Lower two bytes of message pointer */\r
455         CAN_IF_Write(DA2, IF1, (*msg_ptr++)>>16);       /* Upper two bytes of message pointer */\r
456         CAN_IF_Write(DB1, IF1, *msg_ptr);                       /* Lower two bytes of message pointer */\r
457         CAN_IF_Write(DB2, IF1, (*msg_ptr)>>16);         /* Upper two bytes of message pointer */\r
458 \r
459         /* Configure arbitration */\r
460         if(!(tx_id & (0x1<<30)))                                        /* bit 30 is 0, standard frame */\r
461         {\r
462                 /* Mxtd: 0, Mdir: 1, Mask is 0x7FF */\r
463                 CAN_IF_Write(MSK2, IF1, MASK_MDIR | (ID_STD_MASK << 2));\r
464                 CAN_IF_Write(MSK1, IF1, 0x0000);\r
465 \r
466                 /* MsgVal: 1, Mtd: 0, Dir: 1, ID = 0x200 */\r
467                 CAN_IF_Write(ARB1, IF1, 0x0000);\r
468                 CAN_IF_Write(ARB2, IF1, ID_MVAL| ID_DIR | (tx_id << 2));\r
469         }\r
470         else                                                                            /* Extended frame */\r
471         {\r
472                 /* Mxtd: 1, Mdir: 1, Mask is 0x7FF */\r
473                 CAN_IF_Write(MSK2, IF1, MASK_MXTD | MASK_MDIR | (ID_EXT_MASK >> 16));\r
474                 CAN_IF_Write(MSK1, IF1, ID_EXT_MASK & 0x0000FFFF);\r
475 \r
476                 /* MsgVal: 1, Mtd: 1, Dir: 1, ID = 0x200000 */\r
477                 CAN_IF_Write(ARB1, IF1, tx_id & 0x0000FFFF);\r
478                 CAN_IF_Write(ARB2, IF1, ID_MVAL|ID_MTD | ID_DIR | (tx_id >> 16));\r
479         }\r
480 \r
481         /* Write changes to message RAM */\r
482         CAN_IF_writeBuf(IF1, msg_no);\r
483 \r
484         return;\r
485 }\r
486 \r
487 /*********************************************************************//**\r
488  * @brief               Listen for a message on CAN bus\r
489  * @param[in]   msg_no message object number\r
490  * @param[in]   msg_ptr msg buffer pointer\r
491  * @param[in]   RemoteEnable Enable/disable remote frame support, should be:\r
492  *                                      - TRUE:  enable\r
493  *                                      - FALSE: disable\r
494  * @return              None\r
495  **********************************************************************/\r
496 void CAN_Recv(uint8_t msg_no, uint32_t *msg_ptr, Bool RemoteEnable)\r
497 {\r
498         uint32_t rx_id = *msg_ptr;\r
499         uint32_t rmten = 0;\r
500         if(RemoteEnable){\r
501                 rmten = 1<<8;\r
502         }\r
503         if(!(rx_id & (0x1<<30))){ /* standard frame */\r
504 \r
505                 /* Mxtd: 0, Mdir: 0, Mask is 0x7FF */\r
506                 CAN_IF_Write(MSK1, IF1, 0x0000);\r
507                 CAN_IF_Write(MSK2, IF1, ID_STD_MASK << 2);\r
508                 /* MsgVal: 1, Mtd: 0, Dir: 0 */\r
509                 CAN_IF_Write(ARB1, IF1, 0x0000);\r
510                 CAN_IF_Write(MCTRL, IF1, rmten|UMSK|RXIE|EOB|CAN_DLC_MAX);\r
511                 CAN_IF_Write(DA1, IF1, 0x0000);\r
512                 CAN_IF_Write(DA2, IF1, 0x0000);\r
513                 CAN_IF_Write(DB1, IF1, 0x0000);\r
514                 CAN_IF_Write(DB2, IF1, 0x0000);\r
515                 CAN_IF_Write(ARB2, IF1, ID_MVAL | ((rx_id) << 2));\r
516                 /* Transfer data to message RAM */\r
517                 CAN_IF_writeBuf(IF1, msg_no);\r
518         }\r
519 \r
520         else{\r
521                 rx_id &= (0x1<<30)-1 ; /* Mask ID bit */\r
522                 /* Mxtd: 1, Mdir: 0, Mask is 0x1FFFFFFF */\r
523                 CAN_IF_Write(MSK1, IF1, ID_EXT_MASK & 0xFFFF);\r
524                 CAN_IF_Write(MSK2, IF1, MASK_MXTD | (ID_EXT_MASK >> 16));\r
525                 /* MsgVal: 1, Mtd: 1, Dir: 0 */\r
526                 CAN_IF_Write(ARB1, IF1, (rx_id) & 0xFFFF);\r
527                 CAN_IF_Write(MCTRL, IF1, rmten|UMSK|RXIE|EOB|CAN_DLC_MAX);\r
528                 CAN_IF_Write(DA1, IF1, 0x0000);\r
529                 CAN_IF_Write(DA2, IF1, 0x0000);\r
530                 CAN_IF_Write(DB1, IF1, 0x0000);\r
531                 CAN_IF_Write(DB2, IF1, 0x0000);\r
532                 CAN_IF_Write(ARB2, IF1, ID_MVAL | ID_MTD | ((rx_id) >> 16));\r
533                 /* Transfer data to message RAM */\r
534                 CAN_IF_writeBuf(IF1, msg_no);\r
535         }\r
536         return;\r
537 }\r
538 \r
539 /*********************************************************************//**\r
540  * @brief               Read a message from Message RAM to buffer\r
541  * @param[in]   msg_no message object number\r
542  * @param[in]   buff msg buffer pointer\r
543  * @return              None\r
544  **********************************************************************/\r
545 void CAN_ReadMsg(uint32_t msg_no, message_object* buff){\r
546         int i;\r
547         buff->id = recv_buff.id;\r
548         buff->dlc = recv_buff.dlc;\r
549         if(recv_buff.dlc>CAN_DLC_MAX) recv_buff.dlc = CAN_DLC_MAX;\r
550         for(i=0;i<recv_buff.dlc;i++)\r
551                 buff->data[i] = recv_buff.data[i];\r
552 }\r
553 \r
554 #endif /* _C_CAN*/\r
555 /**\r
556  * @}\r
557  */\r
558 \r
559 /* --------------------------------- End Of File ------------------------------ */\r
560 \r
561 \r