Subversion Repositories HomeAutomation

Rev

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(CAN_BITRATE) != MCP2515_OK) {
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