Subversion Repositories HomeAutomation

Rev

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 Interface. This is a general high-level interface for CAN communication.
2
 * CAN communication interface. This is a general, high-level interface for CAN
3
 * Underlying CAN controllers are abstracted by this interface, so the
3
 * communication. Underlying CAN controllers are abstracted by this interface,
4
 * application needs not work directly against 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
-
 
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-19
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 "timebase.h"
28
#include <timebase.h>
19
 
-
 
20
 
-
 
-
 
29
#include <assert.h>
21
#ifdef CAN_CONTROLLER_MCP2515
30
#if CAN_CONTROLLER == CAN_CONTROLLER_MCP2515
22
    #include "mcp2515.h"
31
    #include "mcp2515.h"
23
#else
32
#endif
-
 
33
 
-
 
34
 
-
 
35
/*-----------------------------------------------------------------------------
-
 
36
 * Prerequisites
-
 
37
 *---------------------------------------------------------------------------*/
-
 
38
#ifndef CAN_CONTROLLER
24
    #error No CAN controller specified! Edit can_cfg.h !
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
 *      CAN_FAILINIT otherwise.
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
    Can_Bitrate_t bitrate = CAN_BITRATE;
140
    #if CAN_CONTROLLER == CAN_CONTROLLER_NULL
-
 
141
        /*
-
 
142
         * Initialize null device.
-
 
143
         */
-
 
144
        return CAN_OK;
-
 
145
    #endif
-
 
146
   
41
#ifdef CAN_CONTROLLER_MCP2515
147
    #if CAN_CONTROLLER == CAN_CONTROLLER_MCP2515
-
 
148
        /*
-
 
149
         * Initialize MCP2515 device.
-
 
150
         */
42
    if (MCP2515_Init(bitrate) != MCP2515_OK) {
151
        if (MCP2515_Init(CAN_BITRATE) != MCP2515_OK) {
43
        return CAN_FAILINIT;
152
            return CAN_FAIL;
44
    }
153
        }
45
    if (MCP2515_SetCanCtrlMode(MODE_NORMAL) != MCP2515_OK) {
154
        if (MCP2515_SetCanCtrlMode(MODE_NORMAL) != MCP2515_OK) {
46
        return CAN_FAILINIT;
155
            return CAN_FAIL;
47
    }
156
        }
48
    return CAN_OK;
157
        return CAN_OK;
49
#endif
158
    #endif
50
 
159
   
51
    return CAN_FAILINIT;
160
    return CAN_FAIL;
52
   
-
 
53
}
161
}
54
 
162
 
55
 
163
 
56
/**
164
/**
57
 * Sends a CAN message. If the CAN controller is busy, the message will be
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
 * copied to an internal transmission queue and transmitted later.
167
 * message will not be taken care of, and CAN_FAIL is returned.
59
 *
168
 *
60
 * @param msg
169
 * @param msg
61
 *      Pointer to the CAN message storage buffer.
170
 *      Pointer to the CAN message.
-
 
171
 *
62
 * @return
172
 * @return
63
 *      CAN_OK if the message was successfully sent (or put in queue).
173
 *      CAN_OK if the message was successfully enqueued.
64
 *      CAN_FAILTX if the controller is busy AND the transmission queue is full.
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
#ifdef CAN_CONTROLLER_MCP2515
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 CAN_FAILTX;
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
 * is empty, a CAN message is moved from the queue into the message storage provided
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
 *      CAN_NOMSG if there are no received messages available.
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
Can_Return_t Can_Receive(Can_Message_t *msg) {
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
#ifdef CAN_CONTROLLER_MCP2515
383
    #if CAN_CONTROLLER == CAN_CONTROLLER_MCP2515
-
 
384
        /*
-
 
385
         * Receive from MCP2515 device.
-
 
386
         */
96
    uint8_t stat, res;
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
        // Msg in Buffer 0
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
        res = CAN_OK;
395
                return CAN_OK;
-
 
396
            }
103
    }
397
        }
-
 
398
        else if (rxBuffer == 1) {
-
 
399
            /* check BUF1 */
104
    else if (stat & MCP_STAT_RX1IF) {
400
            if (stat & MCP_STAT_RX1IF) {
105
        // Msg in Buffer 1
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
        res = CAN_OK;
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 CAN_NOMSG;
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
 *      CAN_CTRLERROR if errors have occured.
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 Can_CheckError(void) {
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
#ifdef CAN_CONTROLLER_MCP2515
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 CAN_CTRLERROR;
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 CAN_OK;
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