348 lines
10 KiB
C
348 lines
10 KiB
C
#include "stm32f1xx_hal.h"
|
|
|
|
#include "can_feedc0de.h"
|
|
#include "can.h"
|
|
|
|
/* Definition for CANx clock resources */
|
|
#define CANx CAN1
|
|
#define CANx_CLK_ENABLE() __HAL_RCC_CAN1_CLK_ENABLE()
|
|
#define CANx_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE()
|
|
|
|
#define CANx_FORCE_RESET() __HAL_RCC_CAN1_FORCE_RESET()
|
|
#define CANx_RELEASE_RESET() __HAL_RCC_CAN1_RELEASE_RESET()
|
|
|
|
/* Definition for CANx Pins */
|
|
#define CANx_TX_PIN GPIO_PIN_9
|
|
#define CANx_TX_GPIO_PORT GPIOB
|
|
#define CANx_RX_PIN GPIO_PIN_8
|
|
#define CANx_RX_GPIO_PORT GPIOB
|
|
|
|
/* Definition for CANx AFIO Remap */
|
|
#define CANx_AFIO_REMAP_CLK_ENABLE() __HAL_RCC_AFIO_CLK_ENABLE()
|
|
#define CANx_AFIO_REMAP_RX_TX_PIN() __HAL_AFIO_REMAP_CAN1_2()
|
|
|
|
/* Definition for CAN's NVIC */
|
|
#define CANx_RX_IRQn USB_LP_CAN1_RX0_IRQn
|
|
#define CANx_RX_IRQHandler USB_LP_CAN1_RX0_IRQHandler
|
|
#define CANx_TX_IRQn USB_HP_CAN1_TX_IRQn
|
|
#define CANx_TX_IRQHandler USB_HP_CAN1_TX_IRQHandler
|
|
|
|
|
|
/**
|
|
******************************************************************************
|
|
* @file CAN/CAN_Networking/Src/main.c
|
|
* @author MCD Application Team
|
|
* @brief This example shows how to configure the CAN peripheral
|
|
* to send and receive CAN frames in normal mode. The sent frames
|
|
* are used to control Leds by pressing KEY Push Button.
|
|
******************************************************************************
|
|
* @attention
|
|
*
|
|
* <h2><center>© Copyright (c) 2016 STMicroelectronics.
|
|
* All rights reserved.</center></h2>
|
|
*
|
|
* This software component is licensed by ST under BSD 3-Clause license,
|
|
* the "License"; You may not use this file except in compliance with the
|
|
* License. You may obtain a copy of the License at:
|
|
* opensource.org/licenses/BSD-3-Clause
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
|
|
/* Private variables ---------------------------------------------------------*/
|
|
uint8_t ubKeyNumber = 0x0;
|
|
CAN_HandleTypeDef CanHandle;
|
|
CAN_TxHeaderTypeDef TxHeader;
|
|
CAN_RxHeaderTypeDef RxHeader;
|
|
uint8_t TxData[8];
|
|
uint8_t RxData[8];
|
|
uint32_t TxMailbox;
|
|
|
|
/* Private function prototypes -----------------------------------------------*/
|
|
static void __NO_RETURN Error_Handler(void);
|
|
static void CAN_MspInit(CAN_HandleTypeDef *hcan);
|
|
static void CAN_MspDeInit(CAN_HandleTypeDef *hcan);
|
|
static void CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan);
|
|
static void CAN_TxMailboxCompleteCallback(CAN_HandleTypeDef *hcan);
|
|
|
|
/* Private functions ---------------------------------------------------------*/
|
|
|
|
static uint32_t len_to_dlc(uint8_t len)
|
|
{
|
|
uint32_t len_u32 = len;
|
|
|
|
if (len_u32 <= 8)
|
|
return len_u32;
|
|
|
|
// CAN-FD-only lengths currently not supported
|
|
Error_Handler();
|
|
}
|
|
|
|
static uint8_t dlc_to_len(uint32_t dlc)
|
|
{
|
|
// Check if DLC valid
|
|
if (dlc & ~0xFu)
|
|
Error_Handler();
|
|
|
|
// CAN-FD-only lengths currently not supported
|
|
if (dlc > 8)
|
|
Error_Handler();
|
|
|
|
return dlc;
|
|
}
|
|
|
|
void can_tx(uint16_t id, const uint8_t* data, uint8_t len)
|
|
{
|
|
TxHeader.StdId = id;
|
|
TxHeader.DLC = len_to_dlc(len);
|
|
|
|
while (HAL_CAN_GetTxMailboxesFreeLevel(&CanHandle) < 1)
|
|
{
|
|
}
|
|
|
|
/* Start the Transmission process */
|
|
if (HAL_CAN_AddTxMessage(&CanHandle, &TxHeader, (uint8_t *)data, &TxMailbox) != HAL_OK)
|
|
{
|
|
/* Transmission request Error */
|
|
Error_Handler();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief This function is executed in case of error occurrence.
|
|
* @param None
|
|
* @retval None
|
|
*/
|
|
static void __NO_RETURN Error_Handler(void)
|
|
{
|
|
while (1)
|
|
{
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Configures the CAN.
|
|
* @param None
|
|
* @retval None
|
|
*/
|
|
void can_init(void)
|
|
{
|
|
CAN_FilterTypeDef sFilterConfig;
|
|
|
|
/* Configure the CAN peripheral */
|
|
CanHandle.Instance = CANx;
|
|
|
|
CanHandle.MspInitCallback = CAN_MspInit;
|
|
CanHandle.MspDeInitCallback = CAN_MspDeInit;
|
|
|
|
CanHandle.Init.TimeTriggeredMode = DISABLE;
|
|
CanHandle.Init.AutoBusOff = ENABLE;
|
|
CanHandle.Init.AutoWakeUp = DISABLE;
|
|
CanHandle.Init.AutoRetransmission = ENABLE;
|
|
CanHandle.Init.ReceiveFifoLocked = DISABLE;
|
|
CanHandle.Init.TransmitFifoPriority = DISABLE;
|
|
CanHandle.Init.Mode = CAN_MODE_NORMAL;
|
|
CanHandle.Init.SyncJumpWidth = CAN_SJW_1TQ;
|
|
CanHandle.Init.TimeSeg1 = CAN_BS1_6TQ;
|
|
CanHandle.Init.TimeSeg2 = CAN_BS2_1TQ;
|
|
CanHandle.Init.Prescaler = 4;
|
|
|
|
if (HAL_CAN_Init(&CanHandle) != HAL_OK)
|
|
{
|
|
/* Initialization Error */
|
|
Error_Handler();
|
|
}
|
|
|
|
/* Configure the CAN Filter */
|
|
sFilterConfig.FilterBank = 0;
|
|
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
|
|
sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
|
|
sFilterConfig.FilterIdHigh = 0x0000;
|
|
sFilterConfig.FilterIdLow = CAN_ID_BOARD | (BOARD_INDEX << 4) | CAN_DIRECTION_STW_TO_BOARD;
|
|
sFilterConfig.FilterMaskIdHigh = 0x0000;
|
|
sFilterConfig.FilterMaskIdLow = 0x07F1;
|
|
sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;
|
|
sFilterConfig.FilterActivation = ENABLE;
|
|
sFilterConfig.SlaveStartFilterBank = 14;
|
|
|
|
if (HAL_CAN_ConfigFilter(&CanHandle, &sFilterConfig) != HAL_OK)
|
|
{
|
|
/* Filter configuration Error */
|
|
Error_Handler();
|
|
}
|
|
|
|
if (HAL_CAN_RegisterCallback(&CanHandle, HAL_CAN_RX_FIFO0_MSG_PENDING_CB_ID, CAN_RxFifo0MsgPendingCallback) != HAL_OK)
|
|
{
|
|
Error_Handler();
|
|
}
|
|
|
|
if (HAL_CAN_RegisterCallback(&CanHandle, HAL_CAN_TX_MAILBOX0_COMPLETE_CB_ID, CAN_TxMailboxCompleteCallback) != HAL_OK)
|
|
{
|
|
Error_Handler();
|
|
}
|
|
|
|
if (HAL_CAN_RegisterCallback(&CanHandle, HAL_CAN_TX_MAILBOX1_COMPLETE_CB_ID, CAN_TxMailboxCompleteCallback) != HAL_OK)
|
|
{
|
|
Error_Handler();
|
|
}
|
|
|
|
if (HAL_CAN_RegisterCallback(&CanHandle, HAL_CAN_TX_MAILBOX2_COMPLETE_CB_ID, CAN_TxMailboxCompleteCallback) != HAL_OK)
|
|
{
|
|
Error_Handler();
|
|
}
|
|
|
|
/* Start the CAN peripheral */
|
|
if (HAL_CAN_Start(&CanHandle) != HAL_OK)
|
|
{
|
|
/* Start Error */
|
|
Error_Handler();
|
|
}
|
|
|
|
/* Activate CAN RX notification */
|
|
if (HAL_CAN_ActivateNotification(&CanHandle, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK)
|
|
{
|
|
/* Notification Error */
|
|
Error_Handler();
|
|
}
|
|
|
|
/* Activate CAN TX notification */
|
|
if (HAL_CAN_ActivateNotification(&CanHandle, CAN_IT_TX_MAILBOX_EMPTY) != HAL_OK)
|
|
{
|
|
/* Notification Error */
|
|
Error_Handler();
|
|
}
|
|
|
|
/* Configure Transmission process */
|
|
TxHeader.StdId = 0x321;
|
|
TxHeader.ExtId = 0x01;
|
|
TxHeader.RTR = CAN_RTR_DATA;
|
|
TxHeader.IDE = CAN_ID_STD;
|
|
TxHeader.DLC = 2;
|
|
TxHeader.TransmitGlobalTime = DISABLE;
|
|
}
|
|
|
|
/**
|
|
* @brief Rx Fifo 0 message pending callback in non blocking mode
|
|
* @param CanHandle: pointer to a CAN_HandleTypeDef structure that contains
|
|
* the configuration information for the specified CAN.
|
|
* @retval None
|
|
*/
|
|
static void CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *CanHandle)
|
|
{
|
|
/* Get RX message */
|
|
if (HAL_CAN_GetRxMessage(CanHandle, CAN_RX_FIFO0, &RxHeader, RxData) != HAL_OK)
|
|
{
|
|
/* Reception Error */
|
|
Error_Handler();
|
|
}
|
|
|
|
if (RxHeader.IDE == CAN_ID_STD &&
|
|
(RxHeader.StdId == CAN_ID_COMMAND_STW_TO_BOARD(BOARD_INDEX) ||
|
|
RxHeader.StdId == CAN_ID_FEEDBACK_STW_TO_BOARD(BOARD_INDEX)))
|
|
{
|
|
can_feedc0de_handle_frame(RxHeader.StdId, RxData, dlc_to_len(RxHeader.DLC));
|
|
}
|
|
|
|
// slightly yucky, but we don't want to block inside the IRQ handler
|
|
if (HAL_CAN_GetTxMailboxesFreeLevel(CanHandle) >= 2)
|
|
{
|
|
can_feedc0de_poll();
|
|
}
|
|
}
|
|
|
|
static void CAN_TxMailboxCompleteCallback(CAN_HandleTypeDef *hcan)
|
|
{
|
|
// slightly yucky, but we don't want to block inside the IRQ handler
|
|
if (HAL_CAN_GetTxMailboxesFreeLevel(hcan) >= 2)
|
|
{
|
|
can_feedc0de_poll();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief CAN MSP Initialization
|
|
* This function configures the hardware resources used in this example:
|
|
* - Peripheral's clock enable
|
|
* - Peripheral's GPIO Configuration
|
|
* - NVIC configuration for DMA interrupt request enable
|
|
* @param hcan: CAN handle pointer
|
|
* @retval None
|
|
*/
|
|
static void CAN_MspInit(CAN_HandleTypeDef *hcan)
|
|
{
|
|
GPIO_InitTypeDef GPIO_InitStruct;
|
|
|
|
/*##-1- Enable peripherals and GPIO Clocks #################################*/
|
|
/* CAN1 Periph clock enable */
|
|
CANx_CLK_ENABLE();
|
|
/* Enable GPIO clock ****************************************/
|
|
CANx_GPIO_CLK_ENABLE();
|
|
/* Enable AFIO clock and Remap CAN PINs to PB8 and PB9*******/
|
|
CANx_AFIO_REMAP_CLK_ENABLE();
|
|
CANx_AFIO_REMAP_RX_TX_PIN();
|
|
|
|
/*##-2- Configure peripheral GPIO ##########################################*/
|
|
/* CAN1 TX GPIO pin configuration */
|
|
GPIO_InitStruct.Pin = CANx_TX_PIN;
|
|
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
|
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
|
GPIO_InitStruct.Pull = GPIO_PULLUP;
|
|
|
|
HAL_GPIO_Init(CANx_TX_GPIO_PORT, &GPIO_InitStruct);
|
|
|
|
/* CAN1 RX GPIO pin configuration */
|
|
GPIO_InitStruct.Pin = CANx_RX_PIN;
|
|
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
|
|
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
|
GPIO_InitStruct.Pull = GPIO_PULLUP;
|
|
|
|
HAL_GPIO_Init(CANx_RX_GPIO_PORT, &GPIO_InitStruct);
|
|
|
|
/*##-3- Configure the NVIC #################################################*/
|
|
/* NVIC configuration for CAN1 Reception complete interrupt */
|
|
HAL_NVIC_SetPriority(CANx_RX_IRQn, 1, 0);
|
|
HAL_NVIC_EnableIRQ(CANx_RX_IRQn);
|
|
|
|
HAL_NVIC_SetPriority(CANx_TX_IRQn, 1, 0);
|
|
HAL_NVIC_EnableIRQ(CANx_TX_IRQn);
|
|
}
|
|
|
|
/**
|
|
* @brief CAN MSP De-Initialization
|
|
* This function frees the hardware resources used in this example:
|
|
* - Disable the Peripheral's clock
|
|
* - Revert GPIO to their default state
|
|
* @param hcan: CAN handle pointer
|
|
* @retval None
|
|
*/
|
|
static void CAN_MspDeInit(CAN_HandleTypeDef *hcan)
|
|
{
|
|
/*##-1- Reset peripherals ##################################################*/
|
|
CANx_FORCE_RESET();
|
|
CANx_RELEASE_RESET();
|
|
|
|
/*##-2- Disable peripherals and GPIO Clocks ################################*/
|
|
/* De-initialize the CAN1 TX GPIO pin */
|
|
HAL_GPIO_DeInit(CANx_TX_GPIO_PORT, CANx_TX_PIN);
|
|
/* De-initialize the CAN1 RX GPIO pin */
|
|
HAL_GPIO_DeInit(CANx_RX_GPIO_PORT, CANx_RX_PIN);
|
|
|
|
/*##-4- Disable the NVIC for CAN reception #################################*/
|
|
HAL_NVIC_DisableIRQ(CANx_RX_IRQn);
|
|
}
|
|
|
|
/**
|
|
* @brief This function handles CAN1 RX0 interrupt request.
|
|
* @param None
|
|
* @retval None
|
|
*/
|
|
void CANx_RX_IRQHandler(void)
|
|
{
|
|
HAL_CAN_IRQHandler(&CanHandle);
|
|
}
|
|
|
|
void CANx_TX_IRQHandler(void)
|
|
{
|
|
HAL_CAN_IRQHandler(&CanHandle);
|
|
}
|