1 /*
2  * CAN module object for Microchip PIC32MX microcontroller.
3  *
4  * @file        CO_driver.c
5  * @author      Janez Paternoster
6  * @copyright   2004 - 2020 Janez Paternoster
7  *
8  * This file is part of CANopenNode, an opensource CANopen Stack.
9  * Project home page is <https://github.com/CANopenNode/CANopenNode>.
10  * For more information on CANopen see <http://www.can-cia.org/>.
11  *
12  * Licensed under the Apache License, Version 2.0 (the "License");
13  * you may not use this file except in compliance with the License.
14  * You may obtain a copy of the License at
15  *
16  *     http://www.apache.org/licenses/LICENSE-2.0
17  *
18  * Unless required by applicable law or agreed to in writing, software
19  * distributed under the License is distributed on an "AS IS" BASIS,
20  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21  * See the License for the specific language governing permissions and
22  * limitations under the License.
23  */
24 
25 
26 #include "CO_driver.h"
27 #include "CO_Emergency.h"
28 
29 
30 extern const CO_CANbitRateData_t  CO_CANbitRateData[8];
31 unsigned int CO_interruptStatus = 0;
32 
33 
34 /**
35  * Macro and Constants - CAN module registers
36  */
37     #define CAN_REG(base, offset) (*((volatile uint32_t *) (((uintptr_t) base) + _CAN1_BASE_ADDRESS + (offset))))
38 
39     #define CLR          0x04
40     #define SET          0x08
41     #define INV          0x0C
42 
43     #define C_CON        0x000                         /* Control Register */
44     #define C_CFG        0x010                         /* Baud Rate Configuration Register */
45     #define C_INT        0x020                         /* Interrupt Register */
46     #define C_VEC        0x030                         /* Interrupt Code Register */
47     #define C_TREC       0x040                         /* Transmit/Receive Error Counter Register */
48     #define C_FSTAT      0x050                         /* FIFO Status  Register */
49     #define C_RXOVF      0x060                         /* Receive FIFO Overflow Status Register */
50     #define C_TMR        0x070                         /* CAN Timer Register */
51     #define C_RXM        0x080 /*  + (0..3 x 0x10)      //Acceptance Filter Mask Register */
52     #define C_FLTCON     0x0C0 /*  + (0..7(3) x 0x10)   //Filter Control Register */
53     #define C_RXF        0x140 /*  + (0..31(15) x 0x10) //Acceptance Filter Register */
54     #define C_FIFOBA     0x340                         /* Message Buffer Base Address Register */
55     #define C_FIFOCON    0x350 /*  + (0..31(15) x 0x40) //FIFO Control Register */
56     #define C_FIFOINT    0x360 /*  + (0..31(15) x 0x40) //FIFO Interrupt Register */
57     #define C_FIFOUA     0x370 /*  + (0..31(15) x 0x40) //FIFO User Address Register */
58     #define C_FIFOCI     0x380 /*  + (0..31(15) x 0x40) //Module Message Index Register */
59 
60 
61 /* Number of hardware filters */
62 /* device PIC32MX530, 550 and 570 has only 16 registers for CAN reception (not 32). */
63 #ifdef __PIC32MX
64 #if (__PIC32_FEATURE_SET__ == 530) || (__PIC32_FEATURE_SET__ == 550) || (__PIC32_FEATURE_SET__ == 570)
65     #define NO_CAN_RXF  16
66 #endif
67 #endif
68 #ifndef NO_CAN_RXF
69     #define NO_CAN_RXF  32
70 #endif
71 
72 
73 /******************************************************************************/
CO_CANsetConfigurationMode(void * CANdriverState)74 void CO_CANsetConfigurationMode(void *CANdriverState){
75     uint32_t C_CONcopy = CAN_REG(CANdriverState, C_CON);
76 
77     /* switch ON can module */
78     C_CONcopy |= 0x00008000;
79     CAN_REG(CANdriverState, C_CON) = C_CONcopy;
80 
81     /* request configuration mode */
82     C_CONcopy &= 0xF8FFFFFF;
83     C_CONcopy |= 0x04000000;
84     CAN_REG(CANdriverState, C_CON) = C_CONcopy;
85 
86     /* wait for configuration mode */
87     while((CAN_REG(CANdriverState, C_CON) & 0x00E00000) != 0x00800000);
88 }
89 
90 
91 /******************************************************************************/
CO_CANsetNormalMode(CO_CANmodule_t * CANmodule)92 void CO_CANsetNormalMode(CO_CANmodule_t *CANmodule){
93 
94     /* request normal mode */
95     CAN_REG(CANmodule->CANdriverState, C_CON+CLR) = 0x07000000;
96 
97     /* wait for normal mode */
98     while((CAN_REG(CANmodule->CANdriverState, C_CON) & 0x00E00000) != 0x00000000);
99 
100     CANmodule->CANnormal = true;
101 }
102 
103 
104 /******************************************************************************/
CO_CANmodule_init(CO_CANmodule_t * CANmodule,void * CANdriverState,CO_CANrx_t rxArray[],uint16_t rxSize,CO_CANtx_t txArray[],uint16_t txSize,uint16_t CANbitRate)105 CO_ReturnError_t CO_CANmodule_init(
106         CO_CANmodule_t         *CANmodule,
107         void                   *CANdriverState,
108         CO_CANrx_t              rxArray[],
109         uint16_t                rxSize,
110         CO_CANtx_t              txArray[],
111         uint16_t                txSize,
112         uint16_t                CANbitRate)
113 {
114     uint16_t i;
115 
116     /* verify arguments */
117     if(CANmodule==NULL || rxArray==NULL || txArray==NULL){
118         return CO_ERROR_ILLEGAL_ARGUMENT;
119     }
120 
121     /* Configure object variables */
122     CANmodule->CANdriverState = CANdriverState;
123     CANmodule->CANmsgBuffSize = 33; /* Must be the same as size of CANmodule->CANmsgBuff array. */
124     CANmodule->rxArray = rxArray;
125     CANmodule->rxSize = rxSize;
126     CANmodule->txArray = txArray;
127     CANmodule->txSize = txSize;
128     CANmodule->CANnormal = false;
129     CANmodule->useCANrxFilters = (rxSize <= NO_CAN_RXF) ? true : false;
130     CANmodule->bufferInhibitFlag = false;
131     CANmodule->firstCANtxMessage = true;
132     CANmodule->CANtxCount = 0U;
133     CANmodule->errOld = 0U;
134     CANmodule->em = NULL;
135 
136     for(i=0U; i<rxSize; i++){
137         rxArray[i].ident = 0U;
138         rxArray[i].pFunct = NULL;
139     }
140     for(i=0U; i<txSize; i++){
141         txArray[i].bufferFull = false;
142     }
143 
144     /* clear FIFO */
145     if(sizeof(CO_CANrxMsg_t) != 16) while(1);/* some safety */
146     uint32_t* f = (uint32_t*) CANmodule->CANmsgBuff;
147     for(i=0; i<(CANmodule->CANmsgBuffSize*4); i++){
148         *(f++) = 0;
149     }
150 
151 
152     /* Configure control register (configuration mode, receive timer stamp is enabled, module is on) */
153     CAN_REG(CANdriverState, C_CON) = 0x04108000;
154 
155 
156     /* Configure FIFO */
157     CAN_REG(CANdriverState, C_FIFOBA) = CO_KVA_TO_PA(CANmodule->CANmsgBuff);/* FIFO base address */
158     CAN_REG(CANdriverState, C_FIFOCON) = (NO_CAN_RXF==32) ? 0x001F0000 : 0x000F0000;     /* FIFO0: receive FIFO, 32(16) buffers */
159     CAN_REG(CANdriverState, C_FIFOCON+0x40) = 0x00000080;/* FIFO1: transmit FIFO, 1 buffer */
160 
161 
162     /* Configure CAN timing */
163     switch(CANbitRate){
164         case 10:   i=0; break;
165         case 20:   i=1; break;
166         case 50:   i=2; break;
167         default:
168         case 125:  i=3; break;
169         case 250:  i=4; break;
170         case 500:  i=5; break;
171         case 800:  i=6; break;
172         case 1000: i=7; break;
173     }
174     CAN_REG(CANdriverState, C_CFG) =
175         ((uint32_t)(CO_CANbitRateData[i].phSeg2 - 1)) << 16 |  /* SEG2PH */
176         0x00008000                                            |  /* SEG2PHTS = 1, SAM = 0 */
177         ((uint32_t)(CO_CANbitRateData[i].phSeg1 - 1)) << 11 |  /* SEG1PH */
178         ((uint32_t)(CO_CANbitRateData[i].PROP - 1))   << 8  |  /* PRSEG */
179         ((uint32_t)(CO_CANbitRateData[i].SJW - 1))    << 6  |  /* SJW */
180         ((uint32_t)(CO_CANbitRateData[i].BRP - 1));            /* BRP */
181 
182 
183     /* CAN module hardware filters */
184     /* clear all filter control registers (disable filters, mask 0 and FIFO 0 selected for all filters) */
185     for(i=0; i<(NO_CAN_RXF/4); i++)
186         CAN_REG(CANdriverState, C_FLTCON+i*0x10) = 0x00000000;
187     if(CANmodule->useCANrxFilters){
188         /* CAN module filters are used, they will be configured with */
189         /* CO_CANrxBufferInit() functions, called by separate CANopen */
190         /* init functions. */
191         /* Configure all masks so, that received message must match filter */
192         CAN_REG(CANdriverState, C_RXM) = 0xFFE80000;
193         CAN_REG(CANdriverState, C_RXM+0x10) = 0xFFE80000;
194         CAN_REG(CANdriverState, C_RXM+0x20) = 0xFFE80000;
195         CAN_REG(CANdriverState, C_RXM+0x30) = 0xFFE80000;
196     }
197     else{
198         /* CAN module filters are not used, all messages with standard 11-bit */
199         /* identifier will be received */
200         /* Configure mask 0 so, that all messages with standard identifier are accepted */
201         CAN_REG(CANdriverState, C_RXM) = 0x00080000;
202         /* configure one filter for FIFO 0 and enable it */
203         CAN_REG(CANdriverState, C_RXF) = 0x00000000;
204         CAN_REG(CANdriverState, C_FLTCON) = 0x00000080;
205     }
206 
207 
208     /* CAN interrupt registers */
209     /* Enable 'RX buffer not empty' (RXNEMPTYIE) interrupt in FIFO 0 (third layer interrupt) */
210     CAN_REG(CANdriverState, C_FIFOINT) = 0x00010000;
211     /* Enable 'Tx buffer empty' (TXEMPTYIE) interrupt in FIFO 1 (third layer interrupt) */
212     CAN_REG(CANdriverState, C_FIFOINT+0x40) = 0x00000000; /* will be enabled in CO_CANsend */
213     /* Enable receive (RBIE) and transmit (TBIE) buffer interrupt (secont layer interrupt) */
214     CAN_REG(CANdriverState, C_INT) = 0x00030000;
215     /* CAN interrupt (first layer) must be configured by application */
216 
217     return CO_ERROR_NO;
218 }
219 
220 
221 /******************************************************************************/
CO_CANmodule_disable(CO_CANmodule_t * CANmodule)222 void CO_CANmodule_disable(CO_CANmodule_t *CANmodule){
223     CO_CANsetConfigurationMode(CANmodule->CANdriverState);
224 }
225 
226 
227 /******************************************************************************/
CO_CANrxMsg_readIdent(const CO_CANrxMsg_t * rxMsg)228 uint16_t CO_CANrxMsg_readIdent(const CO_CANrxMsg_t *rxMsg){
229     return rxMsg->ident;
230 }
231 
232 
233 /******************************************************************************/
CO_CANrxBufferInit(CO_CANmodule_t * CANmodule,uint16_t index,uint16_t ident,uint16_t mask,bool_t rtr,void * object,void (* pFunct)(void * object,const CO_CANrxMsg_t * message))234 CO_ReturnError_t CO_CANrxBufferInit(
235         CO_CANmodule_t         *CANmodule,
236         uint16_t                index,
237         uint16_t                ident,
238         uint16_t                mask,
239         bool_t                  rtr,
240         void                   *object,
241         void                  (*pFunct)(void *object, const CO_CANrxMsg_t *message))
242 {
243     CO_ReturnError_t ret = CO_ERROR_NO;
244 
245     if((CANmodule!=NULL) && (object!=NULL) && (pFunct!=NULL) && (index < CANmodule->rxSize)){
246         /* buffer, which will be configured */
247         CO_CANrx_t *buffer = &CANmodule->rxArray[index];
248 
249         /* Configure object variables */
250         buffer->object = object;
251         buffer->pFunct = pFunct;
252 
253         /* CAN identifier and CAN mask, bit aligned with CAN module FIFO buffers (RTR is extra) */
254         buffer->ident = ident & 0x07FFU;
255         if(rtr){
256             buffer->ident |= 0x0800U;
257         }
258         buffer->mask = (mask & 0x07FFU) | 0x0800U;
259 
260         /* Set CAN hardware module filter and mask. */
261         if(CANmodule->useCANrxFilters){
262             uint32_t RXF, RXM;
263             volatile uint32_t *pRXF;
264             volatile uint32_t *pRXM0, *pRXM1, *pRXM2, *pRXM3;
265             volatile uint8_t *pFLTCON;
266             uint8_t selectMask;
267             uint16_t addr = CANmodule->CANdriverState;
268 
269             /* get correct part of the filter control register */
270             pFLTCON = (volatile uint8_t*)(&CAN_REG(addr, C_FLTCON)); /* pointer to first filter control register */
271             pFLTCON += (index/4) * 0x10;   /* now points to the correct C_FLTCONi */
272             pFLTCON += index%4;   /* now points to correct part of the correct C_FLTCONi */
273 
274             /* disable filter and wait if necessary */
275             while(*pFLTCON & 0x80) *pFLTCON &= 0x7F;
276 
277             /* align RXF and RXM with C_RXF and C_RXM registers */
278             RXF = (uint32_t)ident << 21;
279             RXM = (uint32_t)mask << 21 | 0x00080000;
280 
281             /* write to filter */
282             pRXF = &CAN_REG(addr, C_RXF); /* pointer to first filter register */
283             pRXF += index * (0x10/4);   /* now points to C_RXFi (i == index) */
284             *pRXF = RXF;         /* write value to filter */
285 
286             /* configure mask (There are four masks, each of them can be asigned to any filter. */
287             /*                 First mask has always the value 0xFFE80000 - all 11 bits must match). */
288             pRXM0 = &CAN_REG(addr, C_RXM);
289             pRXM1 = &CAN_REG(addr, C_RXM+0x10);
290             pRXM2 = &CAN_REG(addr, C_RXM+0x20);
291             pRXM3 = &CAN_REG(addr, C_RXM+0x30);
292             if(RXM == *pRXM0){
293                 selectMask = 0;
294             }
295             else if(RXM == *pRXM1 || *pRXM1 == 0xFFE80000){
296                 /* RXM is equal to mask 1 or mask 1 was not yet configured. */
297                 *pRXM1 = RXM;
298                 selectMask = 1;
299             }
300             else if(RXM == *pRXM2 || *pRXM2 == 0xFFE80000){
301                 /* RXM is equal to mask 2 or mask 2 was not yet configured. */
302                 *pRXM2 = RXM;
303                 selectMask = 2;
304             }
305             else if(RXM == *pRXM3 || *pRXM3 == 0xFFE80000){
306                 /* RXM is equal to mask 3 or mask 3 was not yet configured. */
307                 *pRXM3 = RXM;
308                 selectMask = 3;
309             }
310             else{
311                 /* not enough masks */
312                 selectMask = 0;
313                 ret = CO_ERROR_OUT_OF_MEMORY;
314             }
315             /* write to appropriate filter control register */
316             *pFLTCON = 0x80 | (selectMask << 5); /* enable filter and write filter mask select bit */
317         }
318     }
319     else{
320         ret = CO_ERROR_ILLEGAL_ARGUMENT;
321     }
322 
323     return ret;
324 }
325 
326 
327 /******************************************************************************/
CO_CANtxBufferInit(CO_CANmodule_t * CANmodule,uint16_t index,uint16_t ident,bool_t rtr,uint8_t noOfBytes,bool_t syncFlag)328 CO_CANtx_t *CO_CANtxBufferInit(
329         CO_CANmodule_t         *CANmodule,
330         uint16_t                index,
331         uint16_t                ident,
332         bool_t                  rtr,
333         uint8_t                 noOfBytes,
334         bool_t                  syncFlag)
335 {
336     CO_CANtx_t *buffer = NULL;
337 
338     if((CANmodule != NULL) && (index < CANmodule->txSize)){
339         /* get specific buffer */
340         buffer = &CANmodule->txArray[index];
341 
342         /* CAN identifier, DLC and rtr, bit aligned with CAN module transmit buffer */
343         buffer->CMSGSID = ident & 0x07FF;
344         buffer->CMSGEID = (noOfBytes & 0xF) | (rtr?0x0200:0);
345 
346         buffer->bufferFull = false;
347         buffer->syncFlag = syncFlag;
348     }
349 
350     return buffer;
351 }
352 
353 
354 /******************************************************************************/
CO_CANsend(CO_CANmodule_t * CANmodule,CO_CANtx_t * buffer)355 CO_ReturnError_t CO_CANsend(CO_CANmodule_t *CANmodule, CO_CANtx_t *buffer){
356     CO_ReturnError_t err = CO_ERROR_NO;
357     uint16_t addr = CANmodule->CANdriverState;
358     volatile uint32_t* TX_FIFOcon = &CAN_REG(addr, C_FIFOCON+0x40);
359     volatile uint32_t* TX_FIFOconSet = &CAN_REG(addr, C_FIFOCON+0x48);
360     uint32_t* TXmsgBuffer = CO_PA_TO_KVA1(CAN_REG(addr, C_FIFOUA+0x40));
361     uint32_t* message = (uint32_t*) buffer;
362     uint32_t TX_FIFOconCopy;
363 
364     /* Verify overflow */
365     if(buffer->bufferFull){
366         if(!CANmodule->firstCANtxMessage){
367             /* don't set error, if bootup message is still on buffers */
368             CO_errorReport((CO_EM_t*)CANmodule->em, CO_EM_CAN_TX_OVERFLOW, CO_EMC_CAN_OVERRUN, buffer->CMSGSID);
369         }
370         err = CO_ERROR_TX_OVERFLOW;
371     }
372 
373     CO_LOCK_CAN_SEND();
374     TX_FIFOconCopy = *TX_FIFOcon;
375     /* if CAN TX buffer is free, copy message to it */
376     if((TX_FIFOconCopy & 0x8) == 0 && CANmodule->CANtxCount == 0){
377         CANmodule->bufferInhibitFlag = buffer->syncFlag;
378         *(TXmsgBuffer++) = *(message++);
379         *(TXmsgBuffer++) = *(message++);
380         *(TXmsgBuffer++) = *(message++);
381         *(TXmsgBuffer++) = *(message++);
382         /* if message was aborted, don't set UINC */
383         if((TX_FIFOconCopy & 0x40) == 0)
384             *TX_FIFOconSet = 0x2000;   /* set UINC */
385         *TX_FIFOconSet = 0x0008;   /* set TXREQ */
386     }
387     /* if no buffer is free, message will be sent by interrupt */
388     else{
389         buffer->bufferFull = true;
390         CANmodule->CANtxCount++;
391     }
392     /* Enable 'Tx buffer empty' (TXEMPTYIE) interrupt in FIFO 1 (third layer interrupt) */
393     CAN_REG(addr, C_FIFOINT+0x48) = 0x01000000;
394     CO_UNLOCK_CAN_SEND();
395 
396     return err;
397 }
398 
399 
400 /******************************************************************************/
CO_CANclearPendingSyncPDOs(CO_CANmodule_t * CANmodule)401 void CO_CANclearPendingSyncPDOs(CO_CANmodule_t *CANmodule){
402     uint32_t tpdoDeleted = 0U;
403     volatile uint32_t* TX_FIFOcon = &CAN_REG(CANmodule->CANdriverState, C_FIFOCON+0x40);
404     volatile uint32_t* TX_FIFOconClr = &CAN_REG(CANmodule->CANdriverState, C_FIFOCON+0x44);
405 
406     CO_LOCK_CAN_SEND();
407     /* Abort message from CAN module, if there is synchronous TPDO.
408      * Take special care with this functionality. */
409     if((*TX_FIFOcon & 0x8) && CANmodule->bufferInhibitFlag){
410         *TX_FIFOconClr = 0x0008;   /* clear TXREQ */
411         CANmodule->bufferInhibitFlag = false;
412         tpdoDeleted = 1U;
413     }
414     /* delete also pending synchronous TPDOs in TX buffers */
415     if(CANmodule->CANtxCount != 0U){
416         uint16_t i;
417         CO_CANtx_t *buffer = &CANmodule->txArray[0];
418         for(i = CANmodule->txSize; i > 0U; i--){
419             if(buffer->bufferFull){
420                 if(buffer->syncFlag){
421                     buffer->bufferFull = false;
422                     CANmodule->CANtxCount--;
423                     tpdoDeleted = 2U;
424                 }
425             }
426             buffer++;
427         }
428     }
429     CO_UNLOCK_CAN_SEND();
430 
431 
432     if(tpdoDeleted != 0U){
433         CO_errorReport((CO_EM_t*)CANmodule->em, CO_EM_TPDO_OUTSIDE_WINDOW, CO_EMC_COMMUNICATION, tpdoDeleted);
434     }
435 }
436 
437 
438 /******************************************************************************/
CO_CANverifyErrors(CO_CANmodule_t * CANmodule)439 void CO_CANverifyErrors(CO_CANmodule_t *CANmodule){
440     uint16_t rxErrors, txErrors, overflow;
441     uint32_t TREC;
442     CO_EM_t* em = (CO_EM_t*)CANmodule->em;
443     uint32_t err;
444 
445     TREC = CAN_REG(CANmodule->CANdriverState, C_TREC);
446     rxErrors = (uint8_t) TREC;
447     txErrors = (uint8_t) (TREC>>8);
448     if(TREC&0x00200000) txErrors = 256; /* bus off */
449     overflow = (CAN_REG(CANmodule->CANdriverState, C_FIFOINT)&0x8) ? 1 : 0;
450 
451     err = ((uint32_t)txErrors << 16) | ((uint32_t)rxErrors << 8) | overflow;
452 
453     if(CANmodule->errOld != err){
454         CANmodule->errOld = err;
455 
456         if(txErrors >= 256U){                               /* bus off */
457             CO_errorReport(em, CO_EM_CAN_TX_BUS_OFF, CO_EMC_BUS_OFF_RECOVERED, err);
458         }
459         else{                                               /* not bus off */
460             CO_errorReset(em, CO_EM_CAN_TX_BUS_OFF, err);
461 
462             if((rxErrors >= 96U) || (txErrors >= 96U)){     /* bus warning */
463                 CO_errorReport(em, CO_EM_CAN_BUS_WARNING, CO_EMC_NO_ERROR, err);
464             }
465 
466             if(rxErrors >= 128U){                           /* RX bus passive */
467                 CO_errorReport(em, CO_EM_CAN_RX_BUS_PASSIVE, CO_EMC_CAN_PASSIVE, err);
468             }
469             else{
470                 CO_errorReset(em, CO_EM_CAN_RX_BUS_PASSIVE, err);
471             }
472 
473             if(txErrors >= 128U){                           /* TX bus passive */
474                 if(!CANmodule->firstCANtxMessage){
475                     CO_errorReport(em, CO_EM_CAN_TX_BUS_PASSIVE, CO_EMC_CAN_PASSIVE, err);
476                 }
477             }
478             else{
479                 bool_t isError = CO_isError(em, CO_EM_CAN_TX_BUS_PASSIVE);
480                 if(isError){
481                     CO_errorReset(em, CO_EM_CAN_TX_BUS_PASSIVE, err);
482                     CO_errorReset(em, CO_EM_CAN_TX_OVERFLOW, err);
483                 }
484             }
485 
486             if((rxErrors < 96U) && (txErrors < 96U)){       /* no error */
487                 CO_errorReset(em, CO_EM_CAN_BUS_WARNING, err);
488             }
489         }
490 
491         if(overflow != 0U){                                 /* CAN RX bus overflow */
492             CO_errorReport(em, CO_EM_CAN_RXB_OVERFLOW, CO_EMC_CAN_OVERRUN, err);
493         }
494     }
495 }
496 
497 
498 /******************************************************************************/
CO_CANinterrupt(CO_CANmodule_t * CANmodule)499 void CO_CANinterrupt(CO_CANmodule_t *CANmodule){
500     uint8_t ICODE;
501     ICODE = (uint8_t) CAN_REG(CANmodule->CANdriverState, C_VEC) & 0x7F;
502 
503     /* receive interrupt (New CAN message is available in RX FIFO 0 buffer) */
504     if(ICODE == 0){
505         CO_CANrxMsg_t *rcvMsg;      /* pointer to received message in CAN module */
506         uint16_t index;             /* index of received message */
507         uint16_t rcvMsgIdent;       /* identifier of the received message */
508         CO_CANrx_t *buffer = NULL;  /* receive message buffer from CO_CANmodule_t object. */
509         bool_t msgMatched = false;
510 
511         rcvMsg = (CO_CANrxMsg_t*) CO_PA_TO_KVA1(CAN_REG(CANmodule->CANdriverState, C_FIFOUA));
512         rcvMsgIdent = rcvMsg->ident;
513         if(rcvMsg->RTR) rcvMsgIdent |= 0x0800;
514         if(CANmodule->useCANrxFilters){
515             /* CAN module filters are used. Message with known 11-bit identifier has */
516             /* been received */
517             index = rcvMsg->FILHIT;
518             if(index < CANmodule->rxSize){
519                 buffer = &CANmodule->rxArray[index];
520                 /* verify also RTR */
521                 if(((rcvMsgIdent ^ buffer->ident) & buffer->mask) == 0U){
522                     msgMatched = true;
523                 }
524             }
525         }
526         else{
527             /* CAN module filters are not used, message with any standard 11-bit identifier */
528             /* has been received. Search rxArray form CANmodule for the same CAN-ID. */
529             buffer = &CANmodule->rxArray[0];
530             for(index = CANmodule->rxSize; index > 0U; index--){
531                 if(((rcvMsgIdent ^ buffer->ident) & buffer->mask) == 0U){
532                     msgMatched = true;
533                     break;
534                 }
535                 buffer++;
536             }
537         }
538 
539         /* Call specific function, which will process the message */
540         if(msgMatched && (buffer != NULL) && (buffer->pFunct != NULL)){
541             buffer->pFunct(buffer->object, rcvMsg);
542         }
543 
544         /* Update the message buffer pointer */
545         CAN_REG(CANmodule->CANdriverState, C_FIFOCON+0x08) = 0x2000;   /* set UINC */
546     }
547 
548 
549     /* transmit interrupt (TX buffer FIFO 1 is free) */
550     else if(ICODE == 1){
551         /* First CAN message (bootup) was sent successfully */
552         CANmodule->firstCANtxMessage = false;
553         /* clear flag from previous message */
554         CANmodule->bufferInhibitFlag = false;
555         /* Are there any new messages waiting to be send */
556         if(CANmodule->CANtxCount > 0U){
557             uint16_t i;             /* index of transmitting message */
558 
559             /* first buffer */
560             CO_CANtx_t *buffer = &CANmodule->txArray[0];
561             /* search through whole array of pointers to transmit message buffers. */
562             for(i = CANmodule->txSize; i > 0U; i--){
563                 /* if message buffer is full, send it. */
564                 if(buffer->bufferFull){
565                     buffer->bufferFull = false;
566                     CANmodule->CANtxCount--;
567 
568                     /* Copy message to CAN buffer */
569                     CANmodule->bufferInhibitFlag = buffer->syncFlag;
570                     uint32_t* TXmsgBuffer = CO_PA_TO_KVA1(CAN_REG(CANmodule->CANdriverState, C_FIFOUA+0x40));
571                     uint32_t* message = (uint32_t*) buffer;
572                     volatile uint32_t* TX_FIFOconSet = &CAN_REG(CANmodule->CANdriverState, C_FIFOCON+0x48);
573                     *(TXmsgBuffer++) = *(message++);
574                     *(TXmsgBuffer++) = *(message++);
575                     *(TXmsgBuffer++) = *(message++);
576                     *(TXmsgBuffer++) = *(message++);
577                     *TX_FIFOconSet = 0x2000;    /* set UINC */
578                     *TX_FIFOconSet = 0x0008;    /* set TXREQ */
579                     break;                      /* exit for loop */
580                 }
581                 buffer++;
582             }/* end of for loop */
583 
584             /* Clear counter if no more messages */
585             if(i == 0U){
586                 CANmodule->CANtxCount = 0U;
587             }
588         }
589 
590         /* if no more messages, disable 'Tx buffer empty' (TXEMPTYIE) interrupt */
591         if(CANmodule->CANtxCount == 0U){
592             CAN_REG(CANmodule->CANdriverState, C_FIFOINT+0x44) = 0x01000000;
593         }
594     }
595 }
596