| LPCOpen Platform v1.03 LPCOpen Platform for NXP LPC Microcontrollers

- Main Page
- Modules
- Data Structures
- Files
- Related Pages

- File List
- Globals

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 */
46 static void CCAN_IF_Buf_transfer(IP_CCAN_001_T *pCCAN,
47 IP_CCAN_MSG_INTERFACE_T IFsel,
48 uint32_t msg_num,
49 uint8_t direction) {
50 msg_num &= 0x3F;
51 CCAN_IF_Write(pCCAN, CMDMSK_W, IFsel,
52 (CCAN_RW(direction) | CCAN_MASK | CCAN_ARB | CCAN_CTRL | CCAN_CLRINTPND | CCAN_DATAA | CCAN_DATAB));
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 */
62 void IP_CCAN_SWInit(IP_CCAN_001_T *pCCAN, FunctionalState NewState)
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 */
74 void IP_CCAN_TimingCfg(IP_CCAN_001_T *pCCAN,
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 */
91 void IP_CCAN_IntEnable(IP_CCAN_001_T *pCCAN, IP_CCAN_INT_T Int_type, FunctionalState NewState)
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 */
102 void IP_CCAN_AutoRetransmitEnable(IP_CCAN_001_T *pCCAN, FunctionalState NewState)
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 */
113 uint8_t IP_CCAN_GetErrCounter(IP_CCAN_001_T *pCCAN, IP_CCAN_TRX_MODE_T TRMode)
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 */
119 uint32_t IP_CCAN_GetStatus(IP_CCAN_001_T *pCCAN)
120 {
121 return pCCAN->STAT;
122 }
123
124 /* Set the CCAN status */
125 void IP_CCAN_SetStatus(IP_CCAN_001_T *pCCAN, uint32_t val)
126 {
127 pCCAN->STAT = val & 0x1F;
128 }
129
130 /* Get the source ID of an interrupt */
131 uint32_t IP_CCAN_Get_IntID(IP_CCAN_001_T *pCCAN)
132 {
133 return pCCAN->INT;
134 }
135
136 /* Enable/Disable test mode in CCAN */
137 void IP_CCAN_TestModeEnable(IP_CCAN_001_T *pCCAN, IP_CCAN_TEST_MODE_T test_mode, FunctionalState NewState)
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 */
159 void IP_CCAN_Clear_NewDataFlag(IP_CCAN_001_T *pCCAN, IP_CCAN_MSG_INTERFACE_T IFsel, uint8_t msg_num)
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 */
186 uint32_t IP_CCAN_GetValidMsg(IP_CCAN_001_T *pCCAN)
187 {
188 return pCCAN->MSGV1 | (pCCAN->MSGV2 << 16);
189 }
190
191 /* Get the transmit repuest bit in all message objects */
192 uint32_t IP_CCAN_GetTxRQST(IP_CCAN_001_T *pCCAN)
193 {
194 return pCCAN->TXREQ1 | (pCCAN->TXREQ2 << 16);
195 }
196
197 /* Set a message into the message object in message RAM */
198 void IP_CCAN_SetMsgObject(IP_CCAN_001_T *pCCAN,
199 IP_CCAN_MSG_INTERFACE_T IFsel,
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 }