diff --git a/.editorconfig b/.editorconfig index 493c3b20..55a37f98 100644 --- a/.editorconfig +++ b/.editorconfig @@ -17,6 +17,10 @@ indent_style = tab insert_final_newline = true trim_trailing_whitespace = true +[*.yml] +indent_size = 2 +indent_style = space + [lib/**] indent_size = 2 indent_style = space diff --git a/.github/workflows/compile.yml b/.github/workflows/compile.yml new file mode 100644 index 00000000..05315606 --- /dev/null +++ b/.github/workflows/compile.yml @@ -0,0 +1,53 @@ +name: compile + +on: [push, pull_request] + +jobs: + build: + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + matrix: + release: + - "ubuntu:20.04" + - "ubuntu:22.04" + - "ubuntu:24.04" + - "ubuntu:rolling" + - "debian:oldstable-slim" + - "debian:stable-slim" + - "debian:testing-slim" + - "debian:unstable-slim" + + steps: + - uses: actions/checkout@v4 + + - name: Prepare ${{ matrix.release }} container + run: | + podman version + podman run --name stable -di --userns=keep-id:uid=1000,gid=1000 -v "$PWD":/home -w /home ${{ matrix.release }} bash + podman exec -i stable uname -a + podman exec -i stable id + podman exec -i -u root stable apt update + podman exec -e DEBIAN_FRONTEND='noninteractive' -i -u root stable apt install -o APT::Install-Suggests=false -qy \ + clang \ + cmake \ + gcc-arm-none-eabi \ + git \ + make + + - name: Configure & Build with arm-none-eabi-gcc + env: + toolchain: arm-none-eabi-gcc + run: | + podman exec -i stable cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=cmake/${toolchain}.cmake -B build-${toolchain} + podman exec -i stable cmake --build build-${toolchain} + + - name: Show logs + if: ${{ failure() }} + run: | + for log in build-*/CMakeFiles/{CMakeOutput.log,CMakeConfigureLog.yaml}; do \ + if [ -e ${log} ]; then \ + echo "---------------- ${log} ----------------"; \ + cat ${log}; \ + fi; \ + done diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index f6dece5a..8216efd0 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -8,7 +8,7 @@ jobs: name: Check C Styling steps: - name: Checkout this commit - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 2 - name: uncrustify check diff --git a/.gitignore b/.gitignore index ee7a1694..8f57b206 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +/.ccls-cache/ /.idea/ /.vscode/ /Debug/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 6f3f1a6e..3fb30e73 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,7 +41,7 @@ add_link_options( add_subdirectory(libs/STM32_HAL) add_subdirectory(libs/STM32_USB_Device_Library) -set( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake ) +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake) # Add a custom target that produces version.h, plus @@ -65,6 +65,7 @@ set( include/usbd_gs_can.h src/usbd_gs_can.c src/usbd_conf.c + include/board.h include/can.h include/can_common.h src/can_common.c include/device.h @@ -110,19 +111,22 @@ find_package(DFUSuffix) function(dfu_flash target) if (DFU_SUFFIX_EXECUTABLE) - add_custom_command( TARGET ${target} + add_custom_command(TARGET ${target} + DEPENDS ${target} BYPRODUCTS ${target}.dfu COMMAND ${CMAKE_OBJCOPY} -O binary ${target} ${target}.dfu COMMAND ${DFU_SUFFIX_EXECUTABLE} --add ${target}.dfu --vid 1d50 --pid 606f 1>/dev/null COMMENT "create and sign dfu bin file: ${TGTNAME}_fw" ) - add_custom_target( flash-${target} - dfu-util -a 0 -R -s 0x08000000 -D ${target}.dfu + add_custom_target(flash-${target} + dfu-util -a 0 -s 0x08000000:leave -D ${target}.dfu + DEPENDS ${target}.dfu ) else() - add_custom_target( flash-${target} - dfu-util -d 1d50:606f -a 0 -R -s 0x08000000 -D ${target}.bin + add_custom_target(flash-${target} + dfu-util -d 1d50:606f -a 0 -s 0x08000000:leave -D ${target}.bin + DEPENDS ${target}.bin ) endif() endfunction() @@ -140,9 +144,9 @@ endfunction() # at configure time. function(populate_ldscript) - set(prefix LDV) - set(options) - set(oneValueArgs + set(prefix LDV) + set(options) + set(oneValueArgs CPU_FAMILY FLASH_START FLASH_SIZE @@ -192,9 +196,9 @@ populate_ldscript(CPU_FAMILY STM32F407XE HEAP_SIZE 1k ) -populate_ldscript(CPU_FAMILY STM32G0B1XK +populate_ldscript(CPU_FAMILY STM32G0B1xx FLASH_START 0x08000000 - FLASH_SIZE 512k + FLASH_SIZE 128k RAM_START 0x20000000 RAM_SIZE 144k STACK_SIZE 2k @@ -202,13 +206,13 @@ populate_ldscript(CPU_FAMILY STM32G0B1XK ) ######### commands for adding each target have a lot in common: make helper func. -# Split into two categories, F042-based and F072-based. +# one helper func per STM32 CPU family function(add_target_common TGTNAME CPU_FAMILY) add_executable(${TGTNAME}_fw ${SOURCE_FILES}) add_dependencies(${TGTNAME}_fw version_h) target_include_directories(${TGTNAME}_fw PRIVATE include/ ${CMAKE_CURRENT_BINARY_DIR}) - target_link_options(${TGTNAME}_fw PRIVATE -T ${CPU_FAMILY}_processed.ld) + target_link_options(${TGTNAME}_fw PRIVATE -T ${CPU_FAMILY}_processed.ld LINKER:-Map=${TGTNAME}_fw.map) make_bin_file(${TGTNAME}_fw) dfu_flash(${TGTNAME}_fw) show_object_size(${TGTNAME}_fw) @@ -218,6 +222,7 @@ function(add_f042_target TGTNAME) add_target_common(${TGTNAME} STM32F042X6) target_compile_options(${TGTNAME}_fw BEFORE PRIVATE ${CPUFLAGS_F0}) target_compile_definitions(${TGTNAME}_fw PRIVATE BOARD_${TGTNAME} STM32F0) + target_sources(${TGTNAME}_fw PRIVATE "src/boards/legacy.c") target_sources(${TGTNAME}_fw PRIVATE "src/can/bxcan.c") target_sources(${TGTNAME}_fw PRIVATE "src/device/device_f0.c") target_link_options(${TGTNAME}_fw BEFORE PRIVATE ${CPUFLAGS_F0}) @@ -228,17 +233,18 @@ function(add_f072_target TGTNAME) add_target_common(${TGTNAME} STM32F072XB) target_compile_options(${TGTNAME}_fw BEFORE PRIVATE ${CPUFLAGS_F0}) target_compile_definitions(${TGTNAME}_fw PRIVATE BOARD_${TGTNAME} STM32F0) + target_sources(${TGTNAME}_fw PRIVATE "src/boards/legacy.c") target_sources(${TGTNAME}_fw PRIVATE "src/can/bxcan.c") target_sources(${TGTNAME}_fw PRIVATE "src/device/device_f0.c") target_link_options(${TGTNAME}_fw BEFORE PRIVATE ${CPUFLAGS_F0}) target_link_libraries(${TGTNAME}_fw PRIVATE STM32_HAL_STM32F072xB STM32_USB_Device_Library_STM32F072xB) - endfunction() function(add_f407_target TGTNAME) add_target_common(${TGTNAME} STM32F407XE) target_compile_definitions(${TGTNAME}_fw PRIVATE BOARD_${TGTNAME} STM32F4) target_compile_options(${TGTNAME}_fw BEFORE PRIVATE ${CPUFLAGS_F4}) + target_sources(${TGTNAME}_fw PRIVATE "src/boards/legacy.c") target_sources(${TGTNAME}_fw PRIVATE "src/can/bxcan.c") target_sources(${TGTNAME}_fw PRIVATE "src/device/device_f4.c") target_link_options(${TGTNAME}_fw BEFORE PRIVATE ${CPUFLAGS_F4}) @@ -246,20 +252,42 @@ function(add_f407_target TGTNAME) endfunction() function(add_g0b1_target TGTNAME) - add_target_common(${TGTNAME} STM32G0B1XK) + add_target_common(${TGTNAME} STM32G0B1xx) target_compile_definitions(${TGTNAME}_fw PRIVATE BOARD_${TGTNAME} STM32G0) target_compile_options(${TGTNAME}_fw BEFORE PRIVATE ${CPUFLAGS_G0}) + target_sources(${TGTNAME}_fw PRIVATE "src/boards/g0b1-${TGTNAME}.c") + target_sources(${TGTNAME}_fw PRIVATE "src/can/m_can.c") target_sources(${TGTNAME}_fw PRIVATE "src/device/device_g0.c") target_link_options(${TGTNAME}_fw BEFORE PRIVATE ${CPUFLAGS_G0}) - target_link_libraries(${TGTNAME}_fw PRIVATE STM32_HAL_STM32G0B1xK STM32_USB_Device_Library_STM32G0B1xK) + target_link_libraries(${TGTNAME}_fw PRIVATE STM32_HAL_STM32G0B1xx STM32_USB_Device_Library_STM32G0B1xx) endfunction() ########## generate list of targets. # the "_fw" part is appended automatically -set(TGTF042_LIST "cantact" "canalyze" "canable" "usb2can" "cannette") -set(TGTF072_LIST "candleLight" "CANable_MKS" "CONVERTDEVICE_xCAN" "DSD_TECH_SH_C30A" "FYSETC_UCAN") -set(TGTF407_LIST "STM32F4_DevBoard") -set(TGTG0B1_LIST "budgetcan" "CONVERTDEVICE_xCANFD") +set(TGTF042_LIST + "canable" + "canalyze" + "cannette" + "cantact" + "usb2can" +) +set(TGTF072_LIST + "CANable_MKS" + "CONVERTDEVICE_xCAN" + "DSD_TECH_SH_C30A" + "FYSETC_UCAN" + "candleLight" +) +set(TGTF407_LIST + "STM32F4_DevBoard" +) +set(TGTG0B1_LIST + "2C2L_USB" + "CONVERTDEVICE_xCANFD" + "budgetcan" + "candleLightFD" + "nucleo_g0b1re" +) foreach (TGTNAME IN LISTS TGTF042_LIST) option(BUILD_${TGTNAME} "Build firmware for \"${TGTNAME}\" (default=yes)" ON) @@ -283,7 +311,7 @@ foreach (TGTNAME IN LISTS TGTF407_LIST) endforeach() foreach (TGTNAME IN LISTS TGTG0B1_LIST) - option(BUILD_${TGTNAME} "Build firmware for \"${TGTNAME}\" (default=yes)" OFF) + option(BUILD_${TGTNAME} "Build firmware for \"${TGTNAME}\" (default=yes)" ON) if (BUILD_${TGTNAME}) add_g0b1_target(${TGTNAME}) endif() diff --git a/cmake/FindDFUSuffix.cmake b/cmake/FindDFUSuffix.cmake index 92ac8dcf..d495fa01 100644 --- a/cmake/FindDFUSuffix.cmake +++ b/cmake/FindDFUSuffix.cmake @@ -1,9 +1,8 @@ -# find and set DFU_SUFFIX_EXECUTABLE - -find_program ( DFU_SUFFIX_EXECUTABLE - NAMES dfu-suffix - DOC "dfu-suffix executable" -) - -mark_as_advanced ( DFU_SUFFIX_EXECUTABLE ) - +# find and set DFU_SUFFIX_EXECUTABLE + +find_program(DFU_SUFFIX_EXECUTABLE + NAMES dfu-suffix + DOC "dfu-suffix executable" +) + +mark_as_advanced(DFU_SUFFIX_EXECUTABLE) diff --git a/cmake/arm-none-eabi-clang.cmake b/cmake/arm-none-eabi-clang.cmake new file mode 100644 index 00000000..6ff6e151 --- /dev/null +++ b/cmake/arm-none-eabi-clang.cmake @@ -0,0 +1,8 @@ +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR arm) + +set(CMAKE_C_COMPILER clang) +set(CMAKE_C_COMPILER_TARGET arm-none-eabi) + +SET (CMAKE_C_COMPILER_WORKS 1) +SET (CMAKE_CXX_COMPILER_WORKS 1) diff --git a/cmake/arm-none-eabi-gcc.cmake b/cmake/arm-none-eabi-gcc.cmake new file mode 100644 index 00000000..1b0f8730 --- /dev/null +++ b/cmake/arm-none-eabi-gcc.cmake @@ -0,0 +1,8 @@ +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR arm) + +set(CMAKE_C_COMPILER arm-none-eabi-gcc) +set(CMAKE_C_COMPILER_TARGET arm-none-eabi) + +SET (CMAKE_C_COMPILER_WORKS 1) +SET (CMAKE_CXX_COMPILER_WORKS 1) diff --git a/include/board.h b/include/board.h new file mode 100644 index 00000000..582e86c3 --- /dev/null +++ b/include/board.h @@ -0,0 +1,55 @@ +#pragma once + +/* + * The MIT License (MIT) + * + * Copyright (c) 2023 Pengutronix, + * Jonas Martin + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#include "usbd_gs_can.h" + +struct LEDConfig { + GPIO_TypeDef *port; + uint16_t pin; + bool active_high; +}; + +struct BoardChannelConfig { +#if defined(STM32G0) + FDCAN_GlobalTypeDef *interface; +#else + CAN_TypeDef *interface; +#endif + struct LEDConfig leds[LED_MAX]; +}; + +struct BoardConfig { + struct BoardChannelConfig channels[NUM_CAN_CHANNEL]; + void (*setup)(USBD_GS_CAN_HandleTypeDef *hcan); + void (*phy_power_set)(can_data_t *channel, bool enable); + void (*termination_set)(can_data_t *channel, enum gs_can_termination_state state); +}; + +extern const struct BoardConfig config; diff --git a/include/can.h b/include/can.h index dcd48964..3c0c89a3 100644 --- a/include/can.h +++ b/include/can.h @@ -29,13 +29,18 @@ THE SOFTWARE. #include #include +#include "config.h" #include "gs_usb.h" #include "hal_include.h" #include "led.h" #include "list.h" typedef struct { +#if defined(STM32G0) + FDCAN_HandleTypeDef channel; +#else CAN_TypeDef *instance; +#endif struct list_head list_from_host; led_data_t leds; uint32_t reg_esr_old; @@ -47,9 +52,28 @@ typedef struct { } can_data_t; extern const struct gs_device_bt_const CAN_btconst; +extern const struct gs_device_bt_const_extended CAN_btconst_ext; +#if defined(STM32G0) +void can_init(can_data_t *channel, FDCAN_GlobalTypeDef *instance); +#else void can_init(can_data_t *channel, CAN_TypeDef *instance); -bool can_set_bittiming(can_data_t *channel, const struct gs_device_bittiming *timing); +#endif +void can_set_bittiming(can_data_t *channel, const struct gs_device_bittiming *timing); + +#ifdef CONFIG_CANFD +void can_set_data_bittiming(can_data_t *channel, const struct gs_device_bittiming *timing); +#else +static inline bool can_set_data_bittiming(can_data_t *channel, + const struct gs_device_bittiming *timing) +{ + (void)channel; + (void)timing; + + return false; +} +#endif + void can_enable(can_data_t *channel, uint32_t mode); void can_disable(can_data_t *channel); bool can_is_enabled(can_data_t *channel); diff --git a/include/can_common.h b/include/can_common.h index 7ca34476..329d4d73 100644 --- a/include/can_common.h +++ b/include/can_common.h @@ -31,6 +31,7 @@ THE SOFTWARE. #include "can.h" #include "usbd_gs_can.h" +bool can_check_bittiming_ok(const struct can_bittiming_const *btc, const struct gs_device_bittiming *timing); void CAN_SendFrame(USBD_GS_CAN_HandleTypeDef *hcan, can_data_t *channel); void CAN_ReceiveFrame(USBD_GS_CAN_HandleTypeDef *hcan, can_data_t *channel); void CAN_HandleError(USBD_GS_CAN_HandleTypeDef *hcan, can_data_t *channel); diff --git a/include/config.h b/include/config.h index fb43c04d..2705a0fa 100644 --- a/include/config.h +++ b/include/config.h @@ -45,13 +45,15 @@ THE SOFTWARE. #define USBD_VID 0x1d50 #define USBD_PID_FS 0x606f #define USBD_LANGID_STRING 1033 -#define USBD_CONFIGURATION_STRING_FS (uint8_t*) GIT_HASH -#define USBD_INTERFACE_STRING_FS (uint8_t*) "gs_usb interface" +#define USBD_CONFIGURATION_STRING_FS GIT_HASH +#define USBD_INTERFACE_STRING_FS "gs_usb interface" -#if defined(BOARD_candleLight) - #define USBD_PRODUCT_STRING_FS (uint8_t*) "candleLight USB to CAN adapter" - #define USBD_MANUFACTURER_STRING (uint8_t*) "bytewerk" - #define DFU_INTERFACE_STRING_FS (uint8_t*) "candleLight firmware upgrade interface" +/*************** STM32F042 ***************/ + +#if defined(BOARD_canable) + #define USBD_PRODUCT_STRING_FS "canable gs_usb" + #define USBD_MANUFACTURER_STRING "canable.io" + #define DFU_INTERFACE_STRING_FS "canable firmware upgrade interface" #define TIM2_CLOCK_SPEED 48000000 @@ -59,23 +61,20 @@ THE SOFTWARE. #define CAN_CLOCK_SPEED 48000000 #define NUM_CAN_CHANNEL 1 - #define CAN_S_Pin GPIO_PIN_13 - #define CAN_S_GPIO_Port GPIOC - - #define LEDRX_Pin GPIO_PIN_0 - #define LEDRX_Mode GPIO_MODE_OUTPUT_OD - #define LEDRX_GPIO_Port GPIOA - #define LEDRX_Active_High 0 + #define LEDRX_GPIO_Port GPIOB + #define LEDRX_Pin GPIO_PIN_0 /* green */ + #define LEDRX_Mode GPIO_MODE_OUTPUT_PP + #define LEDRX_Active_High 1 - #define LEDTX_GPIO_Port GPIOA - #define LEDTX_Pin GPIO_PIN_1 - #define LEDTX_Mode GPIO_MODE_OUTPUT_OD + #define LEDTX_GPIO_Port GPIOB + #define LEDTX_Pin GPIO_PIN_1 /* blue */ + #define LEDTX_Mode GPIO_MODE_OUTPUT_PP #define LEDTX_Active_High 0 -#elif defined(BOARD_CANable_MKS) - #define USBD_PRODUCT_STRING_FS (uint8_t*) "CANable-MKS gs_usb" - #define USBD_MANUFACTURER_STRING (uint8_t*) "makerbase" - #define DFU_INTERFACE_STRING_FS (uint8_t*) "CANable-MKS firmware upgrade interface" +#elif defined(BOARD_canalyze) + #define USBD_PRODUCT_STRING_FS "CANAlyze gs_usb" + #define USBD_MANUFACTURER_STRING "STMicroelectronics" + #define DFU_INTERFACE_STRING_FS "CANAlyze firmware upgrade interface" #define TIM2_CLOCK_SPEED 48000000 @@ -83,20 +82,20 @@ THE SOFTWARE. #define CAN_CLOCK_SPEED 48000000 #define NUM_CAN_CHANNEL 1 - #define LEDRX_GPIO_Port GPIOA - #define LEDRX_Pin GPIO_PIN_1 - #define LEDRX_Mode GPIO_MODE_OUTPUT_OD - #define LEDRX_Active_High 0 + #define LEDRX_GPIO_Port GPIOB + #define LEDRX_Pin GPIO_PIN_0 /* green */ + #define LEDRX_Mode GPIO_MODE_OUTPUT_PP + #define LEDRX_Active_High 1 - #define LEDTX_GPIO_Port GPIOA - #define LEDTX_Pin GPIO_PIN_0 - #define LEDTX_Mode GPIO_MODE_OUTPUT_OD - #define LEDTX_Active_High 0 + #define LEDTX_GPIO_Port GPIOB + #define LEDTX_Pin GPIO_PIN_1 /* red */ + #define LEDTX_Mode GPIO_MODE_OUTPUT_PP + #define LEDTX_Active_High 1 -#elif defined(BOARD_CONVERTDEVICE_xCAN) - #define USBD_PRODUCT_STRING_FS (uint8_t*) "ConvertDevice xCAN" - #define USBD_MANUFACTURER_STRING (uint8_t*) "ConvertDevice" - #define DFU_INTERFACE_STRING_FS (uint8_t*) "ConvertDevice xCAN firmware upgrade interface" +#elif defined(BOARD_cannette) + #define USBD_PRODUCT_STRING_FS "cannette gs_usb" + #define USBD_MANUFACTURER_STRING "chacaltech" + #define DFU_INTERFACE_STRING_FS "cannette firmware upgrade interface" #define TIM2_CLOCK_SPEED 48000000 @@ -105,45 +104,50 @@ THE SOFTWARE. #define NUM_CAN_CHANNEL 1 #define LEDRX_GPIO_Port GPIOA - #define LEDRX_Pin GPIO_PIN_0 - #define LEDRX_Mode GPIO_MODE_OUTPUT_PP + #define LEDRX_Pin GPIO_PIN_9 /* RX: green */ + #define LEDRX_Mode GPIO_MODE_OUTPUT_OD #define LEDRX_Active_High 0 #define LEDTX_GPIO_Port GPIOA - #define LEDTX_Pin GPIO_PIN_1 - #define LEDTX_Mode GPIO_MODE_OUTPUT_PP + #define LEDTX_Pin GPIO_PIN_8 /* TX: red */ + #define LEDTX_Mode GPIO_MODE_OUTPUT_OD #define LEDTX_Active_High 0 -#elif defined(BOARD_CONVERTDEVICE_xCANFD) - #define USBD_PRODUCT_STRING_FS (uint8_t*) "ConvertDevice xCANFD" - #define USBD_MANUFACTURER_STRING (uint8_t*) "ConvertDevice" - #define DFU_INTERFACE_STRING_FS (uint8_t*) "ConvertDevice xCANFD firmware upgrade interface" + #define nCANSTBY_Port GPIOC + #define nCANSTBY_Pin GPIO_PIN_14 /* control xceiver standby, active low */ + #define nCANSTBY_Active_High 1 - #define TIM2_CLOCK_SPEED 64000000 + #define nSI86EN_Port GPIOC + #define nSI86EN_Pin GPIO_PIN_13 /* enable power to Si86xx isolater, active low */ - #define CAN_INTERFACE FDCAN1 - #define CAN_CLOCK_SPEED 64000000 + #define DCDCEN_Port GPIOC + #define DCDCEN_Pin GPIO_PIN_15 /* activate DCDC converter, active high */ + +#elif defined(BOARD_cantact) + #define USBD_PRODUCT_STRING_FS "cantact gs_usb" + #define USBD_MANUFACTURER_STRING "cantact.io" + #define DFU_INTERFACE_STRING_FS "cantact firmware upgrade interface" + + #define TIM2_CLOCK_SPEED 48000000 + + #define CAN_INTERFACE CAN + #define CAN_CLOCK_SPEED 48000000 #define NUM_CAN_CHANNEL 1 - #define CONFIG_CANFD 1 - #define LEDRX_GPIO_Port GPIOA - #define LEDRX_Pin GPIO_PIN_0 + #define LEDRX_GPIO_Port GPIOB + #define LEDRX_Pin GPIO_PIN_0 /* green */ #define LEDRX_Mode GPIO_MODE_OUTPUT_PP - #define LEDRX_Active_High 0 + #define LEDRX_Active_High 1 - #define LEDTX_GPIO_Port GPIOA - #define LEDTX_Pin GPIO_PIN_1 + #define LEDTX_GPIO_Port GPIOB + #define LEDTX_Pin GPIO_PIN_1 /* red */ #define LEDTX_Mode GPIO_MODE_OUTPUT_PP - #define LEDTX_Active_High 0 - - #define USB_GPIO_Port GPIOA - #define USB_Pin_DM GPIO_PIN_11 - #define USB_Pin_DP GPIO_PIN_12 + #define LEDTX_Active_High 1 -#elif defined(BOARD_DSD_TECH_SH_C30A) - #define USBD_PRODUCT_STRING_FS (uint8_t*) "SH-C30A USB to CAN adapter" - #define USBD_MANUFACTURER_STRING (uint8_t*) "DSD TECH" - #define DFU_INTERFACE_STRING_FS (uint8_t*) "SH-C30A firmware upgrade interface" +#elif defined(BOARD_usb2can) + #define USBD_PRODUCT_STRING_FS "USB2CAN RCA gs_usb" + #define USBD_MANUFACTURER_STRING "Roboter Club Aachen" + #define DFU_INTERFACE_STRING_FS "usb2can firmware upgrade interface" #define TIM2_CLOCK_SPEED 48000000 @@ -151,20 +155,22 @@ THE SOFTWARE. #define CAN_CLOCK_SPEED 48000000 #define NUM_CAN_CHANNEL 1 + #define LEDTX_GPIO_Port GPIOA + #define LEDTX_Pin GPIO_PIN_1 /* blue */ + #define LEDTX_Mode GPIO_MODE_OUTPUT_OD + #define LEDTX_Active_High 0 + #define LEDRX_GPIO_Port GPIOB - #define LEDRX_Pin GPIO_PIN_1 - #define LEDRX_Mode GPIO_MODE_OUTPUT_PP + #define LEDRX_Pin GPIO_PIN_3 /* green */ + #define LEDRX_Mode GPIO_MODE_OUTPUT_OD #define LEDRX_Active_High 0 - #define LEDTX_GPIO_Port GPIOB - #define LEDTX_Pin GPIO_PIN_0 - #define LEDTX_Mode GPIO_MODE_OUTPUT_PP - #define LEDTX_Active_High 0 +/*************** STM32F072 ***************/ -#elif defined(BOARD_FYSETC_UCAN) - #define USBD_PRODUCT_STRING_FS (uint8_t*) "UCAN USB to CAN adapter" - #define USBD_MANUFACTURER_STRING (uint8_t*) "FYSETC" - #define DFU_INTERFACE_STRING_FS (uint8_t*) "UCAN firmware upgrade interface" +#elif defined(BOARD_CANable_MKS) + #define USBD_PRODUCT_STRING_FS "CANable-MKS gs_usb" + #define USBD_MANUFACTURER_STRING "makerbase" + #define DFU_INTERFACE_STRING_FS "CANable-MKS firmware upgrade interface" #define TIM2_CLOCK_SPEED 48000000 @@ -174,18 +180,18 @@ THE SOFTWARE. #define LEDRX_GPIO_Port GPIOA #define LEDRX_Pin GPIO_PIN_1 - #define LEDRX_Mode GPIO_MODE_OUTPUT_PP - #define LEDRX_Active_High 1 + #define LEDRX_Mode GPIO_MODE_OUTPUT_OD + #define LEDRX_Active_High 0 #define LEDTX_GPIO_Port GPIOA #define LEDTX_Pin GPIO_PIN_0 - #define LEDTX_Mode GPIO_MODE_OUTPUT_PP - #define LEDTX_Active_High 1 + #define LEDTX_Mode GPIO_MODE_OUTPUT_OD + #define LEDTX_Active_High 0 -#elif defined(BOARD_cantact) - #define USBD_PRODUCT_STRING_FS (uint8_t*) "cantact gs_usb" - #define USBD_MANUFACTURER_STRING (uint8_t*) "cantact.io" - #define DFU_INTERFACE_STRING_FS (uint8_t*) "cantact firmware upgrade interface" +#elif defined(BOARD_CONVERTDEVICE_xCAN) + #define USBD_PRODUCT_STRING_FS "ConvertDevice xCAN" + #define USBD_MANUFACTURER_STRING "ConvertDevice" + #define DFU_INTERFACE_STRING_FS "ConvertDevice xCAN firmware upgrade interface" #define TIM2_CLOCK_SPEED 48000000 @@ -193,20 +199,20 @@ THE SOFTWARE. #define CAN_CLOCK_SPEED 48000000 #define NUM_CAN_CHANNEL 1 - #define LEDRX_GPIO_Port GPIOB - #define LEDRX_Pin GPIO_PIN_0 /* green */ + #define LEDRX_GPIO_Port GPIOA + #define LEDRX_Pin GPIO_PIN_0 #define LEDRX_Mode GPIO_MODE_OUTPUT_PP - #define LEDRX_Active_High 1 + #define LEDRX_Active_High 0 - #define LEDTX_GPIO_Port GPIOB - #define LEDTX_Pin GPIO_PIN_1 /* red */ + #define LEDTX_GPIO_Port GPIOA + #define LEDTX_Pin GPIO_PIN_1 #define LEDTX_Mode GPIO_MODE_OUTPUT_PP - #define LEDTX_Active_High 1 + #define LEDTX_Active_High 0 -#elif defined(BOARD_canable) - #define USBD_PRODUCT_STRING_FS (uint8_t*) "canable gs_usb" - #define USBD_MANUFACTURER_STRING (uint8_t*) "canable.io" - #define DFU_INTERFACE_STRING_FS (uint8_t*) "canable firmware upgrade interface" +#elif defined(BOARD_DSD_TECH_SH_C30A) + #define USBD_PRODUCT_STRING_FS "SH-C30A USB to CAN adapter" + #define USBD_MANUFACTURER_STRING "DSD TECH" + #define DFU_INTERFACE_STRING_FS "SH-C30A firmware upgrade interface" #define TIM2_CLOCK_SPEED 48000000 @@ -215,40 +221,19 @@ THE SOFTWARE. #define NUM_CAN_CHANNEL 1 #define LEDRX_GPIO_Port GPIOB - #define LEDRX_Pin GPIO_PIN_0 /* green */ + #define LEDRX_Pin GPIO_PIN_1 #define LEDRX_Mode GPIO_MODE_OUTPUT_PP - #define LEDRX_Active_High 1 + #define LEDRX_Active_High 0 #define LEDTX_GPIO_Port GPIOB - #define LEDTX_Pin GPIO_PIN_1 /* blue */ + #define LEDTX_Pin GPIO_PIN_0 #define LEDTX_Mode GPIO_MODE_OUTPUT_PP #define LEDTX_Active_High 0 -#elif defined(BOARD_usb2can) - #define USBD_PRODUCT_STRING_FS (uint8_t*) "USB2CAN RCA gs_usb" - #define USBD_MANUFACTURER_STRING (uint8_t*) "Roboter Club Aachen" - #define DFU_INTERFACE_STRING_FS (uint8_t*) "usb2can firmware upgrade interface" - - #define TIM2_CLOCK_SPEED 48000000 - - #define CAN_INTERFACE CAN - #define CAN_CLOCK_SPEED 48000000 - #define NUM_CAN_CHANNEL 1 - - #define LEDTX_GPIO_Port GPIOA - #define LEDTX_Pin GPIO_PIN_1 /* blue */ - #define LEDTX_Mode GPIO_MODE_OUTPUT_OD - #define LEDTX_Active_High 0 - - #define LEDRX_GPIO_Port GPIOB - #define LEDRX_Pin GPIO_PIN_3 /* green */ - #define LEDRX_Mode GPIO_MODE_OUTPUT_OD - #define LEDRX_Active_High 0 - -#elif defined(BOARD_canalyze) - #define USBD_PRODUCT_STRING_FS (uint8_t*) "CANAlyze gs_usb" - #define USBD_MANUFACTURER_STRING (uint8_t*) "STMicroelectronics" - #define DFU_INTERFACE_STRING_FS (uint8_t*) "CANAlyze firmware upgrade interface" +#elif defined(BOARD_FYSETC_UCAN) + #define USBD_PRODUCT_STRING_FS "UCAN USB to CAN adapter" + #define USBD_MANUFACTURER_STRING "FYSETC" + #define DFU_INTERFACE_STRING_FS "UCAN firmware upgrade interface" #define TIM2_CLOCK_SPEED 48000000 @@ -256,20 +241,20 @@ THE SOFTWARE. #define CAN_CLOCK_SPEED 48000000 #define NUM_CAN_CHANNEL 1 - #define LEDRX_GPIO_Port GPIOB - #define LEDRX_Pin GPIO_PIN_0 /* green */ + #define LEDRX_GPIO_Port GPIOA + #define LEDRX_Pin GPIO_PIN_1 #define LEDRX_Mode GPIO_MODE_OUTPUT_PP #define LEDRX_Active_High 1 - #define LEDTX_GPIO_Port GPIOB - #define LEDTX_Pin GPIO_PIN_1 /* red */ + #define LEDTX_GPIO_Port GPIOA + #define LEDTX_Pin GPIO_PIN_0 #define LEDTX_Mode GPIO_MODE_OUTPUT_PP #define LEDTX_Active_High 1 -#elif defined(BOARD_cannette) - #define USBD_PRODUCT_STRING_FS (uint8_t*) "cannette gs_usb" - #define USBD_MANUFACTURER_STRING (uint8_t*) "chacaltech" - #define DFU_INTERFACE_STRING_FS (uint8_t*) "cannette firmware upgrade interface" +#elif defined(BOARD_candleLight) + #define USBD_PRODUCT_STRING_FS "candleLight USB to CAN adapter" + #define USBD_MANUFACTURER_STRING "bytewerk" + #define DFU_INTERFACE_STRING_FS "candleLight firmware upgrade interface" #define TIM2_CLOCK_SPEED 48000000 @@ -277,66 +262,25 @@ THE SOFTWARE. #define CAN_CLOCK_SPEED 48000000 #define NUM_CAN_CHANNEL 1 - #define LEDRX_GPIO_Port GPIOA - #define LEDRX_Pin GPIO_PIN_9 /* RX: green */ + #define CAN_S_Pin GPIO_PIN_13 + #define CAN_S_GPIO_Port GPIOC + + #define LEDRX_Pin GPIO_PIN_0 #define LEDRX_Mode GPIO_MODE_OUTPUT_OD + #define LEDRX_GPIO_Port GPIOA #define LEDRX_Active_High 0 #define LEDTX_GPIO_Port GPIOA - #define LEDTX_Pin GPIO_PIN_8 /* TX: red */ + #define LEDTX_Pin GPIO_PIN_1 #define LEDTX_Mode GPIO_MODE_OUTPUT_OD #define LEDTX_Active_High 0 - #define nCANSTBY_Port GPIOC - #define nCANSTBY_Pin GPIO_PIN_14 /* control xceiver standby, active low */ - #define nCANSTBY_Active_High 1 - - #define nSI86EN_Port GPIOC - #define nSI86EN_Pin GPIO_PIN_13 /* enable power to Si86xx isolater, active low */ - - #define DCDCEN_Port GPIOC - #define DCDCEN_Pin GPIO_PIN_15 /* activate DCDC converter, active high */ - -#elif defined(BOARD_budgetcan) - #define USBD_PRODUCT_STRING_FS (uint8_t*) "budgetcan gs_usb" - #define USBD_MANUFACTURER_STRING (uint8_t*) "budgetcan" - #define DFU_INTERFACE_STRING_FS (uint8_t*) "budgetcan firmware upgrade interface" - - #define TIM2_CLOCK_SPEED 64000000 - - #define CAN_INTERFACE FDCAN1 - #define CAN_INTERFACE2 FDCAN2 - #define CAN_CLOCK_SPEED 64000000 - #define NUM_CAN_CHANNEL 2 - #define CONFIG_CANFD 1 - - #define nCANSTBY_Port GPIOA - #define nCANSTBY_Pin GPIO_PIN_0 /* control xceiver standby, active low */ - #define nCANSTBY_Active_High 0 - - #define LEDRX_GPIO_Port GPIOB - #define LEDRX_Pin GPIO_PIN_4 - #define LEDRX_Mode GPIO_MODE_OUTPUT_PP - #define LEDRX_Active_High 1 - - #define LEDTX_GPIO_Port GPIOB - #define LEDTX_Pin GPIO_PIN_3 - #define LEDTX_Mode GPIO_MODE_OUTPUT_PP - #define LEDTX_Active_High 1 - - #define USB_GPIO_Port GPIOA - #define USB_Pin_DM GPIO_PIN_11 - #define USB_Pin_DP GPIO_PIN_12 - - #define TERM_GPIO_Port GPIOA - #define TERM_Pin GPIO_PIN_1 - #define TERM_Mode GPIO_MODE_OUTPUT_PP - #define TERM_Active_High 1 +/*************** STM32F407 ***************/ #elif defined(BOARD_STM32F4_DevBoard) - #define USBD_PRODUCT_STRING_FS (uint8_t*) "STM32F4VE Dev Board" - #define USBD_MANUFACTURER_STRING (uint8_t*) "misc" - #define DFU_INTERFACE_STRING_FS (uint8_t*) "STM32F4VE firmware upgrade interface" + #define USBD_PRODUCT_STRING_FS "STM32F4VE Dev Board" + #define USBD_MANUFACTURER_STRING "misc" + #define DFU_INTERFACE_STRING_FS "STM32F4VE firmware upgrade interface" #define TIM2_CLOCK_SPEED 96000000 @@ -366,6 +310,65 @@ THE SOFTWARE. #define TERM_Mode GPIO_MODE_OUTPUT_PP #define TERM_Active_High 1 +/*************** STM32G0B1 ***************/ + +#elif defined(BOARD_2C2L_USB) + #define USBD_PRODUCT_STRING_FS "intive 2C2L-USB gs_usb" + #define USBD_MANUFACTURER_STRING "intive" + #define DFU_INTERFACE_STRING_FS "intive 2C2L-USB firmware upgrade interface" + + #define HSE_OSC_SPEED 8000000 + #define TIM2_CLOCK_SPEED 64000000 + + #define CAN_CLOCK_SPEED 40000000 + #define NUM_CAN_CHANNEL 2 + #define CONFIG_CANFD 1 + +#elif defined(BOARD_CONVERTDEVICE_xCANFD) + #define USBD_PRODUCT_STRING_FS "ConvertDevice xCANFD" + #define USBD_MANUFACTURER_STRING "ConvertDevice" + #define DFU_INTERFACE_STRING_FS "ConvertDevice xCANFD firmware upgrade interface" + + #define TIM2_CLOCK_SPEED 64000000 + + #define CAN_CLOCK_SPEED 40000000 + #define NUM_CAN_CHANNEL 1 + #define CONFIG_CANFD 1 + +#elif defined(BOARD_budgetcan) + #define USBD_PRODUCT_STRING_FS "budgetcan gs_usb" + #define USBD_MANUFACTURER_STRING "budgetcan" + #define DFU_INTERFACE_STRING_FS "budgetcan firmware upgrade interface" + + #define TIM2_CLOCK_SPEED 64000000 + + #define CAN_CLOCK_SPEED 40000000 + #define NUM_CAN_CHANNEL 2 + #define CONFIG_CANFD 1 + +#elif defined(BOARD_candleLightFD) + #define USBD_PRODUCT_STRING_FS "candleLightFD gs_usb" + #define USBD_MANUFACTURER_STRING "candleLightFD" + #define DFU_INTERFACE_STRING_FS "candleLightFD firmware upgrade interface" + + #define HSE_OSC_SPEED 8000000 + #define TIM2_CLOCK_SPEED 64000000 + + #define CAN_CLOCK_SPEED 40000000 + #define NUM_CAN_CHANNEL 2 + #define CONFIG_CANFD 1 + +#elif defined(BOARD_nucleo_g0b1re) + #define USBD_PRODUCT_STRING_FS "NUCLEO-G0B1RE gs_usb" + #define USBD_MANUFACTURER_STRING "STMicroelectronics" + #define DFU_INTERFACE_STRING_FS "NUCLEO-G0B1RE firmware upgrade interface" + + #define TIM2_CLOCK_SPEED 64000000 + + #define CAN_CLOCK_SPEED 64000000 + #define NUM_CAN_CHANNEL 1 + #define CONFIG_CANFD 1 + #else #error please define BOARD #endif diff --git a/include/device.h b/include/device.h index 7947dbed..bdfeec0c 100644 --- a/include/device.h +++ b/include/device.h @@ -29,6 +29,8 @@ THE SOFTWARE. #include "can.h" #include "hal_include.h" +#if !defined(STM32G0) void device_can_init(can_data_t *channel, CAN_TypeDef *instance); +#endif void device_sysclock_config(void); diff --git a/include/gpio.h b/include/gpio.h index 705d6c3f..0b29c0a0 100644 --- a/include/gpio.h +++ b/include/gpio.h @@ -26,6 +26,7 @@ THE SOFTWARE. #pragma once +#include "can.h" #include "config.h" #include "gs_usb.h" @@ -35,18 +36,18 @@ void gpio_init(void); #define GPIO_INIT_STATE(active_high) (((active_high) == 1) ? GPIO_PIN_RESET : GPIO_PIN_SET) #ifdef TERM_Pin -enum gs_can_termination_state set_term(unsigned int channel, enum gs_can_termination_state state); -enum gs_can_termination_state get_term(unsigned int channel); +enum gs_can_termination_state set_term(can_data_t *channel, enum gs_can_termination_state state); +enum gs_can_termination_state get_term(can_data_t *channel); #else -static inline enum gs_can_termination_state set_term(unsigned int channel, enum gs_can_termination_state state) +static inline enum gs_can_termination_state set_term(can_data_t *channel, enum gs_can_termination_state state) { (void)channel; (void)state; return GS_CAN_TERMINATION_UNSUPPORTED; } -static inline enum gs_can_termination_state get_term(unsigned int channel) +static inline enum gs_can_termination_state get_term(can_data_t * channel) { (void)channel; return GS_CAN_TERMINATION_UNSUPPORTED; diff --git a/include/gs_usb.h b/include/gs_usb.h index 7e3d5d31..1d1a6160 100644 --- a/include/gs_usb.h +++ b/include/gs_usb.h @@ -247,9 +247,7 @@ struct gs_device_bittiming { u32 brp; } __packed __aligned(4); -struct gs_device_bt_const { - u32 feature; - u32 fclk_can; +struct can_bittiming_const { u32 tseg1_min; u32 tseg1_max; u32 tseg2_min; @@ -260,26 +258,17 @@ struct gs_device_bt_const { u32 brp_inc; } __packed __aligned(4); -struct gs_device_bt_const_extended { +struct gs_device_bt_const { u32 feature; u32 fclk_can; - u32 tseg1_min; - u32 tseg1_max; - u32 tseg2_min; - u32 tseg2_max; - u32 sjw_max; - u32 brp_min; - u32 brp_max; - u32 brp_inc; + struct can_bittiming_const btc; +} __packed __aligned(4); - u32 dtseg1_min; - u32 dtseg1_max; - u32 dtseg2_min; - u32 dtseg2_max; - u32 dsjw_max; - u32 dbrp_min; - u32 dbrp_max; - u32 dbrp_inc; +struct gs_device_bt_const_extended { + u32 feature; + u32 fclk_can; + struct can_bittiming_const btc; + struct can_bittiming_const dbtc; } __packed __aligned(4); struct gs_identify_mode { diff --git a/include/usbd_gs_can.h b/include/usbd_gs_can.h index 7329af43..5de535b4 100644 --- a/include/usbd_gs_can.h +++ b/include/usbd_gs_can.h @@ -105,6 +105,9 @@ typedef struct { // RX FIFO size chosen according to reference manual RM0368 which suggests // using (largest packet size / 4) + 1 # define USB_RX_FIFO_SIZE ((256U / 4U) + 1U) +#elif defined(STM32G0) +# define USB_INTERFACE USB_DRD_FS +# define USB_INTERRUPT USB_UCPD1_2_IRQn #endif uint8_t USBD_GS_CAN_Init(USBD_GS_CAN_HandleTypeDef *hcan, USBD_HandleTypeDef *pdev); diff --git a/libs/STM32_HAL/CMakeLists.txt b/libs/STM32_HAL/CMakeLists.txt index d70293fe..aa1fed47 100644 --- a/libs/STM32_HAL/CMakeLists.txt +++ b/libs/STM32_HAL/CMakeLists.txt @@ -193,7 +193,7 @@ add_library(STM32_HAL_STM32F407xE STATIC ${STM32F4_SOURCES}) target_compile_options(STM32_HAL_STM32F407xE PRIVATE ${CPUFLAGS_F4} -Wno-unused-parameter) target_compile_definitions(STM32_HAL_STM32F407xE PUBLIC STM32F407xx HAL_TARGET_PREFIX=stm32f4xx) -add_library(STM32_HAL_STM32G0B1xK STATIC ${STM32G0_SOURCES}) - target_include_directories(STM32_HAL_STM32G0B1xK PUBLIC ${INCLUDE_DIRS} include/stm32g0xx) - target_compile_options(STM32_HAL_STM32G0B1xK PRIVATE ${CPUFLAGS_G0} -Wno-unused-parameter) - target_compile_definitions(STM32_HAL_STM32G0B1xK PUBLIC STM32G0B1xx HAL_TARGET_PREFIX=stm32g0xx) +add_library(STM32_HAL_STM32G0B1xx STATIC ${STM32G0_SOURCES}) + target_include_directories(STM32_HAL_STM32G0B1xx PUBLIC ${INCLUDE_DIRS} include/stm32g0xx) + target_compile_options(STM32_HAL_STM32G0B1xx PRIVATE ${CPUFLAGS_G0} -Wno-unused-parameter) + target_compile_definitions(STM32_HAL_STM32G0B1xx PUBLIC STM32G0B1xx HAL_TARGET_PREFIX=stm32g0xx) diff --git a/libs/STM32_USB_Device_Library/CMakeLists.txt b/libs/STM32_USB_Device_Library/CMakeLists.txt index 30534caa..bdd6239f 100644 --- a/libs/STM32_USB_Device_Library/CMakeLists.txt +++ b/libs/STM32_USB_Device_Library/CMakeLists.txt @@ -30,7 +30,7 @@ add_library(STM32_USB_Device_Library_STM32F407xE STATIC ${SOURCES}) target_compile_options(STM32_USB_Device_Library_STM32F407xE PRIVATE ${CPUFLAGS_F4} -Wno-unused-parameter -DSTM32F4) target_link_libraries(STM32_USB_Device_Library_STM32F407xE PRIVATE STM32_HAL_STM32F407xE) -add_library(STM32_USB_Device_Library_STM32G0B1xK STATIC ${SOURCES}) - target_include_directories(STM32_USB_Device_Library_STM32G0B1xK PUBLIC ${INCLUDE_DIRS}) - target_compile_options(STM32_USB_Device_Library_STM32G0B1xK PRIVATE ${CPUFLAGS_G0} -Wno-unused-parameter -DSTM32G0) - target_link_libraries(STM32_USB_Device_Library_STM32G0B1xK PRIVATE STM32_HAL_STM32G0B1xK) +add_library(STM32_USB_Device_Library_STM32G0B1xx STATIC ${SOURCES}) + target_include_directories(STM32_USB_Device_Library_STM32G0B1xx PUBLIC ${INCLUDE_DIRS}) + target_compile_options(STM32_USB_Device_Library_STM32G0B1xx PRIVATE ${CPUFLAGS_G0} -Wno-unused-parameter -DSTM32G0) + target_link_libraries(STM32_USB_Device_Library_STM32G0B1xx PRIVATE STM32_HAL_STM32G0B1xx) diff --git a/src/boards/g0b1-2C2L_USB.c b/src/boards/g0b1-2C2L_USB.c new file mode 100644 index 00000000..dfe71946 --- /dev/null +++ b/src/boards/g0b1-2C2L_USB.c @@ -0,0 +1,174 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2023 Pengutronix, + * Marc Kleine-Budde + * (c) 2024 intive GmbH, + * Hubert Denkmair + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#include "board.h" +#include "config.h" +#include "device.h" +#include "gpio.h" +#include "usbd_gs_can.h" + +/* + LED_RX PB14 + LEX_TX PB13 + UART_TX PB6 + UART_RX PB7 + USB_P PA12 + USB_N PA11 + CAN1_RX PD0 + CAN1_TX PD1 + CAN1_S PD2 + CAN2_RX PB0 + CAN2_TX PB1 + CAN2_S PB9 +*/ + +#define LEDRX_GPIO_Port GPIOB +#define LEDRX_Pin GPIO_PIN_14 +#define LEDRX_Mode GPIO_MODE_OUTPUT_PP +#define LEDRX_Active_High 1 + +#define LEDTX_GPIO_Port GPIOB +#define LEDTX_Pin GPIO_PIN_13 +#define LEDTX_Mode GPIO_MODE_OUTPUT_PP +#define LEDTX_Active_High 1 + +static void intive2c2lusb_setup(USBD_GS_CAN_HandleTypeDef *hcan) +{ + GPIO_InitTypeDef GPIO_InitStruct; + + UNUSED(hcan); + + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOD_CLK_ENABLE(); + + /* LEDs */ + HAL_GPIO_WritePin(LEDRX_GPIO_Port, LEDRX_Pin, GPIO_INIT_STATE(LEDRX_Active_High)); + GPIO_InitStruct.Pin = LEDRX_Pin; + GPIO_InitStruct.Mode = LEDRX_Mode; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(LEDRX_GPIO_Port, &GPIO_InitStruct); + + HAL_GPIO_WritePin(LEDTX_GPIO_Port, LEDTX_Pin, GPIO_INIT_STATE(LEDTX_Active_High)); + GPIO_InitStruct.Pin = LEDTX_Pin; + GPIO_InitStruct.Mode = LEDTX_Mode; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(LEDTX_GPIO_Port, &GPIO_InitStruct); + + /* Setup transceiver silent pin */ + HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET); + GPIO_InitStruct.Pin = GPIO_PIN_2; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); + + HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, GPIO_PIN_RESET); + GPIO_InitStruct.Pin = GPIO_PIN_9; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + /* FDCAN */ + + RCC_PeriphCLKInitTypeDef PeriphClkInit = { + .PeriphClockSelection = RCC_PERIPHCLK_FDCAN, + .FdcanClockSelection = RCC_FDCANCLKSOURCE_PLL, + }; + + HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit); + __HAL_RCC_FDCAN_CLK_ENABLE(); + + /* FDCAN1_RX, FDCAN1_TX */ + GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Alternate = GPIO_AF3_FDCAN1; + HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); + + /* FDCAN2_RX, FDCAN2_TX */ + GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Alternate = GPIO_AF3_FDCAN2; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); +} + +static void intive2c2lusb_phy_power_set(can_data_t *channel, bool enable) +{ + UNUSED(channel); + UNUSED(enable); +} + +static void intive2c2lusb_termination_set(can_data_t *channel, enum gs_can_termination_state enable) +{ + UNUSED(channel); + UNUSED(enable); +} + +const struct BoardConfig config = { + .setup = intive2c2lusb_setup, + .phy_power_set = intive2c2lusb_phy_power_set, + .termination_set = intive2c2lusb_termination_set, + .channels[0] = { + .interface = FDCAN1, + .leds = { + [LED_RX] = { + .port = LEDRX_GPIO_Port, + .pin = LEDRX_Pin, + .active_high = LEDRX_Active_High, + }, + [LED_TX] = { + .port = LEDTX_GPIO_Port, + .pin = LEDTX_Pin, + .active_high = LEDTX_Active_High, + }, + }, + }, + .channels[1] = { + .interface = FDCAN2, + .leds = { + [LED_RX] = { + .port = LEDRX_GPIO_Port, + .pin = LEDRX_Pin, + .active_high = LEDRX_Active_High, + }, + [LED_TX] = { + .port = LEDTX_GPIO_Port, + .pin = LEDTX_Pin, + .active_high = LEDTX_Active_High, + }, + }, + }, +}; diff --git a/src/boards/g0b1-CONVERTDEVICE_xCANFD.c b/src/boards/g0b1-CONVERTDEVICE_xCANFD.c new file mode 100644 index 00000000..2ba0e467 --- /dev/null +++ b/src/boards/g0b1-CONVERTDEVICE_xCANFD.c @@ -0,0 +1,124 @@ +/* + +The MIT License (MIT) + +Copyright (c) 2023 Pengutronix, + Marc Kleine-Budde + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +#include "board.h" +#include "config.h" +#include "device.h" +#include "gpio.h" +#include "led.h" +#include "usbd_gs_can.h" + +#define LEDRX_GPIO_Port GPIOA +#define LEDRX_Pin GPIO_PIN_0 +#define LEDRX_Mode GPIO_MODE_OUTPUT_PP +#define LEDRX_Active_High 0 + +#define LEDTX_GPIO_Port GPIOA +#define LEDTX_Pin GPIO_PIN_1 +#define LEDTX_Mode GPIO_MODE_OUTPUT_PP +#define LEDTX_Active_High 0 + +static void convertdevice_xcanfd_setup(USBD_GS_CAN_HandleTypeDef *hcan) +{ + GPIO_InitTypeDef GPIO_InitStruct; + + UNUSED(hcan); + + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); + + /* LEDs */ + + HAL_GPIO_WritePin(LEDRX_GPIO_Port, LEDRX_Pin, GPIO_INIT_STATE(LEDRX_Active_High)); + GPIO_InitStruct.Pin = LEDRX_Pin; + GPIO_InitStruct.Mode = LEDRX_Mode; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(LEDRX_GPIO_Port, &GPIO_InitStruct); + + HAL_GPIO_WritePin(LEDTX_GPIO_Port, LEDTX_Pin, GPIO_INIT_STATE(LEDTX_Active_High)); + GPIO_InitStruct.Pin = LEDTX_Pin; + GPIO_InitStruct.Mode = LEDTX_Mode; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(LEDTX_GPIO_Port, &GPIO_InitStruct); + + /* FDCAN */ + + RCC_PeriphCLKInitTypeDef PeriphClkInit = { + .PeriphClockSelection = RCC_PERIPHCLK_FDCAN, + .FdcanClockSelection = RCC_FDCANCLKSOURCE_PLL, + }; + + HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit); + __HAL_RCC_FDCAN_CLK_ENABLE(); + + /* FDCAN1_RX, FDCAN1_TX */ + GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_8; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Alternate = GPIO_AF3_FDCAN1; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); +} + +static void +convertdevice_xcanfd_phy_power_set(can_data_t *channel, bool enable) +{ + UNUSED(channel); + UNUSED(enable); +} + +static void +convertdevice_xcanfd_termination_set(can_data_t *channel, + enum gs_can_termination_state enable) +{ + UNUSED(channel); + UNUSED(enable); +} + +const struct BoardConfig config = { + .setup = convertdevice_xcanfd_setup, + .phy_power_set = convertdevice_xcanfd_phy_power_set, + .termination_set = convertdevice_xcanfd_termination_set, + .channels[0] = { + .interface = FDCAN1, + .leds = { + [LED_RX] = { + .port = LEDRX_GPIO_Port, + .pin = LEDRX_Pin, + .active_high = LEDRX_Active_High, + }, + [LED_TX] = { + .port = LEDTX_GPIO_Port, + .pin = LEDTX_Pin, + .active_high = LEDTX_Active_High, + }, + }, + }, +}; diff --git a/src/boards/g0b1-budgetcan.c b/src/boards/g0b1-budgetcan.c new file mode 100644 index 00000000..72fe0f29 --- /dev/null +++ b/src/boards/g0b1-budgetcan.c @@ -0,0 +1,189 @@ +/* + +The MIT License (MIT) + +Copyright (c) 2023 Pengutronix, + Marc Kleine-Budde + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +#include "board.h" +#include "config.h" +#include "device.h" +#include "gpio.h" +#include "led.h" +#include "usbd_gs_can.h" + +#define LEDRX_GPIO_Port GPIOB +#define LEDRX_Pin GPIO_PIN_4 +#define LEDRX_Mode GPIO_MODE_OUTPUT_PP +#define LEDRX_Active_High 1 + +#define LEDTX_GPIO_Port GPIOB +#define LEDTX_Pin GPIO_PIN_3 +#define LEDTX_Mode GPIO_MODE_OUTPUT_PP +#define LEDTX_Active_High 1 + +static void nucleo_g0b1re_setup(USBD_GS_CAN_HandleTypeDef *hcan) +{ + GPIO_InitTypeDef GPIO_InitStruct; + + UNUSED(hcan); + + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); + + /* LEDs */ + + HAL_GPIO_WritePin(LEDRX_GPIO_Port, LEDRX_Pin, GPIO_INIT_STATE(LEDRX_Active_High)); + GPIO_InitStruct.Pin = LEDRX_Pin; + GPIO_InitStruct.Mode = LEDRX_Mode; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(LEDRX_GPIO_Port, &GPIO_InitStruct); + + HAL_GPIO_WritePin(LEDTX_GPIO_Port, LEDTX_Pin, GPIO_INIT_STATE(LEDTX_Active_High)); + GPIO_InitStruct.Pin = LEDTX_Pin; + GPIO_InitStruct.Mode = LEDTX_Mode; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(LEDTX_GPIO_Port, &GPIO_InitStruct); + + /* FDCAN */ + + RCC_PeriphCLKInitTypeDef PeriphClkInit = { + .PeriphClockSelection = RCC_PERIPHCLK_FDCAN, + .FdcanClockSelection = RCC_FDCANCLKSOURCE_PLL, + }; + + HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit); + __HAL_RCC_FDCAN_CLK_ENABLE(); + + /* FDCAN1_RX, FDCAN1_TX */ + GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_8; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Alternate = GPIO_AF3_FDCAN1; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + /* FDCAN1_SLEEP_EN */ + GPIO_InitStruct.Pin = GPIO_PIN_0; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Alternate = 0; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* FDCAN1_TERM_EN */ + GPIO_InitStruct.Pin = GPIO_PIN_1; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Alternate = 0; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* FDCAN2 */ + GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Alternate = GPIO_AF3_FDCAN1; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + /* FDCAN2_SLEEP_EN */ + GPIO_InitStruct.Pin = GPIO_PIN_4; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Alternate = 0; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* FDCAN2_TERM_EN */ + GPIO_InitStruct.Pin = GPIO_PIN_5; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Alternate = 0; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); +} + +static void +nucleo_g0b1re_phy_power_set(can_data_t *channel, bool enable) +{ + const uint8_t nr = channel->nr; + + if (nr == 0) { + HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, enable ? GPIO_PIN_RESET : GPIO_PIN_SET); + } else { + HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, enable ? GPIO_PIN_RESET : GPIO_PIN_SET); + } +} + +static void +nucleo_g0b1re_termination_set(can_data_t *channel, + enum gs_can_termination_state enable) +{ + const uint8_t nr = channel->nr; + + if (nr == 0) { + HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, enable ? GPIO_PIN_RESET : GPIO_PIN_SET); + } else { + HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, enable ? GPIO_PIN_RESET : GPIO_PIN_SET); + } +} + +const struct BoardConfig config = { + .setup = nucleo_g0b1re_setup, + .phy_power_set = nucleo_g0b1re_phy_power_set, + .termination_set = nucleo_g0b1re_termination_set, + .channels[0] = { + .interface = FDCAN1, + .leds = { + [LED_RX] = { + .port = LEDRX_GPIO_Port, + .pin = LEDRX_Pin, + .active_high = LEDRX_Active_High, + }, + [LED_TX] = { + .port = LEDTX_GPIO_Port, + .pin = LEDTX_Pin, + .active_high = LEDTX_Active_High, + }, + }, + }, + .channels[1] = { + .interface = FDCAN2, + .leds = { + [LED_RX] = { + .port = LEDRX_GPIO_Port, + .pin = LEDRX_Pin, + .active_high = LEDRX_Active_High, + }, + [LED_TX] = { + .port = LEDTX_GPIO_Port, + .pin = LEDTX_Pin, + .active_high = LEDTX_Active_High, + }, + }, + }, +}; diff --git a/src/boards/g0b1-candleLightFD.c b/src/boards/g0b1-candleLightFD.c new file mode 100644 index 00000000..48f622bf --- /dev/null +++ b/src/boards/g0b1-candleLightFD.c @@ -0,0 +1,181 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2023 Pengutronix, + * Marc Kleine-Budde + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#include "board.h" +#include "config.h" +#include "device.h" +#include "gpio.h" +#include "usbd_gs_can.h" + +/* + * LED_RX PA3 + * LEX_TX PA4 + * UART_TX PA9 + * UART_RX PA10 + * USB_P PA12 + * USB_N PA11 + * CAN1_RX PD0 + * CAN1_TX PD1 + * CAN1_S PA15 + * CAN2_RX PB0 + * CAN2_TX PB1 + * CAN2_S PB2 + */ + +#define LEDRX_GPIO_Port GPIOA +#define LEDRX_Pin GPIO_PIN_3 +#define LEDRX_Mode GPIO_MODE_OUTPUT_PP +#define LEDRX_Active_High 1 + +#define LEDTX_GPIO_Port GPIOA +#define LEDTX_Pin GPIO_PIN_4 +#define LEDTX_Mode GPIO_MODE_OUTPUT_PP +#define LEDTX_Active_High 1 + +static void candlelightfd_setup(USBD_GS_CAN_HandleTypeDef *hcan) +{ + GPIO_InitTypeDef GPIO_InitStruct; + + UNUSED(hcan); + + __HAL_RCC_GPIOA_CLK_ENABLE(); +#if NUM_CAN_CHANNEL == 2 + __HAL_RCC_GPIOB_CLK_ENABLE(); +#endif + __HAL_RCC_GPIOD_CLK_ENABLE(); + + /* LEDs */ + HAL_GPIO_WritePin(LEDRX_GPIO_Port, LEDRX_Pin, GPIO_INIT_STATE(LEDRX_Active_High)); + GPIO_InitStruct.Pin = LEDRX_Pin; + GPIO_InitStruct.Mode = LEDRX_Mode; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(LEDRX_GPIO_Port, &GPIO_InitStruct); + + HAL_GPIO_WritePin(LEDTX_GPIO_Port, LEDTX_Pin, GPIO_INIT_STATE(LEDTX_Active_High)); + GPIO_InitStruct.Pin = LEDTX_Pin; + GPIO_InitStruct.Mode = LEDTX_Mode; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(LEDTX_GPIO_Port, &GPIO_InitStruct); + + /* Setup transceiver silent pin */ + HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET); + GPIO_InitStruct.Pin = GPIO_PIN_15; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + +#if NUM_CAN_CHANNEL == 2 + HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET); + GPIO_InitStruct.Pin = GPIO_PIN_2; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); +#endif + + /* FDCAN */ + + RCC_PeriphCLKInitTypeDef PeriphClkInit = { + .PeriphClockSelection = RCC_PERIPHCLK_FDCAN, + .FdcanClockSelection = RCC_FDCANCLKSOURCE_PLL, + }; + + HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit); + __HAL_RCC_FDCAN_CLK_ENABLE(); + + /* FDCAN1_RX, FDCAN1_TX */ + GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Alternate = GPIO_AF3_FDCAN1; + HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); + +#if NUM_CAN_CHANNEL == 2 + /* FDCAN2_RX, FDCAN2_TX */ + GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Alternate = GPIO_AF3_FDCAN2; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); +#endif +} + +static void candlelightfd_phy_power_set(can_data_t *channel, bool enable) +{ + UNUSED(channel); + UNUSED(enable); +} + +static void candlelightfd_termination_set(can_data_t *channel, enum gs_can_termination_state enable) +{ + UNUSED(channel); + UNUSED(enable); +} + +const struct BoardConfig config = { + .setup = candlelightfd_setup, + .phy_power_set = candlelightfd_phy_power_set, + .termination_set = candlelightfd_termination_set, + .channels[0] = { + .interface = FDCAN1, + .leds = { + [LED_RX] = { + .port = LEDRX_GPIO_Port, + .pin = LEDRX_Pin, + .active_high = LEDRX_Active_High, + }, + [LED_TX] = { + .port = LEDTX_GPIO_Port, + .pin = LEDTX_Pin, + .active_high = LEDTX_Active_High, + }, + }, + }, +#if NUM_CAN_CHANNEL == 2 + .channels[1] = { + .interface = FDCAN2, + .leds = { + [LED_RX] = { + .port = LEDRX_GPIO_Port, + .pin = LEDRX_Pin, + .active_high = LEDRX_Active_High, + }, + [LED_TX] = { + .port = LEDTX_GPIO_Port, + .pin = LEDTX_Pin, + .active_high = LEDTX_Active_High, + }, + }, + }, +#endif +}; diff --git a/src/boards/g0b1-nucleo_g0b1re.c b/src/boards/g0b1-nucleo_g0b1re.c new file mode 100644 index 00000000..b076d5b3 --- /dev/null +++ b/src/boards/g0b1-nucleo_g0b1re.c @@ -0,0 +1,141 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2023 Pengutronix, + * Marc Kleine-Budde + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#include "board.h" +#include "config.h" +#include "device.h" +#include "gpio.h" +#include "usbd_gs_can.h" + +#define LEDRX_GPIO_Port GPIOA +#define LEDRX_Pin GPIO_PIN_5 +#define LEDRX_Mode GPIO_MODE_OUTPUT_PP +#define LEDRX_Active_High 1 + +#define LEDTX_GPIO_Port GPIOA +#define LEDTX_Pin GPIO_PIN_5 +#define LEDTX_Mode GPIO_MODE_OUTPUT_PP +#define LEDTX_Active_High 1 + +static void nucleo_g0b1re_setup(USBD_GS_CAN_HandleTypeDef *hcan) +{ + GPIO_InitTypeDef GPIO_InitStruct; + + UNUSED(hcan); + + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOD_CLK_ENABLE(); + + HAL_GPIO_WritePin(LEDRX_GPIO_Port, LEDRX_Pin, GPIO_INIT_STATE(LEDRX_Active_High)); + GPIO_InitStruct.Pin = LEDRX_Pin; + GPIO_InitStruct.Mode = LEDRX_Mode; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(LEDRX_GPIO_Port, &GPIO_InitStruct); + + /* FDCAN */ + + RCC_PeriphCLKInitTypeDef PeriphClkInit = { + .PeriphClockSelection = RCC_PERIPHCLK_FDCAN, + .FdcanClockSelection = RCC_FDCANCLKSOURCE_PLL, + }; + + HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit); + __HAL_RCC_FDCAN_CLK_ENABLE(); + + /* FDCAN1_RX, FDCAN1_TX */ + GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Alternate = GPIO_AF3_FDCAN1; + HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); + + /* FDCAN2_RX, FDCAN2_TX */ +#if NUM_CAN_CHANNEL == 2 + GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Alternate = GPIO_AF3_FDCAN2; + HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); +#endif +} + +static void nucleo_g0b1re_phy_power_set(can_data_t *channel, bool enable) +{ + UNUSED(channel); + UNUSED(enable); +} + +static void +nucleo_g0b1re_termination_set(can_data_t *channel, + enum gs_can_termination_state enable) +{ + UNUSED(channel); + UNUSED(enable); +} + +const struct BoardConfig config = { + .setup = nucleo_g0b1re_setup, + .phy_power_set = nucleo_g0b1re_phy_power_set, + .termination_set = nucleo_g0b1re_termination_set, + .channels[0] = { + .interface = FDCAN1, + .leds = { + [LED_RX] = { + .port = LEDRX_GPIO_Port, + .pin = LEDRX_Pin, + .active_high = LEDRX_Active_High, + }, + [LED_TX] = { + .port = LEDTX_GPIO_Port, + .pin = LEDTX_Pin, + .active_high = LEDTX_Active_High, + }, + }, + }, +#if NUM_CAN_CHANNEL == 2 + .channels[1] = { + .interface = FDCAN2, + .leds = { + [LED_RX] = { + .port = LEDRX_GPIO_Port, + .pin = LEDRX_Pin, + .active_high = LEDRX_Active_High, + }, + [LED_TX] = { + .port = LEDTX_GPIO_Port, + .pin = LEDTX_Pin, + .active_high = LEDTX_Active_High, + }, + }, + }, +#endif +}; diff --git a/src/boards/legacy.c b/src/boards/legacy.c new file mode 100644 index 00000000..ad54a177 --- /dev/null +++ b/src/boards/legacy.c @@ -0,0 +1,203 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2023 Pengutronix, + * Jonas Martin + * Copyright (c) 2016 Hubert Denkmair + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#include "board.h" +#include "config.h" +#include "device.h" +#include "gpio.h" +#include "usbd_gs_can.h" + +#ifdef TERM_Pin + +static void legacy_gpio_init_termination(void) +{ + HAL_GPIO_WritePin(TERM_GPIO_Port, TERM_Pin, GPIO_INIT_STATE(TERM_Active_High)); + + GPIO_InitTypeDef GPIO_InitStruct = { + .Pin = TERM_Pin, + .Mode = TERM_Mode, + .Pull = GPIO_NOPULL, + .Speed = GPIO_SPEED_FREQ_LOW, + .Alternate = 0 + }; + HAL_GPIO_Init(TERM_GPIO_Port, &GPIO_InitStruct); +} + +static void legacy_termination_set(can_data_t *channel, + enum gs_can_termination_state state) +{ + UNUSED(channel); + +#if (TERM_Active_High == 1) + #define TERM_ON GPIO_PIN_SET + #define TERM_OFF GPIO_PIN_RESET +#else + #define TERM_ON GPIO_PIN_RESET + #define TERM_OFF GPIO_PIN_SET +#endif + + HAL_GPIO_WritePin(TERM_GPIO_Port, TERM_Pin, (state ? TERM_ON : TERM_OFF)); +} + +#else + +static inline void legacy_gpio_init_termination(void) +{ +} + +static void legacy_termination_set(can_data_t *channel, + enum gs_can_termination_state state) +{ + UNUSED(channel); + UNUSED(state); +} + +#endif + +void legacy_setup(USBD_GS_CAN_HandleTypeDef *hcan) { + GPIO_InitTypeDef GPIO_InitStruct; + + UNUSED(hcan); + + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); +#if defined(STM32F4) + __HAL_RCC_GPIOD_CLK_ENABLE(); +#endif + +#ifdef CAN_S_Pin + HAL_GPIO_WritePin(CAN_S_GPIO_Port, CAN_S_Pin, GPIO_PIN_SET); + GPIO_InitStruct.Pin = CAN_S_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(CAN_S_GPIO_Port, &GPIO_InitStruct); +#endif + +#ifdef LEDRX_Pin + HAL_GPIO_WritePin(LEDRX_GPIO_Port, LEDRX_Pin, GPIO_INIT_STATE(LEDRX_Active_High)); + GPIO_InitStruct.Pin = LEDRX_Pin; + GPIO_InitStruct.Mode = LEDRX_Mode; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(LEDRX_GPIO_Port, &GPIO_InitStruct); +#endif + +#ifdef LEDTX_Pin + HAL_GPIO_WritePin(LEDTX_GPIO_Port, LEDTX_Pin, GPIO_INIT_STATE(LEDTX_Active_High)); + GPIO_InitStruct.Pin = LEDTX_Pin; + GPIO_InitStruct.Mode = LEDTX_Mode; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(LEDTX_GPIO_Port, &GPIO_InitStruct); +#endif + +#ifdef nCANSTBY_Pin + HAL_GPIO_WritePin(nCANSTBY_Port, nCANSTBY_Pin, GPIO_INIT_STATE(nCANSTBY_Active_High)); + GPIO_InitStruct.Pin = nCANSTBY_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(nCANSTBY_Port, &GPIO_InitStruct); //xceiver standby. +#endif + +#ifdef DCDCEN_Pin + HAL_GPIO_WritePin(DCDCEN_Port, DCDCEN_Pin, GPIO_PIN_SET); + GPIO_InitStruct.Pin = DCDCEN_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(DCDCEN_Port, &GPIO_InitStruct); //start DCDC (TODO : wait until enumerated) +#endif + +#ifdef nSI86EN_Pin + HAL_GPIO_WritePin(nSI86EN_Port, nSI86EN_Pin, GPIO_PIN_RESET); + GPIO_InitStruct.Pin = nSI86EN_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(nSI86EN_Port, &GPIO_InitStruct); //enable si86 +#endif + +#if defined(BOARD_STM32F4_DevBoard) + // initialize USB pins + GPIO_InitStruct.Pin = USB_Pin_DM | USB_Pin_DP; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS; + HAL_GPIO_Init(USB_GPIO_Port, &GPIO_InitStruct); +#endif + + legacy_gpio_init_termination(); +} + +static void legacy_phy_power_set(can_data_t *channel, bool enable) { + UNUSED(channel); + + if (enable) { +#ifdef CAN_S_GPIO_Port + HAL_GPIO_WritePin(CAN_S_GPIO_Port, CAN_S_Pin, GPIO_PIN_RESET); +#endif +#ifdef nCANSTBY_Pin + HAL_GPIO_WritePin(nCANSTBY_Port, nCANSTBY_Pin, + !GPIO_INIT_STATE(nCANSTBY_Active_High)); +#endif + } else { +#ifdef nCANSTBY_Pin + HAL_GPIO_WritePin(nCANSTBY_Port, nCANSTBY_Pin, + GPIO_INIT_STATE(nCANSTBY_Active_High)); +#endif +#ifdef CAN_S_GPIO_Port + HAL_GPIO_WritePin(CAN_S_GPIO_Port, CAN_S_Pin, GPIO_PIN_SET); +#endif + } +} + +const struct BoardConfig config = { + .setup = legacy_setup, + .phy_power_set = legacy_phy_power_set, + .termination_set = legacy_termination_set, + .channels[0] = { + .interface = CAN_INTERFACE, + .leds = { + [LED_RX] = { + .port = LEDRX_GPIO_Port, + .pin = LEDRX_Pin, + .active_high = LEDRX_Active_High, + }, + [LED_TX] = { + .port = LEDTX_GPIO_Port, + .pin = LEDTX_Pin, + .active_high = LEDTX_Active_High, + }, + }, + }, +}; diff --git a/src/can/bxcan.c b/src/can/bxcan.c index f7feb101..ee313b36 100644 --- a/src/can/bxcan.c +++ b/src/can/bxcan.c @@ -24,6 +24,7 @@ */ +#include "board.h" #include "can.h" #include "config.h" #include "device.h" @@ -45,14 +46,16 @@ const struct gs_device_bt_const CAN_btconst = { #endif , .fclk_can = CAN_CLOCK_SPEED, - .tseg1_min = 1, - .tseg1_max = 16, - .tseg2_min = 1, - .tseg2_max = 8, - .sjw_max = 4, - .brp_min = 1, - .brp_max = 1024, - .brp_inc = 1, + .btc = { + .tseg1_min = 1, + .tseg1_max = 16, + .tseg2_min = 1, + .tseg2_max = 8, + .sjw_max = 4, + .brp_min = 1, + .brp_max = 1024, + .brp_inc = 1, + }, }; // The STM32F0 only has one CAN interface, define it as CAN1 as @@ -84,23 +87,14 @@ void can_init(can_data_t *channel, CAN_TypeDef *instance) device_can_init(channel, instance); } -bool can_set_bittiming(can_data_t *channel, const struct gs_device_bittiming *timing) +void can_set_bittiming(can_data_t *channel, const struct gs_device_bittiming *timing) { const uint8_t tseg1 = timing->prop_seg + timing->phase_seg1; - if ( (timing->brp>0) && (timing->brp<=1024) - && (tseg1>0) && (tseg1<=16) - && (timing->phase_seg2>0) && (timing->phase_seg2<=8) - && (timing->sjw>0) && (timing->sjw<=4) - ) { - channel->brp = timing->brp & 0x3FF; - channel->phase_seg1 = tseg1; - channel->phase_seg2 = timing->phase_seg2; - channel->sjw = timing->sjw; - return true; - } else { - return false; - } + channel->brp = timing->brp; + channel->phase_seg1 = tseg1; + channel->phase_seg2 = timing->phase_seg2; + channel->sjw = timing->sjw; } void can_enable(can_data_t *channel, uint32_t mode) @@ -157,17 +151,14 @@ void can_enable(can_data_t *channel, uint32_t mode) can->FA1R |= filter_bit; // enable filter can->FMR &= ~CAN_FMR_FINIT; -#ifdef nCANSTBY_Pin - HAL_GPIO_WritePin(nCANSTBY_Port, nCANSTBY_Pin, !GPIO_INIT_STATE(nCANSTBY_Active_High)); -#endif + config.phy_power_set(channel, true); } void can_disable(can_data_t *channel) { CAN_TypeDef *can = channel->instance; -#ifdef nCANSTBY_Pin - HAL_GPIO_WritePin(nCANSTBY_Port, nCANSTBY_Pin, GPIO_INIT_STATE(nCANSTBY_Active_High)); -#endif + + config.phy_power_set(channel, false); can->MCR |= CAN_MCR_INRQ; // send can controller into initialization mode } diff --git a/src/can/m_can.c b/src/can/m_can.c new file mode 100644 index 00000000..94ded8aa --- /dev/null +++ b/src/can/m_can.c @@ -0,0 +1,414 @@ +/* + +The MIT License (MIT) + +Copyright (c) 2016 Hubert Denkmair + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +#include "board.h" +#include "can.h" +#include "hal_include.h" +#include "stm32g0b1xx.h" +#include "timer.h" + +// bit timing constraints +const struct gs_device_bt_const CAN_btconst = { + .feature = + GS_CAN_FEATURE_LISTEN_ONLY | + GS_CAN_FEATURE_LOOP_BACK | + GS_CAN_FEATURE_HW_TIMESTAMP | + GS_CAN_FEATURE_IDENTIFY | + GS_CAN_FEATURE_PAD_PKTS_TO_MAX_PKT_SIZE | + (IS_ENABLED(CONFIG_CANFD) ? + GS_CAN_FEATURE_FD | GS_CAN_FEATURE_BT_CONST_EXT : 0) +#ifdef TERM_Pin + | GS_CAN_FEATURE_TERMINATION +#endif + , + .fclk_can = CAN_CLOCK_SPEED, + .btc = { + .tseg1_min = 1, + .tseg1_max = 256, + .tseg2_min = 1, + .tseg2_max = 128, + .sjw_max = 128, + .brp_min = 1, + .brp_max = 512, + .brp_inc = 1, + }, +}; + +const struct gs_device_bt_const_extended CAN_btconst_ext = { + .feature = + GS_CAN_FEATURE_LISTEN_ONLY | + GS_CAN_FEATURE_LOOP_BACK | + GS_CAN_FEATURE_HW_TIMESTAMP | + GS_CAN_FEATURE_IDENTIFY | + GS_CAN_FEATURE_PAD_PKTS_TO_MAX_PKT_SIZE | + (IS_ENABLED(CONFIG_CANFD) ? + GS_CAN_FEATURE_FD | GS_CAN_FEATURE_BT_CONST_EXT : 0) +#ifdef TERM_Pin + | GS_CAN_FEATURE_TERMINATION +#endif + , + .fclk_can = CAN_CLOCK_SPEED, + .btc = { + .tseg1_min = 1, + .tseg1_max = 256, + .tseg2_min = 1, + .tseg2_max = 128, + .sjw_max = 128, + .brp_min = 1, + .brp_max = 512, + .brp_inc = 1, + }, + .dbtc = { + .tseg1_min = 1, + .tseg1_max = 32, + .tseg2_min = 1, + .tseg2_max = 16, + .sjw_max = 16, + .brp_min = 1, + .brp_max = 32, + .brp_inc = 1, + }, +}; + +void can_init(can_data_t *channel, FDCAN_GlobalTypeDef *instance) +{ + channel->channel.Instance = instance; + channel->channel.Init.ClockDivider = FDCAN_CLOCK_DIV1; + channel->channel.Init.FrameFormat = FDCAN_FRAME_FD_BRS; + channel->channel.Init.Mode = FDCAN_MODE_NORMAL; + channel->channel.Init.AutoRetransmission = ENABLE; + channel->channel.Init.TransmitPause = DISABLE; + channel->channel.Init.ProtocolException = ENABLE; + channel->channel.Init.NominalPrescaler = 8; + channel->channel.Init.NominalSyncJumpWidth = 1; + channel->channel.Init.NominalTimeSeg1 = 13; + channel->channel.Init.NominalTimeSeg2 = 2; + channel->channel.Init.DataPrescaler = 2; + channel->channel.Init.DataSyncJumpWidth = 4; + channel->channel.Init.DataTimeSeg1 = 15; + channel->channel.Init.DataTimeSeg2 = 4; + channel->channel.Init.StdFiltersNbr = 0; + channel->channel.Init.ExtFiltersNbr = 0; + channel->channel.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION; +} + +void can_set_bittiming(can_data_t *channel, const struct gs_device_bittiming *timing) +{ + const uint8_t tseg1 = timing->prop_seg + timing->phase_seg1; + + channel->channel.Init.NominalSyncJumpWidth = timing->sjw; + channel->channel.Init.NominalTimeSeg1 = tseg1; + channel->channel.Init.NominalTimeSeg2 = timing->phase_seg2; + channel->channel.Init.NominalPrescaler = timing->brp; +} + +void can_set_data_bittiming(can_data_t *channel, const struct gs_device_bittiming *timing) +{ + const uint8_t tseg1 = timing->prop_seg + timing->phase_seg1; + + channel->channel.Init.DataSyncJumpWidth = timing->sjw; + channel->channel.Init.DataTimeSeg1 = tseg1; + channel->channel.Init.DataTimeSeg2 = timing->phase_seg2; + channel->channel.Init.DataPrescaler = timing->brp; +} + +void can_enable(can_data_t *channel, uint32_t mode) +{ + if (mode & GS_CAN_MODE_ONE_SHOT) { + channel->channel.Init.AutoRetransmission = DISABLE; + } else { + channel->channel.Init.AutoRetransmission = ENABLE; + } + + if ((mode & (GS_CAN_MODE_LISTEN_ONLY | GS_CAN_MODE_LOOP_BACK)) == + (GS_CAN_MODE_LISTEN_ONLY | GS_CAN_MODE_LOOP_BACK)) { + channel->channel.Init.Mode = FDCAN_MODE_INTERNAL_LOOPBACK; + } else if (mode & GS_CAN_MODE_LISTEN_ONLY) { + channel->channel.Init.Mode = FDCAN_MODE_BUS_MONITORING; + } else if (mode & GS_CAN_MODE_LOOP_BACK) { + channel->channel.Init.Mode = FDCAN_MODE_EXTERNAL_LOOPBACK; + } else { + channel->channel.Init.Mode = FDCAN_MODE_NORMAL; + } + + if (mode & GS_CAN_MODE_FD) { + channel->channel.Init.FrameFormat = FDCAN_FRAME_FD_BRS; + } else { + channel->channel.Init.FrameFormat = FDCAN_FRAME_CLASSIC; + } + + HAL_FDCAN_Init(&channel->channel); + HAL_FDCAN_EnableISOMode(&channel->channel); + + /* Enable automatic transceiver delay compensation */ + HAL_FDCAN_ConfigTxDelayCompensation(&channel->channel, + channel->channel.Init.DataTimeSeg1 * channel->channel.Init.DataPrescaler, + 0U); + HAL_FDCAN_EnableTxDelayCompensation(&channel->channel); + + /* Configure reception filter to Rx FIFO 0 on both FDCAN instances */ + FDCAN_FilterTypeDef sFilterConfig = { + .IdType = FDCAN_STANDARD_ID, + .FilterIndex = 0, + .FilterType = FDCAN_FILTER_RANGE, + .FilterConfig = FDCAN_FILTER_DISABLE, + .FilterID1 = 0x000, + .FilterID2 = 0x7FF, + }; + + HAL_FDCAN_ConfigFilter(&channel->channel, &sFilterConfig); + + /* + * Configure global filter on both FDCAN instances: + * Filter all remote frames with STD and EXT ID + * Reject non matching frames with STD ID and EXT ID + */ + HAL_FDCAN_ConfigGlobalFilter(&channel->channel, + FDCAN_ACCEPT_IN_RX_FIFO0, FDCAN_ACCEPT_IN_RX_FIFO0, + FDCAN_FILTER_REMOTE, FDCAN_FILTER_REMOTE); + + config.phy_power_set(channel, true); + + // Start CAN using HAL + HAL_FDCAN_Start(&channel->channel); +} + +void can_disable(can_data_t *channel) +{ + HAL_FDCAN_Stop(&channel->channel); + + config.phy_power_set(channel, false); +} + +bool can_is_enabled(can_data_t *channel) +{ + return channel->channel.State == HAL_FDCAN_STATE_BUSY; +} + +bool can_receive(can_data_t *channel, struct gs_host_frame *rx_frame) +{ + FDCAN_RxHeaderTypeDef RxHeader; + uint32_t timestamp_us = timer_get(); + + if (HAL_FDCAN_GetRxMessage(&channel->channel, FDCAN_RX_FIFO0, &RxHeader, rx_frame->canfd->data) != HAL_OK) { + return false; + } + + rx_frame->channel = channel->nr; + rx_frame->flags = 0; + rx_frame->can_id = RxHeader.Identifier; + + if (RxHeader.IdType == FDCAN_EXTENDED_ID) { + rx_frame->can_id |= CAN_EFF_FLAG; + } + + if (RxHeader.RxFrameType == FDCAN_REMOTE_FRAME) { + rx_frame->can_id |= CAN_RTR_FLAG; + } + + rx_frame->can_dlc = (RxHeader.DataLength & 0x000F0000) >> 16; + + if (RxHeader.FDFormat == FDCAN_FD_CAN) { + rx_frame->canfd_ts->timestamp_us = timestamp_us; + + /* this is a CAN-FD frame */ + rx_frame->flags = GS_CAN_FLAG_FD; + if (RxHeader.BitRateSwitch == FDCAN_BRS_ON) { + rx_frame->flags |= GS_CAN_FLAG_BRS; + } + + if (RxHeader.ErrorStateIndicator == FDCAN_ESI_PASSIVE) { + rx_frame->flags |= GS_CAN_FLAG_ESI; + } + } else { + rx_frame->classic_can_ts->timestamp_us = timestamp_us; + } + + return true; +} + +bool can_is_rx_pending(can_data_t *channel) +{ + return (HAL_FDCAN_GetRxFifoFillLevel(&channel->channel, FDCAN_RX_FIFO0) >= 1); +} + +bool can_send(can_data_t *channel, struct gs_host_frame *frame) +{ + FDCAN_TxHeaderTypeDef TxHeader = { + .DataLength = frame->can_dlc << 16, + .TxEventFifoControl = FDCAN_NO_TX_EVENTS, + }; + + TxHeader.TxFrameType = + frame->can_id & CAN_RTR_FLAG ? FDCAN_REMOTE_FRAME : FDCAN_DATA_FRAME; + + if (frame->can_id & CAN_EFF_FLAG) { + TxHeader.IdType = FDCAN_EXTENDED_ID; + TxHeader.Identifier = frame->can_id & 0x1FFFFFFF; + } else { + TxHeader.IdType = FDCAN_STANDARD_ID; + TxHeader.Identifier = frame->can_id & 0x7FF; + } + + if (frame->flags & GS_CAN_FLAG_FD) { + TxHeader.FDFormat = FDCAN_FD_CAN; + if (frame->flags & GS_CAN_FLAG_BRS) { + TxHeader.BitRateSwitch = FDCAN_BRS_ON; + } else { + TxHeader.BitRateSwitch = FDCAN_BRS_OFF; + } + + if (frame->flags & GS_CAN_FLAG_ESI) { + TxHeader.ErrorStateIndicator = FDCAN_ESI_PASSIVE; + } else { + TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE; + } + } else { + TxHeader.FDFormat = FDCAN_CLASSIC_CAN; + TxHeader.BitRateSwitch = FDCAN_BRS_OFF; + } + + if (HAL_FDCAN_AddMessageToTxFifoQ(&channel->channel, &TxHeader, frame->canfd->data) != HAL_OK) { + return false; + } + + return true; +} + +uint32_t can_get_error_status(can_data_t *channel) +{ + uint32_t err = channel->channel.Instance->PSR; + + /* Write 7 to LEC so we know if it gets set to the same thing again */ + channel->channel.Instance->PSR = 7; + + return err; +} + +static bool status_is_active(uint32_t err) +{ + return !(err & (FDCAN_PSR_BO | FDCAN_PSR_EP)); +} + +bool can_parse_error_status(can_data_t *channel, struct gs_host_frame *frame, uint32_t err) +{ + uint32_t last_err = channel->reg_esr_old; + /* + * We build up the detailed error information at the same time as + * we decide whether there's anything worth sending. This variable + * tracks that final result. + */ + bool should_send = false; + + channel->reg_esr_old = err; + + frame->echo_id = 0xFFFFFFFF; + frame->can_id = CAN_ERR_FLAG; + frame->can_dlc = CAN_ERR_DLC; + frame->classic_can->data[0] = CAN_ERR_LOSTARB_UNSPEC; + frame->classic_can->data[1] = CAN_ERR_CRTL_UNSPEC; + frame->classic_can->data[2] = CAN_ERR_PROT_UNSPEC; + frame->classic_can->data[3] = CAN_ERR_PROT_LOC_UNSPEC; + frame->classic_can->data[4] = CAN_ERR_TRX_UNSPEC; + frame->classic_can->data[5] = 0; + frame->classic_can->data[6] = 0; + frame->classic_can->data[7] = 0; + + /* We transitioned from passive/bus-off to active, so report the edge. */ + if (!status_is_active(last_err) && status_is_active(err)) { + frame->can_id |= CAN_ERR_CRTL; + frame->classic_can->data[1] |= CAN_ERR_CRTL_ACTIVE; + should_send = true; + } + + if (err & FDCAN_PSR_BO) { + if (!(last_err & FDCAN_PSR_BO)) { + /* We transitioned to bus-off. */ + frame->can_id |= CAN_ERR_BUSOFF; + should_send = true; + } + } + + /* + * The Linux sja1000 driver puts these counters here. Seems like + * as good a place as any. + */ + // TX error count + frame->classic_can->data[6] = ((channel->channel.Instance->ECR & FDCAN_ECR_TEC) >> FDCAN_ECR_TEC_Pos); + // RX error count + frame->classic_can->data[7] = ((channel->channel.Instance->ECR & FDCAN_ECR_REC) >> FDCAN_ECR_REC_Pos); + + if (err & FDCAN_PSR_EP) { + if (!(last_err & FDCAN_PSR_EP)) { + frame->can_id |= CAN_ERR_CRTL; + frame->classic_can->data[1] |= CAN_ERR_CRTL_RX_PASSIVE | CAN_ERR_CRTL_TX_PASSIVE; + should_send = true; + } + } else if (err & FDCAN_PSR_EW) { + if (!(last_err & FDCAN_PSR_EW)) { + frame->can_id |= CAN_ERR_CRTL; + frame->classic_can->data[1] |= CAN_ERR_CRTL_RX_WARNING | CAN_ERR_CRTL_TX_WARNING; + should_send = true; + } + } + + uint8_t lec = err & FDCAN_PSR_LEC; + switch (lec) { + case 0x01: /* stuff error */ + frame->can_id |= CAN_ERR_PROT; + frame->classic_can->data[2] |= CAN_ERR_PROT_STUFF; + should_send = true; + break; + case 0x02: /* form error */ + frame->can_id |= CAN_ERR_PROT; + frame->classic_can->data[2] |= CAN_ERR_PROT_FORM; + should_send = true; + break; + case 0x03: /* ack error */ + frame->can_id |= CAN_ERR_ACK; + should_send = true; + break; + case 0x04: /* bit recessive error */ + frame->can_id |= CAN_ERR_PROT; + frame->classic_can->data[2] |= CAN_ERR_PROT_BIT1; + should_send = true; + break; + case 0x05: /* bit dominant error */ + frame->can_id |= CAN_ERR_PROT; + frame->classic_can->data[2] |= CAN_ERR_PROT_BIT0; + should_send = true; + break; + case 0x06: /* CRC error */ + frame->can_id |= CAN_ERR_PROT; + frame->classic_can->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ; + should_send = true; + break; + default: /* 0=no error, 7=no change */ + break; + } + + return should_send; +} diff --git a/src/can_common.c b/src/can_common.c index 8634097c..42d70b3e 100644 --- a/src/can_common.c +++ b/src/can_common.c @@ -29,6 +29,27 @@ THE SOFTWARE. #include "timer.h" #include "usbd_gs_can.h" +#ifndef CONFIG_CANFD +const struct gs_device_bt_const_extended CAN_btconst_ext; +#endif + +bool can_check_bittiming_ok(const struct can_bittiming_const *btc, + const struct gs_device_bittiming *timing) +{ + const uint32_t tseg1 = timing->prop_seg + timing->phase_seg1; + + if (tseg1 < btc->tseg1_min || + tseg1 > btc->tseg1_max || + timing->phase_seg2 < btc->tseg2_min || + timing->phase_seg2 > btc->tseg2_max || + timing->sjw > btc->sjw_max || + timing->brp < btc->brp_min || + timing->brp > btc->brp_max) + return false; + + return true; +} + void CAN_SendFrame(USBD_GS_CAN_HandleTypeDef *hcan, can_data_t *channel) { struct gs_host_frame_object *frame_object; diff --git a/src/device/device_g0.c b/src/device/device_g0.c index 12f6cf4e..b8d50de0 100644 --- a/src/device/device_g0.c +++ b/src/device/device_g0.c @@ -31,12 +31,6 @@ THE SOFTWARE. #include "device.h" #include "hal_include.h" -void device_can_init(can_data_t *channel, CAN_TypeDef *instance) { - // XXX TODO - while (1); - return; -} - void device_sysclock_config(void) { RCC_OscInitTypeDef RCC_OscInitStruct; RCC_ClkInitTypeDef RCC_ClkInitStruct; @@ -47,18 +41,26 @@ void device_sysclock_config(void) { /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ +#if defined(HSE_OSC_SPEED) + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE|RCC_OSCILLATORTYPE_HSI48; + RCC_OscInitStruct.HSEState = RCC_HSE_ON; + RCC_OscInitStruct.HSI48State = RCC_HSI48_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; + RCC_OscInitStruct.PLL.PLLN = 320000000 / HSE_OSC_SPEED; +#else RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_HSI48; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSI48State = RCC_HSI48_ON; RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; - RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; + RCC_OscInitStruct.PLL.PLLN = 20; +#endif + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV1; - RCC_OscInitStruct.PLL.PLLN = 8; + RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV8; + RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV5; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; - RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2; - RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2; HAL_RCC_OscConfig(&RCC_OscInitStruct); /** Initializes the CPU, AHB and APB buses clocks */ diff --git a/src/dfu.c b/src/dfu.c index 7fae19a7..438ab767 100644 --- a/src/dfu.c +++ b/src/dfu.c @@ -32,6 +32,7 @@ THE SOFTWARE. #define SYSMEM_STM32F042 0x1FFFC400 #define SYSMEM_STM32F072 0x1FFFC800 +#define SYSMEM_STM32G0B1 0x1FFF0000 static uint32_t dfu_reset_to_bootloader_magic; @@ -60,6 +61,9 @@ void __initialize_hardware_early(void) dfu_jump_to_bootloader(SYSMEM_STM32F072); break; + case 0x467: + dfu_jump_to_bootloader(SYSMEM_STM32G0B1); + break; } } diff --git a/src/gpio.c b/src/gpio.c index 2474b71f..f61f1506 100644 --- a/src/gpio.c +++ b/src/gpio.c @@ -24,140 +24,38 @@ THE SOFTWARE. */ +#include "board.h" +#include "config.h" #include "gpio.h" #include "hal_include.h" #ifdef TERM_Pin static int term_state = 0; -enum gs_can_termination_state get_term(unsigned int channel) +enum gs_can_termination_state get_term(can_data_t * channel) { - if (term_state & (1 << channel)) { + const uint8_t nr = channel->nr; + + if (term_state & (1 << nr)) { return GS_CAN_TERMINATION_STATE_ON; } else { return GS_CAN_TERMINATION_STATE_OFF; } } -enum gs_can_termination_state set_term(unsigned int channel, enum gs_can_termination_state state) +enum gs_can_termination_state set_term(can_data_t *channel, enum gs_can_termination_state state) { + const uint8_t nr = channel->nr; + if (state == GS_CAN_TERMINATION_STATE_ON) { - term_state |= 1 << channel; + term_state |= 1 << nr; } else { - term_state &= ~(1 << channel); + term_state &= ~(1 << nr); } -#if (TERM_Active_High == 1) - #define TERM_ON GPIO_PIN_SET - #define TERM_OFF GPIO_PIN_RESET -#else - #define TERM_ON GPIO_PIN_RESET - #define TERM_OFF GPIO_PIN_SET -#endif - - HAL_GPIO_WritePin(TERM_GPIO_Port, TERM_Pin, (state ? TERM_ON : TERM_OFF)); + config.termination_set(channel, state); return state; } -static inline void gpio_init_term(void) -{ - HAL_GPIO_WritePin(TERM_GPIO_Port, TERM_Pin, GPIO_INIT_STATE(TERM_Active_High)); - - GPIO_InitTypeDef GPIO_InitStruct = { - .Pin = TERM_Pin, - .Mode = TERM_Mode, - .Pull = GPIO_NOPULL, - .Speed = GPIO_SPEED_FREQ_LOW, - .Alternate = 0 - }; - HAL_GPIO_Init(TERM_GPIO_Port, &GPIO_InitStruct); -} - -#else - -static inline void gpio_init_term(void) -{ -} - -#endif - -// must run before can_init -void gpio_init(void) -{ - GPIO_InitTypeDef GPIO_InitStruct; - - __HAL_RCC_GPIOA_CLK_ENABLE(); - __HAL_RCC_GPIOB_CLK_ENABLE(); - __HAL_RCC_GPIOC_CLK_ENABLE(); -#if defined(STM32F4) - __HAL_RCC_GPIOD_CLK_ENABLE(); #endif - -#ifdef CAN_S_Pin - HAL_GPIO_WritePin(CAN_S_GPIO_Port, CAN_S_Pin, GPIO_PIN_SET); - GPIO_InitStruct.Pin = CAN_S_Pin; - GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; - HAL_GPIO_Init(CAN_S_GPIO_Port, &GPIO_InitStruct); -#endif - -#ifdef LEDRX_Pin - HAL_GPIO_WritePin(LEDRX_GPIO_Port, LEDRX_Pin, GPIO_INIT_STATE(LEDRX_Active_High)); - GPIO_InitStruct.Pin = LEDRX_Pin; - GPIO_InitStruct.Mode = LEDRX_Mode; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; - HAL_GPIO_Init(LEDRX_GPIO_Port, &GPIO_InitStruct); -#endif - -#ifdef LEDTX_Pin - HAL_GPIO_WritePin(LEDTX_GPIO_Port, LEDTX_Pin, GPIO_INIT_STATE(LEDTX_Active_High)); - GPIO_InitStruct.Pin = LEDTX_Pin; - GPIO_InitStruct.Mode = LEDTX_Mode; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; - HAL_GPIO_Init(LEDTX_GPIO_Port, &GPIO_InitStruct); -#endif - -#ifdef nCANSTBY_Pin - HAL_GPIO_WritePin(nCANSTBY_Port, nCANSTBY_Pin, GPIO_INIT_STATE(nCANSTBY_Active_High)); - GPIO_InitStruct.Pin = nCANSTBY_Pin; - GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; - HAL_GPIO_Init(nCANSTBY_Port, &GPIO_InitStruct); //xceiver standby. -#endif - -#ifdef DCDCEN_Pin - HAL_GPIO_WritePin(DCDCEN_Port, DCDCEN_Pin, GPIO_PIN_SET); - GPIO_InitStruct.Pin = DCDCEN_Pin; - GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; - HAL_GPIO_Init(DCDCEN_Port, &GPIO_InitStruct); //start DCDC (TODO : wait until enumerated) -#endif - -#ifdef nSI86EN_Pin - HAL_GPIO_WritePin(nSI86EN_Port, nSI86EN_Pin, GPIO_PIN_RESET); - GPIO_InitStruct.Pin = nSI86EN_Pin; - GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; - HAL_GPIO_Init(nSI86EN_Port, &GPIO_InitStruct); //enable si86 -#endif - - -#if defined(BOARD_STM32F4_DevBoard) - // initialize USB pins - GPIO_InitStruct.Pin = USB_Pin_DM | USB_Pin_DP; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; - GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS; - HAL_GPIO_Init(USB_GPIO_Port, &GPIO_InitStruct); -#endif - - gpio_init_term(); -} diff --git a/src/main.c b/src/main.c index 6abebf27..0ff37deb 100644 --- a/src/main.c +++ b/src/main.c @@ -28,6 +28,7 @@ THE SOFTWARE. #include #include +#include "board.h" #include "can.h" #include "can_common.h" #include "config.h" @@ -65,7 +66,7 @@ int main(void) HAL_Init(); SystemClock_Config(); - gpio_init(); + config.setup(&hGS_CAN); timer_init(); INIT_LIST_HEAD(&hGS_CAN.list_frame_pool); @@ -76,6 +77,8 @@ int main(void) } for (unsigned int i = 0; i < ARRAY_SIZE(hGS_CAN.channels); i++) { + const struct BoardChannelConfig *channel_config = &config.channels[i]; + const struct LEDConfig *led_config = channel_config->leds; can_data_t *channel = &hGS_CAN.channels[i]; channel->nr = i; @@ -83,24 +86,20 @@ int main(void) INIT_LIST_HEAD(&channel->list_from_host); led_init(&channel->leds, - LEDRX_GPIO_Port, LEDRX_Pin, LEDRX_Active_High, - LEDTX_GPIO_Port, LEDTX_Pin, LEDTX_Active_High); + led_config[LED_RX].port, led_config[LED_RX].pin, led_config[LED_RX].active_high, + led_config[LED_TX].port, led_config[LED_TX].pin, led_config[LED_TX].active_high); /* nice wake-up pattern */ for (uint8_t j = 0; j < 10; j++) { - HAL_GPIO_TogglePin(LEDRX_GPIO_Port, LEDRX_Pin); + HAL_GPIO_TogglePin(led_config[LED_RX].port, led_config[LED_RX].pin); HAL_Delay(50); - HAL_GPIO_TogglePin(LEDTX_GPIO_Port, LEDTX_Pin); + HAL_GPIO_TogglePin(led_config[LED_TX].port, led_config[LED_TX].pin); } led_set_mode(&channel->leds, LED_MODE_OFF); - can_init(channel, CAN_INTERFACE); + can_init(channel, config.channels[i].interface); can_disable(channel); - -#ifdef CAN_S_GPIO_Port - HAL_GPIO_WritePin(CAN_S_GPIO_Port, CAN_S_Pin, GPIO_PIN_RESET); -#endif } USBD_Init(&hUSB, (USBD_DescriptorsTypeDef*)&FS_Desc, DEVICE_FS); diff --git a/src/usbd_desc.c b/src/usbd_desc.c index d5df5bac..e76b4b2b 100644 --- a/src/usbd_desc.c +++ b/src/usbd_desc.c @@ -102,14 +102,14 @@ uint8_t *USBD_FS_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) uint8_t *USBD_FS_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) { UNUSED(speed); - USBD_GetString(USBD_PRODUCT_STRING_FS, USBD_DescBuf, length); + USBD_GetString((uint8_t *)USBD_PRODUCT_STRING_FS, USBD_DescBuf, length); return USBD_DescBuf; } uint8_t *USBD_FS_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) { UNUSED(speed); - USBD_GetString (USBD_MANUFACTURER_STRING, USBD_DescBuf, length); + USBD_GetString ((uint8_t *)USBD_MANUFACTURER_STRING, USBD_DescBuf, length); return USBD_DescBuf; } @@ -130,13 +130,13 @@ uint8_t *USBD_FS_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) uint8_t *USBD_FS_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) { UNUSED(speed); - USBD_GetString(USBD_CONFIGURATION_STRING_FS, USBD_DescBuf, length); + USBD_GetString((uint8_t *)USBD_CONFIGURATION_STRING_FS, USBD_DescBuf, length); return USBD_DescBuf; } uint8_t *USBD_FS_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) { UNUSED(speed); - USBD_GetString(USBD_INTERFACE_STRING_FS, USBD_DescBuf, length); + USBD_GetString((uint8_t *)USBD_INTERFACE_STRING_FS, USBD_DescBuf, length); return USBD_DescBuf; } diff --git a/src/usbd_gs_can.c b/src/usbd_gs_can.c index 0a79b67e..d59cdda8 100644 --- a/src/usbd_gs_can.c +++ b/src/usbd_gs_can.c @@ -28,6 +28,7 @@ THE SOFTWARE. #include #include "can.h" +#include "can_common.h" #include "compiler.h" #include "config.h" #include "gpio.h" @@ -300,7 +301,7 @@ static uint8_t USBD_GS_CAN_Config_Request(USBD_HandleTypeDef *pdev, USBD_SetupRe { USBD_GS_CAN_HandleTypeDef *hcan = (USBD_GS_CAN_HandleTypeDef*) pdev->pClassData; struct gs_device_termination_state term_state; - can_data_t *channel; + can_data_t *channel = NULL; const void *src = NULL; size_t len; @@ -322,6 +323,14 @@ static uint8_t USBD_GS_CAN_Config_Request(USBD_HandleTypeDef *pdev, USBD_SetupRe } } + if (!IS_ENABLED(CONFIG_CANFD)) { + switch (req->bRequest) { + case GS_USB_BREQ_DATA_BITTIMING: + case GS_USB_BREQ_BT_CONST_EXT: + goto out_fail; + } + } + switch (req->bRequest) { // Host -> Device case GS_USB_BREQ_HOST_FORMAT: @@ -348,8 +357,15 @@ static uint8_t USBD_GS_CAN_Config_Request(USBD_HandleTypeDef *pdev, USBD_SetupRe case GS_USB_BREQ_IDENTIFY: len = sizeof(struct gs_identify_mode); break; + case GS_USB_BREQ_DATA_BITTIMING: + len = sizeof(struct gs_device_bittiming); + break; + case GS_USB_BREQ_BT_CONST_EXT: + src = &CAN_btconst_ext; + len = sizeof(CAN_btconst_ext); + break; case GS_USB_BREQ_SET_TERMINATION: - if (get_term(req->wValue) == GS_CAN_TERMINATION_UNSUPPORTED) { + if (get_term(channel) == GS_CAN_TERMINATION_UNSUPPORTED) { goto out_fail; } @@ -358,7 +374,7 @@ static uint8_t USBD_GS_CAN_Config_Request(USBD_HandleTypeDef *pdev, USBD_SetupRe case GS_USB_BREQ_GET_TERMINATION: { enum gs_can_termination_state state; - state = get_term(req->wValue); + state = get_term(channel); if (state == GS_CAN_TERMINATION_UNSUPPORTED) { goto out_fail; } @@ -381,6 +397,7 @@ static uint8_t USBD_GS_CAN_Config_Request(USBD_HandleTypeDef *pdev, USBD_SetupRe case GS_USB_BREQ_BITTIMING: case GS_USB_BREQ_MODE: case GS_USB_BREQ_IDENTIFY: + case GS_USB_BREQ_DATA_BITTIMING: case GS_USB_BREQ_SET_TERMINATION: if (req->wLength > sizeof(hcan->ep0_buf)) { goto out_fail; @@ -394,6 +411,7 @@ static uint8_t USBD_GS_CAN_Config_Request(USBD_HandleTypeDef *pdev, USBD_SetupRe case GS_USB_BREQ_BT_CONST: case GS_USB_BREQ_DEVICE_CONFIG: case GS_USB_BREQ_TIMESTAMP: + case GS_USB_BREQ_BT_CONST_EXT: case GS_USB_BREQ_GET_TERMINATION: USBD_CtlSendData(pdev, (uint8_t *)src, len); break; @@ -490,6 +508,9 @@ static uint8_t USBD_GS_CAN_EP0_RxReady(USBD_HandleTypeDef *pdev) { case GS_USB_BREQ_BITTIMING: { const struct gs_device_bittiming *timing = (struct gs_device_bittiming *)hcan->ep0_buf; + if (!can_check_bittiming_ok(&CAN_btconst.btc, timing)) + goto out_fail; + can_set_bittiming(channel, timing); break; } @@ -523,12 +544,21 @@ static uint8_t USBD_GS_CAN_EP0_RxReady(USBD_HandleTypeDef *pdev) { } break; } + case GS_USB_BREQ_DATA_BITTIMING: { + const struct gs_device_bittiming *timing = (struct gs_device_bittiming *)hcan->ep0_buf; + + if (!can_check_bittiming_ok(&CAN_btconst_ext.dbtc, timing)) + goto out_fail; + + can_set_data_bittiming(channel, timing); + break; + } case GS_USB_BREQ_SET_TERMINATION: { - if (get_term(req->wValue) != GS_CAN_TERMINATION_UNSUPPORTED) { + if (get_term(channel) != GS_CAN_TERMINATION_UNSUPPORTED) { struct gs_device_termination_state *term_state; term_state = (struct gs_device_termination_state *)hcan->ep0_buf; - if (set_term(req->wValue, term_state->state) == GS_CAN_TERMINATION_UNSUPPORTED) { + if (set_term(channel, term_state->state) == GS_CAN_TERMINATION_UNSUPPORTED) { USBD_CtlError(pdev, req); } } @@ -540,6 +570,9 @@ static uint8_t USBD_GS_CAN_EP0_RxReady(USBD_HandleTypeDef *pdev) { req->bRequest = 0xFF; return USBD_OK; + +out_fail: + return USBD_FAIL; } static uint8_t USBD_GS_CAN_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) { @@ -630,7 +663,7 @@ uint8_t *USBD_GS_CAN_GetStrDesc(USBD_HandleTypeDef *pdev, uint8_t index, uint16_ switch (index) { case DFU_INTERFACE_STR_INDEX: - USBD_GetString(DFU_INTERFACE_STRING_FS, USBD_DescBuf, length); + USBD_GetString((uint8_t *)DFU_INTERFACE_STRING_FS, USBD_DescBuf, length); return USBD_DescBuf; case 0xEE: *length = sizeof(USBD_GS_CAN_WINUSB_STR);