Rev 240 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | SVN | RSS feed
| Rev 240 | Rev 244 | ||
|---|---|---|---|
| 1 | /** |
1 | /** |
| 2 | * CAN communication interface. This is a general, high-level interface for CAN |
2 | * CAN communication interface. This is a general, high-level interface for CAN |
| 3 | * communication. Underlying CAN controllers are abstracted by this interface, |
3 | * communication. Underlying CAN controllers are abstracted by this interface, |
| 4 | * so the application needs not work directly with the CAN controllers. |
4 | * so the application needs not work directly with the CAN controllers. |
| 5 | * |
5 | * |
| 6 | * The interface is fully queued in both directions. Both queues can configured |
6 | * The interface is fully queued in both directions. Both queues can configured |
| 7 | * in terms of size, and can also be disabled completely to save both RAM and |
7 | * in terms of size, and can also be disabled completely to save both RAM and |
| 8 | * FLASH space (the queue routines are removed by preprocessor when queues |
8 | * FLASH space (the queue routines are removed by preprocessor when queues |
| 9 | * are disabled). When queues are enabled, the application has to call |
9 | * are disabled). When queues are enabled, the application has to call |
| 10 | * Can_Service as often as possible, so messages can be moved between the CAN |
10 | * Can_Service as often as possible, so messages can be moved between the CAN |
| 11 | * controller and the message queues. This might be handled by interrupts in |
11 | * controller and the message queues. This might be handled by interrupts in |
| 12 | * future. When queues are disabled, on the other hand, the application has |
12 | * future. When queues are disabled, on the other hand, the application has |
| 13 | * to call Can_Receive as often as possible in order not to loose any messages. |
13 | * to call Can_Receive as often as possible in order not to loose any messages. |
| 14 | * |
14 | * |
| 15 | * @date 2006-11-21 |
15 | * @date 2006-11-21 |
| 16 | * |
16 | * |
| 17 | * @author Jimmy Myhrman |
17 | * @author Jimmy Myhrman |
| 18 | * |
18 | * |
| 19 | */ |
19 | */ |
| 20 | 20 | ||
| 21 | /*----------------------------------------------------------------------------- |
21 | /*----------------------------------------------------------------------------- |
| 22 | * Includes |
22 | * Includes |
| 23 | *---------------------------------------------------------------------------*/ |
23 | *---------------------------------------------------------------------------*/ |
| 24 | //#include <string.h> |
24 | //#include <string.h> |
| 25 | #include "can.h" |
25 | #include "can.h" |
| 26 | //#include <mcu.h> |
26 | //#include <mcu.h> |
| 27 | //#include <stdio.h> |
27 | //#include <stdio.h> |
| 28 | //#include <timebase.h> |
28 | //#include <timebase.h> |
| 29 | //#include <assert.h> |
29 | //#include <assert.h> |
| 30 | #if CAN_CONTROLLER == CAN_CONTROLLER_MCP2515 |
30 | #if CAN_CONTROLLER == CAN_CONTROLLER_MCP2515 |
| 31 | #include "mcp2515/mcp2515.h" |
31 | #include "mcp2515/mcp2515.h" |
| 32 | #endif |
32 | #endif |
| 33 | 33 | ||
| 34 | 34 | ||
| 35 | /*----------------------------------------------------------------------------- |
35 | /*----------------------------------------------------------------------------- |
| 36 | * Prerequisites |
36 | * Prerequisites |
| 37 | *---------------------------------------------------------------------------*/ |
37 | *---------------------------------------------------------------------------*/ |
| 38 | #ifndef CAN_CONTROLLER |
38 | #ifndef CAN_CONTROLLER |
| 39 | #error CAN_CONTROLLER not specified! Edit can_cfg.h ! |
39 | #error CAN_CONTROLLER not specified! Edit can_cfg.h ! |
| 40 | #endif |
40 | #endif |
| 41 | 41 | ||
| 42 | #ifndef CAN_BITRATE |
42 | #ifndef CAN_BITRATE |
| 43 | #error CAN_BITRATE not defined! Edit can_cfg.h ! |
43 | #error CAN_BITRATE not defined! Edit can_cfg.h ! |
| 44 | #endif |
44 | #endif |
| 45 | 45 | ||
| 46 | #ifndef CAN_QUEUE_SIZE_RX |
46 | #ifndef CAN_QUEUE_SIZE_RX |
| 47 | #error CAN_QUEUE_SIZE_RX not defined! Edit can_cfg.h ! |
47 | #error CAN_QUEUE_SIZE_RX not defined! Edit can_cfg.h ! |
| 48 | #endif |
48 | #endif |
| 49 | 49 | ||
| 50 | #ifndef CAN_QUEUE_SIZE_TX |
50 | #ifndef CAN_QUEUE_SIZE_TX |
| 51 | #error CAN_QUEUE_SIZE_TX not defined! Edit can_cfg.h ! |
51 | #error CAN_QUEUE_SIZE_TX not defined! Edit can_cfg.h ! |
| 52 | #endif |
52 | #endif |
| 53 | 53 | ||
| 54 | #ifndef CAN_CONTROLLER_NR_TX_BUFFERS |
54 | #ifndef CAN_CONTROLLER_NR_TX_BUFFERS |
| 55 | #error CAN_CONTROLLER_NR_TX_BUFFERS not defined! Edit can_cfg.h ! |
55 | #error CAN_CONTROLLER_NR_TX_BUFFERS not defined! Edit can_cfg.h ! |
| 56 | #endif |
56 | #endif |
| 57 | 57 | ||
| 58 | #ifndef CAN_CONTROLLER_NR_RX_BUFFERS |
58 | #ifndef CAN_CONTROLLER_NR_RX_BUFFERS |
| 59 | #error CAN_CONTROLLER_NR_RX_BUFFERS not defined! Edit can_cfg.h ! |
59 | #error CAN_CONTROLLER_NR_RX_BUFFERS not defined! Edit can_cfg.h ! |
| 60 | #endif |
60 | #endif |
| 61 | 61 | ||
| 62 | 62 | ||
| 63 | /*----------------------------------------------------------------------------- |
63 | /*----------------------------------------------------------------------------- |
| 64 | * Type Definitions |
64 | * Type Definitions |
| 65 | *---------------------------------------------------------------------------*/ |
65 | *---------------------------------------------------------------------------*/ |
| 66 | 66 | ||
| 67 | #if (CAN_QUEUE_SIZE_TX > 0) || (CAN_QUEUE_SIZE_RX > 0) |
67 | #if (CAN_QUEUE_SIZE_TX > 0) || (CAN_QUEUE_SIZE_RX > 0) |
| 68 | /** |
68 | /** |
| 69 | * CAN Message Queue Type. Stores and manages several CAN messages |
69 | * CAN Message Queue Type. Stores and manages several CAN messages |
| 70 | * in a FIFO structure. |
70 | * in a FIFO structure. |
| 71 | */ |
71 | */ |
| 72 | typedef struct { |
72 | typedef struct { |
| 73 | Can_Message_t *dataPtr; /* pointer to the data storage */ |
73 | Can_Message_t *dataPtr; /* pointer to the data storage */ |
| 74 | uint8_t head; /* current OUTPUT position */ |
74 | uint8_t head; /* current OUTPUT position */ |
| 75 | uint8_t tail; /* current INPUT position */ |
75 | uint8_t tail; /* current INPUT position */ |
| 76 | uint8_t nrElements; /* nr of elements currently queued */ |
76 | uint8_t nrElements; /* nr of elements currently queued */ |
| 77 | uint8_t size; /* total size of the queue */ |
77 | uint8_t size; /* total size of the queue */ |
| 78 | } Can_MessageQueue_t; |
78 | } Can_MessageQueue_t; |
| 79 | #endif |
79 | #endif |
| 80 | 80 | ||
| 81 | 81 | ||
| 82 | /*----------------------------------------------------------------------------- |
82 | /*----------------------------------------------------------------------------- |
| 83 | * Private (static) variables |
83 | * Private (static) variables |
| 84 | *---------------------------------------------------------------------------*/ |
84 | *---------------------------------------------------------------------------*/ |
| 85 | 85 | ||
| 86 | #if CAN_QUEUE_SIZE_TX > 0 |
86 | #if CAN_QUEUE_SIZE_TX > 0 |
| 87 | /* TX queue object and static memory storage buffer for this queue */ |
87 | /* TX queue object and static memory storage buffer for this queue */ |
| 88 | static Can_MessageQueue_t canTxQueue; |
88 | static Can_MessageQueue_t canTxQueue; |
| 89 | static Can_Message_t canTxQueueDataStorage[CAN_QUEUE_SIZE_TX]; |
89 | static Can_Message_t canTxQueueDataStorage[CAN_QUEUE_SIZE_TX]; |
| 90 | #endif |
90 | #endif |
| 91 | #if CAN_QUEUE_SIZE_RX > 0 |
91 | #if CAN_QUEUE_SIZE_RX > 0 |
| 92 | /* RX queue object and static memory storage buffer for this queue */ |
92 | /* RX queue object and static memory storage buffer for this queue */ |
| 93 | static Can_MessageQueue_t canRxQueue; |
93 | static Can_MessageQueue_t canRxQueue; |
| 94 | static Can_Message_t canRxQueueDataStorage[CAN_QUEUE_SIZE_RX]; |
94 | static Can_Message_t canRxQueueDataStorage[CAN_QUEUE_SIZE_RX]; |
| 95 | #endif |
95 | #endif |
| 96 | 96 | ||
| 97 | 97 | ||
| 98 | /*----------------------------------------------------------------------------- |
98 | /*----------------------------------------------------------------------------- |
| 99 | * Private Function Prototypes |
99 | * Private Function Prototypes |
| 100 | *---------------------------------------------------------------------------*/ |
100 | *---------------------------------------------------------------------------*/ |
| 101 | 101 | ||
| 102 | /* functions that deal with the controller hardware */ |
102 | /* functions that deal with the controller hardware */ |
| 103 | static Can_Return_t Can_SendImmediately(Can_Message_t *msg); |
103 | static Can_Return_t Can_SendImmediately(Can_Message_t *msg); |
| 104 | static Can_Return_t Can_ReceiveFromController(Can_Message_t *msg, uint8_t rxBuffer); |
104 | static Can_Return_t Can_ReceiveFromController(Can_Message_t *msg, uint8_t rxBuffer); |
| 105 | static uint8_t Can_MessagesAvailableInController(void) __attribute__((unused)); |
105 | static uint8_t Can_MessagesAvailableInController(void) __attribute__((unused)); |
| 106 | static Can_Return_t Can_ControllerCheckError(void) __attribute__((unused)); |
106 | static Can_Return_t Can_ControllerCheckError(void) __attribute__((unused)); |
| 107 | 107 | ||
| 108 | #if (CAN_QUEUE_SIZE_TX > 0) || (CAN_QUEUE_SIZE_RX > 0) |
108 | #if (CAN_QUEUE_SIZE_TX > 0) || (CAN_QUEUE_SIZE_RX > 0) |
| 109 | /* functions that deal with the message queues */ |
109 | /* functions that deal with the message queues */ |
| 110 | static void Can_QueueInit(Can_MessageQueue_t *q, uint8_t size, Can_Message_t *dataPtr); |
110 | static void Can_QueueInit(Can_MessageQueue_t *q, uint8_t size, Can_Message_t *dataPtr); |
| 111 | static Can_Message_t* Can_QueueInsert(Can_MessageQueue_t *q); |
111 | static Can_Message_t* Can_QueueInsert(Can_MessageQueue_t *q); |
| 112 | static Can_Message_t* Can_QueueReadTailPtr(Can_MessageQueue_t *q); |
112 | static Can_Message_t* Can_QueueReadTailPtr(Can_MessageQueue_t *q); |
| 113 | static void Can_QueueRemoveTail(Can_MessageQueue_t *q); |
113 | static void Can_QueueRemoveTail(Can_MessageQueue_t *q); |
| 114 | #endif |
114 | #endif |
| 115 | 115 | ||
| 116 | 116 | ||
| 117 | /*----------------------------------------------------------------------------- |
117 | /*----------------------------------------------------------------------------- |
| 118 | * Public Functions |
118 | * Public Functions |
| 119 | *---------------------------------------------------------------------------*/ |
119 | *---------------------------------------------------------------------------*/ |
| 120 | 120 | ||
| 121 | /** |
121 | /** |
| 122 | * Initializes the CAN interface. Edit can_cfg.h to choose bitrate. |
122 | * Initializes the CAN interface. Edit can_cfg.h to choose bitrate. |
| 123 | * |
123 | * |
| 124 | * @return |
124 | * @return |
| 125 | * CAN_OK if initialization was successful. |
125 | * CAN_OK if initialization was successful. |
| 126 | * CAN_INIT_FAIL_SET_BITRATE if bitrate could not be set correctly. |
126 | * CAN_INIT_FAIL_SET_BITRATE if bitrate could not be set correctly. |
| 127 | * CAN_INIT_FAIL_SET_MODE if the controller could not be set to normal operation mode. |
127 | * CAN_INIT_FAIL_SET_MODE if the controller could not be set to normal operation mode. |
| 128 | * CAN_INIT_FAIL in case of general error. |
128 | * CAN_INIT_FAIL in case of general error. |
| 129 | */ |
129 | */ |
| 130 | Can_Return_t Can_Init() { |
130 | Can_Return_t Can_Init() { |
| 131 | #if CAN_QUEUE_SIZE_TX > 0 |
131 | #if CAN_QUEUE_SIZE_TX > 0 |
| 132 | /* initialize TX queue */ |
132 | /* initialize TX queue */ |
| 133 | Can_QueueInit(&canTxQueue, CAN_QUEUE_SIZE_TX, canTxQueueDataStorage); |
133 | Can_QueueInit(&canTxQueue, CAN_QUEUE_SIZE_TX, canTxQueueDataStorage); |
| 134 | #endif |
134 | #endif |
| 135 | #if CAN_QUEUE_SIZE_RX > 0 |
135 | #if CAN_QUEUE_SIZE_RX > 0 |
| 136 | /* initialize RX queue */ |
136 | /* initialize RX queue */ |
| 137 | Can_QueueInit(&canRxQueue, CAN_QUEUE_SIZE_RX, canRxQueueDataStorage); |
137 | Can_QueueInit(&canRxQueue, CAN_QUEUE_SIZE_RX, canRxQueueDataStorage); |
| 138 | #endif |
138 | #endif |
| 139 | 139 | ||
| 140 | #if CAN_CONTROLLER == CAN_CONTROLLER_NULL |
140 | #if CAN_CONTROLLER == CAN_CONTROLLER_NULL |
| 141 | /* |
141 | /* |
| 142 | * Initialize null device. |
142 | * Initialize null device. |
| 143 | */ |
143 | */ |
| 144 | return CAN_OK; |
144 | return CAN_OK; |
| 145 | #endif |
145 | #endif |
| 146 | 146 | ||
| 147 | #if CAN_CONTROLLER == CAN_CONTROLLER_MCP2515 |
147 | #if CAN_CONTROLLER == CAN_CONTROLLER_MCP2515 |
| 148 | /* |
148 | /* |
| 149 | * Initialize MCP2515 device. |
149 | * Initialize MCP2515 device. |
| 150 | */ |
150 | */ |
| 151 | if (MCP2515_Init( |
151 | if (MCP2515_Init() != MCP2515_OK) { |
| 152 | return CAN_FAIL; |
152 | return CAN_FAIL; |
| 153 | } |
153 | } |
| 154 | if (MCP2515_SetCanCtrlMode(MODE_NORMAL) != MCP2515_OK) { |
154 | if (MCP2515_SetCanCtrlMode(MODE_NORMAL) != MCP2515_OK) { |
| 155 | return CAN_FAIL; |
155 | return CAN_FAIL; |
| 156 | } |
156 | } |
| 157 | return CAN_OK; |
157 | return CAN_OK; |
| 158 | #endif |
158 | #endif |
| 159 | 159 | ||
| 160 | return CAN_FAIL; |
160 | return CAN_FAIL; |
| 161 | } |
161 | } |
| 162 | 162 | ||
| 163 | 163 | ||
| 164 | /** |
164 | /** |
| 165 | * Sends a CAN message. The message will be put into the transmission queue, |
165 | * Sends a CAN message. The message will be put into the transmission queue, |
| 166 | * and hence, it might not be sent immediately. If the queue is full, the |
166 | * and hence, it might not be sent immediately. If the queue is full, the |
| 167 | * message will not be taken care of, and CAN_FAIL is returned. |
167 | * message will not be taken care of, and CAN_FAIL is returned. |
| 168 | * |
168 | * |
| 169 | * @param msg |
169 | * @param msg |
| 170 | * Pointer to the CAN message. |
170 | * Pointer to the CAN message. |
| 171 | * |
171 | * |
| 172 | * @return |
172 | * @return |
| 173 | * CAN_OK if the message was successfully enqueued. |
173 | * CAN_OK if the message was successfully enqueued. |
| 174 | * CAN_FAIL if the transmission queue is full. |
174 | * CAN_FAIL if the transmission queue is full. |
| 175 | */ |
175 | */ |
| 176 | Can_Return_t Can_Send(Can_Message_t *msg) { |
176 | Can_Return_t Can_Send(Can_Message_t *msg) { |
| 177 | #if CAN_QUEUE_SIZE_TX == 0 |
177 | #if CAN_QUEUE_SIZE_TX == 0 |
| 178 | /* TX queue is disabled, so send immediately */ |
178 | /* TX queue is disabled, so send immediately */ |
| 179 | return Can_SendImmediately(msg); |
179 | return Can_SendImmediately(msg); |
| 180 | #else |
180 | #else |
| 181 | #if 0 |
181 | #if 0 |
| 182 | printf("Can_Send()\n\r"); |
182 | printf("Can_Send()\n\r"); |
| 183 | printf(" queue size before = %u\n\r", canTxQueue.nrElements); |
183 | printf(" queue size before = %u\n\r", canTxQueue.nrElements); |
| 184 | #endif |
184 | #endif |
| 185 | /* check if there is room available in the tx queue */ |
185 | /* check if there is room available in the tx queue */ |
| 186 | if (canTxQueue.nrElements >= canTxQueue.size) { |
186 | if (canTxQueue.nrElements >= canTxQueue.size) { |
| 187 | #if 0 |
187 | #if 0 |
| 188 | printf(" TX queue full!\n\r"); |
188 | printf(" TX queue full!\n\r"); |
| 189 | #endif |
189 | #endif |
| 190 | return CAN_FAIL; |
190 | return CAN_FAIL; |
| 191 | } |
191 | } |
| 192 | /* put message in queue */ |
192 | /* put message in queue */ |
| 193 | Can_Message_t *ptr = Can_QueueInsert(&canTxQueue); |
193 | Can_Message_t *ptr = Can_QueueInsert(&canTxQueue); |
| 194 | memcpy(ptr, msg, sizeof(Can_Message_t)); |
194 | memcpy(ptr, msg, sizeof(Can_Message_t)); |
| 195 | #if 0 |
195 | #if 0 |
| 196 | printf(" queue size after = %u\n\r", canTxQueue.nrElements); |
196 | printf(" queue size after = %u\n\r", canTxQueue.nrElements); |
| 197 | #endif |
197 | #endif |
| 198 | return CAN_OK; |
198 | return CAN_OK; |
| 199 | #endif |
199 | #endif |
| 200 | } |
200 | } |
| 201 | 201 | ||
| 202 | 202 | ||
| 203 | /** |
203 | /** |
| 204 | * Services the CAN subsystem. Messages waiting in the transmission queue |
204 | * Services the CAN subsystem. Messages waiting in the transmission queue |
| 205 | * will be transmitted if the controller is not busy, and any messages |
205 | * will be transmitted if the controller is not busy, and any messages |
| 206 | * received by the controller will be moved from the controller buffers |
206 | * received by the controller will be moved from the controller buffers |
| 207 | * into the internal reception queue. |
207 | * into the internal reception queue. |
| 208 | */ |
208 | */ |
| 209 | void Can_Service() { |
209 | void Can_Service() { |
| 210 | #if CAN_QUEUE_SIZE_TX > 0 |
210 | #if CAN_QUEUE_SIZE_TX > 0 |
| 211 | /* try to transmit messages waiting in the transmission queue */ |
211 | /* try to transmit messages waiting in the transmission queue */ |
| 212 | for (uint8_t i=0; i<CAN_CONTROLLER_NR_TX_BUFFERS; i++) { |
212 | for (uint8_t i=0; i<CAN_CONTROLLER_NR_TX_BUFFERS; i++) { |
| 213 | if (canTxQueue.nrElements > 0) { |
213 | if (canTxQueue.nrElements > 0) { |
| 214 | #if 0 |
214 | #if 0 |
| 215 | printf("msg in TX queue. trying to send...\n"); |
215 | printf("msg in TX queue. trying to send...\n"); |
| 216 | #endif |
216 | #endif |
| 217 | /* ensure the queue operations are atomic */ |
217 | /* ensure the queue operations are atomic */ |
| 218 | cli(); |
218 | cli(); |
| 219 | Can_Message_t *txMsg = Can_QueueReadTailPtr(&canTxQueue); |
219 | Can_Message_t *txMsg = Can_QueueReadTailPtr(&canTxQueue); |
| 220 | if (Can_SendImmediately(txMsg) == CAN_OK) { |
220 | if (Can_SendImmediately(txMsg) == CAN_OK) { |
| 221 | /* transmission OK, remove from queue */ |
221 | /* transmission OK, remove from queue */ |
| 222 | Can_QueueRemoveTail(&canTxQueue); |
222 | Can_QueueRemoveTail(&canTxQueue); |
| 223 | } |
223 | } |
| 224 | //TODO: dont enable interrupts, restore previous state |
224 | //TODO: dont enable interrupts, restore previous state |
| 225 | sei(); |
225 | sei(); |
| 226 | } |
226 | } |
| 227 | else { |
227 | else { |
| 228 | /* quit the loop if the queue is empty */ |
228 | /* quit the loop if the queue is empty */ |
| 229 | break; |
229 | break; |
| 230 | } |
230 | } |
| 231 | } |
231 | } |
| 232 | #endif |
232 | #endif |
| 233 | 233 | ||
| 234 | #if CAN_QUEUE_SIZE_RX > 0 |
234 | #if CAN_QUEUE_SIZE_RX > 0 |
| 235 | /* move all received messages from CAN controller to reception queue */ |
235 | /* move all received messages from CAN controller to reception queue */ |
| 236 | Can_Message_t rxMsg; |
236 | Can_Message_t rxMsg; |
| 237 | /* all RX buffers have to be checked (and in correct order) */ |
237 | /* all RX buffers have to be checked (and in correct order) */ |
| 238 | for (uint8_t buf=0; buf<CAN_CONTROLLER_NR_RX_BUFFERS; buf++) { |
238 | for (uint8_t buf=0; buf<CAN_CONTROLLER_NR_RX_BUFFERS; buf++) { |
| 239 | /* if buffer contains a message, handle it */ |
239 | /* if buffer contains a message, handle it */ |
| 240 | if (Can_ReceiveFromController(&rxMsg, buf) == CAN_OK) { |
240 | if (Can_ReceiveFromController(&rxMsg, buf) == CAN_OK) { |
| 241 | /* ensure the queue operations are atomic */ |
241 | /* ensure the queue operations are atomic */ |
| 242 | cli(); |
242 | cli(); |
| 243 | /* try to get access to the queue */ |
243 | /* try to get access to the queue */ |
| 244 | Can_Message_t *destPtr = Can_QueueInsert(&canRxQueue); |
244 | Can_Message_t *destPtr = Can_QueueInsert(&canRxQueue); |
| 245 | /* if we can insert into queue, copy the message */ |
245 | /* if we can insert into queue, copy the message */ |
| 246 | if (destPtr != 0) { |
246 | if (destPtr != 0) { |
| 247 | memcpy(destPtr, &rxMsg, sizeof(Can_Message_t)); |
247 | memcpy(destPtr, &rxMsg, sizeof(Can_Message_t)); |
| 248 | } |
248 | } |
| 249 | else { |
249 | else { |
| 250 | /* otherwise, the received message will be discarded... */ |
250 | /* otherwise, the received message will be discarded... */ |
| 251 | } |
251 | } |
| 252 | //TODO: dont enable interrupts, restore previous state |
252 | //TODO: dont enable interrupts, restore previous state |
| 253 | sei(); |
253 | sei(); |
| 254 | } |
254 | } |
| 255 | } |
255 | } |
| 256 | #endif |
256 | #endif |
| 257 | 257 | ||
| 258 | /* TODO: check error status in controller */ |
258 | /* TODO: check error status in controller */ |
| 259 | } |
259 | } |
| 260 | 260 | ||
| 261 | 261 | ||
| 262 | /** |
262 | /** |
| 263 | * Receives a CAN message that is waiting in the reception queue. If no |
263 | * Receives a CAN message that is waiting in the reception queue. If no |
| 264 | * messages have been received, CAN_NO_MSG_AVAILABLE is returned. |
264 | * messages have been received, CAN_NO_MSG_AVAILABLE is returned. |
| 265 | * Otherwise, a CAN message is copied into the specified message buffer |
265 | * Otherwise, a CAN message is copied into the specified message buffer |
| 266 | * and deleted from the internal message reception queue. In this case, |
266 | * and deleted from the internal message reception queue. In this case, |
| 267 | * CAN_OK is returned. |
267 | * CAN_OK is returned. |
| 268 | * |
268 | * |
| 269 | * @param msg |
269 | * @param msg |
| 270 | * Pointer to the message storage buffer into which the message |
270 | * Pointer to the message storage buffer into which the message |
| 271 | * should be copied. |
271 | * should be copied. |
| 272 | * |
272 | * |
| 273 | * @return |
273 | * @return |
| 274 | * CAN_OK if a received message was successfully copied into the buffer. |
274 | * CAN_OK if a received message was successfully copied into the buffer. |
| 275 | * CAN_NO_MSG_AVAILABLE if no messages are available. |
275 | * CAN_NO_MSG_AVAILABLE if no messages are available. |
| 276 | */ |
276 | */ |
| 277 | Can_Return_t Can_Receive(Can_Message_t *msg) { |
277 | Can_Return_t Can_Receive(Can_Message_t *msg) { |
| 278 | 278 | ||
| 279 | #if CAN_QUEUE_SIZE_RX > 0 |
279 | #if CAN_QUEUE_SIZE_RX > 0 |
| 280 | /* |
280 | /* |
| 281 | * RX queue is enabled, so try to get message from queue. |
281 | * RX queue is enabled, so try to get message from queue. |
| 282 | */ |
282 | */ |
| 283 | Can_Message_t *pSrc; /* Source pointer */ |
283 | Can_Message_t *pSrc; /* Source pointer */ |
| 284 | /* Check if there is anything available in the RxQueue */ |
284 | /* Check if there is anything available in the RxQueue */ |
| 285 | if (canRxQueue.nrElements == 0) { |
285 | if (canRxQueue.nrElements == 0) { |
| 286 | return CAN_NO_MSG_AVAILABLE; |
286 | return CAN_NO_MSG_AVAILABLE; |
| 287 | } |
287 | } |
| 288 | /* ensure the queue operations are atomic */ |
288 | /* ensure the queue operations are atomic */ |
| 289 | cli(); |
289 | cli(); |
| 290 | pSrc = Can_QueueReadTailPtr(&canRxQueue); |
290 | pSrc = Can_QueueReadTailPtr(&canRxQueue); |
| 291 | /* copy frame from queue, and then remove from queue */ |
291 | /* copy frame from queue, and then remove from queue */ |
| 292 | memcpy(msg, pSrc, sizeof(Can_Message_t)); |
292 | memcpy(msg, pSrc, sizeof(Can_Message_t)); |
| 293 | Can_QueueRemoveTail(&canRxQueue); |
293 | Can_QueueRemoveTail(&canRxQueue); |
| 294 | //TODO: dont enable interrupts, restore previous state |
294 | //TODO: dont enable interrupts, restore previous state |
| 295 | sei(); |
295 | sei(); |
| 296 | /* a message has successfully been copied and removed from queue */ |
296 | /* a message has successfully been copied and removed from queue */ |
| 297 | return CAN_OK; |
297 | return CAN_OK; |
| 298 | #else |
298 | #else |
| 299 | /* |
299 | /* |
| 300 | * RX queue is disabled, so try to get message from controller. |
300 | * RX queue is disabled, so try to get message from controller. |
| 301 | * We don't know which buffer to get the message from, so best |
301 | * We don't know which buffer to get the message from, so best |
| 302 | * we can do is to get from buf0 first time, and then increase |
302 | * we can do is to get from buf0 first time, and then increase |
| 303 | * buffer number at each call, finally wrapping around at |
303 | * buffer number at each call, finally wrapping around at |
| 304 | * CAN_CONTROLLER_NR_RX_BUFFERS. |
304 | * CAN_CONTROLLER_NR_RX_BUFFERS. |
| 305 | */ |
305 | */ |
| 306 | static uint8_t rxBuffer = 0; |
306 | static uint8_t rxBuffer = 0; |
| 307 | uint8_t i; |
307 | uint8_t i; |
| 308 | /* worst case is that we need to check all available rx buffers in order to find a message */ |
308 | /* worst case is that we need to check all available rx buffers in order to find a message */ |
| 309 | for (i=0; i<CAN_CONTROLLER_NR_RX_BUFFERS; i++) { |
309 | for (i=0; i<CAN_CONTROLLER_NR_RX_BUFFERS; i++) { |
| 310 | /* is there a message available in this buffer? */ |
310 | /* is there a message available in this buffer? */ |
| 311 | if (Can_ReceiveFromController(msg, rxBuffer) == CAN_OK) { |
311 | if (Can_ReceiveFromController(msg, rxBuffer) == CAN_OK) { |
| 312 | /* increase buffer number and return the message */ |
312 | /* increase buffer number and return the message */ |
| 313 | rxBuffer = (rxBuffer + 1) % CAN_CONTROLLER_NR_RX_BUFFERS; |
313 | rxBuffer = (rxBuffer + 1) % CAN_CONTROLLER_NR_RX_BUFFERS; |
| 314 | return CAN_OK; |
314 | return CAN_OK; |
| 315 | } |
315 | } |
| 316 | /* increase buffer number so we can check next buffer */ |
316 | /* increase buffer number so we can check next buffer */ |
| 317 | rxBuffer = (rxBuffer + 1) % CAN_CONTROLLER_NR_RX_BUFFERS; |
317 | rxBuffer = (rxBuffer + 1) % CAN_CONTROLLER_NR_RX_BUFFERS; |
| 318 | } |
318 | } |
| 319 | /* all buffers were checked, but no message found */ |
319 | /* all buffers were checked, but no message found */ |
| 320 | return CAN_NO_MSG_AVAILABLE; |
320 | return CAN_NO_MSG_AVAILABLE; |
| 321 | #endif |
321 | #endif |
| 322 | } |
322 | } |
| 323 | 323 | ||
| 324 | 324 | ||
| 325 | 325 | ||
| 326 | /*----------------------------------------------------------------------------- |
326 | /*----------------------------------------------------------------------------- |
| 327 | * Private Functions |
327 | * Private Functions |
| 328 | *---------------------------------------------------------------------------*/ |
328 | *---------------------------------------------------------------------------*/ |
| 329 | 329 | ||
| 330 | /** |
330 | /** |
| 331 | * Sends a CAN message immediately with the controller hardware. If the CAN |
331 | * Sends a CAN message immediately with the controller hardware. If the CAN |
| 332 | * controller is busy, the function will return CAN_SEND_FAIL_TX_BUSY. |
332 | * controller is busy, the function will return CAN_SEND_FAIL_TX_BUSY. |
| 333 | * |
333 | * |
| 334 | * @param msg |
334 | * @param msg |
| 335 | * Pointer to the CAN message storage buffer. |
335 | * Pointer to the CAN message storage buffer. |
| 336 | * |
336 | * |
| 337 | * @return |
337 | * @return |
| 338 | * CAN_OK if the message was successfully sent to the controller. |
338 | * CAN_OK if the message was successfully sent to the controller. |
| 339 | * CAN_FAIL if the controller is busy. |
339 | * CAN_FAIL if the controller is busy. |
| 340 | */ |
340 | */ |
| 341 | static Can_Return_t Can_SendImmediately(Can_Message_t* msg) { |
341 | static Can_Return_t Can_SendImmediately(Can_Message_t* msg) { |
| 342 | #if CAN_CONTROLLER == CAN_CONTROLLER_NULL |
342 | #if CAN_CONTROLLER == CAN_CONTROLLER_NULL |
| 343 | /* |
343 | /* |
| 344 | * Send with null device. |
344 | * Send with null device. |
| 345 | */ |
345 | */ |
| 346 | return CAN_OK; |
346 | return CAN_OK; |
| 347 | #endif |
347 | #endif |
| 348 | 348 | ||
| 349 | #if CAN_CONTROLLER == CAN_CONTROLLER_MCP2515 |
349 | #if CAN_CONTROLLER == CAN_CONTROLLER_MCP2515 |
| 350 | /* |
350 | /* |
| 351 | * Send with MCP2515 device. |
351 | * Send with MCP2515 device. |
| 352 | */ |
352 | */ |
| 353 | uint8_t res, txbuf_n; |
353 | uint8_t res, txbuf_n; |
| 354 | res = MCP2515_GetNextFreeTXBuf(&txbuf_n); // info = addr. |
354 | res = MCP2515_GetNextFreeTXBuf(&txbuf_n); // info = addr. |
| 355 | if (res == MCP_ALLTXBUSY) { |
355 | if (res == MCP_ALLTXBUSY) { |
| 356 | return CAN_FAIL; |
356 | return CAN_FAIL; |
| 357 | } |
357 | } |
| 358 | MCP2515_WriteCanMsg(txbuf_n, msg); |
358 | MCP2515_WriteCanMsg(txbuf_n, msg); |
| 359 | MCP2515_StartTransmit(txbuf_n); |
359 | MCP2515_StartTransmit(txbuf_n); |
| 360 | return CAN_OK; |
360 | return CAN_OK; |
| 361 | #endif |
361 | #endif |
| 362 | } |
362 | } |
| 363 | 363 | ||
| 364 | 364 | ||
| 365 | /** |
365 | /** |
| 366 | * Receives a CAN message from the CAN controller hardware. |
366 | * Receives a CAN message from the CAN controller hardware. |
| 367 | * |
367 | * |
| 368 | * @param msg |
368 | * @param msg |
| 369 | * Pointer to the message storage buffer into which the message should be copied. |
369 | * Pointer to the message storage buffer into which the message should be copied. |
| 370 | * |
370 | * |
| 371 | * @param rxBuffer |
371 | * @param rxBuffer |
| 372 | * Identifies the RX buffer in the controller. Range is [0,CAN_CONTROLLER_NR_RX_BUFFERS-1]. |
372 | * Identifies the RX buffer in the controller. Range is [0,CAN_CONTROLLER_NR_RX_BUFFERS-1]. |
| 373 | * |
373 | * |
| 374 | * @return |
374 | * @return |
| 375 | * CAN_OK if a received message was successfully copied into the buffer. |
375 | * CAN_OK if a received message was successfully copied into the buffer. |
| 376 | * CAN_NO_MSG_AVAILABLE if there are is no message available in the specified buffer. |
376 | * CAN_NO_MSG_AVAILABLE if there are is no message available in the specified buffer. |
| 377 | * CAN_FAIL if the rxBuffer parameter i out of range for the specified controller. |
377 | * CAN_FAIL if the rxBuffer parameter i out of range for the specified controller. |
| 378 | */ |
378 | */ |
| 379 | static Can_Return_t Can_ReceiveFromController(Can_Message_t *msg, uint8_t rxBuffer) { |
379 | static Can_Return_t Can_ReceiveFromController(Can_Message_t *msg, uint8_t rxBuffer) { |
| 380 | #if CAN_CONTROLLER == CAN_CONTROLLER_NULL |
380 | #if CAN_CONTROLLER == CAN_CONTROLLER_NULL |
| 381 | /* |
381 | /* |
| 382 | * Receive from null device. |
382 | * Receive from null device. |
| 383 | */ |
383 | */ |
| 384 | return CAN_NO_MSG_AVAILABLE; |
384 | return CAN_NO_MSG_AVAILABLE; |
| 385 | #endif |
385 | #endif |
| 386 | 386 | ||
| 387 | #if CAN_CONTROLLER == CAN_CONTROLLER_MCP2515 |
387 | #if CAN_CONTROLLER == CAN_CONTROLLER_MCP2515 |
| 388 | /* |
388 | /* |
| 389 | * Receive from MCP2515 device. |
389 | * Receive from MCP2515 device. |
| 390 | */ |
390 | */ |
| 391 | uint8_t stat; |
391 | uint8_t stat; |
| 392 | stat = MCP2515_ReadStatus(); |
392 | stat = MCP2515_ReadStatus(); |
| 393 | if (rxBuffer == 0) { |
393 | if (rxBuffer == 0) { |
| 394 | /* check BUF0 */ |
394 | /* check BUF0 */ |
| 395 | if (stat & MCP_STAT_RX0IF) { |
395 | if (stat & MCP_STAT_RX0IF) { |
| 396 | /* Msg in Buffer 0 */ |
396 | /* Msg in Buffer 0 */ |
| 397 | MCP2515_ReadCanMsg(MCP_RXBUF_0, msg); |
397 | MCP2515_ReadCanMsg(MCP_RXBUF_0, msg); |
| 398 | MCP2515_ModifyRegister(MCP_CANINTF, MCP_RX0IF, 0); |
398 | MCP2515_ModifyRegister(MCP_CANINTF, MCP_RX0IF, 0); |
| 399 | return CAN_OK; |
399 | return CAN_OK; |
| 400 | } |
400 | } |
| 401 | } |
401 | } |
| 402 | else if (rxBuffer == 1) { |
402 | else if (rxBuffer == 1) { |
| 403 | /* check BUF1 */ |
403 | /* check BUF1 */ |
| 404 | if (stat & MCP_STAT_RX1IF) { |
404 | if (stat & MCP_STAT_RX1IF) { |
| 405 | /* Msg in Buffer 1 */ |
405 | /* Msg in Buffer 1 */ |
| 406 | MCP2515_ReadCanMsg(MCP_RXBUF_1, msg); |
406 | MCP2515_ReadCanMsg(MCP_RXBUF_1, msg); |
| 407 | MCP2515_ModifyRegister(MCP_CANINTF, MCP_RX1IF, 0); |
407 | MCP2515_ModifyRegister(MCP_CANINTF, MCP_RX1IF, 0); |
| 408 | return CAN_OK; |
408 | return CAN_OK; |
| 409 | } |
409 | } |
| 410 | } |
410 | } |
| 411 | else { |
411 | else { |
| 412 | /* invalid parameters */ |
412 | /* invalid parameters */ |
| 413 | return CAN_FAIL; |
413 | return CAN_FAIL; |
| 414 | } |
414 | } |
| 415 | return CAN_NO_MSG_AVAILABLE; |
415 | return CAN_NO_MSG_AVAILABLE; |
| 416 | #endif |
416 | #endif |
| 417 | } |
417 | } |
| 418 | 418 | ||
| 419 | 419 | ||
| 420 | /** |
420 | /** |
| 421 | * Checks how many messages are available in the CAN controller hardware. |
421 | * Checks how many messages are available in the CAN controller hardware. |
| 422 | * |
422 | * |
| 423 | * @return |
423 | * @return |
| 424 | * The number of messages available (0 if none). |
424 | * The number of messages available (0 if none). |
| 425 | */ |
425 | */ |
| 426 | static uint8_t Can_MessagesAvailableInController() { |
426 | static uint8_t Can_MessagesAvailableInController() { |
| 427 | #if CAN_CONTROLLER == CAN_CONTROLLER_NULL |
427 | #if CAN_CONTROLLER == CAN_CONTROLLER_NULL |
| 428 | /* |
428 | /* |
| 429 | * Check for messages in null device. |
429 | * Check for messages in null device. |
| 430 | */ |
430 | */ |
| 431 | return 0; |
431 | return 0; |
| 432 | #endif |
432 | #endif |
| 433 | 433 | ||
| 434 | #if CAN_CONTROLLER == CAN_CONTROLLER_MCP2515 |
434 | #if CAN_CONTROLLER == CAN_CONTROLLER_MCP2515 |
| 435 | /* |
435 | /* |
| 436 | * Check for message in MCP2515 device. |
436 | * Check for message in MCP2515 device. |
| 437 | */ |
437 | */ |
| 438 | uint8_t res; |
438 | uint8_t res; |
| 439 | res = MCP2515_ReadStatus(); /* RXnIF in Bit 1 and 0 */ |
439 | res = MCP2515_ReadStatus(); /* RXnIF in Bit 1 and 0 */ |
| 440 | if (res & MCP_STAT_RXIF_MASK) { |
440 | if (res & MCP_STAT_RXIF_MASK) { |
| 441 | //TODO: check how many messages are available |
441 | //TODO: check how many messages are available |
| 442 | return 1; /* at least one message available */ |
442 | return 1; /* at least one message available */ |
| 443 | } |
443 | } |
| 444 | else { |
444 | else { |
| 445 | return 0; /* no messages available */ |
445 | return 0; /* no messages available */ |
| 446 | } |
446 | } |
| 447 | #endif |
447 | #endif |
| 448 | 448 | ||
| 449 | return 0; |
449 | return 0; |
| 450 | } |
450 | } |
| 451 | 451 | ||
| 452 | 452 | ||
| 453 | /* |
453 | /* |
| 454 | * Checks Controller-Error-State. |
454 | * Checks Controller-Error-State. |
| 455 | * |
455 | * |
| 456 | * @return |
456 | * @return |
| 457 | * CAN_OK if the controller is OK. |
457 | * CAN_OK if the controller is OK. |
| 458 | * CAN_FAIL if errors have occured. |
458 | * CAN_FAIL if errors have occured. |
| 459 | * |
459 | * |
| 460 | * @todo |
460 | * @todo |
| 461 | * Styr upp denna funktion lite b�ttre. |
461 | * Styr upp denna funktion lite b�ttre. |
| 462 | */ |
462 | */ |
| 463 | static Can_Return_t Can_ControllerCheckError() { |
463 | static Can_Return_t Can_ControllerCheckError() { |
| 464 | #if CAN_CONTROLLER == CAN_CONTROLLER_NULL |
464 | #if CAN_CONTROLLER == CAN_CONTROLLER_NULL |
| 465 | /* |
465 | /* |
| 466 | * Check for errors in null device. |
466 | * Check for errors in null device. |
| 467 | */ |
467 | */ |
| 468 | return CAN_OK; |
468 | return CAN_OK; |
| 469 | #endif |
469 | #endif |
| 470 | 470 | ||
| 471 | #if CAN_CONTROLLER == CAN_CONTROLLER_MCP2515 |
471 | #if CAN_CONTROLLER == CAN_CONTROLLER_MCP2515 |
| 472 | /* |
472 | /* |
| 473 | * Check for errors in MCP2515 device. |
473 | * Check for errors in MCP2515 device. |
| 474 | */ |
474 | */ |
| 475 | uint8_t eflg = MCP2515_ReadRegister(MCP_EFLG); |
475 | uint8_t eflg = MCP2515_ReadRegister(MCP_EFLG); |
| 476 | if (eflg & MCP_EFLG_ERRORMASK) { |
476 | if (eflg & MCP_EFLG_ERRORMASK) { |
| 477 | return CAN_FAIL; /* errors found */ |
477 | return CAN_FAIL; /* errors found */ |
| 478 | } |
478 | } |
| 479 | else { |
479 | else { |
| 480 | return CAN_OK; /* no errors found */ |
480 | return CAN_OK; /* no errors found */ |
| 481 | } |
481 | } |
| 482 | #endif |
482 | #endif |
| 483 | } |
483 | } |
| 484 | 484 | ||
| 485 | 485 | ||
| 486 | #if (CAN_QUEUE_SIZE_TX > 0) || (CAN_QUEUE_SIZE_RX > 0) |
486 | #if (CAN_QUEUE_SIZE_TX > 0) || (CAN_QUEUE_SIZE_RX > 0) |
| 487 | /** |
487 | /** |
| 488 | * Initializes a CAN queue. |
488 | * Initializes a CAN queue. |
| 489 | * |
489 | * |
| 490 | * @param q |
490 | * @param q |
| 491 | * Pointer to the queue object. |
491 | * Pointer to the queue object. |
| 492 | * |
492 | * |
| 493 | * @param size |
493 | * @param size |
| 494 | * Size of the queue (number of messages that can be queued). |
494 | * Size of the queue (number of messages that can be queued). |
| 495 | * |
495 | * |
| 496 | * @param dataPtr |
496 | * @param dataPtr |
| 497 | * Pointer to the message storage buffer that should be used by the queue. |
497 | * Pointer to the message storage buffer that should be used by the queue. |
| 498 | */ |
498 | */ |
| 499 | static void Can_QueueInit(Can_MessageQueue_t *q, uint8_t size, Can_Message_t *dataPtr) { |
499 | static void Can_QueueInit(Can_MessageQueue_t *q, uint8_t size, Can_Message_t *dataPtr) { |
| 500 | q->dataPtr = dataPtr; |
500 | q->dataPtr = dataPtr; |
| 501 | q->head = 0; |
501 | q->head = 0; |
| 502 | q->tail = 0; |
502 | q->tail = 0; |
| 503 | q->nrElements = 0; |
503 | q->nrElements = 0; |
| 504 | q->size = size; |
504 | q->size = size; |
| 505 | } |
505 | } |
| 506 | 506 | ||
| 507 | 507 | ||
| 508 | /** |
508 | /** |
| 509 | * Inserts a new element in a queue and returns a pointer to the new element. |
509 | * Inserts a new element in a queue and returns a pointer to the new element. |
| 510 | * If the queue is full, the last element (the tail) will be overwritten by |
510 | * If the queue is full, the last element (the tail) will be overwritten by |
| 511 | * the new element. |
511 | * the new element. |
| 512 | * |
512 | * |
| 513 | * @param q |
513 | * @param q |
| 514 | * Pointer to the queue object. |
514 | * Pointer to the queue object. |
| 515 | * |
515 | * |
| 516 | * @return |
516 | * @return |
| 517 | * Pointer to the new message element. Use this pointer to copy data into the queue. |
517 | * Pointer to the new message element. Use this pointer to copy data into the queue. |
| 518 | */ |
518 | */ |
| 519 | static Can_Message_t* Can_QueueInsert(Can_MessageQueue_t *q) { |
519 | static Can_Message_t* Can_QueueInsert(Can_MessageQueue_t *q) { |
| 520 | Can_Message_t *ptr; |
520 | Can_Message_t *ptr; |
| 521 | #if 0 |
521 | #if 0 |
| 522 | printf("INSERT: bef=%u, ", q->nrElements); |
522 | printf("INSERT: bef=%u, ", q->nrElements); |
| 523 | #endif |
523 | #endif |
| 524 | if ((q->nrElements+1) > q->size) { |
524 | if ((q->nrElements+1) > q->size) { |
| 525 | q->tail = (q->tail + 1) % q->size; |
525 | q->tail = (q->tail + 1) % q->size; |
| 526 | q->nrElements--; |
526 | q->nrElements--; |
| 527 | #if 0 |
527 | #if 0 |
| 528 | printf("Can_QueueInsertViaPtr: QUEUE OVERRUN!\n\r"); |
528 | printf("Can_QueueInsertViaPtr: QUEUE OVERRUN!\n\r"); |
| 529 | #endif |
529 | #endif |
| 530 | } |
530 | } |
| 531 | ptr = &(q->dataPtr[q->head]); |
531 | ptr = &(q->dataPtr[q->head]); |
| 532 | #if 0 |
532 | #if 0 |
| 533 | if (q->handled[q->head] == 0) { |
533 | if (q->handled[q->head] == 0) { |
| 534 | printf("Can_QueueInsertViaPtr: discarding non-handled msg!\n\r"); |
534 | printf("Can_QueueInsertViaPtr: discarding non-handled msg!\n\r"); |
| 535 | } |
535 | } |
| 536 | #endif |
536 | #endif |
| 537 | q->head = (q->head + 1) % q->size; |
537 | q->head = (q->head + 1) % q->size; |
| 538 | q->nrElements++; |
538 | q->nrElements++; |
| 539 | #if 0 |
539 | #if 0 |
| 540 | printf("aft=%u\n\n", q->nrElements); |
540 | printf("aft=%u\n\n", q->nrElements); |
| 541 | #endif |
541 | #endif |
| 542 | return ptr; |
542 | return ptr; |
| 543 | } |
543 | } |
| 544 | 544 | ||
| 545 | 545 | ||
| 546 | /** |
546 | /** |
| 547 | * Returns a pointer to the last element in the queue (the tail). Use this pointer |
547 | * Returns a pointer to the last element in the queue (the tail). Use this pointer |
| 548 | * to extract the message, and then call Can_QueueRemoveTail to actually remove |
548 | * to extract the message, and then call Can_QueueRemoveTail to actually remove |
| 549 | * the element. |
549 | * the element. |
| 550 | * |
550 | * |
| 551 | * @param q |
551 | * @param q |
| 552 | * Pointer to the queue object. |
552 | * Pointer to the queue object. |
| 553 | * |
553 | * |
| 554 | * @return |
554 | * @return |
| 555 | * Pointer to the tail message element. |
555 | * Pointer to the tail message element. |
| 556 | */ |
556 | */ |
| 557 | static Can_Message_t* Can_QueueReadTailPtr(Can_MessageQueue_t *q) { |
557 | static Can_Message_t* Can_QueueReadTailPtr(Can_MessageQueue_t *q) { |
| 558 | if (q->nrElements > 0) { |
558 | if (q->nrElements > 0) { |
| 559 | return &(q->dataPtr[q->tail]); |
559 | return &(q->dataPtr[q->tail]); |
| 560 | } |
560 | } |
| 561 | else { |
561 | else { |
| 562 | return 0; |
562 | return 0; |
| 563 | } |
563 | } |
| 564 | } |
564 | } |
| 565 | 565 | ||
| 566 | 566 | ||
| 567 | /** |
567 | /** |
| 568 | * Removes the last element in the queue (the tail). You should have extracted |
568 | * Removes the last element in the queue (the tail). You should have extracted |
| 569 | * the data using Can_QueueReadTailPtr before using this function. |
569 | * the data using Can_QueueReadTailPtr before using this function. |
| 570 | * |
570 | * |
| 571 | * @param q |
571 | * @param q |
| 572 | * Pointer to the queue object. |
572 | * Pointer to the queue object. |
| 573 | */ |
573 | */ |
| 574 | static void Can_QueueRemoveTail(Can_MessageQueue_t *q) { |
574 | static void Can_QueueRemoveTail(Can_MessageQueue_t *q) { |
| 575 | if (q->nrElements > 0) { |
575 | if (q->nrElements > 0) { |
| 576 | q->tail = (q->tail + 1) % q->size; |
576 | q->tail = (q->tail + 1) % q->size; |
| 577 | q->nrElements--; |
577 | q->nrElements--; |
| 578 | #if 0 |
578 | #if 0 |
| 579 | printf("queue size = %u\n", q->nrElements); |
579 | printf("queue size = %u\n", q->nrElements); |
| 580 | #endif |
580 | #endif |
| 581 | } |
581 | } |
| 582 | } |
582 | } |
| 583 | 583 | ||
| 584 | #endif |
584 | #endif |
| 585 | 585 | ||