LPCOpen Platform  v1.03
LPCOpen Platform for NXP LPC Microcontrollers
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ccan_18xx_43xx.c
Go to the documentation of this file.
1 /*
2  * @brief LPC18xx/43xx CCAN driver
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 "chip.h"
33 
34 /*****************************************************************************
35  * Private types/enumerations/variables
36  ****************************************************************************/
37 
38 #define MAX_OBJECT 32
39 #define CHIP_CCAN_DETERMINECLK(n) (((n) == LPC_C_CAN0) ? CLK_APB3_CAN0 : CLK_APB1_CAN1)
40 
41 /*****************************************************************************
42  * Public types/enumerations/variables
43  ****************************************************************************/
44 
45 /*****************************************************************************
46  * Private functions
47  ****************************************************************************/
48 
49 /* Return 1->32; 0 if not find free msg */
50 static uint8_t getFreeMsgObject(LPC_CCAN_T *pCCAN)
51 {
52  uint32_t msg_valid;
53  uint8_t i;
54  msg_valid = IP_CCAN_GetValidMsg(pCCAN);
55  for (i = 0; i < MAX_OBJECT; i++) {
56  if (!((msg_valid >> i) & 1UL)) {
57  return i + 1;
58  }
59  }
60  return 0; // No free object
61 }
62 
63 static void Free_msg_object(LPC_CCAN_T *pCCAN, uint8_t msg_num)
64 {
65  IP_CCAN_SetValidMsg(pCCAN, IF1, msg_num, DISABLE);
66 }
67 
68 /*****************************************************************************
69  * Public functions
70  ****************************************************************************/
71 
72 /* Select bit rate for CCAN bus */
74 {
75  uint32_t pClk, clk_div = 1, div, quanta, segs, seg1, seg2, clk_per_bit, can_sjw;
77  clk_per_bit = pClk / bitRate;
78 
79  for (div = 0; div <= 15; div++) {
80  if (div) {
81  clk_div = (1 << (div - 1)) + 1;
82  }
83  for (quanta = 1; quanta <= 32; quanta++) {
84  for (segs = 3; segs <= 17; segs++) {
85  if (clk_per_bit == (segs * quanta * clk_div)) {
86  segs -= 3;
87  seg1 = segs / 2;
88  seg2 = segs - seg1;
89  can_sjw = seg1 > 3 ? 3 : seg1;
90  IP_CCAN_TimingCfg(pCCAN, div, quanta - 1, can_sjw, seg1, seg2);
91  return;
92  }
93  }
94  }
95  }
96  while (1) { // Can not find a correct value with input bitrate
97  }
98 }
99 
100 /* Send a message */
101 void Chip_CCAN_Send(LPC_CCAN_T *pCCAN, uint32_t RemoteEnable, message_object *msg_ptr)
102 {
103  uint8_t msg_num_send = getFreeMsgObject(pCCAN);
104  if (!msg_num_send) {
105  return;
106  }
107  IP_CCAN_SetMsgObject(pCCAN, IF1, CCAN_TX_DIR, RemoteEnable, msg_num_send, msg_ptr);
108  while (IP_CCAN_GetTxRQST(pCCAN) >> (msg_num_send - 1)) { // blocking , wait for sending completed
109  }
110  if (!RemoteEnable) {
111  Free_msg_object(pCCAN, msg_num_send);
112  }
113 }
114 
115 /* Initialize the CCAN peripheral, free all message object in RAM */
117 {
118  uint8_t i;
119  uint32_t can_stat;
120 
121  Chip_Clock_EnableOpts(CHIP_CCAN_DETERMINECLK(pCCAN), true, false, 1);
122  can_stat = IP_CCAN_GetStatus(pCCAN);
123  for (i = 1; i <= MAX_OBJECT; i++) {
124  Free_msg_object(pCCAN, i);
125  }
126  IP_CCAN_SetStatus(pCCAN, can_stat & (~(CCAN_STAT_RXOK | CCAN_STAT_TXOK)));
127 }
128 
129 /* De-initialize the CCAN peripheral */
131 {
132  // FIXME is any specific CAN shutdown code needed here?
134 }
135 
136 /* Register a message ID for receiving */
138 {
139  message_object temp;
140  uint8_t msg_num_rev = getFreeMsgObject(pCCAN);
141  if (!msg_num_rev) {
142  return;
143  }
144  temp.id = rev_id;
145  IP_CCAN_SetMsgObject(pCCAN, IF2, CCAN_RX_DIR, 0, msg_num_rev, &temp);
146 }
147 
148 /* Remove a registered message ID from receiving */
150 {
151  uint8_t i;
152  message_object temp;
153  for (i = 1; i <= MAX_OBJECT; i++) {
154  IP_CCAN_GetMsgObject(pCCAN, IF1, i, &temp);
155  if (temp.id == rev_id) {
156  Free_msg_object(pCCAN, i);
157  }
158  }
159 }
160 
161 /* Clear the pending interrupt */
162 void Chip_CCAN_ClearIntPend(LPC_CCAN_T *pCCAN, uint8_t msg_num, uint8_t TRxMode)
163 {
164  uint32_t can_stat = IP_CCAN_GetStatus(pCCAN);
165  if (TRxMode == CCAN_TX_DIR) {
166  IP_CCAN_SetStatus(pCCAN, can_stat & (~CCAN_STAT_TXOK));
167  }
168  else {
169  IP_CCAN_SetStatus(pCCAN, can_stat & (~CCAN_STAT_RXOK));
170  }
171  IP_CCAN_ClearIntPend(pCCAN, IF1, msg_num);
172 
173 }
174 
175 /* Clear the status of CCAN bus */
177 {
178  uint32_t tmp = IP_CCAN_GetStatus(pCCAN);
179  IP_CCAN_SetStatus(pCCAN, tmp & (~status));
180 }