/**
******************************************************************************
* @file stm32f1xx_hal_msp.c
* @author MCD Application Team
* @version V1.0.0
* @date 17-December-2014
* @brief HAL MSP module.
******************************************************************************
* @attention
*
*
© COPYRIGHT(c) 2014 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*
* Modified by Zoltan Hudak
*
******************************************************************************
*/
#include "stm32f1xx_hal.h"
#include "can_api.h"
#include "pinmap.h"
CAN_HandleTypeDef _canHandle;
CanRxMsgTypeDef _canRxMsg;
CanTxMsgTypeDef _canTxMsg;
PinName _rxPin;
PinName _txPin;
void (*rxCompleteCallback) (void);
/**
* @brief CAN initialization.
* @param obj: can_t object
* @param rxPin: RX pin name
* @param txPin: TX pin name
* @param abom: Automatic recovery from bus-off state
* @retval None
*/
void initCAN(can_t* obj, PinName rxPin, PinName txPin, FunctionalState abom) {
_rxPin = rxPin;
_txPin = txPin;
_canHandle.Instance = CAN1;
_canHandle.pTxMsg = &_canTxMsg;
_canHandle.pRxMsg = &_canRxMsg;
_canHandle.Init.TTCM = DISABLE;
_canHandle.Init.ABOM = abom;
_canHandle.Init.AWUM = DISABLE;
_canHandle.Init.NART = DISABLE;
_canHandle.Init.RFLM = DISABLE;
_canHandle.Init.TXFP = DISABLE;
_canHandle.Init.Mode = CAN_MODE_NORMAL;
// 125kbps bit rate (default)
// APB1 peripheral clock = 36000000Hz
_canHandle.Init.Prescaler = 18; // number of time quanta = 36000000/18/125000 = 16
_canHandle.Init.SJW = CAN_SJW_1TQ;
_canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at (1 + 11) / 16 * 100 = 75%
_canHandle.Init.BS2 = CAN_BS2_4TQ;
HAL_CAN_Init(&_canHandle);
}
/**
* @brief CAN MSP Initialization
* @param hcan: CAN handle pointer
* @retval None
*/
void HAL_CAN_MspInit(CAN_HandleTypeDef* hcan) {
GPIO_InitTypeDef GPIO_InitStruct;
if((_rxPin == PA_11) && (_txPin == PA_12)) {
/* CAN1 Periph clock enable */
__HAL_RCC_CAN1_CLK_ENABLE();
/* Enable GPIO clock */
__HAL_RCC_GPIOA_CLK_ENABLE();
/* Enable AFIO clock and remap CAN PINs to PA11 and PA12*/
__HAL_RCC_AFIO_CLK_ENABLE();
__HAL_AFIO_REMAP_CAN1_1();
/* CAN1 RX GPIO pin configuration */
GPIO_InitStruct.Pin = GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
else
if((_rxPin == PB_8) && (_txPin == PB_9)) {
/* CAN1 Periph clock enable */
__HAL_RCC_CAN1_CLK_ENABLE();
/* Enable GPIO clock */
__HAL_RCC_GPIOB_CLK_ENABLE();
/* Enable AFIO clock and remap CAN PINs to PB_8 and PB_9*/
__HAL_RCC_AFIO_CLK_ENABLE();
__HAL_AFIO_REMAP_CAN1_2();
/* CAN1 RX GPIO pin configuration */
GPIO_InitStruct.Pin = GPIO_PIN_8;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
else
return;
/* NVIC configuration for CAN1 Reception complete interrupt */
HAL_NVIC_SetPriority(USB_LP_CAN1_RX0_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn);
}
/**
* @brief CAN MSP De-Initialization
* This function frees the hardware resources used:
* - Disable the Peripheral's clock
* - Revert GPIO to their default state
* @param hcan: CAN handle pointer
* @retval None
*/
void HAL_CAN_MspDeInit(CAN_HandleTypeDef* hcan) {
/* Reset peripherals */
__HAL_RCC_CAN1_FORCE_RESET();
__HAL_RCC_CAN1_RELEASE_RESET();
/* Disable peripherals and GPIO Clocks */
if((_rxPin == PA_11) && (_txPin == PA_12)) {
/* De-initialize the CAN1 TX GPIO pin */
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_11);
/* De-initialize the CAN1 RX GPIO pin */
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_12);
}
else {
/* De-initialize the CAN1 TX GPIO pin */
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_8);
/* De-initialize the CAN1 RX GPIO pin */
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_9);
}
/* Disable the NVIC for CAN reception */
HAL_NVIC_DisableIRQ(USB_LP_CAN1_RX0_IRQn);
}
/**
* @brief Handles CAN1 RX0 interrupt request.
* @param None
* @retval None
*/
void USB_LP_CAN1_RX0_IRQHandler(void) {
HAL_CAN_IRQHandler(&_canHandle);
}
/**
* @brief Reception complete callback in non blocking mode
* @param _canHandle: pointer to a CAN_HandleTypeDef structure that contains
* the configuration information for the specified CAN.
* @retval None
*/
void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* _canHandle) {
// if(HAL_CAN_Receive_IT(_canHandle, CAN_FIFO0) == HAL_OK) {
// if(rxCompleteCallback != NULL)
// rxCompleteCallback();
// }
// else {
// error_handler(error);
// }
// BUG: CAN race condition if HAL_CAN_Receive_IT() is used.
// 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
//
// Fixed by Mark Burton:
// ideally, we should be able to call HAL_CAN_Receive_IT() here to set up for another
// receive but the API is flawed because that function will fail if HAL_CAN_Transmit()
// had already locked the handle when the receive interrupt occurred - so we do what
// HAL_CAN_Receive_IT() would do
if (rxCompleteCallback != NULL)
rxCompleteCallback();
if (_canHandle->State == HAL_CAN_STATE_BUSY_TX)
_canHandle->State = HAL_CAN_STATE_BUSY_TX_RX;
else {
_canHandle->State = HAL_CAN_STATE_BUSY_RX;
/* Set CAN error code to none */
_canHandle->ErrorCode = HAL_CAN_ERROR_NONE;
/* Enable Error warning Interrupt */
__HAL_CAN_ENABLE_IT(_canHandle, CAN_IT_EWG);
/* Enable Error passive Interrupt */
__HAL_CAN_ENABLE_IT(_canHandle, CAN_IT_EPV);
/* Enable Bus-off Interrupt */
__HAL_CAN_ENABLE_IT(_canHandle, CAN_IT_BOF);
/* Enable Last error code Interrupt */
__HAL_CAN_ENABLE_IT(_canHandle, CAN_IT_LEC);
/* Enable Error Interrupt */
__HAL_CAN_ENABLE_IT(_canHandle, CAN_IT_ERR);
}
// Enable FIFO 0 message pending Interrupt
__HAL_CAN_ENABLE_IT(_canHandle, CAN_IT_FMP0);
}