Add CAN
This commit is contained in:
@ -21,7 +21,7 @@ set(CMAKE_SHARED_LINKER_FLAGS "${COMMON_LINKER_FLAGS}")
|
|||||||
|
|
||||||
project(bobbycar-controller-firmware ASM C CXX)
|
project(bobbycar-controller-firmware ASM C CXX)
|
||||||
|
|
||||||
add_definitions(-DUSE_HAL_DRIVER -DSTM32F103xE)
|
add_definitions(-DUSE_HAL_DRIVER -DSTM32F103xE -DFEATURE_CAN)
|
||||||
|
|
||||||
include_directories(
|
include_directories(
|
||||||
.
|
.
|
||||||
@ -54,6 +54,7 @@ add_executable(firmware.elf
|
|||||||
STM32CubeF1/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_adc.c
|
STM32CubeF1/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_adc.c
|
||||||
STM32CubeF1/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_uart.c
|
STM32CubeF1/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_uart.c
|
||||||
STM32CubeF1/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_dma.c
|
STM32CubeF1/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_dma.c
|
||||||
|
STM32CubeF1/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_can.c
|
||||||
|
|
||||||
bobbycar-foc-model/BLDC_controller.h
|
bobbycar-foc-model/BLDC_controller.h
|
||||||
bobbycar-foc-model/BLDC_controller.c
|
bobbycar-foc-model/BLDC_controller.c
|
||||||
@ -68,6 +69,8 @@ add_executable(firmware.elf
|
|||||||
config.h
|
config.h
|
||||||
defines.h
|
defines.h
|
||||||
main.cpp
|
main.cpp
|
||||||
|
can.c
|
||||||
|
can_feedc0de.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
add_custom_command(OUTPUT firmware.hex
|
add_custom_command(OUTPUT firmware.hex
|
||||||
|
369
can.c
Normal file
369
can.c
Normal file
@ -0,0 +1,369 @@
|
|||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Main program.
|
||||||
|
* @param None
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void can_test(void)
|
||||||
|
{
|
||||||
|
TxHeader.DLC = 2;
|
||||||
|
TxHeader.StdId = 0x321;
|
||||||
|
|
||||||
|
/* Set the data to be transmitted */
|
||||||
|
TxData[0] = ubKeyNumber + 1;
|
||||||
|
TxData[1] = 0xAD;
|
||||||
|
|
||||||
|
/* Start the Transmission process */
|
||||||
|
if (HAL_CAN_AddTxMessage(&CanHandle, &TxHeader, TxData, &TxMailbox) != HAL_OK)
|
||||||
|
{
|
||||||
|
/* Transmission request Error */
|
||||||
|
Error_Handler();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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_config(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_5TQ;
|
||||||
|
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 = 0x0310;
|
||||||
|
sFilterConfig.FilterMaskIdHigh = 0x0000;
|
||||||
|
sFilterConfig.FilterMaskIdLow = 0x07F8;
|
||||||
|
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_BACK ||
|
||||||
|
RxHeader.StdId == CAN_ID_FEEDBACK_STW_TO_BACK))
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
29
can.h
Normal file
29
can.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define CAN_ID_COMMAND_STW_TO_BACK 0x311
|
||||||
|
#define CAN_ID_COMMAND_BACK_TO_STW 0x312
|
||||||
|
#define CAN_ID_COMMAND_STW_TO_FRONT 0x315
|
||||||
|
#define CAN_ID_COMMAND_FRONT_TO_STW 0x316
|
||||||
|
|
||||||
|
#define CAN_ID_FEEDBACK_STW_TO_BACK 0x319
|
||||||
|
#define CAN_ID_FEEDBACK_BACK_TO_STW 0x31A
|
||||||
|
#define CAN_ID_FEEDBACK_STW_TO_FRONT 0x31D
|
||||||
|
#define CAN_ID_FEEDBACK_FRONT_TO_STW 0x31E
|
||||||
|
|
||||||
|
#define CAN_ID_HB_BACK_TO_STW 0x331
|
||||||
|
#define CAN_ID_HB_FRONT_TO_STW 0x333
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void can_config(void);
|
||||||
|
void can_test(void);
|
||||||
|
void can_tx(uint16_t id, const uint8_t* data, uint8_t len);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
216
can_fc.h
Normal file
216
can_fc.h
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstring>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "can.h"
|
||||||
|
|
||||||
|
//#define FC_STRICT
|
||||||
|
|
||||||
|
#define FC_PROTOCOL_ERROR()
|
||||||
|
#define Error_Handler() while(1)
|
||||||
|
|
||||||
|
constexpr const uint8_t FC_CHUNK_SIZE = 7;
|
||||||
|
constexpr const uint8_t FC_TAG_INIT = 0x45;
|
||||||
|
constexpr const uint8_t FC_TAG_END = 0x7d;
|
||||||
|
|
||||||
|
static uint8_t next_tag(uint8_t tag)
|
||||||
|
{
|
||||||
|
if (tag == 0)
|
||||||
|
{
|
||||||
|
return FC_TAG_INIT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return tag + 0x04;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FCSender
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FCSender(uint16_t id) : id(id)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool tx_pending()
|
||||||
|
{
|
||||||
|
return pos_sent != len && pos_sent == pos_acked;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool transfer_in_progress()
|
||||||
|
{
|
||||||
|
return data != nullptr && pos_acked != len;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool transfer_finished()
|
||||||
|
{
|
||||||
|
return data != nullptr && pos_acked == len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset(const uint8_t* data, size_t len)
|
||||||
|
{
|
||||||
|
pos_sent = 0;
|
||||||
|
pos_acked = 0;
|
||||||
|
tag_sent = 0;
|
||||||
|
|
||||||
|
this->data = data;
|
||||||
|
this->len = len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_frame(const uint8_t* payload, uint8_t payload_len)
|
||||||
|
{
|
||||||
|
if (pos_sent == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (payload_len != 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (payload[0] != tag_sent)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pos_acked = pos_sent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tx()
|
||||||
|
{
|
||||||
|
uint8_t payload[1 + FC_CHUNK_SIZE];
|
||||||
|
|
||||||
|
// Still waiting for ack, or done transmitting
|
||||||
|
if (!tx_pending())
|
||||||
|
return;
|
||||||
|
|
||||||
|
size_t new_pos_sent = std::min(pos_sent + FC_CHUNK_SIZE, len);
|
||||||
|
uint8_t sent_size = new_pos_sent - pos_sent;
|
||||||
|
uint8_t new_tag_sent = next_tag(tag_sent);
|
||||||
|
if (new_tag_sent == FC_TAG_END)
|
||||||
|
Error_Handler();
|
||||||
|
|
||||||
|
payload[0] = new_tag_sent;
|
||||||
|
memcpy(&payload[1], data + pos_sent, sent_size);
|
||||||
|
can_tx(id, payload, 1 + sent_size);
|
||||||
|
|
||||||
|
pos_sent = new_pos_sent;
|
||||||
|
tag_sent = new_tag_sent;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint16_t id;
|
||||||
|
const uint8_t* data;
|
||||||
|
size_t len;
|
||||||
|
size_t pos_sent;
|
||||||
|
size_t pos_acked;
|
||||||
|
uint8_t tag_sent;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FCReceiver
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FCReceiver(uint16_t id, uint8_t* data, size_t len) : id(id)
|
||||||
|
{
|
||||||
|
reset(data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ack_pending()
|
||||||
|
{
|
||||||
|
return pos_received != pos_acked;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool transfer_in_progress()
|
||||||
|
{
|
||||||
|
return ready && data != nullptr && pos_acked != len;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool transfer_finished()
|
||||||
|
{
|
||||||
|
return ready && data != nullptr && pos_acked == len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset(uint8_t* data, size_t len)
|
||||||
|
{
|
||||||
|
// Poor man's mutex
|
||||||
|
ready = false;
|
||||||
|
|
||||||
|
pos_received = 0;
|
||||||
|
pos_acked = 0;
|
||||||
|
tag_expected = next_tag(0);
|
||||||
|
|
||||||
|
this->data = data;
|
||||||
|
this->len = len;
|
||||||
|
|
||||||
|
ready = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_frame(const uint8_t* payload, uint8_t payload_len)
|
||||||
|
{
|
||||||
|
if (!transfer_in_progress())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (tag_expected == FC_TAG_END)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (payload_len < 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Reset receiver if frame with FC_TAG_INIT received when expecting different one
|
||||||
|
if (payload[0] == FC_TAG_INIT && tag_expected != FC_TAG_INIT)
|
||||||
|
reset(data, len);
|
||||||
|
|
||||||
|
// Don't accept new data if we haven't acked the previous data yet
|
||||||
|
if (ack_pending())
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint8_t data_len = payload_len - 1;
|
||||||
|
if (data_len > len - pos_received)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Ignore all other tags
|
||||||
|
if (payload[0] != tag_expected)
|
||||||
|
return;
|
||||||
|
|
||||||
|
memcpy(&data[pos_received], &payload[1], data_len);
|
||||||
|
|
||||||
|
pos_received += data_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ack()
|
||||||
|
{
|
||||||
|
uint8_t payload[1];
|
||||||
|
|
||||||
|
if (!ack_pending())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Poor man's mutex
|
||||||
|
ready = false;
|
||||||
|
|
||||||
|
// ISR may have called reset() in the mean time
|
||||||
|
if (!ack_pending())
|
||||||
|
{
|
||||||
|
ready = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
payload[0] = tag_expected;
|
||||||
|
can_tx(id, payload, sizeof(payload));
|
||||||
|
|
||||||
|
pos_acked = pos_received;
|
||||||
|
tag_expected = next_tag(tag_expected);
|
||||||
|
|
||||||
|
ready = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool ready;
|
||||||
|
|
||||||
|
uint16_t id;
|
||||||
|
uint8_t* data;
|
||||||
|
size_t len;
|
||||||
|
size_t pos_received;
|
||||||
|
size_t pos_acked;
|
||||||
|
uint8_t tag_expected;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __cplusplus
|
69
can_feedc0de.cpp
Normal file
69
can_feedc0de.cpp
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#include <cstdint>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#include "protocol.h"
|
||||||
|
#include "can_fc.h"
|
||||||
|
|
||||||
|
#include "can_feedc0de.h"
|
||||||
|
|
||||||
|
|
||||||
|
static_assert((sizeof(Command) + FC_CHUNK_SIZE - 1) / FC_CHUNK_SIZE < 15);
|
||||||
|
|
||||||
|
void CANFeedc0de::poll()
|
||||||
|
{
|
||||||
|
if (feedc0de_fcs.tx_pending())
|
||||||
|
feedc0de_fcs.tx();
|
||||||
|
|
||||||
|
if (feedc0de_fcr.ack_pending())
|
||||||
|
feedc0de_fcr.ack();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CANFeedc0de::send_feedback(const Feedback& in)
|
||||||
|
{
|
||||||
|
feedback = in;
|
||||||
|
feedc0de_fcs.reset(((uint8_t*)&feedback) + 2, sizeof(feedback) - 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CANFeedc0de::get_command(Command& out)
|
||||||
|
{
|
||||||
|
if (!feedc0de_fcr.transfer_finished())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
out = command;
|
||||||
|
feedc0de_fcr.reset(((uint8_t*)&command) + 2, sizeof(command) - 4);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CANFeedc0de::handle_frame(uint16_t id, uint8_t* frame, uint8_t len)
|
||||||
|
{
|
||||||
|
switch (id)
|
||||||
|
{
|
||||||
|
case CAN_ID_FEEDBACK_STW_TO_BACK:
|
||||||
|
feedc0de_fcs.handle_frame(frame, len);
|
||||||
|
break;
|
||||||
|
case CAN_ID_COMMAND_STW_TO_BACK:
|
||||||
|
feedc0de_fcr.handle_frame(frame, len);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Error_Handler();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
|
||||||
|
void can_feedc0de_handle_frame(uint16_t id, uint8_t* frame, uint8_t len)
|
||||||
|
{
|
||||||
|
extern CANFeedc0de can_feedc0de;
|
||||||
|
can_feedc0de.handle_frame(id, frame, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void can_feedc0de_poll()
|
||||||
|
{
|
||||||
|
extern CANFeedc0de can_feedc0de;
|
||||||
|
can_feedc0de.poll();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
31
can_feedc0de.h
Normal file
31
can_feedc0de.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#include <cstdint>
|
||||||
|
#include "protocol.h"
|
||||||
|
#include "can_fc.h"
|
||||||
|
class CANFeedc0de
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void poll();
|
||||||
|
void handle_frame(uint16_t id, uint8_t* frame, uint8_t len);
|
||||||
|
void send_feedback(const Feedback& in);
|
||||||
|
bool get_command(Command& out);
|
||||||
|
private:
|
||||||
|
Command command;
|
||||||
|
Feedback feedback;
|
||||||
|
|
||||||
|
FCSender feedc0de_fcs = FCSender(CAN_ID_FEEDBACK_BACK_TO_STW);
|
||||||
|
FCReceiver feedc0de_fcr = FCReceiver(CAN_ID_COMMAND_BACK_TO_STW, ((uint8_t *)&command) + 2, sizeof(command) - 4);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void can_feedc0de_handle_frame(uint16_t id, uint8_t* frame, uint8_t len);
|
||||||
|
void can_feedc0de_poll();
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
105
main.cpp
105
main.cpp
@ -34,6 +34,14 @@ extern "C" {
|
|||||||
extern const P rtP_Left; // default settings defined in BLDC_controller_data.c
|
extern const P rtP_Left; // default settings defined in BLDC_controller_data.c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef FEATURE_CAN
|
||||||
|
#include "can.h"
|
||||||
|
#include "can_feedc0de.h"
|
||||||
|
|
||||||
|
CANFeedc0de can_feedc0de;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
TIM_HandleTypeDef htim_right;
|
TIM_HandleTypeDef htim_right;
|
||||||
TIM_HandleTypeDef htim_left;
|
TIM_HandleTypeDef htim_left;
|
||||||
@ -104,8 +112,6 @@ struct {
|
|||||||
Command command;
|
Command command;
|
||||||
Feedback feedback;
|
Feedback feedback;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void filtLowPass32(int16_t u, uint16_t coef, int32_t *y);
|
void filtLowPass32(int16_t u, uint16_t coef, int32_t *y);
|
||||||
|
|
||||||
void SystemClock_Config();
|
void SystemClock_Config();
|
||||||
@ -222,6 +228,11 @@ int main()
|
|||||||
int pwm = 0;
|
int pwm = 0;
|
||||||
int8_t dir = 1;
|
int8_t dir = 1;
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
can_config();
|
||||||
|
MODIFY_REG(RCC->CR, RCC_CR_HSITRIM, (0x1aU << RCC_CR_HSITRIM_Pos));
|
||||||
|
|
||||||
|
#ifndef FEATURE_CAN
|
||||||
HAL_UART_Receive_DMA(&huart2, (uint8_t *)&command, sizeof(command));
|
HAL_UART_Receive_DMA(&huart2, (uint8_t *)&command, sizeof(command));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -265,6 +276,7 @@ int main()
|
|||||||
board_temp_deg_c = (TEMP_CAL_HIGH_DEG_C - TEMP_CAL_LOW_DEG_C) * (board_temp_adcFilt - TEMP_CAL_LOW_ADC) / (TEMP_CAL_HIGH_ADC - TEMP_CAL_LOW_ADC) + TEMP_CAL_LOW_DEG_C;
|
board_temp_deg_c = (TEMP_CAL_HIGH_DEG_C - TEMP_CAL_LOW_DEG_C) * (board_temp_adcFilt - TEMP_CAL_LOW_ADC) / (TEMP_CAL_HIGH_ADC - TEMP_CAL_LOW_ADC) + TEMP_CAL_LOW_DEG_C;
|
||||||
|
|
||||||
sendFeedback();
|
sendFeedback();
|
||||||
|
can_feedc0de.poll();
|
||||||
|
|
||||||
#ifdef FEATURE_BUTTON
|
#ifdef FEATURE_BUTTON
|
||||||
if (HAL_GPIO_ReadPin(BUTTON_PORT, BUTTON_PIN))
|
if (HAL_GPIO_ReadPin(BUTTON_PORT, BUTTON_PIN))
|
||||||
@ -1049,6 +1061,9 @@ void parseCommand()
|
|||||||
{
|
{
|
||||||
bool any_parsed{false};
|
bool any_parsed{false};
|
||||||
|
|
||||||
|
#ifdef FEATURE_CAN
|
||||||
|
any_parsed = can_feedc0de.get_command(command);
|
||||||
|
#else
|
||||||
for (int i = 0; i < 1; i++)
|
for (int i = 0; i < 1; i++)
|
||||||
{
|
{
|
||||||
if (command.start != Command::VALID_HEADER)
|
if (command.start != Command::VALID_HEADER)
|
||||||
@ -1058,6 +1073,13 @@ void parseCommand()
|
|||||||
if (command.checksum != checksum)
|
if (command.checksum != checksum)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
any_parsed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (any_parsed)
|
||||||
|
{
|
||||||
left.state = command.left;
|
left.state = command.left;
|
||||||
right.state = command.right;
|
right.state = command.right;
|
||||||
|
|
||||||
@ -1070,12 +1092,8 @@ void parseCommand()
|
|||||||
|
|
||||||
command.start = Command::INVALID_HEADER; // Change the Start Frame for timeout detection in the next cycle
|
command.start = Command::INVALID_HEADER; // Change the Start Frame for timeout detection in the next cycle
|
||||||
timeoutCntSerial = 0; // Reset the timeout counter
|
timeoutCntSerial = 0; // Reset the timeout counter
|
||||||
|
|
||||||
any_parsed = true;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (!any_parsed)
|
|
||||||
{
|
{
|
||||||
if (timeoutCntSerial++ >= 100) // Timeout qualification
|
if (timeoutCntSerial++ >= 100) // Timeout qualification
|
||||||
{
|
{
|
||||||
@ -1087,58 +1105,69 @@ void parseCommand()
|
|||||||
|
|
||||||
HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_RESET);
|
HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_RESET);
|
||||||
|
|
||||||
|
#ifndef FEATURE_CAN
|
||||||
// Check periodically the received Start Frame. Try to re-sync by reseting the DMA
|
// Check periodically the received Start Frame. Try to re-sync by reseting the DMA
|
||||||
if (main_loop_counter % 25 == 0)
|
if (main_loop_counter % 25 == 0)
|
||||||
{
|
{
|
||||||
HAL_UART_DMAStop(&huart2);
|
HAL_UART_DMAStop(&huart2);
|
||||||
HAL_UART_Receive_DMA(&huart2, (uint8_t *)&command, sizeof(command));
|
HAL_UART_Receive_DMA(&huart2, (uint8_t *)&command, sizeof(command));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sendFeedback()
|
void sendFeedback()
|
||||||
{
|
{
|
||||||
if (main_loop_counter % 50 == 0) { // Send data periodically
|
// Send data periodically
|
||||||
if(UART_DMA_CHANNEL->CNDTR == 0) {
|
if (main_loop_counter % 50 != 0)
|
||||||
feedback.start = Feedback::VALID_HEADER;
|
return;
|
||||||
|
|
||||||
feedback.left.angle = left.rtY.a_elecAngle;
|
#ifndef FEATURE_CAN
|
||||||
feedback.right.angle = right.rtY.a_elecAngle;
|
if (UART_DMA_CHANNEL->CNDTR != 0)
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
feedback.left.speed = left.rtY.n_mot;
|
feedback.start = Feedback::VALID_HEADER;
|
||||||
feedback.right.speed = right.rtY.n_mot;
|
|
||||||
|
|
||||||
feedback.left.error = left.rtY.z_errCode;
|
feedback.left.angle = left.rtY.a_elecAngle;
|
||||||
feedback.right.error = right.rtY.z_errCode;
|
feedback.right.angle = right.rtY.a_elecAngle;
|
||||||
|
|
||||||
feedback.left.current = left.rtU.i_DCLink;
|
feedback.left.speed = left.rtY.n_mot;
|
||||||
feedback.right.current = right.rtU.i_DCLink;
|
feedback.right.speed = right.rtY.n_mot;
|
||||||
|
|
||||||
feedback.left.chops = left.chops;
|
feedback.left.error = left.rtY.z_errCode;
|
||||||
feedback.right.chops = right.chops;
|
feedback.right.error = right.rtY.z_errCode;
|
||||||
left.chops = 0;
|
|
||||||
right.chops = 0;
|
|
||||||
|
|
||||||
feedback.left.hallA = left.rtU.b_hallA;
|
feedback.left.current = left.rtU.i_DCLink;
|
||||||
feedback.left.hallB = left.rtU.b_hallB;
|
feedback.right.current = right.rtU.i_DCLink;
|
||||||
feedback.left.hallC = left.rtU.b_hallC;
|
|
||||||
feedback.right.hallA = right.rtU.b_hallA;
|
|
||||||
feedback.right.hallB = right.rtU.b_hallB;
|
|
||||||
feedback.right.hallC = right.rtU.b_hallC;
|
|
||||||
|
|
||||||
feedback.batVoltage = batVoltage * BAT_CALIB_REAL_VOLTAGE / BAT_CALIB_ADC;
|
feedback.left.chops = left.chops;
|
||||||
feedback.boardTemp = board_temp_deg_c;
|
feedback.right.chops = right.chops;
|
||||||
feedback.timeoutCntSerial = timeoutCntSerial;
|
left.chops = 0;
|
||||||
|
right.chops = 0;
|
||||||
|
|
||||||
feedback.checksum = calculateChecksum(feedback);
|
feedback.left.hallA = left.rtU.b_hallA;
|
||||||
|
feedback.left.hallB = left.rtU.b_hallB;
|
||||||
|
feedback.left.hallC = left.rtU.b_hallC;
|
||||||
|
feedback.right.hallA = right.rtU.b_hallA;
|
||||||
|
feedback.right.hallB = right.rtU.b_hallB;
|
||||||
|
feedback.right.hallC = right.rtU.b_hallC;
|
||||||
|
|
||||||
UART_DMA_CHANNEL->CCR &= ~DMA_CCR_EN;
|
feedback.batVoltage = batVoltage * BAT_CALIB_REAL_VOLTAGE / BAT_CALIB_ADC;
|
||||||
UART_DMA_CHANNEL->CNDTR = sizeof(feedback);
|
feedback.boardTemp = board_temp_deg_c;
|
||||||
UART_DMA_CHANNEL->CMAR = uint64_t(&feedback);
|
feedback.timeoutCntSerial = timeoutCntSerial;
|
||||||
UART_DMA_CHANNEL->CCR |= DMA_CCR_EN;
|
|
||||||
}
|
feedback.checksum = calculateChecksum(feedback);
|
||||||
}
|
|
||||||
|
#ifdef FEATURE_CAN
|
||||||
|
can_feedc0de.send_feedback(feedback);
|
||||||
|
#else
|
||||||
|
UART_DMA_CHANNEL->CCR &= ~DMA_CCR_EN;
|
||||||
|
UART_DMA_CHANNEL->CNDTR = sizeof(feedback);
|
||||||
|
UART_DMA_CHANNEL->CMAR = uint64_t(&feedback);
|
||||||
|
UART_DMA_CHANNEL->CCR |= DMA_CCR_EN;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
@ -36,7 +36,7 @@ extern "C" {
|
|||||||
*/
|
*/
|
||||||
#define HAL_MODULE_ENABLED
|
#define HAL_MODULE_ENABLED
|
||||||
#define HAL_ADC_MODULE_ENABLED
|
#define HAL_ADC_MODULE_ENABLED
|
||||||
/* #define HAL_CAN_MODULE_ENABLED */
|
#define HAL_CAN_MODULE_ENABLED
|
||||||
/* #define HAL_CAN_LEGACY_MODULE_ENABLED */
|
/* #define HAL_CAN_LEGACY_MODULE_ENABLED */
|
||||||
/* #define HAL_CEC_MODULE_ENABLED */
|
/* #define HAL_CEC_MODULE_ENABLED */
|
||||||
#define HAL_CORTEX_MODULE_ENABLED
|
#define HAL_CORTEX_MODULE_ENABLED
|
||||||
@ -129,7 +129,7 @@ extern "C" {
|
|||||||
#define PREFETCH_ENABLE 1U
|
#define PREFETCH_ENABLE 1U
|
||||||
|
|
||||||
#define USE_HAL_ADC_REGISTER_CALLBACKS 0U /* ADC register callback disabled */
|
#define USE_HAL_ADC_REGISTER_CALLBACKS 0U /* ADC register callback disabled */
|
||||||
#define USE_HAL_CAN_REGISTER_CALLBACKS 0U /* CAN register callback disabled */
|
#define USE_HAL_CAN_REGISTER_CALLBACKS 1U /* CAN register callback disabled */
|
||||||
#define USE_HAL_CEC_REGISTER_CALLBACKS 0U /* CEC register callback disabled */
|
#define USE_HAL_CEC_REGISTER_CALLBACKS 0U /* CEC register callback disabled */
|
||||||
#define USE_HAL_DAC_REGISTER_CALLBACKS 0U /* DAC register callback disabled */
|
#define USE_HAL_DAC_REGISTER_CALLBACKS 0U /* DAC register callback disabled */
|
||||||
#define USE_HAL_ETH_REGISTER_CALLBACKS 0U /* ETH register callback disabled */
|
#define USE_HAL_ETH_REGISTER_CALLBACKS 0U /* ETH register callback disabled */
|
||||||
|
Reference in New Issue
Block a user