LPCOpen Platform  v1.03
LPCOpen Platform for NXP LPC Microcontrollers
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ccan_001.c
Go to the documentation of this file.
1 /*
2  * @brief CCAN Registers and control functions
3  *
4  * @note
5  * Copyright(C) NXP Semiconductors, 2012
6  * All rights reserved.
7  *
8  * @par
9  * Software that is described herein is for illustrative purposes only
10  * which provides customers with programming information regarding the
11  * LPC products. This software is supplied "AS IS" without any warranties of
12  * any kind, and NXP Semiconductors and its licensor disclaim any and
13  * all warranties, express or implied, including all implied warranties of
14  * merchantability, fitness for a particular purpose and non-infringement of
15  * intellectual property rights. NXP Semiconductors assumes no responsibility
16  * or liability for the use of the software, conveys no license or rights under any
17  * patent, copyright, mask work right, or any other intellectual property rights in
18  * or to any products. NXP Semiconductors reserves the right to make changes
19  * in the software without notification. NXP Semiconductors also makes no
20  * representation or warranty that such application will be suitable for the
21  * specified use without further testing or modification.
22  *
23  * @par
24  * Permission to use, copy, modify, and distribute this software and its
25  * documentation is hereby granted, under NXP Semiconductors' and its
26  * licensor's relevant copyrights in the software, without fee, provided that it
27  * is used in conjunction with NXP Semiconductors microcontrollers. This
28  * copyright, permission, and disclaimer notice must appear in all copies of
29  * this code.
30  */
31 
32 #include "ccan_001.h"
33 
34 /*****************************************************************************
35  * Private types/enumerations/variables
36  ****************************************************************************/
37 
38 /*****************************************************************************
39  * Public types/enumerations/variables
40  ****************************************************************************/
41 
42 /*****************************************************************************
43  * Private functions
44  ****************************************************************************/
45 /* Macro for reading specific RAM message object to IF */
48  uint32_t msg_num,
49  uint8_t direction) {
50  msg_num &= 0x3F;
51  CCAN_IF_Write(pCCAN, CMDMSK_W, IFsel,
53  CCAN_IF_Write(pCCAN, CMDREQ, IFsel, msg_num);
54  while ((CCAN_IF_Read(pCCAN, CMDREQ, IFsel)) & CCAN_IFCREQ_BUSY ) {}
55 }
56 
57 /*****************************************************************************
58  * Public functions
59  ****************************************************************************/
60 
61 /* Initialize the CAN controller */
63 {
64  if (NewState == ENABLE) {
65  pCCAN->CNTL |= CCAN_CTRL_INIT;
66  }
67  else {
68  pCCAN->CNTL &= ~CCAN_CTRL_INIT; /* Initialization finished, normal operation now. */
69  while ( pCCAN->CNTL & CCAN_CTRL_INIT ) {}
70  }
71 }
72 
73 /* Configure the bit timing for CCAN bus */
75  uint32_t ClkDiv,
76  uint32_t BaudRatePrescaler,
77  uint8_t SynJumpWidth,
78  uint8_t Tseg1,
79  uint8_t Tseg2)
80 {
81  IP_CCAN_SWInit(pCCAN, ENABLE);
82  pCCAN->CLKDIV = ClkDiv; /* Divider for CAN VPB3 clock */
83  pCCAN->CNTL |= CCAN_CTRL_CCE; /* Start configuring bit timing */
84  pCCAN->BT = (BaudRatePrescaler & 0x3F) | (SynJumpWidth & 0x03) << 6 | (Tseg1 & 0x0F) << 8 | (Tseg2 & 0x07) << 12;
85  pCCAN->BRPE = BaudRatePrescaler >> 6; /* Set Baud Rate Prescaler MSBs */
86  pCCAN->CNTL &= ~CCAN_CTRL_CCE; /* Stop configuring bit timing */
87  IP_CCAN_SWInit(pCCAN, DISABLE);
88 }
89 
90 /* Enable/Disable CCAN Interrupts */
92 {
93  if (NewState == ENABLE) {
94  pCCAN->CNTL |= Int_type;
95  }
96  else {
97  pCCAN->CNTL &= ~Int_type;
98  }
99 }
100 
101 /* Enable/Disable automatic retransmission */
103 {
104  if (NewState == ENABLE) {
105  pCCAN->CNTL &= ~CCAN_CTRL_DAR;
106  }
107  else {
108  pCCAN->CNTL |= CCAN_CTRL_DAR;
109  }
110 }
111 
112 /* Get the current value of the transmit/receive error counter */
114 {
115  return (TRMode == CCAN_TX_MODE) ? (pCCAN->EC & 0x0FF) : ((pCCAN->EC >> 8) & 0x0FF); // TODO: Confirm bit number of TEC_7_0 and REC_6_0
116 }
117 
118 /* Get the CCAN status register */
120 {
121  return pCCAN->STAT;
122 }
123 
124 /* Set the CCAN status */
126 {
127  pCCAN->STAT = val & 0x1F;
128 }
129 
130 /* Get the source ID of an interrupt */
132 {
133  return pCCAN->INT;
134 }
135 
136 /* Enable/Disable test mode in CCAN */
138 {
139  if (NewState == ENABLE) {
140  pCCAN->CNTL |= CCAN_CTRL_TEST;
141  pCCAN->TEST |= test_mode;
142  }
143  else {
144  pCCAN->CNTL &= ~CCAN_CTRL_TEST;
145  pCCAN->TEST &= ~test_mode;
146  }
147 }
148 
149 /* Clear interrupt pending bit in the message object */
150 void IP_CCAN_ClearIntPend(IP_CCAN_001_T *pCCAN, IP_CCAN_MSG_INTERFACE_T IFsel, uint8_t msg_num)
151 {
152  msg_num &= 0x3F;
153  CCAN_IF_Write(pCCAN, CMDMSK_R, IFsel, CCAN_RD | CCAN_CLRINTPND);
154  CCAN_IF_Write(pCCAN, CMDREQ, IFsel, msg_num);
155  while (CCAN_IF_Read(pCCAN, CMDREQ, IFsel) & CCAN_IFCREQ_BUSY ) {}
156 }
157 
158 /* Clear new data flag bit in the message object */
160 {
161  msg_num &= 0x3F;
162  CCAN_IF_Write(pCCAN, CMDMSK_R, IFsel, CCAN_RD | CCAN_NEWDAT);
163  CCAN_IF_Write(pCCAN, CMDREQ, IFsel, msg_num);
164  while (CCAN_IF_Read(pCCAN, CMDREQ, IFsel) & CCAN_IFCREQ_BUSY ) {}
165 }
166 
167 /* Enable/Disable the message object to valid */
168 void IP_CCAN_SetValidMsg(IP_CCAN_001_T *pCCAN, IP_CCAN_MSG_INTERFACE_T IFsel, uint8_t msg_num, FunctionalState NewState)
169 {
170 
171  uint32_t temp;
172  temp = CCAN_IF_Read(pCCAN, ARB2, IFsel);
173  if (NewState == DISABLE) {
174  CCAN_IF_Write(pCCAN, ARB2, IFsel, (temp & (~CCAN_ID_MVAL)));
175  }
176  else {
177  CCAN_IF_Write(pCCAN, ARB2, IFsel, (temp | (CCAN_ID_MVAL)));
178  }
179  CCAN_IF_Write(pCCAN, CMDMSK_W, IFsel, CCAN_RW(CCAN_WR) | CCAN_ARB);
180  CCAN_IF_Write(pCCAN, CMDREQ, IFsel, msg_num);
181  while (CCAN_IF_Read(pCCAN, CMDREQ, IFsel) & CCAN_IFCREQ_BUSY) {}
182 
183 }
184 
185 /* Check the message objects is valid or not */
187 {
188  return pCCAN->MSGV1 | (pCCAN->MSGV2 << 16);
189 }
190 
191 /* Get the transmit repuest bit in all message objects */
193 {
194  return pCCAN->TXREQ1 | (pCCAN->TXREQ2 << 16);
195 }
196 
197 /* Set a message into the message object in message RAM */
200  uint8_t direction,
201  uint32_t RemoteEnable,
202  uint8_t msg_num,
203  const message_object *msg_ptr)
204 {
205  uint16_t *buff_data;
206  uint32_t msg_ctrl = 0;
207  if (msg_ptr == NULL) {
208  return;
209  }
210  buff_data = (uint16_t *) (msg_ptr->data);
211 
212  if (direction == CCAN_TX_DIR) {
213  msg_ctrl |= CCAN_UMSK | CCAN_TXIE | CCAN_RMTEN(RemoteEnable) | CCAN_EOB | (msg_ptr->dlc & CCAN_DLC_MASK);
214  if (!RemoteEnable) {
215  msg_ctrl |= CCAN_TXRQ;
216  }
217  }
218  else {
219  msg_ctrl |= CCAN_UMSK | CCAN_RXIE | CCAN_RMTEN(RemoteEnable) | CCAN_EOB | (msg_ptr->dlc & CCAN_DLC_MASK);
220  }
221 
222  CCAN_IF_Write(pCCAN, MCTRL, IFsel, msg_ctrl);
223  CCAN_IF_Write(pCCAN, DA1, IFsel, *buff_data++); /* Lower two bytes of message pointer */
224  CCAN_IF_Write(pCCAN, DA2, IFsel, *buff_data++); /* Upper two bytes of message pointer */
225  CCAN_IF_Write(pCCAN, DB1, IFsel, *buff_data++); /* Lower two bytes of message pointer */
226  CCAN_IF_Write(pCCAN, DB2, IFsel, *buff_data); /* Upper two bytes of message pointer */
227  /* Configure arbitration */
228  if (!(msg_ptr->id & (0x1 << 30))) { /* bit 30 is 0, standard frame */
229  /* Mxtd: 0, Mdir: 1, Mask is 0x7FF */
230  CCAN_IF_Write(pCCAN, MSK2, IFsel, CCAN_MASK_MDIR(direction) | (CCAN_ID_STD_MASK << 2));
231  CCAN_IF_Write(pCCAN, MSK1, IFsel, 0x0000);
232 
233  /* MsgVal: 1, Mtd: 0, Dir: 1, ID = 0x200 */
234  CCAN_IF_Write(pCCAN, ARB2, IFsel, CCAN_ID_MVAL | CCAN_ID_DIR(direction) | (msg_ptr->id << 2));
235  CCAN_IF_Write(pCCAN, ARB1, IFsel, 0x0000);
236  }
237  else { /* Extended frame */
238  /* Mxtd: 1, Mdir: 1, Mask is 0x1FFFFFFF */
239  CCAN_IF_Write(pCCAN, MSK2, IFsel, CCAN_MASK_MXTD | CCAN_MASK_MDIR(direction) | (CCAN_ID_EXT_MASK >> 16));
240  CCAN_IF_Write(pCCAN, MSK1, IFsel, CCAN_ID_EXT_MASK & 0x0000FFFF);
241 
242  /* MsgVal: 1, Mtd: 1, Dir: 1, ID = 0x200000 */
243  CCAN_IF_Write(pCCAN, ARB2, IFsel, CCAN_ID_MVAL | CCAN_ID_MTD | CCAN_ID_DIR(direction) | (msg_ptr->id >> 16));
244  CCAN_IF_Write(pCCAN, ARB1, IFsel, msg_ptr->id & 0x0000FFFF);
245  }
246 
247  CCAN_IF_Buf_transfer(pCCAN, IFsel, msg_num, CCAN_WR);
248 }
249 
250 /* Get a message object in message RAM into the message buffer */
251 void IP_CCAN_GetMsgObject(IP_CCAN_001_T *pCCAN, IP_CCAN_MSG_INTERFACE_T IFsel, uint8_t msg_num, message_object *msg_buf)
252 {
253  uint32_t *temp_data;
254  if (!msg_buf) {
255  return;
256  }
257  temp_data = (uint32_t *) msg_buf->data;
258  CCAN_IF_Buf_transfer(pCCAN, IFsel, msg_num, CCAN_RD);
259 
260  msg_buf->id = (CCAN_IF_Read(pCCAN, ARB1, IFsel) | (CCAN_IF_Read(pCCAN, ARB2, IFsel) << 16));
261  msg_buf->dlc = CCAN_IF_Read(pCCAN, MCTRL, IFsel) & 0x000F;
262  *temp_data++ = (CCAN_IF_Read(pCCAN, DA2, IFsel) << 16) | CCAN_IF_Read(pCCAN, DA1, IFsel);
263  *temp_data = (CCAN_IF_Read(pCCAN, DB2, IFsel) << 16) | CCAN_IF_Read(pCCAN, DB1, IFsel);
264 
265  if (msg_buf->id & (0x1 << 30)) {
266  msg_buf->id &= CCAN_ID_EXT_MASK;
267  }
268  else {
269  msg_buf->id >>= 18;
270  msg_buf->id &= CCAN_ID_STD_MASK;
271  }
272 }