mirror of https://github.com/ARMmbed/mbed-os.git
STM32: FDCAN support for H7 family
parent
aff2bee8a4
commit
f1d10cfeff
|
@ -127,10 +127,10 @@ uint8_t SetSysClock_PLL_HSE(uint8_t bypass)
|
|||
RCC_OscInitStruct.HSI48State = RCC_HSI48_ON;
|
||||
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
|
||||
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
|
||||
RCC_OscInitStruct.PLL.PLLM = 4;
|
||||
RCC_OscInitStruct.PLL.PLLN = 400;
|
||||
RCC_OscInitStruct.PLL.PLLP = 2;
|
||||
RCC_OscInitStruct.PLL.PLLQ = 32;
|
||||
RCC_OscInitStruct.PLL.PLLM = 4; // 2 MHz
|
||||
RCC_OscInitStruct.PLL.PLLN = 400; // 800 MHz
|
||||
RCC_OscInitStruct.PLL.PLLP = 2; // PLLCLK = SYSCLK = 400 MHz
|
||||
RCC_OscInitStruct.PLL.PLLQ = 80; // PLL1Q used for FDCAN = 10 MHz
|
||||
RCC_OscInitStruct.PLL.PLLR = 2;
|
||||
RCC_OscInitStruct.PLL.PLLFRACN = 0;
|
||||
RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
|
||||
|
|
|
@ -1,73 +0,0 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2017 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef MBED_CAN_DEVICE_H
|
||||
#define MBED_CAN_DEVICE_H
|
||||
|
||||
#include "cmsis.h"
|
||||
#include "stm32h7xx.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if DEVICE_CAN
|
||||
|
||||
#if defined(CAN3_BASE)
|
||||
|
||||
#define CAN_NUM 3 // Number of CAN peripherals present in the STM32 serie
|
||||
|
||||
#define CAN3_IRQ_RX_IRQN CAN3_RX0_IRQn
|
||||
#define CAN3_IRQ_RX_VECT CAN3_RX0_IRQHandler
|
||||
#define CAN3_IRQ_TX_IRQN CAN3_TX_IRQn
|
||||
#define CAN3_IRQ_TX_VECT CAN3_TX_IRQHandler
|
||||
#define CAN3_IRQ_ERROR_IRQN CAN3_SCE_IRQn
|
||||
#define CAN3_IRQ_ERROR_VECT CAN3_SCE_IRQHandler
|
||||
#define CAN3_IRQ_PASSIVE_IRQN CAN3_SCE_IRQn
|
||||
#define CAN3_IRQ_PASSIVE_VECT CAN3_SCE_IRQHandler
|
||||
#define CAN3_IRQ_BUS_IRQN CAN3_SCE_IRQn
|
||||
#define CAN3_IRQ_BUS_VECT CAN3_SCE_IRQHandler
|
||||
|
||||
#else
|
||||
|
||||
#define CAN_NUM 2 // Number of CAN peripherals present in the STM32 serie
|
||||
|
||||
#endif
|
||||
|
||||
#define CAN1_IRQ_RX_IRQN CAN1_RX0_IRQn
|
||||
#define CAN1_IRQ_RX_VECT CAN1_RX0_IRQHandler
|
||||
#define CAN1_IRQ_TX_IRQN CAN1_TX_IRQn
|
||||
#define CAN1_IRQ_TX_VECT CAN1_TX_IRQHandler
|
||||
#define CAN1_IRQ_ERROR_IRQN CAN1_SCE_IRQn
|
||||
#define CAN1_IRQ_ERROR_VECT CAN1_SCE_IRQHandler
|
||||
#define CAN1_IRQ_PASSIVE_IRQN CAN1_SCE_IRQn
|
||||
#define CAN1_IRQ_PASSIVE_VECT CAN1_SCE_IRQHandler
|
||||
#define CAN1_IRQ_BUS_IRQN CAN1_SCE_IRQn
|
||||
#define CAN1_IRQ_BUS_VECT CAN1_SCE_IRQHandler
|
||||
|
||||
#define CAN2_IRQ_RX_IRQN CAN2_RX0_IRQn
|
||||
#define CAN2_IRQ_RX_VECT CAN2_RX0_IRQHandler
|
||||
#define CAN2_IRQ_TX_IRQN CAN2_TX_IRQn
|
||||
#define CAN2_IRQ_TX_VECT CAN2_TX_IRQHandler
|
||||
#define CAN2_IRQ_ERROR_IRQN CAN2_SCE_IRQn
|
||||
#define CAN2_IRQ_ERROR_VECT CAN2_SCE_IRQHandler
|
||||
#define CAN2_IRQ_PASSIVE_IRQN CAN2_SCE_IRQn
|
||||
#define CAN2_IRQ_PASSIVE_VECT CAN2_SCE_IRQHandler
|
||||
#define CAN2_IRQ_BUS_IRQN CAN2_SCE_IRQn
|
||||
#define CAN2_IRQ_BUS_VECT CAN2_SCE_IRQHandler
|
||||
|
||||
#endif // DEVICE_CAN
|
||||
|
||||
#endif
|
|
@ -17,6 +17,495 @@
|
|||
|
||||
#if DEVICE_CAN
|
||||
|
||||
#ifdef FDCAN1
|
||||
|
||||
#include "pinmap.h"
|
||||
#include "PeripheralPins.h"
|
||||
#include "mbed_error.h"
|
||||
|
||||
static uint32_t can_irq_ids[2] = {0};
|
||||
static can_irq_handler irq_handler;
|
||||
|
||||
/** Call all the init functions
|
||||
*
|
||||
* @returns
|
||||
* 0 if mode change failed or unsupported,
|
||||
* 1 if mode change was successful
|
||||
*/
|
||||
int can_internal_init(can_t *obj)
|
||||
{
|
||||
if (HAL_FDCAN_Init(&obj->CanHandle) != HAL_OK) {
|
||||
error("HAL_FDCAN_Init error\n");
|
||||
}
|
||||
|
||||
if (can_filter(obj, 0, 0, CANStandard, 0) == 0) {
|
||||
error("can_filter error\n");
|
||||
}
|
||||
|
||||
if (can_filter(obj, 0, 0, CANExtended, 0) == 0) {
|
||||
error("can_filter error\n");
|
||||
}
|
||||
|
||||
if (HAL_FDCAN_ConfigGlobalFilter(&obj->CanHandle, FDCAN_REJECT, FDCAN_REJECT, FDCAN_FILTER_REMOTE, FDCAN_FILTER_REMOTE) != HAL_OK) {
|
||||
error("HAL_FDCAN_ConfigGlobalFilter error\n");
|
||||
}
|
||||
|
||||
if (HAL_FDCAN_Start(&obj->CanHandle) != HAL_OK) {
|
||||
error("HAL_FDCAN_Start error\n");
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void can_init(can_t *obj, PinName rd, PinName td)
|
||||
{
|
||||
/* default frequency is 100 kHz */
|
||||
can_init_freq(obj, rd, td, 100000);
|
||||
}
|
||||
|
||||
|
||||
void can_init_freq(can_t *obj, PinName rd, PinName td, int hz)
|
||||
{
|
||||
CANName can_rd = (CANName)pinmap_peripheral(rd, PinMap_CAN_RD);
|
||||
CANName can_td = (CANName)pinmap_peripheral(td, PinMap_CAN_TD);
|
||||
CANName can = (CANName)pinmap_merge(can_rd, can_td);
|
||||
MBED_ASSERT((int)can != NC);
|
||||
|
||||
__HAL_RCC_FDCAN_CLK_ENABLE();
|
||||
|
||||
if (can == CAN_1) {
|
||||
obj->index = 0;
|
||||
}
|
||||
#if defined(FDCAN2_BASE)
|
||||
else if (can == CAN_2) {
|
||||
obj->index = 1;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
error("can_init wrong instance\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Select PLL1Q as source of FDCAN clock
|
||||
RCC_PeriphCLKInitTypeDef RCC_PeriphClkInit;
|
||||
RCC_PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_FDCAN;
|
||||
RCC_PeriphClkInit.FdcanClockSelection = RCC_FDCANCLKSOURCE_PLL; // 10 MHz (RCC_OscInitStruct.PLL.PLLQ = 80)
|
||||
if (HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit) != HAL_OK) {
|
||||
error("HAL_RCCEx_PeriphCLKConfig error\n");
|
||||
}
|
||||
|
||||
// Configure CAN pins
|
||||
pinmap_pinout(rd, PinMap_CAN_RD);
|
||||
pinmap_pinout(td, PinMap_CAN_TD);
|
||||
// Add pull-ups
|
||||
if (rd != NC) {
|
||||
pin_mode(rd, PullUp);
|
||||
}
|
||||
if (td != NC) {
|
||||
pin_mode(td, PullUp);
|
||||
}
|
||||
|
||||
// Default values
|
||||
obj->CanHandle.Instance = (FDCAN_GlobalTypeDef *)can;
|
||||
|
||||
/* Bit time parameter
|
||||
ex with 100 kHz requested frequency hz
|
||||
fdcan_ker_ck | 10 MHz | 10 MHz
|
||||
Prescaler | 1 | 1
|
||||
Time_quantum (tq) | 100 ns | 100 ns
|
||||
Bit_rate | 0.1 MBit/s | <hz>
|
||||
Bit_length | 10 µs = 100 tq | <n_tq> = 10 000 000 / <hz>
|
||||
Synchronization_segment | 1 tq | 1 tq
|
||||
Phase_segment_1 | 69 tq | <nts1> = <n_tq> * 0.75
|
||||
Phase_segment_2 | 30 tq | <nts2> = <n_tq> - 1 - <nts1>
|
||||
Synchronization_Jump_width | 30 tq | <nsjw> = <nts2>
|
||||
*/
|
||||
int ntq = 10000000 / hz;
|
||||
|
||||
obj->CanHandle.Init.FrameFormat = FDCAN_FRAME_CLASSIC;
|
||||
obj->CanHandle.Init.Mode = FDCAN_MODE_NORMAL;
|
||||
obj->CanHandle.Init.AutoRetransmission = ENABLE;
|
||||
obj->CanHandle.Init.TransmitPause = DISABLE;
|
||||
obj->CanHandle.Init.ProtocolException = ENABLE;
|
||||
obj->CanHandle.Init.NominalPrescaler = 1; // Prescaler
|
||||
obj->CanHandle.Init.NominalTimeSeg1 = ntq * 0.75; // Phase_segment_1
|
||||
obj->CanHandle.Init.NominalTimeSeg2 = ntq - 1 - obj->CanHandle.Init.NominalTimeSeg1; // Phase_segment_2
|
||||
obj->CanHandle.Init.NominalSyncJumpWidth = obj->CanHandle.Init.NominalTimeSeg2; // Synchronization_Jump_width
|
||||
obj->CanHandle.Init.DataPrescaler = 0x1; // Not used - only in FDCAN
|
||||
obj->CanHandle.Init.DataSyncJumpWidth = 0x1; // Not used - only in FDCAN
|
||||
obj->CanHandle.Init.DataTimeSeg1 = 0x1; // Not used - only in FDCAN
|
||||
obj->CanHandle.Init.DataTimeSeg2 = 0x1; // Not used - only in FDCAN
|
||||
obj->CanHandle.Init.MessageRAMOffset = 0;
|
||||
obj->CanHandle.Init.StdFiltersNbr = 1; // to be aligned with the handle parameter in can_filter
|
||||
obj->CanHandle.Init.ExtFiltersNbr = 1; // to be aligned with the handle parameter in can_filter
|
||||
obj->CanHandle.Init.RxFifo0ElmtsNbr = 8;
|
||||
obj->CanHandle.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8;
|
||||
obj->CanHandle.Init.RxFifo1ElmtsNbr = 0;
|
||||
obj->CanHandle.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_8;
|
||||
obj->CanHandle.Init.RxBuffersNbr = 0;
|
||||
obj->CanHandle.Init.RxBufferSize = FDCAN_DATA_BYTES_8;
|
||||
obj->CanHandle.Init.TxEventsNbr = 3;
|
||||
obj->CanHandle.Init.TxBuffersNbr = 0;
|
||||
obj->CanHandle.Init.TxFifoQueueElmtsNbr = 3;
|
||||
obj->CanHandle.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
|
||||
obj->CanHandle.Init.TxElmtSize = FDCAN_DATA_BYTES_8;
|
||||
|
||||
can_internal_init(obj);
|
||||
}
|
||||
|
||||
|
||||
void can_irq_init(can_t *obj, can_irq_handler handler, uint32_t id)
|
||||
{
|
||||
irq_handler = handler;
|
||||
can_irq_ids[obj->index] = id;
|
||||
}
|
||||
|
||||
void can_irq_free(can_t *obj)
|
||||
{
|
||||
CANName can = (CANName)obj->CanHandle.Instance;
|
||||
if (can == CAN_1) {
|
||||
HAL_NVIC_DisableIRQ(FDCAN1_IT0_IRQn);
|
||||
HAL_NVIC_DisableIRQ(FDCAN1_IT1_IRQn);
|
||||
}
|
||||
#if defined(FDCAN2_BASE)
|
||||
else if (can == CAN_2) {
|
||||
HAL_NVIC_DisableIRQ(FDCAN2_IT0_IRQn);
|
||||
HAL_NVIC_DisableIRQ(FDCAN2_IT1_IRQn);
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
return;
|
||||
}
|
||||
HAL_NVIC_DisableIRQ(FDCAN_CAL_IRQn);
|
||||
can_irq_ids[obj->index] = 0;
|
||||
}
|
||||
|
||||
void can_free(can_t *obj)
|
||||
{
|
||||
__HAL_RCC_FDCAN_FORCE_RESET();
|
||||
__HAL_RCC_FDCAN_RELEASE_RESET();
|
||||
__HAL_RCC_FDCAN_CLK_DISABLE();
|
||||
}
|
||||
|
||||
|
||||
/** Reset CAN interface.
|
||||
*
|
||||
* To use after error overflow.
|
||||
*/
|
||||
void can_reset(can_t *obj)
|
||||
{
|
||||
can_mode(obj, MODE_RESET);
|
||||
HAL_FDCAN_ResetTimeoutCounter(&obj->CanHandle);
|
||||
HAL_FDCAN_ResetTimestampCounter(&obj->CanHandle);
|
||||
}
|
||||
|
||||
|
||||
int can_frequency(can_t *obj, int f)
|
||||
{
|
||||
if (HAL_FDCAN_Stop(&obj->CanHandle) != HAL_OK) {
|
||||
error("HAL_FDCAN_Stop error\n");
|
||||
}
|
||||
|
||||
/* See can_init_freq function for calculation details */
|
||||
int ntq = 10000000 / f;
|
||||
obj->CanHandle.Init.NominalTimeSeg1 = ntq * 0.75; // Phase_segment_1
|
||||
obj->CanHandle.Init.NominalTimeSeg2 = ntq - 1 - obj->CanHandle.Init.NominalTimeSeg1; // Phase_segment_2
|
||||
obj->CanHandle.Init.NominalSyncJumpWidth = obj->CanHandle.Init.NominalTimeSeg2; // Synchronization_Jump_width
|
||||
|
||||
return can_internal_init(obj);
|
||||
}
|
||||
|
||||
|
||||
/** Filter out incoming messages
|
||||
*
|
||||
* @param obj CAN object
|
||||
* @param id the id to filter on
|
||||
* @param mask the mask applied to the id
|
||||
* @param format format to filter on
|
||||
* @param handle message filter handle (not supported yet)
|
||||
*
|
||||
* @returns
|
||||
* 0 if filter change failed or unsupported,
|
||||
* new filter handle if successful (not supported yet => returns 1)
|
||||
*/
|
||||
int can_filter(can_t *obj, uint32_t id, uint32_t mask, CANFormat format, int32_t handle)
|
||||
{
|
||||
UNUSED(handle); // Not supported yet (seems to be a used in read function?)
|
||||
|
||||
FDCAN_FilterTypeDef sFilterConfig = {0};
|
||||
|
||||
if (format == CANStandard) {
|
||||
sFilterConfig.IdType = FDCAN_STANDARD_ID;
|
||||
sFilterConfig.FilterIndex = 0;
|
||||
sFilterConfig.FilterType = FDCAN_FILTER_MASK;
|
||||
sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
|
||||
sFilterConfig.FilterID1 = id;
|
||||
sFilterConfig.FilterID2 = mask;
|
||||
} else if (format == CANExtended) {
|
||||
sFilterConfig.IdType = FDCAN_EXTENDED_ID;
|
||||
sFilterConfig.FilterIndex = 0;
|
||||
sFilterConfig.FilterType = FDCAN_FILTER_MASK;
|
||||
sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
|
||||
sFilterConfig.FilterID1 = id;
|
||||
sFilterConfig.FilterID2 = mask;
|
||||
} else { // Filter for CANAny format cannot be configured for STM32
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (HAL_FDCAN_ConfigFilter(&obj->CanHandle, &sFilterConfig) != HAL_OK) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int can_write(can_t *obj, CAN_Message msg, int cc)
|
||||
{
|
||||
FDCAN_TxHeaderTypeDef TxHeader = {0};
|
||||
|
||||
UNUSED(cc);
|
||||
|
||||
// Configure Tx buffer message
|
||||
TxHeader.Identifier = msg.id;
|
||||
if (msg.format == CANStandard) {
|
||||
TxHeader.IdType = FDCAN_STANDARD_ID;
|
||||
} else {
|
||||
TxHeader.IdType = FDCAN_EXTENDED_ID;
|
||||
}
|
||||
|
||||
TxHeader.TxFrameType = FDCAN_DATA_FRAME;
|
||||
TxHeader.DataLength = msg.len << 16;
|
||||
TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
|
||||
TxHeader.BitRateSwitch = FDCAN_BRS_OFF;
|
||||
TxHeader.FDFormat = FDCAN_CLASSIC_CAN;
|
||||
TxHeader.TxEventFifoControl = FDCAN_STORE_TX_EVENTS;
|
||||
TxHeader.MessageMarker = 0;
|
||||
|
||||
if (HAL_FDCAN_AddMessageToTxFifoQ(&obj->CanHandle, &TxHeader, msg.data) != HAL_OK) {
|
||||
// Note for debug: you can get the error code calling HAL_FDCAN_GetError(&obj->CanHandle)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int can_read(can_t *obj, CAN_Message *msg, int handle)
|
||||
{
|
||||
UNUSED(handle); // Not supported yet (seems to be a handle to a filter configuration?)
|
||||
|
||||
if (HAL_FDCAN_GetRxFifoFillLevel(&obj->CanHandle, FDCAN_RX_FIFO0) == 0) {
|
||||
return 0; // No message arrived
|
||||
}
|
||||
|
||||
FDCAN_RxHeaderTypeDef RxHeader = {0};
|
||||
if (HAL_FDCAN_GetRxMessage(&obj->CanHandle, FDCAN_RX_FIFO0, &RxHeader, msg->data) != HAL_OK) {
|
||||
error("HAL_FDCAN_GetRxMessage error\n"); // Should not occur as previous HAL_FDCAN_GetRxFifoFillLevel call reported some data
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (RxHeader.IdType == FDCAN_STANDARD_ID) {
|
||||
msg->format = CANStandard;
|
||||
} else {
|
||||
msg->format = CANExtended;
|
||||
}
|
||||
msg->id = RxHeader.Identifier;
|
||||
msg->type = CANData;
|
||||
msg->len = RxHeader.DataLength >> 16; // see FDCAN_data_length_code value
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned char can_rderror(can_t *obj)
|
||||
{
|
||||
FDCAN_ErrorCountersTypeDef ErrorCounters;
|
||||
|
||||
HAL_FDCAN_GetErrorCounters(&obj->CanHandle, &ErrorCounters);
|
||||
|
||||
return (unsigned char)ErrorCounters.RxErrorCnt;
|
||||
}
|
||||
|
||||
unsigned char can_tderror(can_t *obj)
|
||||
{
|
||||
FDCAN_ErrorCountersTypeDef ErrorCounters;
|
||||
|
||||
HAL_FDCAN_GetErrorCounters(&obj->CanHandle, &ErrorCounters);
|
||||
|
||||
return (unsigned char)ErrorCounters.TxErrorCnt;
|
||||
}
|
||||
|
||||
void can_monitor(can_t *obj, int silent)
|
||||
{
|
||||
CanMode mode = MODE_NORMAL;
|
||||
if (silent) {
|
||||
switch (obj->CanHandle.Init.Mode) {
|
||||
case FDCAN_MODE_INTERNAL_LOOPBACK:
|
||||
mode = MODE_TEST_SILENT;
|
||||
break;
|
||||
default:
|
||||
mode = MODE_SILENT;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (obj->CanHandle.Init.Mode) {
|
||||
case FDCAN_MODE_INTERNAL_LOOPBACK:
|
||||
case FDCAN_MODE_EXTERNAL_LOOPBACK:
|
||||
mode = MODE_TEST_LOCAL;
|
||||
break;
|
||||
default:
|
||||
mode = MODE_NORMAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
can_mode(obj, mode);
|
||||
}
|
||||
|
||||
/** Change CAN operation to the specified mode
|
||||
*
|
||||
* @param mode The new operation mode (MODE_RESET, MODE_NORMAL, MODE_SILENT, MODE_TEST_LOCAL, MODE_TEST_GLOBAL, MODE_TEST_SILENT)
|
||||
*
|
||||
* @returns
|
||||
* 0 if mode change failed or unsupported,
|
||||
* 1 if mode change was successful
|
||||
*/
|
||||
int can_mode(can_t *obj, CanMode mode)
|
||||
{
|
||||
if (HAL_FDCAN_Stop(&obj->CanHandle) != HAL_OK) {
|
||||
error("HAL_FDCAN_Stop error\n");
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case MODE_RESET:
|
||||
break;
|
||||
case MODE_NORMAL:
|
||||
obj->CanHandle.Init.Mode = FDCAN_MODE_NORMAL;
|
||||
// obj->CanHandle.Init.NominalPrescaler = 100; // Prescaler
|
||||
break;
|
||||
case MODE_SILENT: // Bus Monitoring
|
||||
obj->CanHandle.Init.Mode = FDCAN_MODE_BUS_MONITORING;
|
||||
break;
|
||||
case MODE_TEST_GLOBAL: // External LoopBack
|
||||
case MODE_TEST_LOCAL:
|
||||
obj->CanHandle.Init.Mode = FDCAN_MODE_EXTERNAL_LOOPBACK;
|
||||
break;
|
||||
case MODE_TEST_SILENT: // Internal LoopBack
|
||||
obj->CanHandle.Init.Mode = FDCAN_MODE_INTERNAL_LOOPBACK;
|
||||
// obj->CanHandle.Init.NominalPrescaler = 1; // Prescaler
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return can_internal_init(obj);
|
||||
}
|
||||
|
||||
|
||||
static void can_irq(CANName name, int id)
|
||||
{
|
||||
FDCAN_HandleTypeDef CanHandle;
|
||||
CanHandle.Instance = (FDCAN_GlobalTypeDef *)name;
|
||||
|
||||
if (__HAL_FDCAN_GET_IT_SOURCE(&CanHandle, FDCAN_IT_TX_COMPLETE)) {
|
||||
if (__HAL_FDCAN_GET_FLAG(&CanHandle, FDCAN_FLAG_TX_COMPLETE)) {
|
||||
__HAL_FDCAN_CLEAR_FLAG(&CanHandle, FDCAN_FLAG_TX_COMPLETE);
|
||||
irq_handler(can_irq_ids[id], IRQ_TX);
|
||||
}
|
||||
}
|
||||
|
||||
if (__HAL_FDCAN_GET_IT_SOURCE(&CanHandle, FDCAN_IT_RX_BUFFER_NEW_MESSAGE)) {
|
||||
if (__HAL_FDCAN_GET_FLAG(&CanHandle, FDCAN_IT_RX_BUFFER_NEW_MESSAGE)) {
|
||||
__HAL_FDCAN_CLEAR_FLAG(&CanHandle, FDCAN_IT_RX_BUFFER_NEW_MESSAGE);
|
||||
irq_handler(can_irq_ids[id], IRQ_RX);
|
||||
}
|
||||
}
|
||||
|
||||
if (__HAL_FDCAN_GET_IT_SOURCE(&CanHandle, FDCAN_IT_ERROR_WARNING)) {
|
||||
if (__HAL_FDCAN_GET_FLAG(&CanHandle, FDCAN_FLAG_ERROR_WARNING)) {
|
||||
__HAL_FDCAN_CLEAR_FLAG(&CanHandle, FDCAN_FLAG_ERROR_WARNING);
|
||||
irq_handler(can_irq_ids[id], IRQ_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
if (__HAL_FDCAN_GET_IT_SOURCE(&CanHandle, FDCAN_IT_ERROR_PASSIVE)) {
|
||||
if (__HAL_FDCAN_GET_FLAG(&CanHandle, FDCAN_FLAG_ERROR_PASSIVE)) {
|
||||
__HAL_FDCAN_CLEAR_FLAG(&CanHandle, FDCAN_FLAG_ERROR_PASSIVE);
|
||||
irq_handler(can_irq_ids[id], IRQ_PASSIVE);
|
||||
}
|
||||
}
|
||||
|
||||
if (__HAL_FDCAN_GET_IT_SOURCE(&CanHandle, FDCAN_IT_BUS_OFF)) {
|
||||
if (__HAL_FDCAN_GET_FLAG(&CanHandle, FDCAN_FLAG_BUS_OFF)) {
|
||||
__HAL_FDCAN_CLEAR_FLAG(&CanHandle, FDCAN_FLAG_BUS_OFF);
|
||||
irq_handler(can_irq_ids[id], IRQ_BUS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FDCAN1_IT0_IRQHandler(void)
|
||||
{
|
||||
can_irq(CAN_1, 0);
|
||||
}
|
||||
|
||||
void FDCAN1_IT1_IRQHandler(void)
|
||||
{
|
||||
can_irq(CAN_1, 0);
|
||||
}
|
||||
|
||||
void FDCAN2_IT0_IRQHandler(void)
|
||||
{
|
||||
can_irq(CAN_2, 1);
|
||||
}
|
||||
|
||||
void FDCAN2_IT1_IRQHandler(void)
|
||||
{
|
||||
can_irq(CAN_2, 1);
|
||||
}
|
||||
|
||||
// TODO Add other interrupts ?
|
||||
void can_irq_set(can_t *obj, CanIrqType type, uint32_t enable)
|
||||
{
|
||||
uint32_t interrupts = 0;
|
||||
|
||||
switch (type) {
|
||||
case IRQ_TX:
|
||||
interrupts = FDCAN_IT_TX_COMPLETE;
|
||||
break;
|
||||
case IRQ_RX:
|
||||
interrupts = FDCAN_IT_RX_BUFFER_NEW_MESSAGE;
|
||||
break;
|
||||
case IRQ_ERROR:
|
||||
interrupts = FDCAN_IT_ERROR_WARNING;
|
||||
break;
|
||||
case IRQ_PASSIVE:
|
||||
interrupts = FDCAN_IT_ERROR_PASSIVE;
|
||||
break;
|
||||
case IRQ_BUS:
|
||||
interrupts = FDCAN_IT_BUS_OFF;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (enable) {
|
||||
HAL_FDCAN_ActivateNotification(&obj->CanHandle, interrupts, 0);
|
||||
} else {
|
||||
HAL_FDCAN_DeactivateNotification(&obj->CanHandle, interrupts);
|
||||
}
|
||||
|
||||
NVIC_SetVector(FDCAN1_IT0_IRQn, (uint32_t)&FDCAN1_IT0_IRQHandler);
|
||||
NVIC_EnableIRQ(FDCAN1_IT0_IRQn);
|
||||
NVIC_SetVector(FDCAN1_IT1_IRQn, (uint32_t)&FDCAN1_IT1_IRQHandler);
|
||||
NVIC_EnableIRQ(FDCAN1_IT1_IRQn);
|
||||
#if defined(FDCAN2_BASE)
|
||||
NVIC_SetVector(FDCAN2_IT0_IRQn, (uint32_t)&FDCAN2_IT0_IRQHandler);
|
||||
NVIC_EnableIRQ(FDCAN2_IT0_IRQn);
|
||||
NVIC_SetVector(FDCAN2_IT1_IRQn, (uint32_t)&FDCAN2_IT1_IRQHandler);
|
||||
NVIC_EnableIRQ(FDCAN2_IT1_IRQn);
|
||||
#endif
|
||||
}
|
||||
|
||||
#else /* FDCAN1 */
|
||||
|
||||
#include "cmsis.h"
|
||||
#include "pinmap.h"
|
||||
#include "PeripheralPins.h"
|
||||
|
@ -454,8 +943,6 @@ int can_mode(can_t *obj, CanMode mode)
|
|||
|
||||
int can_filter(can_t *obj, uint32_t id, uint32_t mask, CANFormat format, int32_t handle)
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
// filter for CANAny format cannot be configured for STM32
|
||||
if ((format == CANStandard) || (format == CANExtended)) {
|
||||
CAN_FilterConfTypeDef sFilterConfig;
|
||||
|
@ -480,9 +967,9 @@ int can_filter(can_t *obj, uint32_t id, uint32_t mask, CANFormat format, int32_t
|
|||
sFilterConfig.BankNumber = 14 + handle;
|
||||
|
||||
HAL_CAN_ConfigFilter(&obj->CanHandle, &sFilterConfig);
|
||||
retval = handle;
|
||||
}
|
||||
return retval;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void can_irq(CANName name, int id)
|
||||
|
@ -716,4 +1203,6 @@ void can_irq_set(can_t *obj, CanIrqType type, uint32_t enable)
|
|||
NVIC_EnableIRQ(irq_n);
|
||||
}
|
||||
|
||||
#endif /* FDCAN1 */
|
||||
|
||||
#endif // DEVICE_CAN
|
||||
|
|
Loading…
Reference in New Issue