diff --git a/bsp/stm32/libraries/STM32MPxx_HAL/SConscript b/bsp/stm32/libraries/STM32MPxx_HAL/SConscript index a55b27925d..815a291865 100644 --- a/bsp/stm32/libraries/STM32MPxx_HAL/SConscript +++ b/bsp/stm32/libraries/STM32MPxx_HAL/SConscript @@ -94,6 +94,9 @@ if GetDepend(['BSP_USING_LTDC']): src += ['STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_dma2d.c'] src += ['STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_dsi.c'] +if GetDepend(['BSP_USING_FDCAN']): + src += ['STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_fdcan.c'] + path = [cwd + '/STM32MP1xx_HAL_Driver/Inc', cwd + '/CMSIS/Device/ST/STM32MP1xx/Include', cwd + '/CMSIS/Core/Include', diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Inc/stm32mp1xx_hal_conf.h b/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Inc/stm32mp1xx_hal_conf.h index 3b5a7e76df..0f22065b6d 100644 --- a/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Inc/stm32mp1xx_hal_conf.h +++ b/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Inc/stm32mp1xx_hal_conf.h @@ -42,7 +42,7 @@ /*#define HAL_DFSDM_MODULE_ENABLED */ /*#define HAL_DTS_MODULE_ENABLED */ /*#define HAL_ETH_MODULE_ENABLED */ -/*#define HAL_FDCAN_MODULE_ENABLED */ +#define HAL_FDCAN_MODULE_ENABLED /*#define HAL_HASH_MODULE_ENABLED */ /*#define HAL_HCD_MODULE_ENABLED */ #define HAL_HSEM_MODULE_ENABLED diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Src/stm32mp1xx_hal_msp.c b/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Src/stm32mp1xx_hal_msp.c index 1a712c3f8d..371a1d85f7 100644 --- a/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Src/stm32mp1xx_hal_msp.c +++ b/bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Src/stm32mp1xx_hal_msp.c @@ -1520,6 +1520,104 @@ void HAL_DCMI_MspDeInit(DCMI_HandleTypeDef* hdcmi) } +/** +* @brief FDCAN MSP Initialization +* This function configures the hardware resources used in this example +* @param hfdcan: FDCAN handle pointer +* @retval None +*/ +void HAL_FDCAN_MspInit(FDCAN_HandleTypeDef* hfdcan) +{ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; + if(hfdcan->Instance==FDCAN1) + { + /* USER CODE BEGIN FDCAN1_MspInit 0 */ + + /* USER CODE END FDCAN1_MspInit 0 */ + if(IS_ENGINEERING_BOOT_MODE()) + { + /** Initializes the peripherals clock + */ + PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_FDCAN; + PeriphClkInit.FdcanClockSelection = RCC_FDCANCLKSOURCE_HSE; + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) + { + Error_Handler(); + } + + } + + /* Peripheral clock enable */ + __HAL_RCC_FDCAN_CLK_ENABLE(); + + __HAL_RCC_GPIOH_CLK_ENABLE(); + __HAL_RCC_GPIOI_CLK_ENABLE(); + /**FDCAN1 GPIO Configuration + PH13 ------> FDCAN1_TX + PI9 ------> FDCAN1_RX + */ + GPIO_InitStruct.Pin = GPIO_PIN_13; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Alternate = GPIO_AF9_FDCAN1; + HAL_GPIO_Init(GPIOH, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = GPIO_PIN_9; + GPIO_InitStruct.Mode = GPIO_MODE_AF; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Alternate = GPIO_AF9_FDCAN1; + HAL_GPIO_Init(GPIOI, &GPIO_InitStruct); + + /* FDCAN1 interrupt Init */ + HAL_NVIC_SetPriority(FDCAN1_IT0_IRQn, 0x02, 0); + HAL_NVIC_EnableIRQ(FDCAN1_IT0_IRQn); + HAL_NVIC_SetPriority(FDCAN1_IT1_IRQn, 0x02, 0); + HAL_NVIC_EnableIRQ(FDCAN1_IT1_IRQn); + HAL_NVIC_SetPriority(FDCAN_CAL_IRQn, 0x02, 0); + HAL_NVIC_EnableIRQ(FDCAN_CAL_IRQn); + /* USER CODE BEGIN FDCAN1_MspInit 1 */ + /* USER CODE END FDCAN1_MspInit 1 */ + } + +} + +/** +* @brief FDCAN MSP De-Initialization +* This function freeze the hardware resources used in this example +* @param hfdcan: FDCAN handle pointer +* @retval None +*/ +void HAL_FDCAN_MspDeInit(FDCAN_HandleTypeDef* hfdcan) +{ + if(hfdcan->Instance==FDCAN1) + { + /* USER CODE BEGIN FDCAN1_MspDeInit 0 */ + + /* USER CODE END FDCAN1_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_FDCAN_CLK_DISABLE(); + + /**FDCAN1 GPIO Configuration + PH13 ------> FDCAN1_TX + PI9 ------> FDCAN1_RX + */ + HAL_GPIO_DeInit(GPIOH, GPIO_PIN_13); + + HAL_GPIO_DeInit(GPIOI, GPIO_PIN_9); + + /* FDCAN1 interrupt DeInit */ + HAL_NVIC_DisableIRQ(FDCAN1_IT0_IRQn); + HAL_NVIC_DisableIRQ(FDCAN1_IT1_IRQn); + HAL_NVIC_DisableIRQ(FDCAN_CAL_IRQn); + /* USER CODE BEGIN FDCAN1_MspDeInit 1 */ + + /* USER CODE END FDCAN1_MspDeInit 1 */ + } + +} + /** * @brief This function is executed in case of error occurrence. * @retval None diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/Kconfig b/bsp/stm32/stm32mp157a-st-ev1/board/Kconfig index 13d562ea95..8a456120cd 100644 --- a/bsp/stm32/stm32mp157a-st-ev1/board/Kconfig +++ b/bsp/stm32/stm32mp157a-st-ev1/board/Kconfig @@ -252,6 +252,15 @@ menu "On-chip Peripheral Drivers" default n endif + menuconfig BSP_USING_FDCAN + bool "Enable FDCAN" + default n + if BSP_USING_FDCAN + config BSP_USING_FDCAN1 + bool "Enable FDCAN1" + default n + endif + source "../libraries/HAL_Drivers/Kconfig" endmenu diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/SConscript b/bsp/stm32/stm32mp157a-st-ev1/board/SConscript index 2d43e1cf64..dec20f29e5 100644 --- a/bsp/stm32/stm32mp157a-st-ev1/board/SConscript +++ b/bsp/stm32/stm32mp157a-st-ev1/board/SConscript @@ -40,6 +40,9 @@ if GetDepend(['BSP_USING_MFX']): src += Glob('ports/drv_mfx.c') src += Glob('ports/mfxstm32l152.c') +if GetDepend(['BSP_USING_FDCAN']): + src += Glob('ports/drv_fdcan.c') + if GetDepend(['BSP_USING_OPENAMP']): src += Glob('CubeMX_Config/CM4/Src/ipcc.c') src += Glob('CubeMX_Config/CM4/Src/openamp.c') diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_fdcan.c b/bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_fdcan.c new file mode 100644 index 0000000000..78c18e8594 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_fdcan.c @@ -0,0 +1,290 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-07-06 thread-liu first version + */ + +#include "board.h" + +#if defined(BSP_USING_FDCAN1) || defined(BSP_USING_FDCAN2) + +#include "drv_fdcan.h" + +//#define DRV_DEBUG +#define LOG_TAG "drv.fdcan" +#include + +struct stm32_fdcan +{ + struct rt_device dev; + FDCAN_HandleTypeDef fdcan; + FDCAN_FilterTypeDef filter; + FDCAN_TxHeaderTypeDef tx_config; + FDCAN_RxHeaderTypeDef rx_config; + volatile rt_uint8_t fifo0; + volatile rt_uint8_t fifo1; +}; +static struct stm32_fdcan rt_fdcan = {0}; + +static rt_err_t rt_fdcan_init(rt_device_t dev) +{ + RT_ASSERT(dev != RT_NULL); + struct stm32_fdcan *device = (struct stm32_fdcan *)dev; + + device->fdcan.Instance = FDCAN1; + device->fdcan.Init.FrameFormat = FDCAN_FRAME_CLASSIC; + device->fdcan.Init.Mode = FDCAN_MODE_INTERNAL_LOOPBACK; + device->fdcan.Init.AutoRetransmission = ENABLE; + device->fdcan.Init.TransmitPause = DISABLE; + device->fdcan.Init.ProtocolException = ENABLE; + device->fdcan.Init.NominalPrescaler = 0x01; /* tq = NominalPrescaler x (1/fdcan_ker_ck) */ + device->fdcan.Init.NominalSyncJumpWidth = 0x08; + device->fdcan.Init.DataPrescaler = 0x01; + device->fdcan.Init.DataSyncJumpWidth = 0x04; + device->fdcan.Init.DataTimeSeg1 = 0x05; /* DataTimeSeg1 = Propagation_segment + Phase_segment_1 */ + device->fdcan.Init.DataTimeSeg2 = 0x04; + device->fdcan.Init.NominalTimeSeg1 = 0x1F; /* NominalTimeSeg1 = Propagation_segment + Phase_segment_1 */ + device->fdcan.Init.NominalTimeSeg2 = 0x08; + device->fdcan.Init.MessageRAMOffset = 0x00; + device->fdcan.Init.StdFiltersNbr = 0x01; + device->fdcan.Init.ExtFiltersNbr = 0x01; + device->fdcan.Init.RxFifo0ElmtsNbr = 0x01; + device->fdcan.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8; + device->fdcan.Init.RxFifo1ElmtsNbr = 0x02; + device->fdcan.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_8; + device->fdcan.Init.RxBuffersNbr = 0x00; + device->fdcan.Init.TxEventsNbr = 0x00; + device->fdcan.Init.TxBuffersNbr = 0x00; + device->fdcan.Init.TxFifoQueueElmtsNbr = 0x01; + device->fdcan.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION; + device->fdcan.Init.TxElmtSize = FDCAN_DATA_BYTES_8; + + if (HAL_FDCAN_Init(&device->fdcan) != HAL_OK) + { + return RT_ERROR; + } + + device->filter.IdType = FDCAN_EXTENDED_ID; + device->filter.FilterIndex = 0; + device->filter.FilterType = FDCAN_FILTER_MASK; + device->filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0; + device->filter.FilterID1 = 0x1111111; + device->filter.FilterID2 = 0x2222222; + + if (HAL_FDCAN_ConfigFilter(&device->fdcan, &device->filter)!=HAL_OK) + { + return RT_ERROR; + } + HAL_FDCAN_Start(&device->fdcan); + HAL_FDCAN_ActivateNotification(&device->fdcan, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0); /* open rx fifo0 new message it */ + + device->fifo0 = RESET; + device->fifo1 = RESET; + + return RT_EOK; +} + +static rt_err_t rt_fdcan_open(rt_device_t dev, rt_uint16_t oflag) +{ + RT_ASSERT(dev != RT_NULL); + + return RT_EOK; +} + +static rt_err_t rt_fdcan_close(rt_device_t dev) +{ + RT_ASSERT(dev != RT_NULL); + + return RT_EOK; +} + +static rt_err_t rt_fdcan_control(rt_device_t dev, int cmd, void *args) +{ + RT_ASSERT(dev != RT_NULL); + struct stm32_fdcan *device = (struct stm32_fdcan *)dev; + + switch (cmd) + { + case FDCAN_MODE_NORMAL: + device->fdcan.Init.Mode = FDCAN_MODE_NORMAL; + break; + case FDCAN_MODE_INTERNAL_LOOPBACK: + device->fdcan.Init.Mode = FDCAN_MODE_INTERNAL_LOOPBACK; + break; + default: + break; + } + + HAL_FDCAN_Init(&device->fdcan); + + return RT_EOK; +} + +static rt_size_t rt_fdcan_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) +{ + RT_ASSERT(dev != RT_NULL); + struct stm32_fdcan *device = (struct stm32_fdcan *)dev; + + if (rt_fdcan.fifo0 == SET) + { + rt_fdcan.fifo0 = RESET; + if (HAL_FDCAN_GetRxMessage(&device->fdcan, FDCAN_RX_FIFO0, &device->rx_config, (uint8_t *)buffer) != HAL_OK) + { + LOG_E("get msg error from fdcan fifo0!"); + return 0; + } + + return device->rx_config.DataLength >> 16; + } + if (rt_fdcan.fifo1 == SET) + { + rt_fdcan.fifo0 = RESET; + if (HAL_FDCAN_GetRxMessage(&device->fdcan, FDCAN_RX_FIFO1, &device->rx_config, (uint8_t *)buffer) != HAL_OK) + { + LOG_E("get msg error from fdcan fifo1!"); + return 0; + } + + return device->rx_config.DataLength >> 16; + } + + return 0; +} + +static rt_size_t rt_fdcan_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) +{ + RT_ASSERT(dev != RT_NULL); + struct stm32_fdcan *device = (struct stm32_fdcan *)dev; + + device->tx_config.Identifier = 0x1111112; + device->tx_config.IdType = FDCAN_EXTENDED_ID; + device->tx_config.TxFrameType = FDCAN_DATA_FRAME; + device->tx_config.DataLength = FDCAN_DLC_BYTES_8; + device->tx_config.ErrorStateIndicator = FDCAN_ESI_ACTIVE; + device->tx_config.BitRateSwitch = FDCAN_BRS_OFF; + device->tx_config.FDFormat = FDCAN_CLASSIC_CAN; + device->tx_config.TxEventFifoControl = FDCAN_NO_TX_EVENTS; + device->tx_config.MessageMarker = 0xCC; + + if (HAL_FDCAN_AddMessageToTxFifoQ(&device->fdcan, &device->tx_config, (uint8_t *)buffer) != HAL_OK) + { + return RT_ERROR; + } + + return RT_EOK; +} + +void FDCAN1_IT0_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + HAL_FDCAN_IRQHandler(&rt_fdcan.fdcan); + + /* leave interrupt */ + rt_interrupt_leave(); +} + +void FDCAN1_IT1_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + HAL_FDCAN_IRQHandler(&rt_fdcan.fdcan); + + /* leave interrupt */ + rt_interrupt_leave(); +} + +void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs) +{ + if (hfdcan->Instance == FDCAN1) + { + if ((RxFifo0ITs & FDCAN_IT_RX_FIFO0_NEW_MESSAGE) != RESET) + { + rt_fdcan.fifo0 = SET; + HAL_FDCAN_ActivateNotification(hfdcan, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0); + } + } +} + +void HAL_FDCAN_RxFifo1Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo1ITs) +{ + if ((RxFifo1ITs & FDCAN_IT_RX_FIFO1_NEW_MESSAGE) != RESET) + { + rt_fdcan.fifo1 = SET; + HAL_FDCAN_ActivateNotification(hfdcan, FDCAN_IT_RX_FIFO1_NEW_MESSAGE, 0); + } +} + +int fdcan_init(void) +{ + rt_fdcan.dev.type = RT_Device_Class_CAN; + rt_fdcan.dev.init = rt_fdcan_init; + rt_fdcan.dev.open = rt_fdcan_open; + rt_fdcan.dev.close = rt_fdcan_close; + rt_fdcan.dev.read = rt_fdcan_read; + rt_fdcan.dev.write = rt_fdcan_write; + rt_fdcan.dev.control = rt_fdcan_control; + rt_fdcan.dev.user_data = RT_NULL; + + rt_device_register(&rt_fdcan.dev, "fdcan1", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE); + + LOG_I("fdcan1 init success!"); + + return RT_EOK; +} +INIT_DEVICE_EXPORT(fdcan_init); + +#ifdef FINSH_USING_MSH +#include + +int fdcan_sample(int argc, char **argv) +{ + rt_err_t result = RT_EOK; + rt_uint8_t i, rx_buf[8], tx_buf[8]; + struct rt_device *dev = RT_NULL; + + if (argc != 9) + { + rt_kprintf("Usage:\n"); + rt_kprintf("fdcan_sample 1 2 3 4 5 6 7 8\n"); + return -1; + } + + for (i = 0; i < 8; i++) + { + tx_buf[i] = atoi(argv[i+1]); + } + + dev = rt_device_find("fdcan1"); + if (dev == RT_NULL) + { + rt_kprintf("can't find fdcan1 device!\n"); + return RT_ERROR; + } + rt_device_open(dev, RT_DEVICE_OFLAG_RDWR); + + rt_device_write(dev, 0, tx_buf, 8); + rt_thread_delay(1); + rt_device_read(dev, 0, rx_buf, 8); + + rt_kprintf("fdcan1 loopback test over, rbuf = "); + for (i = 0; i < 8; i++) + { + rt_kprintf(" %x ", rx_buf[i]); + } + rt_kprintf("\n"); + + return result; +} + +MSH_CMD_EXPORT(fdcan_sample, fdcan loopback mode test); + +#endif + +#endif diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_fdcan.h b/bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_fdcan.h new file mode 100644 index 0000000000..ab4280d360 --- /dev/null +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_fdcan.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-07-06 thread-liu first version + */ + +#ifndef __DRV_FDCAN_H__ +#define __DRV_FDCAN_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif