Controller Area Network library for NUCLEO boards equipped with CAN peripheral.

Dependents:   Nucleo-Courtois CANBLE CANnucleo_Hello3 Nucleo_Serialprintf ... more

Controller Area Network library for the NUCLEO and DISCOVERY boards equipped with CAN peripheral


Information

Because CAN support has been finally implemented into the mbed library also for the ST boards there is no need to use the CANnucleo library anymore (however you may if you want). The CAN_Hello example is trying to demonstrate the mbed built-in CAN API with NUCLEO boards.


Provides CAN support for the following boards:

with the following features:

  • Easy to use. Delete the mbed library from your project and import the latest mbed-dev and CANnucleo libraries. In the mbed-dev library open the device.h file associated with the selected target board and add #undef DEVICE_CAN as follows:

device.h

#ifndef MBED_DEVICE_H
#define MBED_DEVICE_H

//=======================================
#define DEVICE_ID_LENGTH       24

#undef DEVICE_CAN

#include "objects.h"

#endif

See the CANnucleo_Hello demo for more details.

  • Automatic recovery from bus-off state can be enabled/disabled in the constructor (defaults to ENABLE).
  • Up to 14 filters (0 - 13) are available for the application to set up for message filtering performed by hardware.
    For more details see below or have a look at the comments in CANnucleo.cpp.
  • One CAN channel per NUCLEO board is supported. The CAN peripheral can be connected either to pins PA_11, PA_12 (Receiver, Transmitter) or to pins PB_8, PB_9 (Receiver, Transmitter). This is configured when creating a CAN instance.
  • Simplifies adding/getting data to/from a CAN message by using the << (append) and the >> (extract) operators.

Import programCANnucleo_Hello

Using CAN bus with NUCLEO boards (Demo for the CANnucleo library).



Filtering performed by the built-in CAN controller without disturbing the CPU

CANnucleo supports only mask mode and 32-bit filter scale. Identifier list mode filtering and 16-bit filter scale are not supported. There are 14 filters available (0 - 13) for the application to set up. Each filter is a 32-bit filter defined by a filter ID and a filter mask. If no filter is set up then no CAN message is accepted! That's why filter #0 is set up in the constructor to accept all CAN messages by default. On reception of a message it is compared with filter #0. If there is a match, the message is accepted and stored. If there is no match, the incoming identifier is then compared with the next filter. If the received identifier does not match any of the identifiers configured in the filters, the message is discarded by hardware without disturbing the software.

CAN filter function - designed to setup a CAN filter

int CAN::filter(unsigned int id, unsigned int mask, CANFormat format, int handle)

Parameters

id - 'Filter ID' defines the bit values to be compared with the corresponding received bits.

Mapping of 32-bits (4-bytes) :

STID[10:3]STID[2:0] EXID[17:13]EXID[12:5]EXID[4:0] IDE RTR 0
  • STID - Stardard Identifier bits
  • EXID - Extended Identifier bits
  • [x:y]- bit range
  • IDE - Identifier Extension bit (0 -> Standard Identifier, 1 -> Extended Identifier)
  • RTR - Remote Transmission Request bit (0 -> Remote Transmission Request, 1 -> Standard message)

mask - 'Filter mask' defines which bits of the 'Filter ID' are compared with the received bits and which are disregarded.
Mapping of 32-bits (4-bytes) :

STID[10:3]STID[2:0] EXID[17:13]EXID[12:5]EXID[4:0] IDE RTR 0
  • STID - Stardard Identifier bits
  • EXID - Extended Identifier bits
  • [x:y]- bit range
  • IDE - Identifier Extension bit
  • RTR - Remote Transmission Request bit
  • 1 -> bit is considered
  • 0 -> bit is disregarded

format - This parameter must be CANAny
handle - Selects the filter. This parameter must be a number between 0 and 13.
retval - 0 - successful, 1 - error, 2 - busy, 3 - time out

Example of filter set up and filtering

Let's assume we would like to accept only messages with standard identifier 0x207:

STID[15:0] = 0x207 = 00000010 00000111


We map the STID to filter ID by shifting the bits adequately:

Filter ID = STID << (16 + (15 - 10)) = STID << 21 = 01000000 11100000 00000000 00000000


To compare only the bits representing STID we set the filter mask appropriately:

Filter mask = 11111111 11100000 00000000 00000100 = 0xFFE00004
              |||||||| |||                    |
              -------- ---                    |
                  |     |                     |
           STID[10:3]  STID[2:0]             IDE


Recall that filter #0 has been set up in the constructor to accept all CAN messages by default. So we have to reconfigure it. If we were set up filter #1 here then filter #0 would accept all the messages and no message would reach filter #1!
To reconfigure (set up) filter #0 we call:

can.filter(0x207 << 21, 0xFFE00004, CANAny, 0);


            Only these bits of 'Filter id' (set to 1 here in 'Filter mask') are compared 
            with the corresponding bits of received message (the others are disregarded)
                                |
                 ---------------------------------
                 |||||||| |||                    |
   Filter mask = 11111111 11100000 00000000 00000100 (= 0xFFE00004)
   Filter id   = 01000000 11100000 00000000 00000000 (= 0x40E00000)
                 |||||||| |||                    |
                 ---------------------------------
                                |
            To accept the message the values of these bits must match.
            Otherwise the message is passed to the next filter or
            discarded if this was the last active filter.
                                |
                 ---------------------------------
                 |||||||| |||                    |
   Received id = 01000000 11100000 00000000 00000010 (= 0x40E00002)
                             ||||| |||||||| ||||| ||
                             -----------------------
                                         |
                          These bits (set to 0 in 'Filter mask') are disregarded (masked).
                          They can have arbitrary values.


NOTE: For the meaning of individual bits see the mapping of 32-bits explained above.

We can use the filter function to setup more (up to 14) CAN filters for example as follows:

can.filter(0x207 << 21, 0xFFE00004, CANAny, 0);    // filter #0
can.filter(0x251 << 21, 0xFFE00004, CANAny, 1);    // filter #1
can.filter(0x304 << 21, 0xFFE00004, CANAny, 2);    // filter #2
...
Committer:
hudakz
Date:
Wed Dec 30 08:23:30 2015 +0000
Revision:
16:f4c8f45bded9
Child:
18:a11422cf8e0a
Added support for NUCLEO-F072RB, NUCLEO-F091RC and NUCLEO446RE.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
hudakz 16:f4c8f45bded9 1 /**
hudakz 16:f4c8f45bded9 2 ******************************************************************************
hudakz 16:f4c8f45bded9 3 * @file stm32f3xx_hal_msp.c
hudakz 16:f4c8f45bded9 4 * @author MCD Application Team
hudakz 16:f4c8f45bded9 5 * @version V1.0.0
hudakz 16:f4c8f45bded9 6 * @date 17-December-2014
hudakz 16:f4c8f45bded9 7 * @brief HAL MSP module.
hudakz 16:f4c8f45bded9 8 ******************************************************************************
hudakz 16:f4c8f45bded9 9 * @attention
hudakz 16:f4c8f45bded9 10 *
hudakz 16:f4c8f45bded9 11 * <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
hudakz 16:f4c8f45bded9 12 *
hudakz 16:f4c8f45bded9 13 * Redistribution and use in source and binary forms, with or without modification,
hudakz 16:f4c8f45bded9 14 * are permitted provided that the following conditions are met:
hudakz 16:f4c8f45bded9 15 * 1. Redistributions of source code must retain the above copyright notice,
hudakz 16:f4c8f45bded9 16 * this list of conditions and the following disclaimer.
hudakz 16:f4c8f45bded9 17 * 2. Redistributions in binary form must reproduce the above copyright notice,
hudakz 16:f4c8f45bded9 18 * this list of conditions and the following disclaimer in the documentation
hudakz 16:f4c8f45bded9 19 * and/or other materials provided with the distribution.
hudakz 16:f4c8f45bded9 20 * 3. Neither the name of STMicroelectronics nor the names of its contributors
hudakz 16:f4c8f45bded9 21 * may be used to endorse or promote products derived from this software
hudakz 16:f4c8f45bded9 22 * without specific prior written permission.
hudakz 16:f4c8f45bded9 23 *
hudakz 16:f4c8f45bded9 24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
hudakz 16:f4c8f45bded9 25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
hudakz 16:f4c8f45bded9 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
hudakz 16:f4c8f45bded9 27 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
hudakz 16:f4c8f45bded9 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
hudakz 16:f4c8f45bded9 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
hudakz 16:f4c8f45bded9 30 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
hudakz 16:f4c8f45bded9 31 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
hudakz 16:f4c8f45bded9 32 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
hudakz 16:f4c8f45bded9 33 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
hudakz 16:f4c8f45bded9 34 *
hudakz 16:f4c8f45bded9 35 ******************************************************************************
hudakz 16:f4c8f45bded9 36 *
hudakz 16:f4c8f45bded9 37 * Modified by Zoltan Hudak <hudakz@inbox.com>
hudakz 16:f4c8f45bded9 38 *
hudakz 16:f4c8f45bded9 39 ******************************************************************************
hudakz 16:f4c8f45bded9 40 */
hudakz 16:f4c8f45bded9 41 #if defined(TARGET_NUCLEO_F072RB) || \
hudakz 16:f4c8f45bded9 42 defined(TARGET_NUCLEO_F091RC)
hudakz 16:f4c8f45bded9 43
hudakz 16:f4c8f45bded9 44 #include "can_api.h"
hudakz 16:f4c8f45bded9 45 #include "pinmap.h"
hudakz 16:f4c8f45bded9 46
hudakz 16:f4c8f45bded9 47 CAN_HandleTypeDef _canHandle;
hudakz 16:f4c8f45bded9 48 CanRxMsgTypeDef _canRxMsg;
hudakz 16:f4c8f45bded9 49 CanTxMsgTypeDef _canTxMsg;
hudakz 16:f4c8f45bded9 50 PinName _rxPin;
hudakz 16:f4c8f45bded9 51 PinName _txPin;
hudakz 16:f4c8f45bded9 52
hudakz 16:f4c8f45bded9 53 void (*rxCompleteCallback) (void);
hudakz 16:f4c8f45bded9 54
hudakz 16:f4c8f45bded9 55 /**
hudakz 16:f4c8f45bded9 56 * @brief CAN initialization.
hudakz 16:f4c8f45bded9 57 * @param obj: can_t object
hudakz 16:f4c8f45bded9 58 * @param rxPin: RX pin name
hudakz 16:f4c8f45bded9 59 * @param txPin: TX pin name
hudakz 16:f4c8f45bded9 60 * @param abom: Automatic recovery from bus-off state
hudakz 16:f4c8f45bded9 61 * @retval None
hudakz 16:f4c8f45bded9 62 */
hudakz 16:f4c8f45bded9 63 void initCAN(can_t* obj, PinName rxPin, PinName txPin, FunctionalState abom) {
hudakz 16:f4c8f45bded9 64 _rxPin = rxPin;
hudakz 16:f4c8f45bded9 65 _txPin = txPin;
hudakz 16:f4c8f45bded9 66
hudakz 16:f4c8f45bded9 67 _canHandle.Instance = ((CAN_TypeDef*)CAN_BASE);
hudakz 16:f4c8f45bded9 68 _canHandle.pTxMsg = &_canTxMsg;
hudakz 16:f4c8f45bded9 69 _canHandle.pRxMsg = &_canRxMsg;
hudakz 16:f4c8f45bded9 70
hudakz 16:f4c8f45bded9 71 _canHandle.Init.TTCM = DISABLE;
hudakz 16:f4c8f45bded9 72 _canHandle.Init.ABOM = abom;
hudakz 16:f4c8f45bded9 73 _canHandle.Init.AWUM = DISABLE;
hudakz 16:f4c8f45bded9 74 _canHandle.Init.NART = DISABLE;
hudakz 16:f4c8f45bded9 75 _canHandle.Init.RFLM = DISABLE;
hudakz 16:f4c8f45bded9 76 _canHandle.Init.TXFP = DISABLE;
hudakz 16:f4c8f45bded9 77 _canHandle.Init.Mode = CAN_MODE_NORMAL;
hudakz 16:f4c8f45bded9 78
hudakz 16:f4c8f45bded9 79 // 125kbps bit rate (default)
hudakz 16:f4c8f45bded9 80 // APB1 peripheral clock = 48000000Hz
hudakz 16:f4c8f45bded9 81 _canHandle.Init.Prescaler = 24; // number of time quanta = 48000000/24/125000 = 16
hudakz 16:f4c8f45bded9 82 _canHandle.Init.SJW = CAN_SJW_1TQ;
hudakz 16:f4c8f45bded9 83 _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75%
hudakz 16:f4c8f45bded9 84 _canHandle.Init.BS2 = CAN_BS2_4TQ;
hudakz 16:f4c8f45bded9 85
hudakz 16:f4c8f45bded9 86 HAL_CAN_Init(&_canHandle);
hudakz 16:f4c8f45bded9 87 }
hudakz 16:f4c8f45bded9 88
hudakz 16:f4c8f45bded9 89 /**
hudakz 16:f4c8f45bded9 90 * @brief CAN MSP Initialization
hudakz 16:f4c8f45bded9 91 * @param hcan: CAN handle pointer
hudakz 16:f4c8f45bded9 92 * @retval None
hudakz 16:f4c8f45bded9 93 */
hudakz 16:f4c8f45bded9 94 void HAL_CAN_MspInit(CAN_HandleTypeDef* hcan) {
hudakz 16:f4c8f45bded9 95 GPIO_InitTypeDef GPIO_InitStruct;
hudakz 16:f4c8f45bded9 96
hudakz 16:f4c8f45bded9 97 if((_rxPin == PA_11) && (_txPin == PA_12)) {
hudakz 16:f4c8f45bded9 98
hudakz 16:f4c8f45bded9 99 /* CAN1 Periph clock enable */
hudakz 16:f4c8f45bded9 100 __CAN_CLK_ENABLE();
hudakz 16:f4c8f45bded9 101
hudakz 16:f4c8f45bded9 102 /* Enable GPIO clock */
hudakz 16:f4c8f45bded9 103 __GPIOA_CLK_ENABLE();
hudakz 16:f4c8f45bded9 104
hudakz 16:f4c8f45bded9 105 /* CAN1 RX GPIO pin configuration */
hudakz 16:f4c8f45bded9 106 GPIO_InitStruct.Pin = GPIO_PIN_11;
hudakz 16:f4c8f45bded9 107 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
hudakz 16:f4c8f45bded9 108 GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
hudakz 16:f4c8f45bded9 109 GPIO_InitStruct.Pull = GPIO_NOPULL;
hudakz 16:f4c8f45bded9 110 GPIO_InitStruct.Alternate = GPIO_AF4_CAN;
hudakz 16:f4c8f45bded9 111 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
hudakz 16:f4c8f45bded9 112
hudakz 16:f4c8f45bded9 113 /* CAN1 TX GPIO pin configuration */
hudakz 16:f4c8f45bded9 114 GPIO_InitStruct.Pin = GPIO_PIN_12;
hudakz 16:f4c8f45bded9 115 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
hudakz 16:f4c8f45bded9 116 GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
hudakz 16:f4c8f45bded9 117 GPIO_InitStruct.Pull = GPIO_NOPULL;
hudakz 16:f4c8f45bded9 118 GPIO_InitStruct.Alternate = GPIO_AF4_CAN;
hudakz 16:f4c8f45bded9 119 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
hudakz 16:f4c8f45bded9 120 }
hudakz 16:f4c8f45bded9 121 else
hudakz 16:f4c8f45bded9 122 if((_rxPin == PB_8) && (_txPin == PB_9)) {
hudakz 16:f4c8f45bded9 123 /* CAN1 Periph clock enable */
hudakz 16:f4c8f45bded9 124 __CAN_CLK_ENABLE();
hudakz 16:f4c8f45bded9 125
hudakz 16:f4c8f45bded9 126 /* Enable GPIO clock */
hudakz 16:f4c8f45bded9 127 __GPIOB_CLK_ENABLE();
hudakz 16:f4c8f45bded9 128
hudakz 16:f4c8f45bded9 129 /* CAN1 RX GPIO pin configuration */
hudakz 16:f4c8f45bded9 130 GPIO_InitStruct.Pin = GPIO_PIN_8;
hudakz 16:f4c8f45bded9 131 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
hudakz 16:f4c8f45bded9 132 GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
hudakz 16:f4c8f45bded9 133 GPIO_InitStruct.Pull = GPIO_NOPULL;
hudakz 16:f4c8f45bded9 134 GPIO_InitStruct.Alternate = GPIO_AF4_CAN;
hudakz 16:f4c8f45bded9 135 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
hudakz 16:f4c8f45bded9 136
hudakz 16:f4c8f45bded9 137 /* CAN1 TX GPIO pin configuration */
hudakz 16:f4c8f45bded9 138 GPIO_InitStruct.Pin = GPIO_PIN_9;
hudakz 16:f4c8f45bded9 139 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
hudakz 16:f4c8f45bded9 140 GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
hudakz 16:f4c8f45bded9 141 GPIO_InitStruct.Pull = GPIO_NOPULL;
hudakz 16:f4c8f45bded9 142 GPIO_InitStruct.Alternate = GPIO_AF4_CAN;
hudakz 16:f4c8f45bded9 143 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
hudakz 16:f4c8f45bded9 144 }
hudakz 16:f4c8f45bded9 145 else
hudakz 16:f4c8f45bded9 146 return;
hudakz 16:f4c8f45bded9 147 /* NVIC configuration for CAN1 Reception complete interrupt */
hudakz 16:f4c8f45bded9 148 HAL_NVIC_SetPriority(CAN_IRQ, 1, 0);
hudakz 16:f4c8f45bded9 149 HAL_NVIC_EnableIRQ(CAN_IRQ);
hudakz 16:f4c8f45bded9 150 }
hudakz 16:f4c8f45bded9 151
hudakz 16:f4c8f45bded9 152 /**
hudakz 16:f4c8f45bded9 153 * @brief CAN MSP De-Initialization
hudakz 16:f4c8f45bded9 154 * This function frees the hardware resources used:
hudakz 16:f4c8f45bded9 155 * - Disable the Peripheral's clock
hudakz 16:f4c8f45bded9 156 * - Revert GPIO to their default state
hudakz 16:f4c8f45bded9 157 * @param hcan: CAN handle pointer
hudakz 16:f4c8f45bded9 158 * @retval None
hudakz 16:f4c8f45bded9 159 */
hudakz 16:f4c8f45bded9 160 void HAL_CAN_MspDeInit(CAN_HandleTypeDef* hcan) {
hudakz 16:f4c8f45bded9 161
hudakz 16:f4c8f45bded9 162 /* Reset peripherals */
hudakz 16:f4c8f45bded9 163
hudakz 16:f4c8f45bded9 164 __CAN_FORCE_RESET();
hudakz 16:f4c8f45bded9 165 __CAN_RELEASE_RESET();
hudakz 16:f4c8f45bded9 166
hudakz 16:f4c8f45bded9 167 /* Disable peripherals and GPIO Clocks */
hudakz 16:f4c8f45bded9 168 if((_rxPin == PA_11) && (_txPin == PA_12)) {
hudakz 16:f4c8f45bded9 169 /* De-initialize the CAN1 RX GPIO pin */
hudakz 16:f4c8f45bded9 170 HAL_GPIO_DeInit(GPIOA, GPIO_PIN_11);
hudakz 16:f4c8f45bded9 171
hudakz 16:f4c8f45bded9 172 /* De-initialize the CAN1 TX GPIO pin */
hudakz 16:f4c8f45bded9 173 HAL_GPIO_DeInit(GPIOA, GPIO_PIN_12);
hudakz 16:f4c8f45bded9 174 }
hudakz 16:f4c8f45bded9 175 else {
hudakz 16:f4c8f45bded9 176
hudakz 16:f4c8f45bded9 177 /* De-initialize the CAN1 RX GPIO pin */
hudakz 16:f4c8f45bded9 178 HAL_GPIO_DeInit(GPIOB, GPIO_PIN_8);
hudakz 16:f4c8f45bded9 179
hudakz 16:f4c8f45bded9 180 /* De-initialize the CAN1 TX GPIO pin */
hudakz 16:f4c8f45bded9 181 HAL_GPIO_DeInit(GPIOB, GPIO_PIN_9);
hudakz 16:f4c8f45bded9 182 }
hudakz 16:f4c8f45bded9 183
hudakz 16:f4c8f45bded9 184
hudakz 16:f4c8f45bded9 185 /* Disable the NVIC for CAN reception */
hudakz 16:f4c8f45bded9 186 HAL_NVIC_DisableIRQ(CAN_IRQ);
hudakz 16:f4c8f45bded9 187 }
hudakz 16:f4c8f45bded9 188
hudakz 16:f4c8f45bded9 189 /**
hudakz 16:f4c8f45bded9 190 * @brief Handles CAN RX0 interrupt request.
hudakz 16:f4c8f45bded9 191 * @param None
hudakz 16:f4c8f45bded9 192 * @retval None
hudakz 16:f4c8f45bded9 193 */
hudakz 16:f4c8f45bded9 194 void USB_LP_CAN_RX0_IRQHandler(void) {
hudakz 16:f4c8f45bded9 195 HAL_CAN_IRQHandler(&_canHandle);
hudakz 16:f4c8f45bded9 196 }
hudakz 16:f4c8f45bded9 197
hudakz 16:f4c8f45bded9 198 /**
hudakz 16:f4c8f45bded9 199 * @brief Reception complete callback in non blocking mode
hudakz 16:f4c8f45bded9 200 * @param _canHandle: pointer to a CAN_HandleTypeDef structure that contains
hudakz 16:f4c8f45bded9 201 * the configuration information for the specified CAN.
hudakz 16:f4c8f45bded9 202 * @retval None
hudakz 16:f4c8f45bded9 203 */
hudakz 16:f4c8f45bded9 204 void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* _canHandle) {
hudakz 16:f4c8f45bded9 205 // if(HAL_CAN_Receive_IT(_canHandle, CAN_FIFO0) == HAL_OK) {
hudakz 16:f4c8f45bded9 206 // if(rxCompleteCallback != NULL)
hudakz 16:f4c8f45bded9 207 // rxCompleteCallback();
hudakz 16:f4c8f45bded9 208 // }
hudakz 16:f4c8f45bded9 209 // else {
hudakz 16:f4c8f45bded9 210 // error_handler(error);
hudakz 16:f4c8f45bded9 211 // }
hudakz 16:f4c8f45bded9 212
hudakz 16:f4c8f45bded9 213 // BUG: CAN race condition if HAL_CAN_Receive_IT() is used.
hudakz 16:f4c8f45bded9 214 // See https://my.st.com/public/STe2ecommunities/mcu/Lists/STM32Java/Flat.aspx?RootFolder=%2Fpublic%2FSTe2ecommunities%2Fmcu%2FLists%2FSTM32Java%2FBUG%20CAN%20race%20condition%20if%20HAL%5FCAN%5FReceive%5FIT%20is%20used
hudakz 16:f4c8f45bded9 215 //
hudakz 16:f4c8f45bded9 216 // Fixed by Mark Burton:
hudakz 16:f4c8f45bded9 217 // ideally, we should be able to call HAL_CAN_Receive_IT() here to set up for another
hudakz 16:f4c8f45bded9 218 // receive but the API is flawed because that function will fail if HAL_CAN_Transmit()
hudakz 16:f4c8f45bded9 219 // had already locked the handle when the receive interrupt occurred - so we do what
hudakz 16:f4c8f45bded9 220 // HAL_CAN_Receive_IT() would do
hudakz 16:f4c8f45bded9 221
hudakz 16:f4c8f45bded9 222 if (rxCompleteCallback != 0)
hudakz 16:f4c8f45bded9 223 rxCompleteCallback();
hudakz 16:f4c8f45bded9 224
hudakz 16:f4c8f45bded9 225 if (_canHandle->State == HAL_CAN_STATE_BUSY_TX)
hudakz 16:f4c8f45bded9 226 _canHandle->State = HAL_CAN_STATE_BUSY_TX_RX;
hudakz 16:f4c8f45bded9 227 else {
hudakz 16:f4c8f45bded9 228 _canHandle->State = HAL_CAN_STATE_BUSY_RX;
hudakz 16:f4c8f45bded9 229
hudakz 16:f4c8f45bded9 230 /* Set CAN error code to none */
hudakz 16:f4c8f45bded9 231 _canHandle->ErrorCode = HAL_CAN_ERROR_NONE;
hudakz 16:f4c8f45bded9 232
hudakz 16:f4c8f45bded9 233 /* Enable Error warning Interrupt */
hudakz 16:f4c8f45bded9 234 __HAL_CAN_ENABLE_IT(_canHandle, CAN_IT_EWG);
hudakz 16:f4c8f45bded9 235
hudakz 16:f4c8f45bded9 236 /* Enable Error passive Interrupt */
hudakz 16:f4c8f45bded9 237 __HAL_CAN_ENABLE_IT(_canHandle, CAN_IT_EPV);
hudakz 16:f4c8f45bded9 238
hudakz 16:f4c8f45bded9 239 /* Enable Bus-off Interrupt */
hudakz 16:f4c8f45bded9 240 __HAL_CAN_ENABLE_IT(_canHandle, CAN_IT_BOF);
hudakz 16:f4c8f45bded9 241
hudakz 16:f4c8f45bded9 242 /* Enable Last error code Interrupt */
hudakz 16:f4c8f45bded9 243 __HAL_CAN_ENABLE_IT(_canHandle, CAN_IT_LEC);
hudakz 16:f4c8f45bded9 244
hudakz 16:f4c8f45bded9 245 /* Enable Error Interrupt */
hudakz 16:f4c8f45bded9 246 __HAL_CAN_ENABLE_IT(_canHandle, CAN_IT_ERR);
hudakz 16:f4c8f45bded9 247 }
hudakz 16:f4c8f45bded9 248
hudakz 16:f4c8f45bded9 249 // Enable FIFO 0 message pending Interrupt
hudakz 16:f4c8f45bded9 250 __HAL_CAN_ENABLE_IT(_canHandle, CAN_IT_FMP0);
hudakz 16:f4c8f45bded9 251 }
hudakz 16:f4c8f45bded9 252 #endif