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