]> git.gag.com Git - fw/stlink/blob - example/libs_stm/src/stm32f10x/stm32f10x_can.c
Merge pull request #29 from karlp/future_f1plusf4
[fw/stlink] / example / libs_stm / src / stm32f10x / stm32f10x_can.c
1 /**\r
2   ******************************************************************************\r
3   * @file    stm32f10x_can.c\r
4   * @author  MCD Application Team\r
5   * @version V3.3.0\r
6   * @date    04/16/2010\r
7   * @brief   This file provides all the CAN firmware functions.\r
8   ******************************************************************************\r
9   * @copy\r
10   *\r
11   * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS\r
12   * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE\r
13   * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY\r
14   * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING\r
15   * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE\r
16   * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.\r
17   *\r
18   * <h2><center>&copy; COPYRIGHT 2010 STMicroelectronics</center></h2>\r
19   */ \r
20 \r
21 /* Includes ------------------------------------------------------------------*/\r
22 #include "stm32f10x_can.h"\r
23 #include "stm32f10x_rcc.h"\r
24 \r
25 /** @addtogroup STM32F10x_StdPeriph_Driver\r
26   * @{\r
27   */\r
28 \r
29 /** @defgroup CAN \r
30   * @brief CAN driver modules\r
31   * @{\r
32   */ \r
33 \r
34 /** @defgroup CAN_Private_TypesDefinitions\r
35   * @{\r
36   */\r
37 \r
38 /**\r
39   * @}\r
40   */\r
41 \r
42 /** @defgroup CAN_Private_Defines\r
43   * @{\r
44   */\r
45 \r
46 /* CAN Master Control Register bits */\r
47 #define MCR_INRQ     ((uint32_t)0x00000001) /* Initialization request */\r
48 #define MCR_SLEEP    ((uint32_t)0x00000002) /* Sleep mode request */\r
49 #define MCR_TXFP     ((uint32_t)0x00000004) /* Transmit FIFO priority */\r
50 #define MCR_RFLM     ((uint32_t)0x00000008) /* Receive FIFO locked mode */\r
51 #define MCR_NART     ((uint32_t)0x00000010) /* No automatic retransmission */\r
52 #define MCR_AWUM     ((uint32_t)0x00000020) /* Automatic wake up mode */\r
53 #define MCR_ABOM     ((uint32_t)0x00000040) /* Automatic bus-off management */\r
54 #define MCR_TTCM     ((uint32_t)0x00000080) /* time triggered communication */\r
55 #define MCR_RESET    ((uint32_t)0x00008000) /* time triggered communication */\r
56 #define MCR_DBF      ((uint32_t)0x00010000) /* software master reset */\r
57 \r
58 /* CAN Master Status Register bits */\r
59 #define MSR_INAK     ((uint32_t)0x00000001)    /* Initialization acknowledge */\r
60 #define MSR_WKUI     ((uint32_t)0x00000008)    /* Wake-up interrupt */\r
61 #define MSR_SLAKI    ((uint32_t)0x00000010)    /* Sleep acknowledge interrupt */\r
62 \r
63 /* CAN Transmit Status Register bits */\r
64 #define TSR_RQCP0    ((uint32_t)0x00000001)    /* Request completed mailbox0 */\r
65 #define TSR_TXOK0    ((uint32_t)0x00000002)    /* Transmission OK of mailbox0 */\r
66 #define TSR_ABRQ0    ((uint32_t)0x00000080)    /* Abort request for mailbox0 */\r
67 #define TSR_RQCP1    ((uint32_t)0x00000100)    /* Request completed mailbox1 */\r
68 #define TSR_TXOK1    ((uint32_t)0x00000200)    /* Transmission OK of mailbox1 */\r
69 #define TSR_ABRQ1    ((uint32_t)0x00008000)    /* Abort request for mailbox1 */\r
70 #define TSR_RQCP2    ((uint32_t)0x00010000)    /* Request completed mailbox2 */\r
71 #define TSR_TXOK2    ((uint32_t)0x00020000)    /* Transmission OK of mailbox2 */\r
72 #define TSR_ABRQ2    ((uint32_t)0x00800000)    /* Abort request for mailbox2 */\r
73 #define TSR_TME0     ((uint32_t)0x04000000)    /* Transmit mailbox 0 empty */\r
74 #define TSR_TME1     ((uint32_t)0x08000000)    /* Transmit mailbox 1 empty */\r
75 #define TSR_TME2     ((uint32_t)0x10000000)    /* Transmit mailbox 2 empty */\r
76 \r
77 /* CAN Receive FIFO 0 Register bits */\r
78 #define RF0R_FULL0   ((uint32_t)0x00000008)    /* FIFO 0 full */\r
79 #define RF0R_FOVR0   ((uint32_t)0x00000010)    /* FIFO 0 overrun */\r
80 #define RF0R_RFOM0   ((uint32_t)0x00000020)    /* Release FIFO 0 output mailbox */\r
81 \r
82 /* CAN Receive FIFO 1 Register bits */\r
83 #define RF1R_FULL1   ((uint32_t)0x00000008)    /* FIFO 1 full */\r
84 #define RF1R_FOVR1   ((uint32_t)0x00000010)    /* FIFO 1 overrun */\r
85 #define RF1R_RFOM1   ((uint32_t)0x00000020)    /* Release FIFO 1 output mailbox */\r
86 \r
87 /* CAN Error Status Register bits */\r
88 #define ESR_EWGF     ((uint32_t)0x00000001)    /* Error warning flag */\r
89 #define ESR_EPVF     ((uint32_t)0x00000002)    /* Error passive flag */\r
90 #define ESR_BOFF     ((uint32_t)0x00000004)    /* Bus-off flag */\r
91 \r
92 /* CAN Mailbox Transmit Request */\r
93 #define TMIDxR_TXRQ  ((uint32_t)0x00000001) /* Transmit mailbox request */\r
94 \r
95 /* CAN Filter Master Register bits */\r
96 #define FMR_FINIT    ((uint32_t)0x00000001) /* Filter init mode */\r
97 \r
98 /* Time out for INAK bit */\r
99 #define INAK_TimeOut        ((uint32_t)0x0000FFFF)\r
100 \r
101 /* Time out for SLAK bit */\r
102 #define SLAK_TimeOut        ((uint32_t)0x0000FFFF)\r
103 \r
104 /**\r
105   * @}\r
106   */\r
107 \r
108 /** @defgroup CAN_Private_Macros\r
109   * @{\r
110   */\r
111 \r
112 /**\r
113   * @}\r
114   */\r
115 \r
116 /** @defgroup CAN_Private_Variables\r
117   * @{\r
118   */\r
119 \r
120 /**\r
121   * @}\r
122   */\r
123 \r
124 /** @defgroup CAN_Private_FunctionPrototypes\r
125   * @{\r
126   */\r
127 \r
128 static ITStatus CheckITStatus(uint32_t CAN_Reg, uint32_t It_Bit);\r
129 \r
130 /**\r
131   * @}\r
132   */\r
133 \r
134 /** @defgroup CAN_Private_Functions\r
135   * @{\r
136   */\r
137 \r
138 /**\r
139   * @brief  Deinitializes the CAN peripheral registers to their default reset values.\r
140   * @param  CANx: where x can be 1 or 2 to select the CAN peripheral.\r
141   * @retval None.\r
142   */\r
143 void CAN_DeInit(CAN_TypeDef* CANx)\r
144 {\r
145   /* Check the parameters */\r
146   assert_param(IS_CAN_ALL_PERIPH(CANx));\r
147  \r
148   if (CANx == CAN1)\r
149   {\r
150     /* Enable CAN1 reset state */\r
151     RCC_APB1PeriphResetCmd(RCC_APB1Periph_CAN1, ENABLE);\r
152     /* Release CAN1 from reset state */\r
153     RCC_APB1PeriphResetCmd(RCC_APB1Periph_CAN1, DISABLE);\r
154   }\r
155   else\r
156   {  \r
157     /* Enable CAN2 reset state */\r
158     RCC_APB1PeriphResetCmd(RCC_APB1Periph_CAN2, ENABLE);\r
159     /* Release CAN2 from reset state */\r
160     RCC_APB1PeriphResetCmd(RCC_APB1Periph_CAN2, DISABLE);\r
161   }\r
162 }\r
163 \r
164 /**\r
165   * @brief  Initializes the CAN peripheral according to the specified\r
166   *   parameters in the CAN_InitStruct.\r
167   * @param  CANx: where x can be 1 or 2 to to select the CAN peripheral.\r
168   * @param  CAN_InitStruct: pointer to a CAN_InitTypeDef structure that\r
169   *   contains the configuration information for the CAN peripheral.\r
170   * @retval Constant indicates initialization succeed which will be \r
171   *   CANINITFAILED or CANINITOK.\r
172   */\r
173 uint8_t CAN_Init(CAN_TypeDef* CANx, CAN_InitTypeDef* CAN_InitStruct)\r
174 {\r
175   uint8_t InitStatus = CANINITFAILED;\r
176   uint32_t wait_ack = 0x00000000;\r
177   /* Check the parameters */\r
178   assert_param(IS_CAN_ALL_PERIPH(CANx));\r
179   assert_param(IS_FUNCTIONAL_STATE(CAN_InitStruct->CAN_TTCM));\r
180   assert_param(IS_FUNCTIONAL_STATE(CAN_InitStruct->CAN_ABOM));\r
181   assert_param(IS_FUNCTIONAL_STATE(CAN_InitStruct->CAN_AWUM));\r
182   assert_param(IS_FUNCTIONAL_STATE(CAN_InitStruct->CAN_NART));\r
183   assert_param(IS_FUNCTIONAL_STATE(CAN_InitStruct->CAN_RFLM));\r
184   assert_param(IS_FUNCTIONAL_STATE(CAN_InitStruct->CAN_TXFP));\r
185   assert_param(IS_CAN_MODE(CAN_InitStruct->CAN_Mode));\r
186   assert_param(IS_CAN_SJW(CAN_InitStruct->CAN_SJW));\r
187   assert_param(IS_CAN_BS1(CAN_InitStruct->CAN_BS1));\r
188   assert_param(IS_CAN_BS2(CAN_InitStruct->CAN_BS2));\r
189   assert_param(IS_CAN_PRESCALER(CAN_InitStruct->CAN_Prescaler));\r
190 \r
191   /* exit from sleep mode */\r
192   CANx->MCR &= ~MCR_SLEEP;\r
193 \r
194   /* Request initialisation */\r
195   CANx->MCR |= MCR_INRQ ;\r
196 \r
197   /* Wait the acknowledge */\r
198   while (((CANx->MSR & MSR_INAK) != MSR_INAK) && (wait_ack != INAK_TimeOut))\r
199   {\r
200     wait_ack++;\r
201   }\r
202 \r
203   /* ...and check acknowledged */\r
204   if ((CANx->MSR & MSR_INAK) != MSR_INAK)\r
205   {\r
206     InitStatus = CANINITFAILED;\r
207   }\r
208   else \r
209   {\r
210     /* Set the time triggered communication mode */\r
211     if (CAN_InitStruct->CAN_TTCM == ENABLE)\r
212     {\r
213       CANx->MCR |= MCR_TTCM;\r
214     }\r
215     else\r
216     {\r
217       CANx->MCR &= ~MCR_TTCM;\r
218     }\r
219 \r
220     /* Set the automatic bus-off management */\r
221     if (CAN_InitStruct->CAN_ABOM == ENABLE)\r
222     {\r
223       CANx->MCR |= MCR_ABOM;\r
224     }\r
225     else\r
226     {\r
227       CANx->MCR &= ~MCR_ABOM;\r
228     }\r
229 \r
230     /* Set the automatic wake-up mode */\r
231     if (CAN_InitStruct->CAN_AWUM == ENABLE)\r
232     {\r
233       CANx->MCR |= MCR_AWUM;\r
234     }\r
235     else\r
236     {\r
237       CANx->MCR &= ~MCR_AWUM;\r
238     }\r
239 \r
240     /* Set the no automatic retransmission */\r
241     if (CAN_InitStruct->CAN_NART == ENABLE)\r
242     {\r
243       CANx->MCR |= MCR_NART;\r
244     }\r
245     else\r
246     {\r
247       CANx->MCR &= ~MCR_NART;\r
248     }\r
249 \r
250     /* Set the receive FIFO locked mode */\r
251     if (CAN_InitStruct->CAN_RFLM == ENABLE)\r
252     {\r
253       CANx->MCR |= MCR_RFLM;\r
254     }\r
255     else\r
256     {\r
257       CANx->MCR &= ~MCR_RFLM;\r
258     }\r
259 \r
260     /* Set the transmit FIFO priority */\r
261     if (CAN_InitStruct->CAN_TXFP == ENABLE)\r
262     {\r
263       CANx->MCR |= MCR_TXFP;\r
264     }\r
265     else\r
266     {\r
267       CANx->MCR &= ~MCR_TXFP;\r
268     }\r
269 \r
270     /* Set the bit timing register */\r
271     CANx->BTR = (uint32_t)((uint32_t)CAN_InitStruct->CAN_Mode << 30) | ((uint32_t)CAN_InitStruct->CAN_SJW << 24) |\r
272                ((uint32_t)CAN_InitStruct->CAN_BS1 << 16) | ((uint32_t)CAN_InitStruct->CAN_BS2 << 20) |\r
273                ((uint32_t)CAN_InitStruct->CAN_Prescaler - 1);\r
274 \r
275     /* Request leave initialisation */\r
276     CANx->MCR &= ~MCR_INRQ;\r
277 \r
278    /* Wait the acknowledge */\r
279    wait_ack = 0x00;\r
280 \r
281    while (((CANx->MSR & MSR_INAK) == MSR_INAK) && (wait_ack != INAK_TimeOut))\r
282    {\r
283      wait_ack++;\r
284    }\r
285 \r
286     /* ...and check acknowledged */\r
287     if ((CANx->MSR & MSR_INAK) == MSR_INAK)\r
288     {\r
289       InitStatus = CANINITFAILED;\r
290     }\r
291     else\r
292     {\r
293       InitStatus = CANINITOK ;\r
294     }\r
295   }\r
296 \r
297   /* At this step, return the status of initialization */\r
298   return InitStatus;\r
299 }\r
300 \r
301 /**\r
302   * @brief  Initializes the CAN peripheral according to the specified\r
303   *   parameters in the CAN_FilterInitStruct.\r
304   * @param  CAN_FilterInitStruct: pointer to a CAN_FilterInitTypeDef\r
305   *   structure that contains the configuration information.\r
306   * @retval None.\r
307   */\r
308 void CAN_FilterInit(CAN_FilterInitTypeDef* CAN_FilterInitStruct)\r
309 {\r
310   uint32_t filter_number_bit_pos = 0;\r
311   /* Check the parameters */\r
312   assert_param(IS_CAN_FILTER_NUMBER(CAN_FilterInitStruct->CAN_FilterNumber));\r
313   assert_param(IS_CAN_FILTER_MODE(CAN_FilterInitStruct->CAN_FilterMode));\r
314   assert_param(IS_CAN_FILTER_SCALE(CAN_FilterInitStruct->CAN_FilterScale));\r
315   assert_param(IS_CAN_FILTER_FIFO(CAN_FilterInitStruct->CAN_FilterFIFOAssignment));\r
316   assert_param(IS_FUNCTIONAL_STATE(CAN_FilterInitStruct->CAN_FilterActivation));\r
317 \r
318   filter_number_bit_pos = ((uint32_t)0x00000001) << CAN_FilterInitStruct->CAN_FilterNumber;\r
319 \r
320   /* Initialisation mode for the filter */\r
321   CAN1->FMR |= FMR_FINIT;\r
322 \r
323   /* Filter Deactivation */\r
324   CAN1->FA1R &= ~(uint32_t)filter_number_bit_pos;\r
325 \r
326   /* Filter Scale */\r
327   if (CAN_FilterInitStruct->CAN_FilterScale == CAN_FilterScale_16bit)\r
328   {\r
329     /* 16-bit scale for the filter */\r
330     CAN1->FS1R &= ~(uint32_t)filter_number_bit_pos;\r
331 \r
332     /* First 16-bit identifier and First 16-bit mask */\r
333     /* Or First 16-bit identifier and Second 16-bit identifier */\r
334     CAN1->sFilterRegister[CAN_FilterInitStruct->CAN_FilterNumber].FR1 = \r
335     ((0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterMaskIdLow) << 16) |\r
336         (0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterIdLow);\r
337 \r
338     /* Second 16-bit identifier and Second 16-bit mask */\r
339     /* Or Third 16-bit identifier and Fourth 16-bit identifier */\r
340     CAN1->sFilterRegister[CAN_FilterInitStruct->CAN_FilterNumber].FR2 = \r
341     ((0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterMaskIdHigh) << 16) |\r
342         (0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterIdHigh);\r
343   }\r
344 \r
345   if (CAN_FilterInitStruct->CAN_FilterScale == CAN_FilterScale_32bit)\r
346   {\r
347     /* 32-bit scale for the filter */\r
348     CAN1->FS1R |= filter_number_bit_pos;\r
349     /* 32-bit identifier or First 32-bit identifier */\r
350     CAN1->sFilterRegister[CAN_FilterInitStruct->CAN_FilterNumber].FR1 = \r
351     ((0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterIdHigh) << 16) |\r
352         (0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterIdLow);\r
353     /* 32-bit mask or Second 32-bit identifier */\r
354     CAN1->sFilterRegister[CAN_FilterInitStruct->CAN_FilterNumber].FR2 = \r
355     ((0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterMaskIdHigh) << 16) |\r
356         (0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterMaskIdLow);\r
357   }\r
358 \r
359   /* Filter Mode */\r
360   if (CAN_FilterInitStruct->CAN_FilterMode == CAN_FilterMode_IdMask)\r
361   {\r
362     /*Id/Mask mode for the filter*/\r
363     CAN1->FM1R &= ~(uint32_t)filter_number_bit_pos;\r
364   }\r
365   else /* CAN_FilterInitStruct->CAN_FilterMode == CAN_FilterMode_IdList */\r
366   {\r
367     /*Identifier list mode for the filter*/\r
368     CAN1->FM1R |= (uint32_t)filter_number_bit_pos;\r
369   }\r
370 \r
371   /* Filter FIFO assignment */\r
372   if (CAN_FilterInitStruct->CAN_FilterFIFOAssignment == CAN_FilterFIFO0)\r
373   {\r
374     /* FIFO 0 assignation for the filter */\r
375     CAN1->FFA1R &= ~(uint32_t)filter_number_bit_pos;\r
376   }\r
377 \r
378   if (CAN_FilterInitStruct->CAN_FilterFIFOAssignment == CAN_FilterFIFO1)\r
379   {\r
380     /* FIFO 1 assignation for the filter */\r
381     CAN1->FFA1R |= (uint32_t)filter_number_bit_pos;\r
382   }\r
383   \r
384   /* Filter activation */\r
385   if (CAN_FilterInitStruct->CAN_FilterActivation == ENABLE)\r
386   {\r
387     CAN1->FA1R |= filter_number_bit_pos;\r
388   }\r
389 \r
390   /* Leave the initialisation mode for the filter */\r
391   CAN1->FMR &= ~FMR_FINIT;\r
392 }\r
393 \r
394 /**\r
395   * @brief  Fills each CAN_InitStruct member with its default value.\r
396   * @param  CAN_InitStruct: pointer to a CAN_InitTypeDef structure which\r
397   *   will be initialized.\r
398   * @retval None.\r
399   */\r
400 void CAN_StructInit(CAN_InitTypeDef* CAN_InitStruct)\r
401 {\r
402   /* Reset CAN init structure parameters values */\r
403   /* Initialize the time triggered communication mode */\r
404   CAN_InitStruct->CAN_TTCM = DISABLE;\r
405   /* Initialize the automatic bus-off management */\r
406   CAN_InitStruct->CAN_ABOM = DISABLE;\r
407   /* Initialize the automatic wake-up mode */\r
408   CAN_InitStruct->CAN_AWUM = DISABLE;\r
409   /* Initialize the no automatic retransmission */\r
410   CAN_InitStruct->CAN_NART = DISABLE;\r
411   /* Initialize the receive FIFO locked mode */\r
412   CAN_InitStruct->CAN_RFLM = DISABLE;\r
413   /* Initialize the transmit FIFO priority */\r
414   CAN_InitStruct->CAN_TXFP = DISABLE;\r
415   /* Initialize the CAN_Mode member */\r
416   CAN_InitStruct->CAN_Mode = CAN_Mode_Normal;\r
417   /* Initialize the CAN_SJW member */\r
418   CAN_InitStruct->CAN_SJW = CAN_SJW_1tq;\r
419   /* Initialize the CAN_BS1 member */\r
420   CAN_InitStruct->CAN_BS1 = CAN_BS1_4tq;\r
421   /* Initialize the CAN_BS2 member */\r
422   CAN_InitStruct->CAN_BS2 = CAN_BS2_3tq;\r
423   /* Initialize the CAN_Prescaler member */\r
424   CAN_InitStruct->CAN_Prescaler = 1;\r
425 }\r
426 \r
427 /**\r
428   * @brief  Select the start bank filter for slave CAN.\r
429   * @note   This function applies only to STM32 Connectivity line devices.\r
430   * @param  CAN_BankNumber: Select the start slave bank filter from 1..27.\r
431   * @retval None.\r
432   */\r
433 void CAN_SlaveStartBank(uint8_t CAN_BankNumber) \r
434 {\r
435   /* Check the parameters */\r
436   assert_param(IS_CAN_BANKNUMBER(CAN_BankNumber));\r
437   /* enter Initialisation mode for the filter */\r
438   CAN1->FMR |= FMR_FINIT;\r
439   /* Select the start slave bank */\r
440   CAN1->FMR &= (uint32_t)0xFFFFC0F1 ;\r
441   CAN1->FMR |= (uint32_t)(CAN_BankNumber)<<8;\r
442   /* Leave Initialisation mode for the filter */\r
443   CAN1->FMR &= ~FMR_FINIT;\r
444 }\r
445 \r
446 /**\r
447   * @brief  Enables or disables the specified CAN interrupts.\r
448   * @param  CANx: where x can be 1 or 2 to to select the CAN peripheral.\r
449   * @param  CAN_IT: specifies the CAN interrupt sources to be enabled or disabled.\r
450   *   This parameter can be: CAN_IT_TME, CAN_IT_FMP0, CAN_IT_FF0,\r
451   *   CAN_IT_FOV0, CAN_IT_FMP1, CAN_IT_FF1,\r
452   *   CAN_IT_FOV1, CAN_IT_EWG, CAN_IT_EPV,\r
453   *   CAN_IT_LEC, CAN_IT_ERR, CAN_IT_WKU or\r
454   *   CAN_IT_SLK.\r
455   * @param  NewState: new state of the CAN interrupts.\r
456   *   This parameter can be: ENABLE or DISABLE.\r
457   * @retval None.\r
458   */\r
459 void CAN_ITConfig(CAN_TypeDef* CANx, uint32_t CAN_IT, FunctionalState NewState)\r
460 {\r
461   /* Check the parameters */\r
462   assert_param(IS_CAN_ALL_PERIPH(CANx));\r
463   assert_param(IS_CAN_ITConfig(CAN_IT));\r
464   assert_param(IS_FUNCTIONAL_STATE(NewState));\r
465 \r
466   if (NewState != DISABLE)\r
467   {\r
468     /* Enable the selected CAN interrupt */\r
469     CANx->IER |= CAN_IT;\r
470   }\r
471   else\r
472   {\r
473     /* Disable the selected CAN interrupt */\r
474     CANx->IER &= ~CAN_IT;\r
475   }\r
476 }\r
477 \r
478 /**\r
479   * @brief  Initiates the transmission of a message.\r
480   * @param  CANx: where x can be 1 or 2 to to select the CAN peripheral.\r
481   * @param  TxMessage: pointer to a structure which contains CAN Id, CAN\r
482   *   DLC and CAN datas.\r
483   * @retval The number of the mailbox that is used for transmission\r
484   *   or CAN_NO_MB if there is no empty mailbox.\r
485   */\r
486 uint8_t CAN_Transmit(CAN_TypeDef* CANx, CanTxMsg* TxMessage)\r
487 {\r
488   uint8_t transmit_mailbox = 0;\r
489   /* Check the parameters */\r
490   assert_param(IS_CAN_ALL_PERIPH(CANx));\r
491   assert_param(IS_CAN_IDTYPE(TxMessage->IDE));\r
492   assert_param(IS_CAN_RTR(TxMessage->RTR));\r
493   assert_param(IS_CAN_DLC(TxMessage->DLC));\r
494 \r
495   /* Select one empty transmit mailbox */\r
496   if ((CANx->TSR&TSR_TME0) == TSR_TME0)\r
497   {\r
498     transmit_mailbox = 0;\r
499   }\r
500   else if ((CANx->TSR&TSR_TME1) == TSR_TME1)\r
501   {\r
502     transmit_mailbox = 1;\r
503   }\r
504   else if ((CANx->TSR&TSR_TME2) == TSR_TME2)\r
505   {\r
506     transmit_mailbox = 2;\r
507   }\r
508   else\r
509   {\r
510     transmit_mailbox = CAN_NO_MB;\r
511   }\r
512 \r
513   if (transmit_mailbox != CAN_NO_MB)\r
514   {\r
515     /* Set up the Id */\r
516     CANx->sTxMailBox[transmit_mailbox].TIR &= TMIDxR_TXRQ;\r
517     if (TxMessage->IDE == CAN_ID_STD)\r
518     {\r
519       assert_param(IS_CAN_STDID(TxMessage->StdId));  \r
520       CANx->sTxMailBox[transmit_mailbox].TIR |= ((TxMessage->StdId << 21) | TxMessage->RTR);\r
521     }\r
522     else\r
523     {\r
524       assert_param(IS_CAN_EXTID(TxMessage->ExtId));\r
525       CANx->sTxMailBox[transmit_mailbox].TIR |= ((TxMessage->ExtId<<3) | TxMessage->IDE | \r
526                                                TxMessage->RTR);\r
527     }\r
528     \r
529 \r
530     /* Set up the DLC */\r
531     TxMessage->DLC &= (uint8_t)0x0000000F;\r
532     CANx->sTxMailBox[transmit_mailbox].TDTR &= (uint32_t)0xFFFFFFF0;\r
533     CANx->sTxMailBox[transmit_mailbox].TDTR |= TxMessage->DLC;\r
534 \r
535     /* Set up the data field */\r
536     CANx->sTxMailBox[transmit_mailbox].TDLR = (((uint32_t)TxMessage->Data[3] << 24) | \r
537                                              ((uint32_t)TxMessage->Data[2] << 16) |\r
538                                              ((uint32_t)TxMessage->Data[1] << 8) | \r
539                                              ((uint32_t)TxMessage->Data[0]));\r
540     CANx->sTxMailBox[transmit_mailbox].TDHR = (((uint32_t)TxMessage->Data[7] << 24) | \r
541                                              ((uint32_t)TxMessage->Data[6] << 16) |\r
542                                              ((uint32_t)TxMessage->Data[5] << 8) |\r
543                                              ((uint32_t)TxMessage->Data[4]));\r
544     /* Request transmission */\r
545     CANx->sTxMailBox[transmit_mailbox].TIR |= TMIDxR_TXRQ;\r
546   }\r
547   return transmit_mailbox;\r
548 }\r
549 \r
550 /**\r
551   * @brief  Checks the transmission of a message.\r
552   * @param  CANx: where x can be 1 or 2 to to select the CAN peripheral.\r
553   * @param  TransmitMailbox: the number of the mailbox that is used for transmission.\r
554   * @retval CANTXOK if the CAN driver transmits the message, CANTXFAILED in an other case.\r
555   */\r
556 uint8_t CAN_TransmitStatus(CAN_TypeDef* CANx, uint8_t TransmitMailbox)\r
557 {\r
558   /* RQCP, TXOK and TME bits */\r
559   uint8_t state = 0;\r
560   /* Check the parameters */\r
561   assert_param(IS_CAN_ALL_PERIPH(CANx));\r
562   assert_param(IS_CAN_TRANSMITMAILBOX(TransmitMailbox));\r
563   switch (TransmitMailbox)\r
564   {\r
565     case (0): state |= (uint8_t)((CANx->TSR & TSR_RQCP0) << 2);\r
566       state |= (uint8_t)((CANx->TSR & TSR_TXOK0) >> 0);\r
567       state |= (uint8_t)((CANx->TSR & TSR_TME0) >> 26);\r
568       break;\r
569     case (1): state |= (uint8_t)((CANx->TSR & TSR_RQCP1) >> 6);\r
570       state |= (uint8_t)((CANx->TSR & TSR_TXOK1) >> 8);\r
571       state |= (uint8_t)((CANx->TSR & TSR_TME1) >> 27);\r
572       break;\r
573     case (2): state |= (uint8_t)((CANx->TSR & TSR_RQCP2) >> 14);\r
574       state |= (uint8_t)((CANx->TSR & TSR_TXOK2) >> 16);\r
575       state |= (uint8_t)((CANx->TSR & TSR_TME2) >> 28);\r
576       break;\r
577     default:\r
578       state = CANTXFAILED;\r
579       break;\r
580   }\r
581   switch (state)\r
582   {\r
583       /* transmit pending  */\r
584     case (0x0): state = CANTXPENDING;\r
585       break;\r
586       /* transmit failed  */\r
587     case (0x5): state = CANTXFAILED;\r
588       break;\r
589       /* transmit succedeed  */\r
590     case (0x7): state = CANTXOK;\r
591       break;\r
592     default:\r
593       state = CANTXFAILED;\r
594       break;\r
595   }\r
596   return state;\r
597 }\r
598 \r
599 /**\r
600   * @brief  Cancels a transmit request.\r
601   * @param  CANx: where x can be 1 or 2 to to select the CAN peripheral. \r
602   * @param  Mailbox: Mailbox number.\r
603   * @retval None.\r
604   */\r
605 void CAN_CancelTransmit(CAN_TypeDef* CANx, uint8_t Mailbox)\r
606 {\r
607   /* Check the parameters */\r
608   assert_param(IS_CAN_ALL_PERIPH(CANx));\r
609   assert_param(IS_CAN_TRANSMITMAILBOX(Mailbox));\r
610   /* abort transmission */\r
611   switch (Mailbox)\r
612   {\r
613     case (0): CANx->TSR |= TSR_ABRQ0;\r
614       break;\r
615     case (1): CANx->TSR |= TSR_ABRQ1;\r
616       break;\r
617     case (2): CANx->TSR |= TSR_ABRQ2;\r
618       break;\r
619     default:\r
620       break;\r
621   }\r
622 }\r
623 \r
624 /**\r
625   * @brief  Releases a FIFO.\r
626   * @param  CANx: where x can be 1 or 2 to to select the CAN peripheral. \r
627   * @param  FIFONumber: FIFO to release, CAN_FIFO0 or CAN_FIFO1.\r
628   * @retval None.\r
629   */\r
630 void CAN_FIFORelease(CAN_TypeDef* CANx, uint8_t FIFONumber)\r
631 {\r
632   /* Check the parameters */\r
633   assert_param(IS_CAN_ALL_PERIPH(CANx));\r
634   assert_param(IS_CAN_FIFO(FIFONumber));\r
635   /* Release FIFO0 */\r
636   if (FIFONumber == CAN_FIFO0)\r
637   {\r
638     CANx->RF0R = RF0R_RFOM0;\r
639   }\r
640   /* Release FIFO1 */\r
641   else /* FIFONumber == CAN_FIFO1 */\r
642   {\r
643     CANx->RF1R = RF1R_RFOM1;\r
644   }\r
645 }\r
646 \r
647 /**\r
648   * @brief  Returns the number of pending messages.\r
649   * @param  CANx: where x can be 1 or 2 to to select the CAN peripheral.\r
650   * @param  FIFONumber: Receive FIFO number, CAN_FIFO0 or CAN_FIFO1.\r
651   * @retval NbMessage which is the number of pending message.\r
652   */\r
653 uint8_t CAN_MessagePending(CAN_TypeDef* CANx, uint8_t FIFONumber)\r
654 {\r
655   uint8_t message_pending=0;\r
656   /* Check the parameters */\r
657   assert_param(IS_CAN_ALL_PERIPH(CANx));\r
658   assert_param(IS_CAN_FIFO(FIFONumber));\r
659   if (FIFONumber == CAN_FIFO0)\r
660   {\r
661     message_pending = (uint8_t)(CANx->RF0R&(uint32_t)0x03);\r
662   }\r
663   else if (FIFONumber == CAN_FIFO1)\r
664   {\r
665     message_pending = (uint8_t)(CANx->RF1R&(uint32_t)0x03);\r
666   }\r
667   else\r
668   {\r
669     message_pending = 0;\r
670   }\r
671   return message_pending;\r
672 }\r
673 \r
674 /**\r
675   * @brief  Receives a message.\r
676   * @param  CANx: where x can be 1 or 2 to to select the CAN peripheral.\r
677   * @param  FIFONumber: Receive FIFO number, CAN_FIFO0 or CAN_FIFO1.\r
678   * @param  RxMessage: pointer to a structure receive message which \r
679   *   contains CAN Id, CAN DLC, CAN datas and FMI number.\r
680   * @retval None.\r
681   */\r
682 void CAN_Receive(CAN_TypeDef* CANx, uint8_t FIFONumber, CanRxMsg* RxMessage)\r
683 {\r
684   /* Check the parameters */\r
685   assert_param(IS_CAN_ALL_PERIPH(CANx));\r
686   assert_param(IS_CAN_FIFO(FIFONumber));\r
687   /* Get the Id */\r
688   RxMessage->IDE = (uint8_t)0x04 & CANx->sFIFOMailBox[FIFONumber].RIR;\r
689   if (RxMessage->IDE == CAN_ID_STD)\r
690   {\r
691     RxMessage->StdId = (uint32_t)0x000007FF & (CANx->sFIFOMailBox[FIFONumber].RIR >> 21);\r
692   }\r
693   else\r
694   {\r
695     RxMessage->ExtId = (uint32_t)0x1FFFFFFF & (CANx->sFIFOMailBox[FIFONumber].RIR >> 3);\r
696   }\r
697   \r
698   RxMessage->RTR = (uint8_t)0x02 & CANx->sFIFOMailBox[FIFONumber].RIR;\r
699   /* Get the DLC */\r
700   RxMessage->DLC = (uint8_t)0x0F & CANx->sFIFOMailBox[FIFONumber].RDTR;\r
701   /* Get the FMI */\r
702   RxMessage->FMI = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDTR >> 8);\r
703   /* Get the data field */\r
704   RxMessage->Data[0] = (uint8_t)0xFF & CANx->sFIFOMailBox[FIFONumber].RDLR;\r
705   RxMessage->Data[1] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDLR >> 8);\r
706   RxMessage->Data[2] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDLR >> 16);\r
707   RxMessage->Data[3] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDLR >> 24);\r
708   RxMessage->Data[4] = (uint8_t)0xFF & CANx->sFIFOMailBox[FIFONumber].RDHR;\r
709   RxMessage->Data[5] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDHR >> 8);\r
710   RxMessage->Data[6] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDHR >> 16);\r
711   RxMessage->Data[7] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDHR >> 24);\r
712   /* Release the FIFO */\r
713   CAN_FIFORelease(CANx, FIFONumber);\r
714 }\r
715 \r
716 /**\r
717   * @brief  Enables or disables the DBG Freeze for CAN.\r
718   * @param  CANx: where x can be 1 or 2 to to select the CAN peripheral.\r
719   * @param  NewState: new state of the CAN peripheral.\r
720   *   This parameter can be: ENABLE or DISABLE.\r
721   * @retval None.\r
722   */\r
723 void CAN_DBGFreeze(CAN_TypeDef* CANx, FunctionalState NewState)\r
724 {\r
725   /* Check the parameters */\r
726   assert_param(IS_CAN_ALL_PERIPH(CANx));\r
727   assert_param(IS_FUNCTIONAL_STATE(NewState));\r
728   \r
729   if (NewState != DISABLE)\r
730   {\r
731     /* Enable Debug Freeze  */\r
732     CANx->MCR |= MCR_DBF;\r
733   }\r
734   else\r
735   {\r
736     /* Disable Debug Freeze */\r
737     CANx->MCR &= ~MCR_DBF;\r
738   }\r
739 }\r
740 \r
741 /**\r
742   * @brief  Enters the low power mode.\r
743   * @param  CANx: where x can be 1 or 2 to to select the CAN peripheral.\r
744   * @retval CANSLEEPOK if sleep entered, CANSLEEPFAILED in an other case.\r
745   */\r
746 uint8_t CAN_Sleep(CAN_TypeDef* CANx)\r
747 {\r
748   uint8_t sleepstatus = CANSLEEPFAILED;\r
749   \r
750   /* Check the parameters */\r
751   assert_param(IS_CAN_ALL_PERIPH(CANx));\r
752     \r
753   /* Request Sleep mode */\r
754    CANx->MCR = (((CANx->MCR) & (uint32_t)(~MCR_INRQ)) | MCR_SLEEP);\r
755    \r
756   /* Sleep mode status */\r
757   if ((CANx->MSR & (CAN_MSR_SLAK|CAN_MSR_INAK)) == CAN_MSR_SLAK)\r
758   {\r
759     /* Sleep mode not entered */\r
760     sleepstatus =  CANSLEEPOK;\r
761   }\r
762   /* At this step, sleep mode status */\r
763    return (uint8_t)sleepstatus;\r
764 }\r
765 \r
766 /**\r
767   * @brief  Wakes the CAN up.\r
768   * @param  CANx: where x can be 1 or 2 to to select the CAN peripheral.\r
769   * @retval CANWAKEUPOK if sleep mode left, CANWAKEUPFAILED in an other case.\r
770   */\r
771 uint8_t CAN_WakeUp(CAN_TypeDef* CANx)\r
772 {\r
773   uint32_t wait_slak = SLAK_TimeOut     ;\r
774   uint8_t wakeupstatus = CANWAKEUPFAILED;\r
775   \r
776   /* Check the parameters */\r
777   assert_param(IS_CAN_ALL_PERIPH(CANx));\r
778     \r
779   /* Wake up request */\r
780   CANx->MCR &= ~MCR_SLEEP;\r
781     \r
782   /* Sleep mode status */\r
783   while(((CANx->MSR & CAN_MSR_SLAK) == CAN_MSR_SLAK)&&(wait_slak!=0x00))\r
784   {\r
785    wait_slak--;\r
786   }\r
787   if((CANx->MSR & CAN_MSR_SLAK) != CAN_MSR_SLAK)\r
788   {\r
789    /* Sleep mode exited */\r
790     wakeupstatus = CANWAKEUPOK;\r
791   }\r
792   /* At this step, sleep mode status */\r
793   return (uint8_t)wakeupstatus;\r
794 }\r
795 \r
796 /**\r
797   * @brief  Checks whether the specified CAN flag is set or not.\r
798   * @param  CANx: where x can be 1 or 2 to to select the CAN peripheral.\r
799   * @param  CAN_FLAG: specifies the flag to check.\r
800   *   This parameter can be: CAN_FLAG_EWG, CAN_FLAG_EPV or CAN_FLAG_BOF.\r
801   * @retval The new state of CAN_FLAG (SET or RESET).\r
802   */\r
803 FlagStatus CAN_GetFlagStatus(CAN_TypeDef* CANx, uint32_t CAN_FLAG)\r
804 {\r
805   FlagStatus bitstatus = RESET;\r
806   /* Check the parameters */\r
807   assert_param(IS_CAN_ALL_PERIPH(CANx));\r
808   assert_param(IS_CAN_FLAG(CAN_FLAG));\r
809   /* Check the status of the specified CAN flag */\r
810   if ((CANx->ESR & CAN_FLAG) != (uint32_t)RESET)\r
811   {\r
812     /* CAN_FLAG is set */\r
813     bitstatus = SET;\r
814   }\r
815   else\r
816   {\r
817     /* CAN_FLAG is reset */\r
818     bitstatus = RESET;\r
819   }\r
820   /* Return the CAN_FLAG status */\r
821   return  bitstatus;\r
822 }\r
823 \r
824 /**\r
825   * @brief  Clears the CAN's pending flags.\r
826   * @param  CANx: where x can be 1 or 2 to to select the CAN peripheral.\r
827   * @param  CAN_FLAG: specifies the flag to clear.\r
828   * @retval None.\r
829   */\r
830 void CAN_ClearFlag(CAN_TypeDef* CANx, uint32_t CAN_FLAG)\r
831 {\r
832   /* Check the parameters */\r
833   assert_param(IS_CAN_ALL_PERIPH(CANx));\r
834   assert_param(IS_CAN_FLAG(CAN_FLAG));\r
835   /* Clear the selected CAN flags */\r
836   CANx->ESR &= ~CAN_FLAG;\r
837 }\r
838 \r
839 /**\r
840   * @brief  Checks whether the specified CAN interrupt has occurred or not.\r
841   * @param  CANx: where x can be 1 or 2 to to select the CAN peripheral.\r
842   * @param  CAN_IT: specifies the CAN interrupt source to check.\r
843   *   This parameter can be: CAN_IT_RQCP0, CAN_IT_RQCP1, CAN_IT_RQCP2,\r
844   *   CAN_IT_FF0, CAN_IT_FOV0, CAN_IT_FF1,\r
845   *   CAN_IT_FOV1, CAN_IT_EWG, CAN_IT_EPV, \r
846   *   CAN_IT_BOF, CAN_IT_WKU or CAN_IT_SLK.\r
847   * @retval The new state of CAN_IT (SET or RESET).\r
848   */\r
849 ITStatus CAN_GetITStatus(CAN_TypeDef* CANx, uint32_t CAN_IT)\r
850 {\r
851   ITStatus pendingbitstatus = RESET;\r
852   /* Check the parameters */\r
853   assert_param(IS_CAN_ALL_PERIPH(CANx));\r
854   assert_param(IS_CAN_ITStatus(CAN_IT));\r
855   switch (CAN_IT)\r
856   {\r
857     case CAN_IT_RQCP0:\r
858       pendingbitstatus = CheckITStatus(CANx->TSR, TSR_RQCP0);\r
859       break;\r
860     case CAN_IT_RQCP1:\r
861       pendingbitstatus = CheckITStatus(CANx->TSR, TSR_RQCP1);\r
862       break;\r
863     case CAN_IT_RQCP2:\r
864       pendingbitstatus = CheckITStatus(CANx->TSR, TSR_RQCP2);\r
865       break;\r
866     case CAN_IT_FF0:\r
867       pendingbitstatus = CheckITStatus(CANx->RF0R, RF0R_FULL0);\r
868       break;\r
869     case CAN_IT_FOV0:\r
870       pendingbitstatus = CheckITStatus(CANx->RF0R, RF0R_FOVR0);\r
871       break;\r
872     case CAN_IT_FF1:\r
873       pendingbitstatus = CheckITStatus(CANx->RF1R, RF1R_FULL1);\r
874       break;\r
875     case CAN_IT_FOV1:\r
876       pendingbitstatus = CheckITStatus(CANx->RF1R, RF1R_FOVR1);\r
877       break;\r
878     case CAN_IT_EWG:\r
879       pendingbitstatus = CheckITStatus(CANx->ESR, ESR_EWGF);\r
880       break;\r
881     case CAN_IT_EPV:\r
882       pendingbitstatus = CheckITStatus(CANx->ESR, ESR_EPVF);\r
883       break;\r
884     case CAN_IT_BOF:\r
885       pendingbitstatus = CheckITStatus(CANx->ESR, ESR_BOFF);\r
886       break;\r
887     case CAN_IT_SLK:\r
888       pendingbitstatus = CheckITStatus(CANx->MSR, MSR_SLAKI);\r
889       break;\r
890     case CAN_IT_WKU:\r
891       pendingbitstatus = CheckITStatus(CANx->MSR, MSR_WKUI);\r
892       break;\r
893     default :\r
894       pendingbitstatus = RESET;\r
895       break;\r
896   }\r
897   /* Return the CAN_IT status */\r
898   return  pendingbitstatus;\r
899 }\r
900 \r
901 /**\r
902   * @brief  Clears the CAN\92s interrupt pending bits.\r
903   * @param  CANx: where x can be 1 or 2 to to select the CAN peripheral.\r
904   * @param  CAN_IT: specifies the interrupt pending bit to clear.\r
905   * @retval None.\r
906   */\r
907 void CAN_ClearITPendingBit(CAN_TypeDef* CANx, uint32_t CAN_IT)\r
908 {\r
909   /* Check the parameters */\r
910   assert_param(IS_CAN_ALL_PERIPH(CANx));\r
911   assert_param(IS_CAN_ITStatus(CAN_IT));\r
912   switch (CAN_IT)\r
913   {\r
914     case CAN_IT_RQCP0:\r
915       CANx->TSR = TSR_RQCP0; /* rc_w1*/\r
916       break;\r
917     case CAN_IT_RQCP1:\r
918       CANx->TSR = TSR_RQCP1; /* rc_w1*/\r
919       break;\r
920     case CAN_IT_RQCP2:\r
921       CANx->TSR = TSR_RQCP2; /* rc_w1*/\r
922       break;\r
923     case CAN_IT_FF0:\r
924       CANx->RF0R = RF0R_FULL0; /* rc_w1*/\r
925       break;\r
926     case CAN_IT_FOV0:\r
927       CANx->RF0R = RF0R_FOVR0; /* rc_w1*/\r
928       break;\r
929     case CAN_IT_FF1:\r
930       CANx->RF1R = RF1R_FULL1; /* rc_w1*/\r
931       break;\r
932     case CAN_IT_FOV1:\r
933       CANx->RF1R = RF1R_FOVR1; /* rc_w1*/\r
934       break;\r
935     case CAN_IT_EWG:\r
936       CANx->ESR &= ~ ESR_EWGF; /* rw */\r
937       break;\r
938     case CAN_IT_EPV:\r
939       CANx->ESR &= ~ ESR_EPVF; /* rw */\r
940       break;\r
941     case CAN_IT_BOF:\r
942       CANx->ESR &= ~ ESR_BOFF; /* rw */\r
943       break;\r
944     case CAN_IT_WKU:\r
945       CANx->MSR = MSR_WKUI;  /* rc_w1*/\r
946       break;\r
947     case CAN_IT_SLK:\r
948       CANx->MSR = MSR_SLAKI;  /* rc_w1*/\r
949       break;\r
950     default :\r
951       break;\r
952   }\r
953 }\r
954 \r
955 /**\r
956   * @brief  Checks whether the CAN interrupt has occurred or not.\r
957   * @param  CAN_Reg: specifies the CAN interrupt register to check.\r
958   * @param  It_Bit: specifies the interrupt source bit to check.\r
959   * @retval The new state of the CAN Interrupt (SET or RESET).\r
960   */\r
961 static ITStatus CheckITStatus(uint32_t CAN_Reg, uint32_t It_Bit)\r
962 {\r
963   ITStatus pendingbitstatus = RESET;\r
964   \r
965   if ((CAN_Reg & It_Bit) != (uint32_t)RESET)\r
966   {\r
967     /* CAN_IT is set */\r
968     pendingbitstatus = SET;\r
969   }\r
970   else\r
971   {\r
972     /* CAN_IT is reset */\r
973     pendingbitstatus = RESET;\r
974   }\r
975   return pendingbitstatus;\r
976 }\r
977 \r
978 /**\r
979   * @}\r
980   */\r
981 \r
982 /**\r
983   * @}\r
984   */\r
985 \r
986 /**\r
987   * @}\r
988   */\r
989 \r
990 /******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/\r