]> rtime.felk.cvut.cz Git - arc.git/blob - arch/arm/arm_cm3/drivers/Can.c
#ifdef:ed all Det includes
[arc.git] / arch / arm / arm_cm3 / drivers / Can.c
1 /* -------------------------------- Arctic Core ------------------------------
2  * Arctic Core - the open source AUTOSAR platform http://arccore.com
3  *
4  * Copyright (C) 2009  ArcCore AB <contact@arccore.com>
5  *
6  * This source code is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License version 2 as published by the
8  * Free Software Foundation; See <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13  * for more details.
14  * -------------------------------- Arctic Core ------------------------------*/
15
16 #include "Can.h"\r
17 \r
18 #ifndef USE_CAN_STUB
19 #include "stm32f10x.h"\r
20 #include "stm32f10x_can.h"
21 #include "Cpu.h"\r
22 #include "Mcu.h"\r
23 #include "CanIf_Cbk.h"
24 #if defined(USE_DET)\r
25 #include "Det.h"
26 #endif
27 #if defined(USE_DEM)
28 #include "Dem.h"\r
29 #endif
30 #include <assert.h>\r
31 #include <stdlib.h>\r
32 #include <string.h>\r
33 #include "Os.h"
34 #include "isr.h"\r
35 #include "arc.h"
36 \r
37
38 /* CONFIGURATION NOTES\r
39  * ------------------------------------------------------------------\r
40  * - CanHandleType must be CAN_ARC_HANDLE_TYPE_BASIC\r
41  *   i.e. CanHandleType=CAN_ARC_HANDLE_TYPE_FULL NOT supported\r
42  *   i.e CanIdValue is NOT supported\r
43  * - All CanXXXProcessing must be CAN_ARC_PROCESS_TYPE_INTERRUPT\r
44  *   ie CAN_ARC_PROCESS_TYPE_POLLED not supported\r
45  * - HOH's for Tx are global and Rx are for each controller\r
46  */\r
47 \r
48 /* IMPLEMENTATION NOTES\r
49  * -----------------------------------------------\r
50  * - A HOH us unique for a controller( not a config-set )\r
51  * - Hrh's are numbered for each controller from 0\r
52  * - loopback in HW NOT supported
53  * - Only one transmit mailbox is used because otherwise
54  *   we cannot use tx_confirmation since there is no way to know
55  *   which mailbox caused the tx interrupt. TP will need this feature.
56  * - Sleep,wakeup not fully implemented since other modules lack functionality\r
57  */\r
58 \r
59 /* ABBREVATIONS\r
60  *  -----------------------------------------------\r
61  * - Can Hardware unit - One or multiple Can controllers of the same type.\r
62  * - Hrh - HOH with receive definitions\r
63  * - Hth - HOH with transmit definitions\r
64  *\r
65  */\r
66
67 typedef CAN_TypeDef CAN_HW_t;\r
68 //-------------------------------------------------------------------\r
69 \r
70 #define GET_CONTROLLER_CONFIG(_controller)      \\r
71                                                 &Can_Global.config->CanConfigSet->CanController[(_controller)]\r
72 \r
73 #define GET_CALLBACKS() \\r
74                                                         (Can_Global.config->CanConfigSet->CanCallbacks)\r
75 \r
76 #define GET_PRIVATE_DATA(_controller) \\r
77                                                                         &CanUnit[_controller]\r
78 \r
79 #define GET_CONTROLLER_CNT() (CAN_CONTROLLER_CNT)\r
80 \r
81 //-------------------------------------------------------------------\r
82 \r
83 #if ( CAN_DEV_ERROR_DETECT == STD_ON )\r
84 #define VALIDATE(_exp,_api,_err ) \\r
85         if( !(_exp) ) { \\r
86           Det_ReportError(MODULE_ID_CAN,0,_api,_err); \\r
87           return CAN_NOT_OK; \\r
88         }\r
89 \r
90 #define VALIDATE_NO_RV(_exp,_api,_err ) \\r
91         if( !(_exp) ) { \\r
92           Det_ReportError(MODULE_ID_CAN,0,_api,_err); \\r
93           return; \\r
94         }\r
95 \r
96 #define DET_REPORTERROR(_x,_y,_z,_q) Det_ReportError(_x, _y, _z, _q)\r
97 #else\r
98 #define VALIDATE(_exp,_api,_err )\r
99 #define VALIDATE_NO_RV(_exp,_api,_err )\r
100 #define DET_REPORTERROR(_x,_y,_z,_q)\r
101 #endif\r
102
103 #if defined(USE_DEM)
104 #define VALIDATE_DEM_NO_RV(_exp,_err ) \
105         if( !(_exp) ) { \
106           Dem_ReportErrorStatus(_err, DEM_EVENT_STATUS_FAILED); \
107           return; \
108         }
109 #else
110 #define VALIDATE_DEM_NO_RV(_exp,_err )
111 #endif\r
112
113 //-------------------------------------------------------------------\r
114
115 typedef enum\r
116 {\r
117   CAN_UNINIT = 0,\r
118   CAN_READY\r
119 } Can_DriverStateType;\r
120 \r
121 // Mapping between HRH and Controller//HOH\r
122 typedef struct Can_Arc_ObjectHOHMapStruct\r
123 {\r
124   CanControllerIdType CanControllerRef;    // Reference to controller\r
125   const Can_HardwareObjectType* CanHOHRef;       // Reference to HOH.\r
126 } Can_Arc_ObjectHOHMapType;\r
127 \r
128 /* Type for holding global information used by the driver */\r
129 typedef struct {\r
130   Can_DriverStateType initRun;\r
131 \r
132   // Our config\r
133   const Can_ConfigType *config;\r
134 \r
135   // One bit for each channel that is configured.\r
136   // Used to determine if validity of a channel\r
137   // 1 - configured\r
138   // 0 - NOT configured\r
139   uint32  configured;\r
140   // Maps the a channel id to a configured channel id\r
141   uint8   channelMap[CAN_CONTROLLER_CNT];\r
142 \r
143   // This is a map that maps the HTH:s with the controller and Hoh. It is built\r
144   // during Can_Init and is used to make things faster during a transmit.\r
145   Can_Arc_ObjectHOHMapType CanHTHMap[NUM_OF_HTHS];\r
146 } Can_GlobalType;\r
147 \r
148 // Global config\r
149 Can_GlobalType Can_Global =\r
150 {\r
151     .initRun = CAN_UNINIT,\r
152 };\r
153 \r
154 /* Type for holding information about each controller */\r
155 typedef struct {\r
156   CanIf_ControllerModeType state;\r
157   uint32                lock_cnt;\r
158 \r
159   // Statistics\r
160   Can_Arc_StatisticsType stats;\r
161 \r
162   // Data stored for Txconfirmation callbacks to CanIf\r
163   PduIdType swPduHandle; //\r
164 } Can_UnitType;\r
165 \r
166 Can_UnitType CanUnit[CAN_CONTROLLER_CNT] =\r
167 {\r
168   {\r
169     .state = CANIF_CS_UNINIT,\r
170   },
171   {\r
172     .state = CANIF_CS_UNINIT,\r
173   },\r
174 };\r
175 \r
176 //-------------------------------------------------------------------\r
177 static CAN_HW_t * GetController(int unit)
178 {
179         return ((CAN_HW_t *)(CAN1_BASE + unit*0x400));
180 }\r
181
182 //-------------------------------------------------------------------\r
183 /**\r
184  * Function that finds the Hoh( HardwareObjectHandle ) from a Hth\r
185  * A HTH may connect to one or several HOH's. Just find the first one.\r
186  *\r
187  * @param hth The transmit handle\r
188  * @returns Ptr to the Hoh\r
189  */\r
190 static const Can_HardwareObjectType * Can_FindHoh( Can_Arc_HTHType hth , uint32* controller)\r
191 {\r
192   const Can_HardwareObjectType *hohObj;\r
193   const Can_Arc_ObjectHOHMapType *map;\r
194   const Can_ControllerConfigType *canHwConfig;\r
195 \r
196   map = &Can_Global.CanHTHMap[hth];\r
197 \r
198   // Verify that this is the correct map\r
199   if (map->CanHOHRef->CanObjectId != hth)\r
200   {\r
201     DET_REPORTERROR(MODULE_ID_CAN, 0, 0x6, CAN_E_PARAM_HANDLE);\r
202   }\r
203 \r
204   canHwConfig= GET_CONTROLLER_CONFIG(Can_Global.channelMap[map->CanControllerRef]);\r
205 \r
206   hohObj = map->CanHOHRef;\r
207 \r
208   // Verify that this is the correct Hoh type\r
209   if ( hohObj->CanObjectType == CAN_OBJECT_TYPE_TRANSMIT)\r
210   {\r
211     *controller = map->CanControllerRef;\r
212     return hohObj;\r
213   }\r
214 \r
215   DET_REPORTERROR(MODULE_ID_CAN, 0, 0x6, CAN_E_PARAM_HANDLE);\r
216 \r
217   return NULL;\r
218 }\r
219 \r
220 //-------------------------------------------------------------------\r
221 \r
222 static void Can_RxIsr( int unit );
223 static void Can_TxIsr( int unit );
224 static void Can_ErrIsr( int unit );\r
225
226 void Can_1_RxIsr( void  ) {     Can_RxIsr(CAN_CTRL_1); }
227 void Can_2_RxIsr( void  ) {     Can_RxIsr(CAN_CTRL_2); }
228
229 void Can_1_TxIsr( void  ) {     Can_TxIsr(CAN_CTRL_1); }
230 void Can_2_TxIsr( void  ) {     Can_TxIsr(CAN_CTRL_2); }
231
232 void Can_1_ErrIsr( void  ) {    Can_ErrIsr(CAN_CTRL_1); }
233 void Can_2_ErrIsr( void  ) {    Can_ErrIsr(CAN_CTRL_2); }
234 \r
235
236 //-------------------------------------------------------------------\r
237
238 // Uses 25.4.5.1 Transmission Abort Mechanism
239 static void Can_AbortTx( CAN_HW_t *canHw, Can_UnitType *canUnit ) {
240         // Disable Transmit irq
241
242         // check if mb's empty
243
244         // Abort all pending mb's
245
246         // Wait for mb's being emptied
247 }
248
249 /**
250  * Hardware wake ISR for CAN
251  *
252  * @param unit CAN controller number( from 0 )
253  */
254 static void Can_WakeIsr( int unit ) {
255         if (GET_CALLBACKS()->ControllerWakeup != NULL)
256         {
257           GET_CALLBACKS()->ControllerWakeup(unit);
258         }
259         // 269,270,271
260         Can_SetControllerMode(unit, CAN_T_STOP);
261
262         // TODO EcuM_CheckWakeup();
263 }\r
264
265 /**\r
266  * Hardware error ISR for CAN\r
267  *\r
268  * @param unit CAN controller number( from 0 )\r
269  */\r
270 static void Can_ErrIsr( int unit ) {\r
271   CAN_HW_t *canHw = GetController(unit);\r
272   Can_UnitType *canUnit = GET_PRIVATE_DATA(unit);
273   Can_Arc_ErrorType err;\r
274   err.R = 0;
275
276   // Check wake up
277   if(SET == CAN_GetITStatus(canHw, CAN_IT_WKU)){\r
278           Can_WakeIsr(unit);\r
279           CAN_ClearITPendingBit(canHw, CAN_IT_WKU);
280   }
281
282   if(SET == CAN_GetITStatus(canHw, CAN_IT_BOF)){
283         canUnit->stats.boffCnt++;
284         if (GET_CALLBACKS()->ControllerBusOff != NULL)
285         {
286           GET_CALLBACKS()->ControllerBusOff(unit);
287         }
288         Can_SetControllerMode(unit, CAN_T_STOP); // CANIF272
289
290         Can_AbortTx( canHw, canUnit ); // CANIF273
291
292         // Clear int
293         CAN_ClearITPendingBit(canHw, CAN_IT_BOF);
294   }
295
296   if (err.R != 0)
297   {
298     if (GET_CALLBACKS()->Arc_Error != NULL)
299     {
300       GET_CALLBACKS()->Arc_Error( unit, err );
301     }
302   }
303 }\r
304 \r
305 //-------------------------------------------------------------------\r
306 \r
307 /**\r
308  * ISR for CAN. Normal Rx/operation\r
309  *\r
310  * @param unit CAN controller number( from 0 )\r
311  */\r
312 static void Can_RxIsr(int unit) {\r
313 \r
314   CAN_HW_t *canHw= GetController(unit);\r
315   const Can_ControllerConfigType *canHwConfig= GET_CONTROLLER_CONFIG(Can_Global.channelMap[unit]);\r
316   Can_UnitType *canUnit = GET_PRIVATE_DATA(unit);\r
317   const Can_HardwareObjectType *hohObj;
318
319   CanRxMsg RxMessage;
320
321   RxMessage.StdId=0x00;
322   RxMessage.ExtId=0x00;
323   RxMessage.IDE=0;
324   RxMessage.DLC=0;
325   RxMessage.FMI=0;
326   RxMessage.Data[0]=0x00;
327   RxMessage.Data[1]=0x00;
328   CAN_Receive(canHw,CAN_FIFO0, &RxMessage);\r
329
330   // Loop over all the Hoh's\r
331   hohObj= canHwConfig->Can_Arc_Hoh;\r
332   --hohObj;\r
333   do {\r
334         ++hohObj;\r
335 \r
336         if (hohObj->CanObjectType == CAN_OBJECT_TYPE_RECEIVE)\r
337         {\r
338             Can_IdType id=0;
339
340             // According to autosar MSB shuould be set if extended\r
341                 if (RxMessage.IDE != CAN_ID_STD) {
342                   id = RxMessage.ExtId;
343                   id |= 0x80000000;\r
344                 } else {
345                   id = RxMessage.StdId;
346                 }\r
347 \r
348                 if (GET_CALLBACKS()->RxIndication != NULL)\r
349                 {\r
350                   GET_CALLBACKS()->RxIndication(hohObj->CanObjectId,\r
351                                                                                 id,\r
352                                                                                 RxMessage.DLC,\r
353                                                                                 (uint8 *)&RxMessage.Data[0] ); // Next layer will copy\r
354                 }\r
355                 // Increment statistics\r
356                 canUnit->stats.rxSuccessCnt++;\r
357         }\r
358   } while ( !hohObj->Can_Arc_EOL);\r
359 }\r
360
361 /**
362  * ISR for CAN. Normal Tx operation
363  *
364  * @param unit CAN controller number( from 0 )
365  */
366 static void Can_TxIsr(int unit) {
367   CAN_HW_t *canHw= GetController(unit);
368   const Can_ControllerConfigType *canHwConfig= GET_CONTROLLER_CONFIG(Can_Global.channelMap[unit]);
369   Can_UnitType *canUnit = GET_PRIVATE_DATA(unit);
370   const Can_HardwareObjectType *hohObj;
371
372   // Loop over all the Hoh's
373   hohObj= canHwConfig->Can_Arc_Hoh;
374   --hohObj;
375   do {
376         ++hohObj;
377
378         if (hohObj->CanObjectType == CAN_OBJECT_TYPE_TRANSMIT)
379         {
380                 if (GET_CALLBACKS()->TxConfirmation != NULL)
381                 {
382                   GET_CALLBACKS()->TxConfirmation(canUnit->swPduHandle);
383                 }
384                 canUnit->swPduHandle = 0;  // Is this really necessary ??
385
386                 // Clear Tx interrupt
387         CAN_ClearITPendingBit(canHw,CAN_IT_RQCP0);
388         CAN_ClearITPendingBit(canHw,CAN_IT_RQCP1);
389         CAN_ClearITPendingBit(canHw,CAN_IT_RQCP2);
390         }
391   } while ( !hohObj->Can_Arc_EOL);
392 }\r
393
394 //-------------------------------------------------------------------\r
395 \r
396 #define INSTALL_HANDLERS(_can_name,_sce,_rx,_tx) \\r
397   do { \\r
398     ISR_INSTALL_ISR2( "Can_Err", _can_name ## _ErrIsr, _sce, 2, 0 ); \
399         ISR_INSTALL_ISR2( "Can_Rx",  _can_name ## _RxIsr,  _rx,  2, 0 ); \
400         ISR_INSTALL_ISR2( "Can_Tx",  _can_name ## _TxIsr,  _tx,  2, 0 ); \
401   } while(0);\r
402 \r
403 // This initiates ALL can controllers\r
404 void Can_Init( const Can_ConfigType *config ) {\r
405   Can_UnitType *canUnit;\r
406   const Can_ControllerConfigType *canHwConfig;\r
407   uint32 ctlrId;\r
408 \r
409   VALIDATE_NO_RV( (Can_Global.initRun == CAN_UNINIT), 0x0, CAN_E_TRANSITION );\r
410   VALIDATE_NO_RV( (config != NULL ), 0x0, CAN_E_PARAM_POINTER );\r
411 \r
412   // Save config\r
413   Can_Global.config = config;\r
414   Can_Global.initRun = CAN_READY;\r
415 \r
416   for (int configId=0; configId < CAN_ARC_CTRL_CONFIG_CNT; configId++) {\r
417     canHwConfig = GET_CONTROLLER_CONFIG(configId);\r
418     ctlrId = canHwConfig->CanControllerId;\r
419 \r
420     // Assign the configuration channel used later..\r
421     Can_Global.channelMap[canHwConfig->CanControllerId] = configId;\r
422     Can_Global.configured |= (1<<ctlrId);\r
423 \r
424     canUnit = GET_PRIVATE_DATA(ctlrId);\r
425     canUnit->state = CANIF_CS_STOPPED;\r
426 \r
427     canUnit->lock_cnt = 0;\r
428 \r
429     // Clear stats\r
430     memset(&canUnit->stats, 0, sizeof(Can_Arc_StatisticsType));
431
432     // Note!
433     // Could install handlers depending on HW objects to trap more errors
434     // in configuration
435     switch( canHwConfig->CanControllerId ) {
436 #ifndef STM32F10X_CL
437     case CAN_CTRL_1:
438         INSTALL_HANDLERS(Can_1, CAN1_SCE_IRQn, USB_LP_CAN1_RX0_IRQn, USB_HP_CAN1_TX_IRQn);      break;
439 #else
440     case CAN_CTRL_1:
441         INSTALL_HANDLERS(Can_1, CAN1_SCE_IRQn, CAN1_RX0_IRQn, CAN1_TX_IRQn);    break;
442     case CAN_CTRL_2:
443         INSTALL_HANDLERS(Can_2, CAN2_SCE_IRQn, CAN2_RX0_IRQn, CAN2_TX_IRQn);    break;
444 #endif
445         default:
446         assert(0);
447     }\r
448 \r
449     Can_InitController(ctlrId, canHwConfig);\r
450 \r
451     // Loop through all Hoh:s and map them into the HTHMap\r
452     const Can_HardwareObjectType* hoh;\r
453     hoh = canHwConfig->Can_Arc_Hoh;\r
454     hoh--;\r
455     do\r
456     {\r
457       hoh++;\r
458 \r
459       if (hoh->CanObjectType == CAN_OBJECT_TYPE_TRANSMIT)\r
460       {\r
461         Can_Global.CanHTHMap[hoh->CanObjectId].CanControllerRef = canHwConfig->CanControllerId;\r
462         Can_Global.CanHTHMap[hoh->CanObjectId].CanHOHRef = hoh;\r
463       }\r
464     } while (!hoh->Can_Arc_EOL);\r
465   }\r
466   return;\r
467 }\r
468 \r
469 // Unitialize the module\r
470 void Can_DeInit()\r
471 {\r
472   Can_UnitType *canUnit;\r
473   const Can_ControllerConfigType *canHwConfig;\r
474   uint32 ctlrId;\r
475 \r
476   for (int configId=0; configId < CAN_ARC_CTRL_CONFIG_CNT; configId++) {\r
477     canHwConfig = GET_CONTROLLER_CONFIG(configId);\r
478     ctlrId = canHwConfig->CanControllerId;\r
479 \r
480     canUnit = GET_PRIVATE_DATA(ctlrId);\r
481     canUnit->state = CANIF_CS_UNINIT;\r
482 \r
483     Can_DisableControllerInterrupts(ctlrId);\r
484 \r
485     canUnit->lock_cnt = 0;\r
486 \r
487     // Clear stats\r
488     memset(&canUnit->stats, 0, sizeof(Can_Arc_StatisticsType));\r
489   }\r
490 \r
491   Can_Global.config = NULL;\r
492   Can_Global.initRun = CAN_UNINIT;\r
493 \r
494   return;\r
495 }\r
496 \r
497 void Can_InitController( uint8 controller, const Can_ControllerConfigType *config)
498 {\r
499   CAN_HW_t *canHw;\r
500   uint8_t tq;\r
501   uint8_t tqSync;
502   uint8_t tq1;
503   uint8_t tq2;\r
504   uint32_t clock;\r
505   Can_UnitType *canUnit;\r
506   uint8 cId = controller;\r
507   const Can_ControllerConfigType *canHwConfig;\r
508   const Can_HardwareObjectType *hohObj;\r
509 \r
510   VALIDATE_NO_RV( (Can_Global.initRun == CAN_READY), 0x2, CAN_E_UNINIT );\r
511   VALIDATE_NO_RV( (config != NULL ), 0x2,CAN_E_PARAM_POINTER);\r
512   VALIDATE_NO_RV( (controller < GET_CONTROLLER_CNT()), 0x2, CAN_E_PARAM_CONTROLLER );\r
513 \r
514   canUnit = GET_PRIVATE_DATA(controller);\r
515 \r
516   VALIDATE_NO_RV( (canUnit->state==CANIF_CS_STOPPED), 0x2, CAN_E_TRANSITION );\r
517 \r
518   canHw = GetController(cId);\r
519   canHwConfig = GET_CONTROLLER_CONFIG(Can_Global.channelMap[cId]);\r
520 \r
521   // Start this baby up
522   CAN_DeInit(canHw);\r
523
524   /* CAN filter init. We set up two filters - one for the master (CAN1) and
525    * one for the slave (CAN2)
526    *
527    * CAN_SlaveStartBank(n) denotes which filter is the first of the slave.
528    *
529    * The filter registers reside in CAN1 and is shared to CAN2, so we only need
530    * to set up this once.
531    */
532
533   // We let all frames in and do the filtering in software.
534   CAN_FilterInitTypeDef  CAN_FilterInitStructure;
535   CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
536   CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;
537   CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;
538   CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
539   CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;
540   CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
541   CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_FIFO0;
542   CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;
543
544   // Init filter 0 (CAN1/master)
545   CAN_FilterInitStructure.CAN_FilterNumber=0;
546   CAN_FilterInit(&CAN_FilterInitStructure);
547
548   // Init filter 1 (CAN2/slave)
549   CAN_FilterInitStructure.CAN_FilterNumber=1;
550   CAN_FilterInit(&CAN_FilterInitStructure);
551
552   // Set which filter to use for CAN2.
553   CAN_SlaveStartBank(1);
554
555   // acceptance filters
556    hohObj = canHwConfig->Can_Arc_Hoh;
557    --hohObj;
558    do {
559          ++hohObj;
560      if (hohObj->CanObjectType == CAN_OBJECT_TYPE_RECEIVE)
561      {
562          // TODO Hw filtering
563      }
564    }while( !hohObj->Can_Arc_EOL );\r
565
566   // Clock calucation\r
567   // -------------------------------------------------------------------\r
568   //\r
569   // * 1 TQ = Sclk period( also called SCK )\r
570   // * Ftq = Fcanclk / ( PRESDIV + 1 ) = Sclk\r
571   //   ( Fcanclk can come from crystal or from the peripheral dividers )\r
572   //\r
573   // -->\r
574   // TQ = 1/Ftq = (PRESDIV+1)/Fcanclk --> PRESDIV = (TQ * Fcanclk - 1 )\r
575   // TQ is between 8 and 25\r
576   clock = McuE_GetSystemClock()/2;
577
578   tqSync = config->CanControllerPropSeg + 1;
579   tq1 = config->CanControllerSeg1 + 1;\r
580   tq2 = config->CanControllerSeg2 + 1;\r
581   tq = tqSync + tq1 + tq2;
582
583   CAN_InitTypeDef        CAN_InitStructure;
584   CAN_StructInit(&CAN_InitStructure);
585
586   /* CAN cell init */
587   CAN_InitStructure.CAN_TTCM=DISABLE;
588   CAN_InitStructure.CAN_ABOM=ENABLE;
589   CAN_InitStructure.CAN_AWUM=ENABLE;
590   CAN_InitStructure.CAN_NART=DISABLE;
591   CAN_InitStructure.CAN_RFLM=DISABLE;
592   CAN_InitStructure.CAN_TXFP=DISABLE;
593   if(config->Can_Arc_Loopback){
594           CAN_InitStructure.CAN_Mode=CAN_Mode_LoopBack;
595   }else{
596           CAN_InitStructure.CAN_Mode=CAN_Mode_Normal;
597   }
598
599   CAN_InitStructure.CAN_SJW=config->CanControllerPropSeg;
600   CAN_InitStructure.CAN_BS1=config->CanControllerSeg1;
601   CAN_InitStructure.CAN_BS2=config->CanControllerSeg2;
602   CAN_InitStructure.CAN_Prescaler= clock/(config->CanControllerBaudRate*1000*tq);
603
604   if(CANINITOK != CAN_Init(canHw,&CAN_InitStructure))
605   {
606         return;
607   }\r
608
609   canUnit->state = CANIF_CS_STOPPED;\r
610   Can_EnableControllerInterrupts(cId);\r
611 \r
612   return;\r
613 }\r
614 \r
615 \r
616 Can_ReturnType Can_SetControllerMode( uint8 controller, Can_StateTransitionType transition ) {\r
617   imask_t state;
618   CAN_HW_t *canHw;\r
619   Can_ReturnType rv = CAN_OK;\r
620   VALIDATE( (controller < GET_CONTROLLER_CNT()), 0x3, CAN_E_PARAM_CONTROLLER );\r
621 \r
622   Can_UnitType *canUnit = GET_PRIVATE_DATA(controller);\r
623 \r
624   VALIDATE( (canUnit->state!=CANIF_CS_UNINIT), 0x3, CAN_E_UNINIT );\r
625   canHw = GetController(controller);\r
626 \r
627   switch(transition )\r
628   {\r
629   case CAN_T_START:\r
630     canUnit->state = CANIF_CS_STARTED;\r
631     Irq_Save(state);\r
632     if (canUnit->lock_cnt == 0){   // REQ CAN196\r
633       Can_EnableControllerInterrupts(controller);
634     }\r
635     Irq_Restore(state);
636     break;\r
637   case CAN_T_WAKEUP:
638         VALIDATE(canUnit->state == CANIF_CS_SLEEP, 0x3, CAN_E_TRANSITION);
639         CAN_WakeUp(canHw);
640         canUnit->state = CANIF_CS_STOPPED;
641         break;\r
642   case CAN_T_SLEEP:  //CAN258, CAN290\r
643     // Should be reported to DEM but DET is the next best\r
644     VALIDATE(canUnit->state == CANIF_CS_STOPPED, 0x3, CAN_E_TRANSITION);\r
645     CAN_Sleep(canHw);
646     canUnit->state = CANIF_CS_SLEEP;
647         break;
648   case CAN_T_STOP:\r
649     // Stop\r
650     canUnit->state = CANIF_CS_STOPPED;\r
651     Can_AbortTx( canHw, canUnit ); // CANIF282\r
652     break;\r
653   default:\r
654     // Should be reported to DEM but DET is the next best\r
655     VALIDATE(canUnit->state == CANIF_CS_STOPPED, 0x3, CAN_E_TRANSITION);\r
656     break;\r
657   }\r
658 \r
659   return rv;\r
660 }\r
661 \r
662 void Can_DisableControllerInterrupts( uint8 controller )\r
663 {\r
664   imask_t state;
665   Can_UnitType *canUnit;\r
666   CAN_HW_t *canHw;\r
667 \r
668   VALIDATE_NO_RV( (controller < GET_CONTROLLER_CNT()), 0x4, CAN_E_PARAM_CONTROLLER );\r
669 \r
670   canUnit = GET_PRIVATE_DATA(controller);\r
671 \r
672   VALIDATE_NO_RV( (canUnit->state!=CANIF_CS_UNINIT), 0x4, CAN_E_UNINIT );\r
673 \r
674   Irq_Save(state);
675   if(canUnit->lock_cnt > 0 )\r
676   {\r
677     // Interrupts already disabled\r
678     canUnit->lock_cnt++;\r
679     Irq_Restore(state);
680     return;\r
681   }\r
682   canUnit->lock_cnt++;\r
683   Irq_Restore(state);
684 \r
685   /* Don't try to be intelligent, turn everything off */\r
686   canHw = GetController(controller);\r
687 \r
688   /* Turn off the tx interrupt mailboxes */\r
689   CAN_ITConfig(canHw, CAN_IT_TME, DISABLE);\r
690
691   /* Turn off the bus off/tx warning/rx warning and error and rx  */\r
692   CAN_ITConfig(canHw, CAN_IT_FMP0 | CAN_IT_BOF | CAN_IT_ERR | CAN_IT_WKU, DISABLE);
693 }\r
694 \r
695 void Can_EnableControllerInterrupts( uint8 controller ) {
696   imask_t state;\r
697   Can_UnitType *canUnit;\r
698   CAN_HW_t *canHw;\r
699   const Can_ControllerConfigType *canHwConfig;\r
700   VALIDATE_NO_RV( (controller < GET_CONTROLLER_CNT()), 0x5, CAN_E_PARAM_CONTROLLER );\r
701 \r
702   canUnit = GET_PRIVATE_DATA(controller);\r
703 \r
704   VALIDATE_NO_RV( (canUnit->state!=CANIF_CS_UNINIT), 0x5, CAN_E_UNINIT );\r
705 \r
706   Irq_Save(state);
707   if( canUnit->lock_cnt > 1 )\r
708   {\r
709     // IRQ should still be disabled so just decrement counter\r
710     canUnit->lock_cnt--;\r
711     Irq_Restore(state);
712     return;\r
713   } else if (canUnit->lock_cnt == 1)\r
714   {\r
715     canUnit->lock_cnt = 0;\r
716   }\r
717   Irq_Restore(state);
718 \r
719   canHw = GetController(controller);\r
720 \r
721   canHwConfig = GET_CONTROLLER_CONFIG(Can_Global.channelMap[controller]);\r
722 \r
723   if( canHwConfig->CanRxProcessing == CAN_ARC_PROCESS_TYPE_INTERRUPT ) {\r
724     /* Turn on the rx interrupt */\r
725         CAN_ITConfig(canHw, CAN_IT_FMP0, ENABLE);
726   }
727   if( canHwConfig->CanTxProcessing == CAN_ARC_PROCESS_TYPE_INTERRUPT ) {
728         /* Turn on the tx interrupt mailboxes */
729         CAN_ITConfig(canHw, CAN_IT_TME, ENABLE);
730   }\r
731 \r
732   // BusOff here represents all errors and warnings\r
733   if( canHwConfig->CanBusOffProcessing == CAN_ARC_PROCESS_TYPE_INTERRUPT ) {\r
734         /* Turn on the bus off/tx warning/rx warning and error and rx  */
735         CAN_ITConfig(canHw, CAN_IT_BOF | CAN_IT_ERR | CAN_IT_WKU, ENABLE);
736   }\r
737 \r
738   return;\r
739 }\r
740
741 Can_ReturnType Can_Write( Can_Arc_HTHType hth, Can_PduType *pduInfo ) {\r
742   Can_ReturnType rv = CAN_OK;\r
743   CAN_HW_t *canHw;\r
744   const Can_HardwareObjectType *hohObj;\r
745   const Can_ControllerConfigType *canHwConfig;
746   uint32 controller;\r
747   imask_t state;\r
748
749   VALIDATE( (Can_Global.initRun == CAN_READY), 0x6, CAN_E_UNINIT );\r
750   VALIDATE( (pduInfo != NULL), 0x6, CAN_E_PARAM_POINTER );\r
751   VALIDATE( (pduInfo->length <= 8), 0x6, CAN_E_PARAM_DLC );\r
752   VALIDATE( (hth < NUM_OF_HTHS ), 0x6, CAN_E_PARAM_HANDLE );\r
753 \r
754   hohObj = Can_FindHoh(hth, &controller);\r
755   if (hohObj == NULL)\r
756     return CAN_NOT_OK;\r
757 \r
758   Can_UnitType *canUnit = GET_PRIVATE_DATA(controller);\r
759 \r
760   canHw = GetController(controller);\r
761   Irq_Save(state);
762
763   CanTxMsg TxMessage;
764
765   TxMessage.RTR=CAN_RTR_DATA;
766   TxMessage.DLC=pduInfo->length;
767
768   memcpy(TxMessage.Data, pduInfo->sdu, pduInfo->length);
769
770   if (hohObj->CanIdType == CAN_ID_TYPE_EXTENDED) {
771         TxMessage.IDE=CAN_ID_EXT;
772         TxMessage.ExtId=pduInfo->id;
773   } else {
774         TxMessage.IDE=CAN_ID_STD;
775         TxMessage.StdId=pduInfo->id;
776   }\r
777
778   // check for any free box\r
779   if(CAN_Transmit(canHw,&TxMessage) != CAN_NO_MB) {
780     canHwConfig = GET_CONTROLLER_CONFIG(Can_Global.channelMap[controller]);
781
782     if( canHwConfig->CanTxProcessing == CAN_ARC_PROCESS_TYPE_INTERRUPT ) {
783           /* Turn on the tx interrupt mailboxes */
784         CAN_ITConfig(canHw,CAN_IT_TME, ENABLE);
785     }
786
787         // Increment statistics
788         canUnit->stats.txSuccessCnt++;\r
789
790     // Store pdu handle in unit to be used by TxConfirmation\r
791     canUnit->swPduHandle = pduInfo->swPduHandle;\r
792   } else {\r
793     rv = CAN_BUSY;\r
794   }\r
795   Irq_Restore(state);
796 \r
797   return rv;\r
798 }\r
799 \r
800 void Can_MainFunction_Read( void ) {\r
801 \r
802         /* NOT SUPPORTED */\r
803 }\r
804 \r
805 void Can_MainFunction_BusOff( void ) {\r
806   /* Bus-off polling events */\r
807 \r
808         /* NOT SUPPORTED */\r
809 }\r
810 \r
811 void Can_MainFunction_Wakeup( void ) {\r
812   /* Wakeup polling events */\r
813 \r
814         /* NOT SUPPORTED */\r
815 }\r
816 \r
817 \r
818 /**\r
819  * Get send/receive/error statistics for a controller\r
820  *\r
821  * @param controller The controller\r
822  * @param stats Pointer to data to copy statistics to\r
823  */\r
824 \r
825 void Can_Arc_GetStatistics( uint8 controller, Can_Arc_StatisticsType *stats)\r
826 {\r
827   Can_UnitType *canUnit = GET_PRIVATE_DATA(controller);\r
828   *stats = canUnit->stats;\r
829 }\r
830 \r
831 #else // Stub all functions for use in simulator environment\r
832 \r
833 #include "debug.h"\r
834 \r
835 void Can_Init( const Can_ConfigType *Config )\r
836 {\r
837   // Do initial configuration of layer here\r
838 }\r
839 \r
840 void Can_InitController( uint8 controller, const Can_ControllerConfigType *config)\r
841 {\r
842         // Do initialisation of controller here.\r
843 }\r
844 \r
845 Can_ReturnType Can_SetControllerMode( uint8 Controller, Can_StateTransitionType transition )\r
846 {\r
847         // Turn on off controller here depending on transition\r
848         return E_OK;\r
849 }\r
850 \r
851 Can_ReturnType Can_Write( Can_Arc_HTHType hth, Can_PduType *pduInfo )\r
852 {\r
853         // Write to mailbox on controller here.\r
854         DEBUG(DEBUG_MEDIUM, "Can_Write(stub): Received data ");\r
855         for (int i = 0; i < pduInfo->length; i++) {\r
856                 DEBUG(DEBUG_MEDIUM, "%d ", pduInfo->sdu[i]);\r
857         }\r
858         DEBUG(DEBUG_MEDIUM, "\n");\r
859 \r
860         return E_OK;\r
861 }\r
862 \r
863 extern void CanIf_RxIndication(uint8 Hrh, Can_IdType CanId, uint8 CanDlc, const uint8 *CanSduPtr);\r
864 Can_ReturnType Can_ReceiveAFrame()\r
865 {\r
866         // This function is not part of autosar but needed to feed the stack with data\r
867         // from the mailboxes. Normally this is an interrup but probably not in the PCAN case.\r
868         uint8 CanSduData[] = {1,2,1,0,0,0,0,0};\r
869         CanIf_RxIndication(CAN_HRH_0_1, 3, 8, CanSduData);\r
870 \r
871         return E_OK;\r
872 }\r
873 \r
874 void Can_DisableControllerInterrupts( uint8 controller )\r
875 {\r
876 }\r
877 \r
878 void Can_EnableControllerInterrupts( uint8 controller )\r
879 {\r
880 }\r
881 \r
882 \r
883 // Hth - for Flexcan, the hardware message box number... .We don't care\r
884 void Can_Cbk_CheckWakeup( uint8 controller ){}\r
885 \r
886 void Can_MainFunction_Write( void ){}\r
887 void Can_MainFunction_Read( void ){}\r
888 void Can_MainFunction_BusOff( void ){}\r
889 void Can_MainFunction_Wakeup( void ){}\r
890 \r
891 void Can_Arc_GetStatistics( uint8 controller, Can_Arc_StatisticsType * stat){}\r
892 \r
893 #endif\r
894 \r
895 \r