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