├── .clang-format ├── .gdbinit ├── .github └── workflows │ ├── build.yml │ ├── clang-format.yml │ └── unittests.yml ├── .gitignore ├── .gitmodules ├── Makefile ├── README.md ├── openocd.cfg ├── rules ├── STM32F302x8.ld ├── rules.ld └── rules.mk ├── src ├── board │ ├── CAN-USB-dongle │ │ ├── RevA │ │ │ ├── board.c │ │ │ ├── board.h │ │ │ └── board.mk │ │ └── RevC │ │ │ ├── board.c │ │ │ ├── board.h │ │ │ └── board.mk │ ├── board_functions.h │ └── nucleo │ │ ├── board.c │ │ ├── board.h │ │ ├── board.mk │ │ └── nucleo-f302r8-prototype.md ├── bus_power.c ├── bus_power.h ├── can_driver.c ├── can_driver.h ├── chconf.h ├── halconf.h ├── main.c ├── mcuconf.h ├── slcan.c ├── slcan.h ├── slcan_thread.c ├── slcan_thread.h ├── timestamp │ ├── timestamp.c │ ├── timestamp.h │ ├── timestamp_stm32.c │ ├── timestamp_stm32.h │ └── timestamp_stm32_settings.h ├── timestamp_stm32_settings.h ├── uart_bridge.c ├── uart_bridge.h ├── usbcfg.c ├── usbcfg.h ├── usbcfg2.c ├── usbcfg2.h └── version.h ├── tests ├── CMakeLists.txt ├── slcan_test.cpp └── timestamp_test.cpp ├── tools ├── .gitignore ├── README.md ├── cvra_can_usb_dongle │ ├── __init__.py │ └── power.py └── setup.py └── version.sh /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | # BasedOnStyle: WebKit 4 | AccessModifierOffset: -4 5 | AlignAfterOpenBracket: Align 6 | AlignConsecutiveAssignments: false 7 | AlignConsecutiveDeclarations: false 8 | AlignEscapedNewlines: Right 9 | AlignOperands: false 10 | AlignTrailingComments: false 11 | AllowAllParametersOfDeclarationOnNextLine: true 12 | AllowShortBlocksOnASingleLine: false 13 | AllowShortCaseLabelsOnASingleLine: false 14 | AllowShortFunctionsOnASingleLine: Inline 15 | AllowShortIfStatementsOnASingleLine: false 16 | AllowShortLoopsOnASingleLine: false 17 | AlwaysBreakAfterDefinitionReturnType: None 18 | AlwaysBreakAfterReturnType: None 19 | AlwaysBreakBeforeMultilineStrings: false 20 | AlwaysBreakTemplateDeclarations: true 21 | BinPackArguments: true 22 | BinPackParameters: false 23 | BreakBeforeBraces: Custom 24 | BraceWrapping: 25 | AfterClass: false 26 | AfterControlStatement: false 27 | AfterEnum: false 28 | AfterFunction: true 29 | AfterNamespace: false 30 | AfterObjCDeclaration: false 31 | AfterStruct: false 32 | AfterUnion: false 33 | AfterExternBlock: false 34 | BeforeCatch: false 35 | BeforeElse: false 36 | IndentBraces: false 37 | SplitEmptyFunction: true 38 | SplitEmptyRecord: true 39 | SplitEmptyNamespace: true 40 | BreakBeforeBinaryOperators: NonAssignment 41 | BreakBeforeInheritanceComma: false 42 | BreakBeforeTernaryOperators: true 43 | BreakConstructorInitializersBeforeComma: false 44 | BreakConstructorInitializers: BeforeComma 45 | BreakAfterJavaFieldAnnotations: false 46 | BreakStringLiterals: true 47 | ColumnLimit: 0 48 | CommentPragmas: '^ IWYU pragma:' 49 | CompactNamespaces: false 50 | ConstructorInitializerAllOnOneLineOrOnePerLine: false 51 | ConstructorInitializerIndentWidth: 4 52 | ContinuationIndentWidth: 4 53 | Cpp11BracedListStyle: true 54 | DisableFormat: false 55 | ExperimentalAutoDetectBinPacking: false 56 | FixNamespaceComments: true 57 | ForEachMacros: 58 | - MESSAGEBUS_TOPIC_FOREACH 59 | - TEST_GROUP 60 | IncludeBlocks: Preserve 61 | IncludeCategories: 62 | - Regex: '^<' 63 | Priority: 1 64 | - Regex: '^("|<)(uavcan/|eigen/|lwip/|gfx.h|ff.h)' 65 | Priority: 2 66 | - Regex: '^"(arm-cortex-tools|can-bootloader|chibios-syscalls|cmp|cmp_mem_access|crc|error|filter|goap|msgbus|parameter|parameter_flash_storage|pid|quadramp|raft|serial-datagram|simplerpc|timestamp|trace|version)' 67 | Priority: 3 68 | - Regex: '^"(blocking_detection_manager|control_system_manager|math|obstacle_avoidance|position_manager|robot_system|trajectory_manager)/' 69 | Priority: 4 70 | - Regex: '^"(protobuf)/' 71 | Priority: 5 72 | - Regex: '.*' 73 | Priority: 6 74 | IncludeIsMainRegex: '(Test)?$' 75 | IndentCaseLabels: true 76 | IndentPPDirectives: None 77 | IndentWidth: 4 78 | IndentWrappedFunctionNames: false 79 | JavaScriptQuotes: Leave 80 | JavaScriptWrapImports: true 81 | KeepEmptyLinesAtTheStartOfBlocks: false 82 | MacroBlockBegin: '' 83 | MacroBlockEnd: '' 84 | MaxEmptyLinesToKeep: 1 85 | NamespaceIndentation: None 86 | ObjCBinPackProtocolList: Auto 87 | ObjCBlockIndentWidth: 4 88 | ObjCSpaceAfterProperty: true 89 | ObjCSpaceBeforeProtocolList: true 90 | PenaltyBreakAssignment: 2 91 | PenaltyBreakBeforeFirstCallParameter: 19 92 | PenaltyBreakComment: 300 93 | PenaltyBreakFirstLessLess: 120 94 | PenaltyBreakString: 1000 95 | PenaltyExcessCharacter: 1000000 96 | PenaltyReturnTypeOnItsOwnLine: 60 97 | DerivePointerAlignment: false 98 | PointerAlignment: Left 99 | ReflowComments: true 100 | SortIncludes: false 101 | SortUsingDeclarations: true 102 | SpaceAfterCStyleCast: false 103 | SpaceAfterTemplateKeyword: true 104 | SpaceBeforeAssignmentOperators: true 105 | # SpaceBeforeCpp11BracedList: false 106 | SpaceBeforeCtorInitializerColon: true 107 | SpaceBeforeInheritanceColon: true 108 | SpaceBeforeParens: ControlStatements 109 | SpaceBeforeRangeBasedForLoopColon: true 110 | SpaceInEmptyParentheses: false 111 | SpacesBeforeTrailingComments: 1 112 | SpacesInAngles: false 113 | SpacesInContainerLiterals: false 114 | SpacesInCStyleCastParentheses: false 115 | SpacesInParentheses: false 116 | SpacesInSquareBrackets: false 117 | Standard: Cpp11 118 | TabWidth: 8 119 | UseTab: Never 120 | --- 121 | Language: Proto 122 | IndentWidth: 4 123 | UseTab: Never 124 | ... 125 | 126 | -------------------------------------------------------------------------------- /.gdbinit: -------------------------------------------------------------------------------- 1 | file ./build/firmware.elf 2 | target remote localhost:3333 3 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: STM32 builds 2 | on: 3 | push: 4 | pull_request: 5 | # Run a build every month (at random time) to make sure firmware does not rot 6 | schedule: 7 | - cron: '27 2 1 * *' 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | strategy: 12 | matrix: 13 | board: 14 | - RevA 15 | - RevC 16 | - nucleo 17 | steps: 18 | - uses: actions/checkout@v2 19 | with: 20 | submodules: 'recursive' 21 | - name: Build 22 | uses: docker://antoinealb/cvra-ci:latest 23 | with: 24 | args: bash -c "cd /github/workspace/ && make TARGET=${{ matrix.board }}" 25 | -------------------------------------------------------------------------------- /.github/workflows/clang-format.yml: -------------------------------------------------------------------------------- 1 | on: push 2 | name: clang-format Code Formatter 3 | jobs: 4 | lint: 5 | name: clang-format Code Formatter 6 | runs-on: ubuntu-latest 7 | steps: 8 | - name: Clang Code Formatter 9 | uses: cvra/clang-format-action@master 10 | env: 11 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 12 | -------------------------------------------------------------------------------- /.github/workflows/unittests.yml: -------------------------------------------------------------------------------- 1 | name: Unit tests 2 | on: [push] 3 | jobs: 4 | build: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - uses: actions/checkout@v2 8 | with: 9 | submodules: 'recursive' 10 | - name: Install prerequisites 11 | run: | 12 | sudo apt-get update -y && sudo apt-get install -y libcpputest-dev build-essential cmake 13 | - name: Build 14 | run: | 15 | cd $GITHUB_WORKSPACE 16 | mkdir build 17 | cd build 18 | cmake ../tests 19 | make 20 | - name: Test 21 | run: | 22 | cd $GITHUB_WORKSPACE/build 23 | make check 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.elf 3 | *.hex 4 | *.bin 5 | *.lst 6 | *.list 7 | *.dmp 8 | *.size 9 | *.addr 10 | 11 | # ChibiOS build folder 12 | build/* 13 | .dep/ 14 | 15 | # ctags 16 | .tags 17 | .tags_sorted_by_file 18 | 19 | src/version.c 20 | 21 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "ChibiOS"] 2 | path = ChibiOS 3 | url = https://github.com/cvra/ChibiOS.git 4 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Build global options 3 | # 4 | 5 | # Compiler options here. 6 | USE_OPT = -Os -ggdb -fomit-frame-pointer -falign-functions=16 7 | 8 | # C specific options here (added to USE_OPT). 9 | USE_COPT = 10 | 11 | # C++ specific options here (added to USE_OPT). 12 | USE_CPPOPT = -fno-rtti 13 | 14 | # Enable this if you want the linker to remove unused code and data 15 | USE_LINK_GC = yes 16 | 17 | # Linker extra options here. 18 | USE_LDOPT = 19 | 20 | # Enable this if you want link time optimizations (LTO) 21 | USE_LTO = no 22 | 23 | # If enabled, this option allows to compile the application in THUMB mode. 24 | USE_THUMB = yes 25 | 26 | # Enable this if you want to see the full log while compiling. 27 | USE_VERBOSE_COMPILE = no 28 | 29 | # If enabled, this option makes the build process faster by not compiling 30 | # modules not used in the current configuration. 31 | USE_SMART_BUILD = no 32 | 33 | # 34 | # Build global options 35 | ############################################################################## 36 | 37 | ############################################################################## 38 | # Architecture or project specific options 39 | # 40 | 41 | # Stack size to be allocated to the Cortex-M process stack. This stack is 42 | # the stack used by the main() thread. 43 | USE_PROCESS_STACKSIZE = 0x400 44 | 45 | # Stack size to the allocated to the Cortex-M main/exceptions stack. This 46 | # stack is used for processing interrupts and exceptions. 47 | USE_EXCEPTIONS_STACKSIZE = 0x400 48 | 49 | # Enables the use of FPU on Cortex-M4 (no, softfp, hard). 50 | USE_FPU = no 51 | 52 | # 53 | # Architecture or project specific options 54 | ############################################################################## 55 | 56 | ############################################################################## 57 | # Project, sources and paths 58 | # 59 | 60 | # set to one of the target boards below 61 | TARGET = RevA 62 | 63 | # RevB is electrically the same as RevA 64 | ifeq ($(TARGET), RevB) 65 | TARGET = RevA 66 | endif 67 | 68 | # target boards 69 | ifeq ($(TARGET), nucleo) 70 | include src/board/nucleo/board.mk 71 | LDSCRIPT = rules/STM32F302x8.ld 72 | endif 73 | 74 | ifeq ($(TARGET), RevA) 75 | include src/board/CAN-USB-dongle/RevA/board.mk 76 | LDSCRIPT = rules/STM32F302x8.ld 77 | endif 78 | 79 | ifeq ($(TARGET), RevC) 80 | include src/board/CAN-USB-dongle/RevC/board.mk 81 | LDSCRIPT = rules/STM32F302x8.ld 82 | endif 83 | 84 | 85 | # Define project name here 86 | PROJECT = firmware 87 | 88 | # Imported source files and paths 89 | CHIBIOS = ChibiOS 90 | # Startup files. 91 | include $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/startup_stm32f3xx.mk 92 | # HAL-OSAL files (optional). 93 | include $(CHIBIOS)/os/hal/hal.mk 94 | include $(CHIBIOS)/os/hal/ports/STM32/STM32F3xx/platform.mk 95 | include $(CHIBIOS)/os/hal/osal/rt/osal.mk 96 | # RTOS files (optional). 97 | include $(CHIBIOS)/os/rt/rt.mk 98 | include $(CHIBIOS)/os/rt/ports/ARMCMx/compilers/GCC/mk/port_v7m.mk 99 | 100 | # C sources that can be compiled in ARM or THUMB mode depending on the global 101 | # setting. 102 | CSRC = $(STARTUPSRC) \ 103 | $(KERNSRC) \ 104 | $(PORTSRC) \ 105 | $(OSALSRC) \ 106 | $(HALSRC) \ 107 | $(PLATFORMSRC) \ 108 | $(CHIBIOS)/os/hal/lib/streams/chprintf.c \ 109 | $(BOARDSRC) \ 110 | src/version.c \ 111 | src/main.c \ 112 | src/slcan.c \ 113 | src/slcan_thread.c \ 114 | src/can_driver.c \ 115 | src/bus_power.c \ 116 | src/usbcfg2.c \ 117 | src/timestamp/timestamp.c \ 118 | src/timestamp/timestamp_stm32.c 119 | 120 | 121 | # C++ sources that can be compiled in ARM or THUMB mode depending on the global 122 | # setting. 123 | CPPSRC = 124 | 125 | # List ASM source files here 126 | ASMSRC = $(STARTUPASM) $(PORTASM) $(OSALASM) 127 | 128 | INCDIR = $(STARTUPINC) $(KERNINC) $(PORTINC) $(OSALINC) \ 129 | $(HALINC) $(PLATFORMINC) $(CHIBIOS)/os/various \ 130 | $(CHIBIOS)/os/hal/lib/streams ./src $(BOARDINC) 131 | 132 | # 133 | # Project, sources and paths 134 | ############################################################################## 135 | 136 | ############################################################################## 137 | # Compiler settings 138 | # 139 | 140 | MCU = cortex-m4 141 | 142 | #TRGT = arm-elf- 143 | TRGT = arm-none-eabi- 144 | CC = $(TRGT)gcc 145 | CPPC = $(TRGT)g++ 146 | # Enable loading with g++ only if you need C++ runtime support. 147 | # NOTE: You can use C++ even without C++ support if you are careful. C++ 148 | # runtime support makes code size explode. 149 | LD = $(TRGT)gcc 150 | #LD = $(TRGT)g++ 151 | CP = $(TRGT)objcopy 152 | AS = $(TRGT)gcc -x assembler-with-cpp 153 | AR = $(TRGT)ar 154 | OD = $(TRGT)objdump 155 | NM = $(TRGT)nm 156 | SZ = $(TRGT)size 157 | HEX = $(CP) -O ihex 158 | BIN = $(CP) -O binary 159 | 160 | # ARM-specific options here 161 | AOPT = 162 | 163 | # THUMB-specific options here 164 | TOPT = -mthumb -DTHUMB 165 | 166 | # Define C warning options here 167 | CWARN = -Wall -Wextra -Wundef -Wstrict-prototypes 168 | 169 | # Define C++ warning options here 170 | CPPWARN = -Wall -Wextra -Wundef 171 | 172 | # 173 | # Compiler settings 174 | ############################################################################## 175 | 176 | ############################################################################## 177 | # Start of user section 178 | # 179 | 180 | # List all user C define here, like -D_DEBUG=1 181 | UDEFS = 182 | # optional device name, build with make DEVICE_NAME="My CAN interface" 183 | ifneq ($(DEVICE_NAME),) 184 | UDEFS += -DDEVICE_NAME_STR=\"$(DEVICE_NAME)\" 185 | endif 186 | 187 | # Define ASM defines here 188 | UADEFS = 189 | 190 | # List all user directories here 191 | UINCDIR = 192 | 193 | # List the user directory to look for the libraries here 194 | ULIBDIR = 195 | 196 | # List all user libraries here 197 | ULIBS = 198 | 199 | # 200 | # End of user defines 201 | ############################################################################## 202 | 203 | RULESPATH = rules 204 | include $(RULESPATH)/rules.mk 205 | 206 | PRE_MAKE_ALL_RULE_HOOK: src/version.c 207 | .PHONY: src/version.c 208 | 209 | src/version.c: 210 | @./version.sh 211 | 212 | .PHONY: flash 213 | flash: build/$(PROJECT).elf 214 | openocd -f openocd.cfg -c "program build/$(PROJECT).elf verify reset" -c "shutdown" 215 | 216 | .PHONY: dfu 217 | dfu: build/$(PROJECT).bin 218 | dfu-util -a 0 -d 0483:df11 --dfuse-address 0x08000000 -D build/$(PROJECT).bin 219 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CVRA CAN to USB interface 2 | 3 | [![STM32 builds](https://github.com/cvra/CAN-USB-dongle-fw/actions/workflows/build.yml/badge.svg)](https://github.com/cvra/CAN-USB-dongle-fw/actions/workflows/build.yml) 4 | 5 | ## Usage 6 | 7 | use with SocketCAN 8 | ``` 9 | sudo modprobe can 10 | sudo modprobe can-raw 11 | sudo modprobe slcan 12 | 13 | # configure CAN interface 14 | sudo slcan_attach -s8 -o /dev/ttyACM0 15 | sudo slcand ttyACM0 slcan0 16 | sudo ifconfig slcan0 up 17 | 18 | # use with can-utils 19 | cansend slcan0 123#2a 20 | candump slcan0 21 | ``` 22 | 23 | ## Building & flashing 24 | 25 | ``` 26 | # make sure all submodules are initialized 27 | git submodule update --init 28 | 29 | # building 30 | make 31 | 32 | # flashing using USB DFU 33 | # to enter DFU mode, press the button while plugging USB in. 34 | make dfu 35 | ``` 36 | 37 | 38 | ## Supported commands 39 | 40 | - 'T', 't', 'R', 'r': send CAN frames 41 | - 'Sx': set bitrate 42 | - 'O': open channel 43 | - 'l', 'L': open in loop back or silent mode 44 | - 'C': close channel 45 | - 'V', 'v': hardware and software version 46 | - 'P', 'p': turn bus power on and off respectively. 47 | This is a proprietary extension to the SLCAN protocol. 48 | A tool is included to make use of this feature. 49 | 50 | -------------------------------------------------------------------------------- /openocd.cfg: -------------------------------------------------------------------------------- 1 | telnet_port 4444 2 | gdb_port 3333 3 | 4 | # ST-Link-V2-1 5 | source [find interface/stlink-v2-1.cfg] 6 | reset_config srst_only srst_nogate 7 | 8 | # ST-Link-V2 9 | # source [find interface/stlink-v2.cfg] 10 | 11 | transport select hla_swd 12 | source [find target/stm32f3x.cfg] 13 | -------------------------------------------------------------------------------- /rules/STM32F302x8.ld: -------------------------------------------------------------------------------- 1 | /* 2 | ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. 3 | 4 | This file is part of ChibiOS. 5 | 6 | ChibiOS is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | ChibiOS is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | /* 21 | * STM32F302x8 memory setup. 22 | */ 23 | MEMORY 24 | { 25 | flash : org = 0x08000000, len = 64k 26 | ram0 : org = 0x20000000, len = 16k 27 | ram1 : org = 0x00000000, len = 0 28 | ram2 : org = 0x00000000, len = 0 29 | ram3 : org = 0x00000000, len = 0 30 | ram4 : org = 0x00000000, len = 0 31 | ram5 : org = 0x00000000, len = 0 32 | ram6 : org = 0x00000000, len = 0 33 | ram7 : org = 0x00000000, len = 0 34 | } 35 | 36 | /* RAM region to be used for Main stack. This stack accommodates the processing 37 | of all exceptions and interrupts*/ 38 | REGION_ALIAS("MAIN_STACK_RAM", ram0); 39 | 40 | /* RAM region to be used for the process stack. This is the stack used by 41 | the main() function.*/ 42 | REGION_ALIAS("PROCESS_STACK_RAM", ram0); 43 | 44 | /* RAM region to be used for data segment.*/ 45 | REGION_ALIAS("DATA_RAM", ram0); 46 | 47 | /* RAM region to be used for BSS segment.*/ 48 | REGION_ALIAS("BSS_RAM", ram0); 49 | 50 | /* RAM REGION to be usded for noinit section. */ 51 | REGION_ALIAS("NOINIT_RAM", ram0); 52 | 53 | /* core coupled memory region */ 54 | REGION_ALIAS("CCM_RAM", ram4); 55 | 56 | INCLUDE rules.ld 57 | -------------------------------------------------------------------------------- /rules/rules.ld: -------------------------------------------------------------------------------- 1 | /* 2 | ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. 3 | 4 | This file is part of ChibiOS. 5 | 6 | ChibiOS is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | ChibiOS is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | __ram0_start__ = ORIGIN(ram0); 21 | __ram0_size__ = LENGTH(ram0); 22 | __ram0_end__ = __ram0_start__ + __ram0_size__; 23 | __ram1_start__ = ORIGIN(ram1); 24 | __ram1_size__ = LENGTH(ram1); 25 | __ram1_end__ = __ram1_start__ + __ram1_size__; 26 | __ram2_start__ = ORIGIN(ram2); 27 | __ram2_size__ = LENGTH(ram2); 28 | __ram2_end__ = __ram2_start__ + __ram2_size__; 29 | __ram3_start__ = ORIGIN(ram3); 30 | __ram3_size__ = LENGTH(ram3); 31 | __ram3_end__ = __ram3_start__ + __ram3_size__; 32 | __ram4_start__ = ORIGIN(ram4); 33 | __ram4_size__ = LENGTH(ram4); 34 | __ram4_end__ = __ram4_start__ + __ram4_size__; 35 | __ram5_start__ = ORIGIN(ram5); 36 | __ram5_size__ = LENGTH(ram5); 37 | __ram5_end__ = __ram5_start__ + __ram5_size__; 38 | __ram6_start__ = ORIGIN(ram6); 39 | __ram6_size__ = LENGTH(ram6); 40 | __ram6_end__ = __ram6_start__ + __ram6_size__; 41 | __ram7_start__ = ORIGIN(ram7); 42 | __ram7_size__ = LENGTH(ram7); 43 | __ram7_end__ = __ram7_start__ + __ram7_size__; 44 | 45 | ENTRY(Reset_Handler) 46 | 47 | SECTIONS 48 | { 49 | . = 0; 50 | _text = .; 51 | 52 | startup : ALIGN(16) SUBALIGN(16) 53 | { 54 | KEEP(*(.vectors)) 55 | } > flash 56 | 57 | constructors : ALIGN(4) SUBALIGN(4) 58 | { 59 | PROVIDE(__init_array_start = .); 60 | KEEP(*(SORT(.init_array.*))) 61 | KEEP(*(.init_array)) 62 | PROVIDE(__init_array_end = .); 63 | } > flash 64 | 65 | destructors : ALIGN(4) SUBALIGN(4) 66 | { 67 | PROVIDE(__fini_array_start = .); 68 | KEEP(*(.fini_array)) 69 | KEEP(*(SORT(.fini_array.*))) 70 | PROVIDE(__fini_array_end = .); 71 | } > flash 72 | 73 | .text : ALIGN(16) SUBALIGN(16) 74 | { 75 | *(.text) 76 | *(.text.*) 77 | *(.rodata) 78 | *(.rodata.*) 79 | *(.glue_7t) 80 | *(.glue_7) 81 | *(.gcc*) 82 | } > flash 83 | 84 | .ARM.extab : 85 | { 86 | *(.ARM.extab* .gnu.linkonce.armextab.*) 87 | } > flash 88 | 89 | .ARM.exidx : { 90 | PROVIDE(__exidx_start = .); 91 | *(.ARM.exidx* .gnu.linkonce.armexidx.*) 92 | PROVIDE(__exidx_end = .); 93 | } > flash 94 | 95 | .eh_frame_hdr : 96 | { 97 | *(.eh_frame_hdr) 98 | } > flash 99 | 100 | .eh_frame : ONLY_IF_RO 101 | { 102 | *(.eh_frame) 103 | } > flash 104 | 105 | .textalign : ONLY_IF_RO 106 | { 107 | . = ALIGN(8); 108 | } > flash 109 | 110 | . = ALIGN(4); 111 | _etext = .; 112 | _textdata = _etext; 113 | 114 | .mstack : 115 | { 116 | . = ALIGN(8); 117 | __main_stack_base__ = .; 118 | . += __main_stack_size__; 119 | . = ALIGN(8); 120 | __main_stack_end__ = .; 121 | } > MAIN_STACK_RAM 122 | 123 | .pstack : 124 | { 125 | __process_stack_base__ = .; 126 | __main_thread_stack_base__ = .; 127 | . += __process_stack_size__; 128 | . = ALIGN(8); 129 | __process_stack_end__ = .; 130 | __main_thread_stack_end__ = .; 131 | } > PROCESS_STACK_RAM 132 | 133 | .data : ALIGN(4) 134 | { 135 | . = ALIGN(4); 136 | PROVIDE(_data = .); 137 | *(.data) 138 | *(.data.*) 139 | *(.ramtext) 140 | . = ALIGN(4); 141 | PROVIDE(_edata = .); 142 | } > DATA_RAM AT > flash 143 | 144 | .bss : ALIGN(4) 145 | { 146 | . = ALIGN(4); 147 | PROVIDE(_bss_start = .); 148 | *(.bss) 149 | *(.bss.*) 150 | *(COMMON) 151 | . = ALIGN(4); 152 | PROVIDE(_bss_end = .); 153 | PROVIDE(end = .); 154 | } > BSS_RAM 155 | 156 | .noinit (NOLOAD) : ALIGN(4) 157 | { 158 | . = ALIGN(4); 159 | *(.noinit) 160 | *(.noinit.*) 161 | . = ALIGN(4); 162 | } > NOINIT_RAM 163 | 164 | .ccm (NOLOAD) : ALIGN(4) 165 | { 166 | . = ALIGN(4); 167 | *(.ccm) 168 | *(.ccm.*) 169 | . = ALIGN(4); 170 | } > CCM_RAM 171 | 172 | .ram0 (NOLOAD) : ALIGN(4) 173 | { 174 | . = ALIGN(4); 175 | *(.ram0) 176 | *(.ram0.*) 177 | . = ALIGN(4); 178 | __ram0_free__ = .; 179 | } > ram0 180 | 181 | .ram1 (NOLOAD) : ALIGN(4) 182 | { 183 | . = ALIGN(4); 184 | *(.ram1) 185 | *(.ram1.*) 186 | . = ALIGN(4); 187 | __ram1_free__ = .; 188 | } > ram1 189 | 190 | .ram2 (NOLOAD) : ALIGN(4) 191 | { 192 | . = ALIGN(4); 193 | *(.ram2) 194 | *(.ram2.*) 195 | . = ALIGN(4); 196 | __ram2_free__ = .; 197 | } > ram2 198 | 199 | .ram3 (NOLOAD) : ALIGN(4) 200 | { 201 | . = ALIGN(4); 202 | *(.ram3) 203 | *(.ram3.*) 204 | . = ALIGN(4); 205 | __ram3_free__ = .; 206 | } > ram3 207 | 208 | .ram4 (NOLOAD) : ALIGN(4) 209 | { 210 | . = ALIGN(4); 211 | *(.ram4) 212 | *(.ram4.*) 213 | . = ALIGN(4); 214 | __ram4_free__ = .; 215 | } > ram4 216 | 217 | .ram5 (NOLOAD) : ALIGN(4) 218 | { 219 | . = ALIGN(4); 220 | *(.ram5) 221 | *(.ram5.*) 222 | . = ALIGN(4); 223 | __ram5_free__ = .; 224 | } > ram5 225 | 226 | .ram6 (NOLOAD) : ALIGN(4) 227 | { 228 | . = ALIGN(4); 229 | *(.ram6) 230 | *(.ram6.*) 231 | . = ALIGN(4); 232 | __ram6_free__ = .; 233 | } > ram6 234 | 235 | .ram7 (NOLOAD) : ALIGN(4) 236 | { 237 | . = ALIGN(4); 238 | *(.ram7) 239 | *(.ram7.*) 240 | . = ALIGN(4); 241 | __ram7_free__ = .; 242 | } > ram7 243 | } 244 | 245 | /* Heap default boundaries, it is defaulted to be the non-used part 246 | of ram0 region.*/ 247 | __heap_base__ = __ram0_free__; 248 | __heap_end__ = __ram0_end__; 249 | -------------------------------------------------------------------------------- /rules/rules.mk: -------------------------------------------------------------------------------- 1 | # ARM Cortex-Mx common makefile scripts and rules. 2 | 3 | ############################################################################## 4 | # Processing options coming from the upper Makefile. 5 | # 6 | 7 | # Compiler options 8 | OPT = $(USE_OPT) 9 | COPT = $(USE_COPT) 10 | CPPOPT = $(USE_CPPOPT) 11 | 12 | # Garbage collection 13 | ifeq ($(USE_LINK_GC),yes) 14 | OPT += -ffunction-sections -fdata-sections -fno-common 15 | LDOPT := ,--gc-sections 16 | else 17 | LDOPT := 18 | endif 19 | 20 | # Linker extra options 21 | ifneq ($(USE_LDOPT),) 22 | LDOPT := $(LDOPT),$(USE_LDOPT) 23 | endif 24 | 25 | # Link time optimizations 26 | ifeq ($(USE_LTO),yes) 27 | OPT += -flto 28 | endif 29 | 30 | # FPU-related options 31 | ifeq ($(USE_FPU),) 32 | USE_FPU = no 33 | endif 34 | ifneq ($(USE_FPU),no) 35 | OPT += -mfloat-abi=$(USE_FPU) -mfpu=fpv4-sp-d16 -fsingle-precision-constant 36 | DDEFS += -DCORTEX_USE_FPU=TRUE 37 | DADEFS += -DCORTEX_USE_FPU=TRUE 38 | else 39 | DDEFS += -DCORTEX_USE_FPU=FALSE 40 | DADEFS += -DCORTEX_USE_FPU=FALSE 41 | endif 42 | 43 | # Process stack size 44 | ifeq ($(USE_PROCESS_STACKSIZE),) 45 | LDOPT := $(LDOPT),--defsym=__process_stack_size__=0x400 46 | else 47 | LDOPT := $(LDOPT),--defsym=__process_stack_size__=$(USE_PROCESS_STACKSIZE) 48 | endif 49 | 50 | # Exceptions stack size 51 | ifeq ($(USE_EXCEPTIONS_STACKSIZE),) 52 | LDOPT := $(LDOPT),--defsym=__main_stack_size__=0x400 53 | else 54 | LDOPT := $(LDOPT),--defsym=__main_stack_size__=$(USE_EXCEPTIONS_STACKSIZE) 55 | endif 56 | 57 | # Output directory and files 58 | ifeq ($(BUILDDIR),) 59 | BUILDDIR = build 60 | endif 61 | ifeq ($(BUILDDIR),.) 62 | BUILDDIR = build 63 | endif 64 | OUTFILES = $(BUILDDIR)/$(PROJECT).elf \ 65 | $(BUILDDIR)/$(PROJECT).hex \ 66 | $(BUILDDIR)/$(PROJECT).bin \ 67 | $(BUILDDIR)/$(PROJECT).size \ 68 | $(BUILDDIR)/$(PROJECT).addr \ 69 | $(BUILDDIR)/$(PROJECT).dmp \ 70 | $(BUILDDIR)/$(PROJECT).list 71 | 72 | ifdef SREC 73 | OUTFILES += $(BUILDDIR)/$(PROJECT).srec 74 | endif 75 | 76 | # Source files groups and paths 77 | ifeq ($(USE_THUMB),yes) 78 | TCSRC += $(CSRC) 79 | TCPPSRC += $(CPPSRC) 80 | else 81 | ACSRC += $(CSRC) 82 | ACPPSRC += $(CPPSRC) 83 | endif 84 | ASRC = $(ACSRC)$(ACPPSRC) 85 | TSRC = $(TCSRC)$(TCPPSRC) 86 | SRCPATHS = $(sort $(dir $(ASMXSRC)) $(dir $(ASMSRC)) $(dir $(ASRC)) $(dir $(TSRC))) 87 | 88 | # Various directories 89 | OBJDIR = $(BUILDDIR)/obj 90 | LSTDIR = $(BUILDDIR)/lst 91 | 92 | # Object files groups 93 | ACOBJS = $(addprefix $(OBJDIR)/, $(notdir $(ACSRC:.c=.o))) 94 | ACPPOBJS = $(addprefix $(OBJDIR)/, $(notdir $(ACPPSRC:.cpp=.o))) 95 | TCOBJS = $(addprefix $(OBJDIR)/, $(notdir $(TCSRC:.c=.o))) 96 | TCPPOBJS = $(addprefix $(OBJDIR)/, $(notdir $(TCPPSRC:.cpp=.o))) 97 | ASMOBJS = $(addprefix $(OBJDIR)/, $(notdir $(ASMSRC:.s=.o))) 98 | ASMXOBJS = $(addprefix $(OBJDIR)/, $(notdir $(ASMXSRC:.S=.o))) 99 | OBJS = $(ASMXOBJS) $(ASMOBJS) $(ACOBJS) $(TCOBJS) $(ACPPOBJS) $(TCPPOBJS) 100 | 101 | # Paths 102 | IINCDIR = $(patsubst %,-I%,$(INCDIR) $(DINCDIR) $(UINCDIR)) 103 | LLIBDIR = $(patsubst %,-L%,$(DLIBDIR) $(ULIBDIR)) 104 | 105 | # Macros 106 | DEFS = $(DDEFS) $(UDEFS) 107 | ADEFS = $(DADEFS) $(UADEFS) 108 | 109 | # Libs 110 | LIBS = $(DLIBS) $(ULIBS) 111 | 112 | # Various settings 113 | MCFLAGS = -mcpu=$(MCU) 114 | ODFLAGS = -x --syms 115 | ASFLAGS = $(MCFLAGS) -Wa,-amhls=$(LSTDIR)/$(notdir $(<:.s=.lst)) $(ADEFS) 116 | ASXFLAGS = $(MCFLAGS) -Wa,-amhls=$(LSTDIR)/$(notdir $(<:.S=.lst)) $(ADEFS) 117 | CFLAGS = $(MCFLAGS) $(OPT) $(COPT) $(CWARN) -Wa,-alms=$(LSTDIR)/$(notdir $(<:.c=.lst)) $(DEFS) 118 | CPPFLAGS = $(MCFLAGS) $(OPT) $(CPPOPT) $(CPPWARN) -Wa,-alms=$(LSTDIR)/$(notdir $(<:.cpp=.lst)) $(DEFS) 119 | LDFLAGS = $(MCFLAGS) $(OPT) -nostartfiles $(LLIBDIR) -Wl,-Map=$(BUILDDIR)/$(PROJECT).map,--cref,--no-warn-mismatch,--library-path=$(RULESPATH),--script=$(LDSCRIPT)$(LDOPT) 120 | 121 | # Thumb interwork enabled only if needed because it kills performance. 122 | ifneq ($(TSRC),) 123 | CFLAGS += -DTHUMB_PRESENT 124 | CPPFLAGS += -DTHUMB_PRESENT 125 | ASFLAGS += -DTHUMB_PRESENT 126 | ifneq ($(ASRC),) 127 | # Mixed ARM and THUMB mode. 128 | CFLAGS += -mthumb-interwork 129 | CPPFLAGS += -mthumb-interwork 130 | ASFLAGS += -mthumb-interwork 131 | LDFLAGS += -mthumb-interwork 132 | else 133 | # Pure THUMB mode, THUMB C code cannot be called by ARM asm code directly. 134 | CFLAGS += -mno-thumb-interwork -DTHUMB_NO_INTERWORKING 135 | CPPFLAGS += -mno-thumb-interwork -DTHUMB_NO_INTERWORKING 136 | ASFLAGS += -mno-thumb-interwork -DTHUMB_NO_INTERWORKING -mthumb 137 | LDFLAGS += -mno-thumb-interwork -mthumb 138 | endif 139 | else 140 | # Pure ARM mode 141 | CFLAGS += -mno-thumb-interwork 142 | CPPFLAGS += -mno-thumb-interwork 143 | ASFLAGS += -mno-thumb-interwork 144 | LDFLAGS += -mno-thumb-interwork 145 | endif 146 | 147 | # Generate dependency information 148 | ASFLAGS += -MD -MP -MF .dep/$(@F).d 149 | CFLAGS += -MD -MP -MF .dep/$(@F).d 150 | CPPFLAGS += -MD -MP -MF .dep/$(@F).d 151 | 152 | # Paths where to search for sources 153 | VPATH = $(SRCPATHS) 154 | 155 | # Colored output messages 156 | COLOR = \033[1;34m 157 | COLOR_CLEAR = \033[0m 158 | COLOR_PRINTF = printf "$(COLOR)%s$(COLOR_CLEAR)\n" 159 | 160 | # 161 | # Makefile rules 162 | # 163 | 164 | all: PRE_MAKE_ALL_RULE_HOOK $(OBJS) $(OUTFILES) POST_MAKE_ALL_RULE_HOOK 165 | 166 | PRE_MAKE_ALL_RULE_HOOK: 167 | 168 | POST_MAKE_ALL_RULE_HOOK: 169 | 170 | $(OBJS): | $(BUILDDIR) $(OBJDIR) $(LSTDIR) 171 | 172 | $(BUILDDIR): 173 | ifneq ($(USE_VERBOSE_COMPILE),yes) 174 | @echo Compiler Options 175 | @echo $(CC) -c $(CFLAGS) -I. $(IINCDIR) main.c -o main.o 176 | @echo 177 | endif 178 | @mkdir -p $(BUILDDIR) 179 | 180 | $(OBJDIR): 181 | @mkdir -p $(OBJDIR) 182 | 183 | $(LSTDIR): 184 | @mkdir -p $(LSTDIR) 185 | 186 | $(ACPPOBJS) : $(OBJDIR)/%.o : %.cpp Makefile $(GLOBAL_SRC_DEP) 187 | ifeq ($(USE_VERBOSE_COMPILE),yes) 188 | @echo 189 | $(CPPC) -c $(CPPFLAGS) $(AOPT) -I. $(IINCDIR) $< -o $@ 190 | else 191 | @$(COLOR_PRINTF) "Compiling $( $@ 276 | else 277 | @$(COLOR_PRINTF) "Creating $@" 278 | @$(NM) --size-sort --print-size $< > $@ 279 | endif 280 | 281 | %.addr: %.elf $(LDSCRIPT) 282 | ifeq ($(USE_VERBOSE_COMPILE),yes) 283 | $(NM) --numeric-sort --print-size $< > $@ 284 | else 285 | @$(COLOR_PRINTF) "Creating $@" 286 | @$(NM) --numeric-sort --print-size $< > $@ 287 | endif 288 | 289 | %.dmp: %.elf $(LDSCRIPT) 290 | ifeq ($(USE_VERBOSE_COMPILE),yes) 291 | $(OD) $(ODFLAGS) $< > $@ 292 | $(SZ) $< 293 | else 294 | @$(COLOR_PRINTF) "Creating $@" 295 | @$(OD) $(ODFLAGS) $< > $@ 296 | @echo 297 | @$(SZ) $< 298 | endif 299 | 300 | %.list: %.elf $(LDSCRIPT) 301 | ifeq ($(USE_VERBOSE_COMPILE),yes) 302 | $(OD) -d $< > $@ 303 | else 304 | @$(COLOR_PRINTF) "Creating $@" 305 | @$(OD) -d $< > $@ 306 | @echo 307 | @echo "\x1b[32mDone\x1b[0m" 308 | endif 309 | 310 | lib: $(OBJS) $(BUILDDIR)/lib$(PROJECT).a 311 | 312 | $(BUILDDIR)/lib$(PROJECT).a: $(OBJS) 313 | @$(AR) -r $@ $^ 314 | @echo 315 | @echo Done 316 | 317 | clean: 318 | @echo Cleaning 319 | -rm -fR .dep $(BUILDDIR) 320 | @echo 321 | @echo Done 322 | 323 | # 324 | # Include the dependency files, should be the last of the makefile 325 | # 326 | -include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*) 327 | 328 | # *** EOF *** 329 | -------------------------------------------------------------------------------- /src/board/CAN-USB-dongle/RevA/board.c: -------------------------------------------------------------------------------- 1 | /* 2 | ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #include "hal.h" 18 | 19 | #if HAL_USE_PAL || defined(__DOXYGEN__) 20 | /** 21 | * @brief PAL setup. 22 | * @details Digital I/O ports static configuration as defined in @p board.h. 23 | * This variable is used by the HAL when initializing the PAL driver. 24 | */ 25 | const PALConfig pal_default_config = { 26 | #if STM32_HAS_GPIOA 27 | {VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR, 28 | VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH}, 29 | #endif 30 | #if STM32_HAS_GPIOB 31 | {VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR, 32 | VAL_GPIOB_ODR, VAL_GPIOB_AFRL, VAL_GPIOB_AFRH}, 33 | #endif 34 | #if STM32_HAS_GPIOC 35 | {VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR, 36 | VAL_GPIOC_ODR, VAL_GPIOC_AFRL, VAL_GPIOC_AFRH}, 37 | #endif 38 | #if STM32_HAS_GPIOD 39 | {VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR, 40 | VAL_GPIOD_ODR, VAL_GPIOD_AFRL, VAL_GPIOD_AFRH}, 41 | #endif 42 | #if STM32_HAS_GPIOE 43 | {VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR, 44 | VAL_GPIOE_ODR, VAL_GPIOE_AFRL, VAL_GPIOE_AFRH}, 45 | #endif 46 | #if STM32_HAS_GPIOF 47 | {VAL_GPIOF_MODER, VAL_GPIOF_OTYPER, VAL_GPIOF_OSPEEDR, VAL_GPIOF_PUPDR, 48 | VAL_GPIOF_ODR, VAL_GPIOF_AFRL, VAL_GPIOF_AFRH}, 49 | #endif 50 | #if STM32_HAS_GPIOG 51 | {VAL_GPIOG_MODER, VAL_GPIOG_OTYPER, VAL_GPIOG_OSPEEDR, VAL_GPIOG_PUPDR, 52 | VAL_GPIOG_ODR, VAL_GPIOG_AFRL, VAL_GPIOG_AFRH}, 53 | #endif 54 | #if STM32_HAS_GPIOH 55 | {VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR, 56 | VAL_GPIOH_ODR, VAL_GPIOH_AFRL, VAL_GPIOH_AFRH}, 57 | #endif 58 | #if STM32_HAS_GPIOI 59 | {VAL_GPIOI_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR, 60 | VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH} 61 | #endif 62 | }; 63 | #endif 64 | 65 | /** 66 | * @brief Early initialization code. 67 | * @details This initialization must be performed just after stack setup 68 | * and before any other initialization. 69 | */ 70 | void __early_init(void) 71 | { 72 | stm32_clock_init(); 73 | } 74 | 75 | #if HAL_USE_SDC || defined(__DOXYGEN__) 76 | /** 77 | * @brief SDC card detection. 78 | */ 79 | bool sdc_lld_is_card_inserted(SDCDriver* sdcp) 80 | { 81 | (void)sdcp; 82 | /* TODO: Fill the implementation.*/ 83 | return true; 84 | } 85 | 86 | /** 87 | * @brief SDC card write protection detection. 88 | */ 89 | bool sdc_lld_is_write_protected(SDCDriver* sdcp) 90 | { 91 | (void)sdcp; 92 | /* TODO: Fill the implementation.*/ 93 | return false; 94 | } 95 | #endif /* HAL_USE_SDC */ 96 | 97 | #if HAL_USE_MMC_SPI || defined(__DOXYGEN__) 98 | /** 99 | * @brief MMC_SPI card detection. 100 | */ 101 | bool mmc_lld_is_card_inserted(MMCDriver* mmcp) 102 | { 103 | (void)mmcp; 104 | /* TODO: Fill the implementation.*/ 105 | return true; 106 | } 107 | 108 | /** 109 | * @brief MMC_SPI card write protection detection. 110 | */ 111 | bool mmc_lld_is_write_protected(MMCDriver* mmcp) 112 | { 113 | (void)mmcp; 114 | /* TODO: Fill the implementation.*/ 115 | return false; 116 | } 117 | #endif 118 | 119 | /** 120 | * @brief Board-specific initialization code. 121 | * @todo Add your board-specific code, if any. 122 | */ 123 | void boardInit(void) 124 | { 125 | } 126 | 127 | #if HAL_USE_USB 128 | void usb_lld_disconnect_bus(void* arg) 129 | { 130 | (void)arg; 131 | palSetPadMode(GPIOA, GPIOA_OTG_FS_DM, PAL_MODE_OUTPUT_OPENDRAIN); 132 | palSetPadMode(GPIOA, GPIOA_OTG_FS_DP, PAL_MODE_OUTPUT_OPENDRAIN); 133 | palClearPort(GPIOA, (1 << GPIOA_OTG_FS_DM) | (1 << GPIOA_OTG_FS_DP)); 134 | } 135 | 136 | void usb_lld_connect_bus(void* arg) 137 | { 138 | (void)arg; 139 | palSetPadMode(GPIOA, GPIOA_OTG_FS_DM, PAL_MODE_ALTERNATE(10)); 140 | palSetPadMode(GPIOA, GPIOA_OTG_FS_DP, PAL_MODE_ALTERNATE(10)); 141 | } 142 | #endif 143 | 144 | void led_toggle(unsigned int led) 145 | { 146 | if (led & STATUS_LED) { 147 | palTogglePad(GPIOB, GPIOB_STATUS_LED); 148 | } 149 | if (led & CAN1_STATUS_LED) { 150 | palTogglePad(GPIOB, GPIOB_CAN1_STATUS_LED); 151 | } 152 | if (led & CAN1_PWR_LED) { 153 | palTogglePad(GPIOA, GPIOA_CAN1_PWR_LED); 154 | } 155 | } 156 | 157 | void led_set(unsigned int led) 158 | { 159 | if (led & STATUS_LED) { 160 | palSetPad(GPIOB, GPIOB_STATUS_LED); 161 | } 162 | if (led & CAN1_STATUS_LED) { 163 | palSetPad(GPIOB, GPIOB_CAN1_STATUS_LED); 164 | } 165 | if (led & CAN1_PWR_LED) { 166 | palSetPad(GPIOA, GPIOA_CAN1_PWR_LED); 167 | } 168 | } 169 | 170 | void led_clear(unsigned int led) 171 | { 172 | if (led & STATUS_LED) { 173 | palClearPad(GPIOB, GPIOB_STATUS_LED); 174 | } 175 | if (led & CAN1_STATUS_LED) { 176 | palClearPad(GPIOB, GPIOB_CAN1_STATUS_LED); 177 | } 178 | if (led & CAN1_PWR_LED) { 179 | palClearPad(GPIOA, GPIOA_CAN1_PWR_LED); 180 | } 181 | } 182 | 183 | void can_set_silent_mode(int silent) 184 | { 185 | palWritePad(GPIOA, GPIOA_CAN_SILENT, silent); 186 | } 187 | 188 | int user_button_pressed(void) 189 | { 190 | return palReadPad(GPIOA, GPIOA_USER_BUTTON); 191 | } 192 | 193 | void can_bus_power_enable(int enabled) 194 | { 195 | palWritePad(GPIOB, GPIOB_V_BUS_ENABLE, enabled); 196 | } 197 | -------------------------------------------------------------------------------- /src/board/CAN-USB-dongle/RevA/board.h: -------------------------------------------------------------------------------- 1 | #ifndef _BOARD_H_ 2 | #define _BOARD_H_ 3 | 4 | /* 5 | * Setup for STMicroelectronics NUCLEO-F302R8 board. 6 | */ 7 | 8 | /* 9 | * Board identifier. 10 | */ 11 | #define CVRA_CAN_TO_USB 12 | #define BOARD_NAME "CVRA CAN to USB dongle RevA" 13 | 14 | /* 15 | * Board oscillators-related settings. 16 | * NOTE: LSE not fitted. 17 | */ 18 | #if !defined(STM32_LSECLK) 19 | #define STM32_LSECLK 0U 20 | #endif 21 | 22 | #define STM32_LSEDRV (3U << 3U) 23 | 24 | #define STM32_HSECLK 16000000U 25 | 26 | /* 27 | * MCU type as defined in the ST header. 28 | */ 29 | #define STM32F302x8 30 | 31 | /* 32 | * IO pins assignments. 33 | */ 34 | #define GPIOA_USER_BUTTON 0U // active high 35 | #define GPIOA_CAN_SILENT 1U // high: silent mode, low: normal mode (driver active) 36 | #define GPIOA_V_BUS_SENSE 2U 37 | #define GPIOA_PIN3 3U 38 | #define GPIOA_PIN4 4U 39 | #define GPIOA_PIN5 5U 40 | #define GPIOA_PIN6 6U 41 | #define GPIOA_PIN7 7U 42 | #define GPIOA_PIN8 8U 43 | #define GPIOA_PIN9 9U 44 | #define GPIOA_PIN10 10U 45 | #define GPIOA_OTG_FS_DM 11U 46 | #define GPIOA_OTG_FS_DP 12U 47 | #define GPIOA_SWDIO 13U 48 | #define GPIOA_SWCLK 14U 49 | #define GPIOA_CAN1_PWR_LED 15U 50 | 51 | #define GPIOB_PIN0 0U 52 | #define GPIOB_PIN1 1U 53 | #define GPIOB_PIN2 2U 54 | #define GPIOB_CAN1_STATUS_LED 3U 55 | #define GPIOB_PIN4 4U 56 | #define GPIOB_V_BUS_ENABLE 5U // active high 57 | #define GPIOB_UART1_TX 6U 58 | #define GPIOB_UART1_RX 7U 59 | #define GPIOB_CAN1_RX 8U 60 | #define GPIOB_CAN1_TX 9U 61 | #define GPIOB_PIN10 10U 62 | #define GPIOB_PIN11 11U 63 | #define GPIOB_STATUS_LED 12U 64 | #define GPIOB_PIN13 13U 65 | #define GPIOB_PIN14 14U 66 | #define GPIOB_PIN15 15U 67 | 68 | #define GPIOC_PIN0 0U 69 | #define GPIOC_PIN1 1U 70 | #define GPIOC_PIN2 2U 71 | #define GPIOC_PIN3 3U 72 | #define GPIOC_PIN4 4U 73 | #define GPIOC_PIN5 5U 74 | #define GPIOC_PIN6 6U 75 | #define GPIOC_PIN7 7U 76 | #define GPIOC_PIN8 8U 77 | #define GPIOC_PIN9 9U 78 | #define GPIOC_PIN10 10U 79 | #define GPIOC_PIN11 11U 80 | #define GPIOC_PIN12 12U 81 | #define GPIOC_PIN13 13U 82 | #define GPIOC_PIN14 14U 83 | #define GPIOC_PIN15 15U 84 | 85 | #define GPIOD_PIN0 0U 86 | #define GPIOD_PIN1 1U 87 | #define GPIOD_PIN2 2U 88 | #define GPIOD_PIN3 3U 89 | #define GPIOD_PIN4 4U 90 | #define GPIOD_PIN5 5U 91 | #define GPIOD_PIN6 6U 92 | #define GPIOD_PIN7 7U 93 | #define GPIOD_PIN8 8U 94 | #define GPIOD_PIN9 9U 95 | #define GPIOD_PIN10 10U 96 | #define GPIOD_PIN11 11U 97 | #define GPIOD_PIN12 12U 98 | #define GPIOD_PIN13 13U 99 | #define GPIOD_PIN14 14U 100 | #define GPIOD_PIN15 15U 101 | 102 | #define GPIOE_PIN0 0U 103 | #define GPIOE_PIN1 1U 104 | #define GPIOE_PIN2 2U 105 | #define GPIOE_PIN3 3U 106 | #define GPIOE_PIN4 4U 107 | #define GPIOE_PIN5 5U 108 | #define GPIOE_PIN6 6U 109 | #define GPIOE_PIN7 7U 110 | #define GPIOE_PIN8 8U 111 | #define GPIOE_PIN9 9U 112 | #define GPIOE_PIN10 10U 113 | #define GPIOE_PIN11 11U 114 | #define GPIOE_PIN12 12U 115 | #define GPIOE_PIN13 13U 116 | #define GPIOE_PIN14 14U 117 | #define GPIOE_PIN15 15U 118 | 119 | #define GPIOF_PIN0 0U 120 | #define GPIOF_PIN1 1U 121 | #define GPIOF_PIN2 2U 122 | #define GPIOF_PIN3 3U 123 | #define GPIOF_PIN4 4U 124 | #define GPIOF_PIN5 5U 125 | #define GPIOF_PIN6 6U 126 | #define GPIOF_PIN7 7U 127 | #define GPIOF_PIN8 8U 128 | #define GPIOF_PIN9 9U 129 | #define GPIOF_PIN10 10U 130 | #define GPIOF_PIN11 11U 131 | #define GPIOF_PIN12 12U 132 | #define GPIOF_PIN13 13U 133 | #define GPIOF_PIN14 14U 134 | #define GPIOF_PIN15 15U 135 | 136 | /* 137 | * I/O ports initial setup, this configuration is established soon after reset 138 | * in the initialization code. 139 | * Please refer to the STM32 Reference Manual for details. 140 | */ 141 | #define PIN_MODE_INPUT(n) (0U << ((n)*2U)) 142 | #define PIN_MODE_OUTPUT(n) (1U << ((n)*2U)) 143 | #define PIN_MODE_ALTERNATE(n) (2U << ((n)*2U)) 144 | #define PIN_MODE_ANALOG(n) (3U << ((n)*2U)) 145 | #define PIN_ODR_LOW(n) (0U << (n)) 146 | #define PIN_ODR_HIGH(n) (1U << (n)) 147 | #define PIN_OTYPE_PUSHPULL(n) (0U << (n)) 148 | #define PIN_OTYPE_OPENDRAIN(n) (1U << (n)) 149 | #define PIN_OSPEED_2M(n) (0U << ((n)*2U)) 150 | #define PIN_OSPEED_25M(n) (1U << ((n)*2U)) 151 | #define PIN_OSPEED_50M(n) (2U << ((n)*2U)) 152 | #define PIN_OSPEED_100M(n) (3U << ((n)*2U)) 153 | #define PIN_PUPDR_FLOATING(n) (0U << ((n)*2U)) 154 | #define PIN_PUPDR_PULLUP(n) (1U << ((n)*2U)) 155 | #define PIN_PUPDR_PULLDOWN(n) (2U << ((n)*2U)) 156 | #define PIN_AFIO_AF(n, v) ((v) << (((n) % 8U) * 4U)) 157 | 158 | /* 159 | * GPIOA setup: 160 | * 161 | * PA0 - PIN0 (input pullup). 162 | * PA1 - GPIOA_CAN_SILENT (output high). 163 | * PA2 - GPIOA_V_BUS_SENSE (analog). 164 | * PA3 - GPIOA_PIN3 (input pullup). 165 | * PA4 - GPIOA_PIN4 (input pullup). 166 | * PA5 - GPIOA_PIN5 (input pullup). 167 | * PA6 - GPIOA_PIN6 (input pullup). 168 | * PA7 - GPIOA_PIN7 (input pullup). 169 | * PA8 - GPIOA_PIN8 (input pullup). 170 | * PA9 - GPIOA_PIN9 (input pullup). 171 | * PA10 - GPIOA_PIN10 (input pullup). 172 | * PA11 - GPIOA_OTG_FS_DM (output opendrain low). 173 | * PA12 - GPIOA_OTG_FS_DP (output opendrain low). 174 | * PA13 - GPIOA_SWDIO (alternate 0). 175 | * PA14 - GPIOA_SWCLK (alternate 0). 176 | * PA15 - GPIOA_CAN1_PWR_LED (output low). 177 | */ 178 | #define VAL_GPIOA_MODER (PIN_MODE_INPUT(GPIOA_USER_BUTTON) | PIN_MODE_OUTPUT(GPIOA_CAN_SILENT) | PIN_MODE_ANALOG(GPIOA_V_BUS_SENSE) | PIN_MODE_ALTERNATE(GPIOA_PIN3) | PIN_MODE_INPUT(GPIOA_PIN4) | PIN_MODE_INPUT(GPIOA_PIN5) | PIN_MODE_INPUT(GPIOA_PIN6) | PIN_MODE_INPUT(GPIOA_PIN7) | PIN_MODE_INPUT(GPIOA_PIN8) | PIN_MODE_INPUT(GPIOA_PIN9) | PIN_MODE_INPUT(GPIOA_PIN10) | PIN_MODE_OUTPUT(GPIOA_OTG_FS_DM) | PIN_MODE_OUTPUT(GPIOA_OTG_FS_DP) | PIN_MODE_ALTERNATE(GPIOA_SWDIO) | PIN_MODE_ALTERNATE(GPIOA_SWCLK) | PIN_MODE_OUTPUT(GPIOA_CAN1_PWR_LED)) 179 | #define VAL_GPIOA_OTYPER (PIN_OTYPE_PUSHPULL(GPIOA_USER_BUTTON) | PIN_OTYPE_PUSHPULL(GPIOA_CAN_SILENT) | PIN_OTYPE_PUSHPULL(GPIOA_V_BUS_SENSE) | PIN_OTYPE_PUSHPULL(GPIOA_PIN3) | PIN_OTYPE_PUSHPULL(GPIOA_PIN4) | PIN_OTYPE_PUSHPULL(GPIOA_PIN5) | PIN_OTYPE_PUSHPULL(GPIOA_PIN6) | PIN_OTYPE_PUSHPULL(GPIOA_PIN7) | PIN_OTYPE_PUSHPULL(GPIOA_PIN8) | PIN_OTYPE_PUSHPULL(GPIOA_PIN9) | PIN_OTYPE_PUSHPULL(GPIOA_PIN10) | PIN_OTYPE_OPENDRAIN(GPIOA_OTG_FS_DM) | PIN_OTYPE_OPENDRAIN(GPIOA_OTG_FS_DP) | PIN_OTYPE_PUSHPULL(GPIOA_SWDIO) | PIN_OTYPE_PUSHPULL(GPIOA_SWCLK) | PIN_OTYPE_PUSHPULL(GPIOA_CAN1_PWR_LED)) 180 | #define VAL_GPIOA_OSPEEDR (PIN_OSPEED_100M(GPIOA_USER_BUTTON) | PIN_OSPEED_100M(GPIOA_CAN_SILENT) | PIN_OSPEED_100M(GPIOA_V_BUS_SENSE) | PIN_OSPEED_50M(GPIOA_PIN3) | PIN_OSPEED_100M(GPIOA_PIN4) | PIN_OSPEED_50M(GPIOA_PIN5) | PIN_OSPEED_100M(GPIOA_PIN6) | PIN_OSPEED_100M(GPIOA_PIN7) | PIN_OSPEED_100M(GPIOA_PIN8) | PIN_OSPEED_100M(GPIOA_PIN9) | PIN_OSPEED_100M(GPIOA_PIN10) | PIN_OSPEED_100M(GPIOA_OTG_FS_DM) | PIN_OSPEED_100M(GPIOA_OTG_FS_DP) | PIN_OSPEED_100M(GPIOA_SWDIO) | PIN_OSPEED_100M(GPIOA_SWCLK) | PIN_OSPEED_100M(GPIOA_CAN1_PWR_LED)) 181 | #define VAL_GPIOA_PUPDR (PIN_PUPDR_FLOATING(GPIOA_USER_BUTTON) | PIN_PUPDR_FLOATING(GPIOA_CAN_SILENT) | PIN_PUPDR_FLOATING(GPIOA_V_BUS_SENSE) | PIN_PUPDR_FLOATING(GPIOA_PIN3) | PIN_PUPDR_PULLUP(GPIOA_PIN4) | PIN_PUPDR_PULLUP(GPIOA_PIN5) | PIN_PUPDR_PULLUP(GPIOA_PIN6) | PIN_PUPDR_PULLUP(GPIOA_PIN7) | PIN_PUPDR_PULLUP(GPIOA_PIN8) | PIN_PUPDR_PULLUP(GPIOA_PIN9) | PIN_PUPDR_PULLUP(GPIOA_PIN10) | PIN_PUPDR_FLOATING(GPIOA_OTG_FS_DM) | PIN_PUPDR_FLOATING(GPIOA_OTG_FS_DP) | PIN_PUPDR_PULLUP(GPIOA_SWDIO) | PIN_PUPDR_PULLDOWN(GPIOA_SWCLK) | PIN_PUPDR_FLOATING(GPIOA_CAN1_PWR_LED)) 182 | #define VAL_GPIOA_ODR (PIN_ODR_HIGH(GPIOA_USER_BUTTON) | PIN_ODR_HIGH(GPIOA_CAN_SILENT) | PIN_ODR_HIGH(GPIOA_V_BUS_SENSE) | PIN_ODR_HIGH(GPIOA_PIN3) | PIN_ODR_HIGH(GPIOA_PIN4) | PIN_ODR_LOW(GPIOA_PIN5) | PIN_ODR_HIGH(GPIOA_PIN6) | PIN_ODR_HIGH(GPIOA_PIN7) | PIN_ODR_HIGH(GPIOA_PIN8) | PIN_ODR_HIGH(GPIOA_PIN9) | PIN_ODR_HIGH(GPIOA_PIN10) | PIN_ODR_LOW(GPIOA_OTG_FS_DM) | PIN_ODR_LOW(GPIOA_OTG_FS_DP) | PIN_ODR_HIGH(GPIOA_SWDIO) | PIN_ODR_HIGH(GPIOA_SWCLK) | PIN_ODR_LOW(GPIOA_CAN1_PWR_LED)) 183 | #define VAL_GPIOA_AFRL (PIN_AFIO_AF(GPIOA_USER_BUTTON, 0) | PIN_AFIO_AF(GPIOA_CAN_SILENT, 0) | PIN_AFIO_AF(GPIOA_V_BUS_SENSE, 0) | PIN_AFIO_AF(GPIOA_PIN3, 7) | PIN_AFIO_AF(GPIOA_PIN4, 0) | PIN_AFIO_AF(GPIOA_PIN5, 0) | PIN_AFIO_AF(GPIOA_PIN6, 0) | PIN_AFIO_AF(GPIOA_PIN7, 0)) 184 | #define VAL_GPIOA_AFRH (PIN_AFIO_AF(GPIOA_PIN8, 0) | PIN_AFIO_AF(GPIOA_PIN9, 0) | PIN_AFIO_AF(GPIOA_PIN10, 0) | PIN_AFIO_AF(GPIOA_OTG_FS_DM, 10) | PIN_AFIO_AF(GPIOA_OTG_FS_DP, 10) | PIN_AFIO_AF(GPIOA_SWDIO, 0) | PIN_AFIO_AF(GPIOA_SWCLK, 0) | PIN_AFIO_AF(GPIOA_CAN1_PWR_LED, 0)) 185 | 186 | /* 187 | * GPIOB setup: 188 | * 189 | * PB0 - GPIOB_PIN0 (input pullup). 190 | * PB1 - GPIOB_PIN1 (input pullup). 191 | * PB2 - GPIOB_PIN2 (input pullup). 192 | * PB3 - GPIOB_CAN1_STATUS_LED (output low). 193 | * PB4 - GPIOB_PIN4 (input pullup). 194 | * PB5 - GPIOB_V_BUS_ENABLE (output low). 195 | * PB6 - GPIOB_UART1_TX (alternate 7). 196 | * PB7 - GPIOB_UART1_RX (alternate 7). 197 | * PB8 - GPIOB_CAN1_RX (alternate 9). 198 | * PB9 - GPIOB_CAN1_TX (alternate 9). 199 | * PB10 - GPIOB_PIN10 (input pullup). 200 | * PB11 - GPIOB_PIN11 (input pullup). 201 | * PB12 - GPIOB_STATUS_LED (output pushpull). 202 | * PB13 - GPIOB_PIN13 (input pullup). 203 | * PB14 - GPIOB_PIN14 (input pullup). 204 | * PB15 - GPIOB_PIN15 (input pullup). 205 | */ 206 | #define VAL_GPIOB_MODER (PIN_MODE_INPUT(GPIOB_PIN0) | PIN_MODE_INPUT(GPIOB_PIN1) | PIN_MODE_INPUT(GPIOB_PIN2) | PIN_MODE_OUTPUT(GPIOB_CAN1_STATUS_LED) | PIN_MODE_INPUT(GPIOB_PIN4) | PIN_MODE_OUTPUT(GPIOB_V_BUS_ENABLE) | PIN_MODE_ALTERNATE(GPIOB_UART1_TX) | PIN_MODE_ALTERNATE(GPIOB_UART1_RX) | PIN_MODE_ALTERNATE(GPIOB_CAN1_RX) | PIN_MODE_ALTERNATE(GPIOB_CAN1_TX) | PIN_MODE_INPUT(GPIOB_PIN10) | PIN_MODE_INPUT(GPIOB_PIN11) | PIN_MODE_OUTPUT(GPIOB_STATUS_LED) | PIN_MODE_INPUT(GPIOB_PIN13) | PIN_MODE_INPUT(GPIOB_PIN14) | PIN_MODE_INPUT(GPIOB_PIN15)) 207 | #define VAL_GPIOB_OTYPER (PIN_OTYPE_PUSHPULL(GPIOB_PIN0) | PIN_OTYPE_PUSHPULL(GPIOB_PIN1) | PIN_OTYPE_PUSHPULL(GPIOB_PIN2) | PIN_OTYPE_PUSHPULL(GPIOB_CAN1_STATUS_LED) | PIN_OTYPE_PUSHPULL(GPIOB_PIN4) | PIN_OTYPE_PUSHPULL(GPIOB_V_BUS_ENABLE) | PIN_OTYPE_PUSHPULL(GPIOB_UART1_TX) | PIN_OTYPE_PUSHPULL(GPIOB_UART1_RX) | PIN_OTYPE_PUSHPULL(GPIOB_CAN1_RX) | PIN_OTYPE_PUSHPULL(GPIOB_CAN1_TX) | PIN_OTYPE_PUSHPULL(GPIOB_PIN10) | PIN_OTYPE_PUSHPULL(GPIOB_PIN11) | PIN_OTYPE_PUSHPULL(GPIOB_STATUS_LED) | PIN_OTYPE_PUSHPULL(GPIOB_PIN13) | PIN_OTYPE_PUSHPULL(GPIOB_PIN14) | PIN_OTYPE_PUSHPULL(GPIOB_PIN15)) 208 | #define VAL_GPIOB_OSPEEDR (PIN_OSPEED_100M(GPIOB_PIN0) | PIN_OSPEED_100M(GPIOB_PIN1) | PIN_OSPEED_100M(GPIOB_PIN2) | PIN_OSPEED_100M(GPIOB_CAN1_STATUS_LED) | PIN_OSPEED_100M(GPIOB_PIN4) | PIN_OSPEED_100M(GPIOB_V_BUS_ENABLE) | PIN_OSPEED_100M(GPIOB_UART1_TX) | PIN_OSPEED_100M(GPIOB_UART1_RX) | PIN_OSPEED_100M(GPIOB_CAN1_RX) | PIN_OSPEED_100M(GPIOB_CAN1_TX) | PIN_OSPEED_100M(GPIOB_PIN10) | PIN_OSPEED_100M(GPIOB_PIN11) | PIN_OSPEED_100M(GPIOB_STATUS_LED) | PIN_OSPEED_100M(GPIOB_PIN13) | PIN_OSPEED_100M(GPIOB_PIN14) | PIN_OSPEED_100M(GPIOB_PIN15)) 209 | #define VAL_GPIOB_PUPDR (PIN_PUPDR_PULLUP(GPIOB_PIN0) | PIN_PUPDR_PULLUP(GPIOB_PIN1) | PIN_PUPDR_PULLUP(GPIOB_PIN2) | PIN_PUPDR_FLOATING(GPIOB_CAN1_STATUS_LED) | PIN_PUPDR_PULLUP(GPIOB_PIN4) | PIN_PUPDR_FLOATING(GPIOB_V_BUS_ENABLE) | PIN_PUPDR_FLOATING(GPIOB_UART1_TX) | PIN_PUPDR_PULLUP(GPIOB_UART1_RX) | PIN_PUPDR_FLOATING(GPIOB_CAN1_RX) | PIN_PUPDR_FLOATING(GPIOB_CAN1_TX) | PIN_PUPDR_PULLUP(GPIOB_PIN10) | PIN_PUPDR_PULLUP(GPIOB_PIN11) | PIN_PUPDR_FLOATING(GPIOB_STATUS_LED) | PIN_PUPDR_PULLUP(GPIOB_PIN13) | PIN_PUPDR_PULLUP(GPIOB_PIN14) | PIN_PUPDR_PULLUP(GPIOB_PIN15)) 210 | #define VAL_GPIOB_ODR (PIN_ODR_HIGH(GPIOB_PIN0) | PIN_ODR_HIGH(GPIOB_PIN1) | PIN_ODR_HIGH(GPIOB_PIN2) | PIN_ODR_LOW(GPIOB_CAN1_STATUS_LED) | PIN_ODR_HIGH(GPIOB_PIN4) | PIN_ODR_LOW(GPIOB_V_BUS_ENABLE) | PIN_ODR_HIGH(GPIOB_UART1_TX) | PIN_ODR_HIGH(GPIOB_UART1_RX) | PIN_ODR_HIGH(GPIOB_CAN1_RX) | PIN_ODR_HIGH(GPIOB_CAN1_TX) | PIN_ODR_HIGH(GPIOB_PIN10) | PIN_ODR_HIGH(GPIOB_PIN11) | PIN_ODR_LOW(GPIOB_STATUS_LED) | PIN_ODR_HIGH(GPIOB_PIN13) | PIN_ODR_HIGH(GPIOB_PIN14) | PIN_ODR_HIGH(GPIOB_PIN15)) 211 | #define VAL_GPIOB_AFRL (PIN_AFIO_AF(GPIOB_PIN0, 0) | PIN_AFIO_AF(GPIOB_PIN1, 0) | PIN_AFIO_AF(GPIOB_PIN2, 0) | PIN_AFIO_AF(GPIOB_CAN1_STATUS_LED, 0) | PIN_AFIO_AF(GPIOB_PIN4, 0) | PIN_AFIO_AF(GPIOB_V_BUS_ENABLE, 0) | PIN_AFIO_AF(GPIOB_UART1_TX, 7) | PIN_AFIO_AF(GPIOB_UART1_RX, 7)) 212 | #define VAL_GPIOB_AFRH (PIN_AFIO_AF(GPIOB_CAN1_RX, 9) | PIN_AFIO_AF(GPIOB_CAN1_TX, 9) | PIN_AFIO_AF(GPIOB_PIN10, 0) | PIN_AFIO_AF(GPIOB_PIN11, 0) | PIN_AFIO_AF(GPIOB_STATUS_LED, 0) | PIN_AFIO_AF(GPIOB_PIN13, 0) | PIN_AFIO_AF(GPIOB_PIN14, 0) | PIN_AFIO_AF(GPIOB_PIN15, 0)) 213 | 214 | /* 215 | * GPIOC setup: 216 | * 217 | * PC0 - PIN0 (input pullup). 218 | * PC1 - PIN1 (input pullup). 219 | * PC2 - PIN2 (input pullup). 220 | * PC3 - PIN3 (input pullup). 221 | * PC4 - PIN4 (input pullup). 222 | * PC5 - PIN5 (input pullup). 223 | * PC6 - PIN6 (input pullup). 224 | * PC7 - PIN7 (input pullup). 225 | * PC8 - PIN8 (input pullup). 226 | * PC9 - PIN9 (input pullup). 227 | * PC10 - PIN10 (input pullup). 228 | * PC11 - PIN11 (input pullup). 229 | * PC12 - PIN12 (input pullup). 230 | * PC13 - PIN13 (input pullup). 231 | * PC14 - PIN14 (input pullup). 232 | * PC15 - PIN15 (input pullup). 233 | */ 234 | #define VAL_GPIOC_MODER (PIN_MODE_INPUT(GPIOC_PIN0) | PIN_MODE_INPUT(GPIOC_PIN1) | PIN_MODE_INPUT(GPIOC_PIN2) | PIN_MODE_INPUT(GPIOC_PIN3) | PIN_MODE_INPUT(GPIOC_PIN4) | PIN_MODE_INPUT(GPIOC_PIN5) | PIN_MODE_INPUT(GPIOC_PIN6) | PIN_MODE_INPUT(GPIOC_PIN7) | PIN_MODE_INPUT(GPIOC_PIN8) | PIN_MODE_INPUT(GPIOC_PIN9) | PIN_MODE_INPUT(GPIOC_PIN10) | PIN_MODE_INPUT(GPIOC_PIN11) | PIN_MODE_INPUT(GPIOC_PIN12) | PIN_MODE_INPUT(GPIOC_PIN13) | PIN_MODE_INPUT(GPIOC_PIN14) | PIN_MODE_INPUT(GPIOC_PIN15)) 235 | #define VAL_GPIOC_OTYPER (PIN_OTYPE_PUSHPULL(GPIOC_PIN0) | PIN_OTYPE_PUSHPULL(GPIOC_PIN1) | PIN_OTYPE_PUSHPULL(GPIOC_PIN2) | PIN_OTYPE_PUSHPULL(GPIOC_PIN3) | PIN_OTYPE_PUSHPULL(GPIOC_PIN4) | PIN_OTYPE_PUSHPULL(GPIOC_PIN5) | PIN_OTYPE_PUSHPULL(GPIOC_PIN6) | PIN_OTYPE_PUSHPULL(GPIOC_PIN7) | PIN_OTYPE_PUSHPULL(GPIOC_PIN8) | PIN_OTYPE_PUSHPULL(GPIOC_PIN9) | PIN_OTYPE_PUSHPULL(GPIOC_PIN10) | PIN_OTYPE_PUSHPULL(GPIOC_PIN11) | PIN_OTYPE_PUSHPULL(GPIOC_PIN12) | PIN_OTYPE_PUSHPULL(GPIOC_PIN13) | PIN_OTYPE_PUSHPULL(GPIOC_PIN14) | PIN_OTYPE_PUSHPULL(GPIOC_PIN15)) 236 | #define VAL_GPIOC_OSPEEDR (PIN_OSPEED_100M(GPIOC_PIN0) | PIN_OSPEED_100M(GPIOC_PIN1) | PIN_OSPEED_100M(GPIOC_PIN2) | PIN_OSPEED_100M(GPIOC_PIN3) | PIN_OSPEED_100M(GPIOC_PIN4) | PIN_OSPEED_100M(GPIOC_PIN5) | PIN_OSPEED_100M(GPIOC_PIN6) | PIN_OSPEED_100M(GPIOC_PIN7) | PIN_OSPEED_100M(GPIOC_PIN8) | PIN_OSPEED_100M(GPIOC_PIN9) | PIN_OSPEED_100M(GPIOC_PIN10) | PIN_OSPEED_100M(GPIOC_PIN11) | PIN_OSPEED_100M(GPIOC_PIN12) | PIN_OSPEED_100M(GPIOC_PIN13) | PIN_OSPEED_100M(GPIOC_PIN14) | PIN_OSPEED_100M(GPIOC_PIN15)) 237 | #define VAL_GPIOC_PUPDR (PIN_PUPDR_PULLUP(GPIOC_PIN0) | PIN_PUPDR_PULLUP(GPIOC_PIN1) | PIN_PUPDR_PULLUP(GPIOC_PIN2) | PIN_PUPDR_PULLUP(GPIOC_PIN3) | PIN_PUPDR_PULLUP(GPIOC_PIN4) | PIN_PUPDR_PULLUP(GPIOC_PIN5) | PIN_PUPDR_PULLUP(GPIOC_PIN6) | PIN_PUPDR_PULLUP(GPIOC_PIN7) | PIN_PUPDR_PULLUP(GPIOC_PIN8) | PIN_PUPDR_PULLUP(GPIOC_PIN9) | PIN_PUPDR_PULLUP(GPIOC_PIN10) | PIN_PUPDR_PULLUP(GPIOC_PIN11) | PIN_PUPDR_PULLUP(GPIOC_PIN12) | PIN_PUPDR_PULLUP(GPIOC_PIN13) | PIN_PUPDR_PULLUP(GPIOC_PIN14) | PIN_PUPDR_PULLUP(GPIOC_PIN15)) 238 | #define VAL_GPIOC_ODR (PIN_ODR_HIGH(GPIOC_PIN0) | PIN_ODR_HIGH(GPIOC_PIN1) | PIN_ODR_HIGH(GPIOC_PIN2) | PIN_ODR_HIGH(GPIOC_PIN3) | PIN_ODR_HIGH(GPIOC_PIN4) | PIN_ODR_HIGH(GPIOC_PIN5) | PIN_ODR_HIGH(GPIOC_PIN6) | PIN_ODR_HIGH(GPIOC_PIN7) | PIN_ODR_HIGH(GPIOC_PIN8) | PIN_ODR_HIGH(GPIOC_PIN9) | PIN_ODR_HIGH(GPIOC_PIN10) | PIN_ODR_HIGH(GPIOC_PIN11) | PIN_ODR_HIGH(GPIOC_PIN12) | PIN_ODR_HIGH(GPIOC_PIN13) | PIN_ODR_HIGH(GPIOC_PIN14) | PIN_ODR_HIGH(GPIOC_PIN15)) 239 | #define VAL_GPIOC_AFRL (PIN_AFIO_AF(GPIOC_PIN0, 0) | PIN_AFIO_AF(GPIOC_PIN1, 0) | PIN_AFIO_AF(GPIOC_PIN2, 0) | PIN_AFIO_AF(GPIOC_PIN3, 0) | PIN_AFIO_AF(GPIOC_PIN4, 0) | PIN_AFIO_AF(GPIOC_PIN5, 0) | PIN_AFIO_AF(GPIOC_PIN6, 0) | PIN_AFIO_AF(GPIOC_PIN7, 0)) 240 | #define VAL_GPIOC_AFRH (PIN_AFIO_AF(GPIOC_PIN8, 0) | PIN_AFIO_AF(GPIOC_PIN9, 0) | PIN_AFIO_AF(GPIOC_PIN10, 0) | PIN_AFIO_AF(GPIOC_PIN11, 0) | PIN_AFIO_AF(GPIOC_PIN12, 0) | PIN_AFIO_AF(GPIOC_PIN13, 0) | PIN_AFIO_AF(GPIOC_PIN14, 0) | PIN_AFIO_AF(GPIOC_PIN15, 0)) 241 | 242 | /* 243 | * GPIOD setup: 244 | * 245 | * PD0 - PIN0 (input pullup). 246 | * PD1 - PIN1 (input pullup). 247 | * PD2 - PIN2 (input pullup). 248 | * PD3 - PIN3 (input pullup). 249 | * PD4 - PIN4 (input pullup). 250 | * PD5 - PIN5 (input pullup). 251 | * PD6 - PIN6 (input pullup). 252 | * PD7 - PIN7 (input pullup). 253 | * PD8 - PIN8 (input pullup). 254 | * PD9 - PIN9 (input pullup). 255 | * PD10 - PIN10 (input pullup). 256 | * PD11 - PIN11 (input pullup). 257 | * PD12 - PIN12 (input pullup). 258 | * PD13 - PIN13 (input pullup). 259 | * PD14 - PIN14 (input pullup). 260 | * PD15 - PIN15 (input pullup). 261 | */ 262 | #define VAL_GPIOD_MODER (PIN_MODE_INPUT(GPIOD_PIN0) | PIN_MODE_INPUT(GPIOD_PIN1) | PIN_MODE_INPUT(GPIOD_PIN2) | PIN_MODE_INPUT(GPIOD_PIN3) | PIN_MODE_INPUT(GPIOD_PIN4) | PIN_MODE_INPUT(GPIOD_PIN5) | PIN_MODE_INPUT(GPIOD_PIN6) | PIN_MODE_INPUT(GPIOD_PIN7) | PIN_MODE_INPUT(GPIOD_PIN8) | PIN_MODE_INPUT(GPIOD_PIN9) | PIN_MODE_INPUT(GPIOD_PIN10) | PIN_MODE_INPUT(GPIOD_PIN11) | PIN_MODE_INPUT(GPIOD_PIN12) | PIN_MODE_INPUT(GPIOD_PIN13) | PIN_MODE_INPUT(GPIOD_PIN14) | PIN_MODE_INPUT(GPIOD_PIN15)) 263 | #define VAL_GPIOD_OTYPER (PIN_OTYPE_PUSHPULL(GPIOD_PIN0) | PIN_OTYPE_PUSHPULL(GPIOD_PIN1) | PIN_OTYPE_PUSHPULL(GPIOD_PIN2) | PIN_OTYPE_PUSHPULL(GPIOD_PIN3) | PIN_OTYPE_PUSHPULL(GPIOD_PIN4) | PIN_OTYPE_PUSHPULL(GPIOD_PIN5) | PIN_OTYPE_PUSHPULL(GPIOD_PIN6) | PIN_OTYPE_PUSHPULL(GPIOD_PIN7) | PIN_OTYPE_PUSHPULL(GPIOD_PIN8) | PIN_OTYPE_PUSHPULL(GPIOD_PIN9) | PIN_OTYPE_PUSHPULL(GPIOD_PIN10) | PIN_OTYPE_PUSHPULL(GPIOD_PIN11) | PIN_OTYPE_PUSHPULL(GPIOD_PIN12) | PIN_OTYPE_PUSHPULL(GPIOD_PIN13) | PIN_OTYPE_PUSHPULL(GPIOD_PIN14) | PIN_OTYPE_PUSHPULL(GPIOD_PIN15)) 264 | #define VAL_GPIOD_OSPEEDR (PIN_OSPEED_100M(GPIOD_PIN0) | PIN_OSPEED_100M(GPIOD_PIN1) | PIN_OSPEED_100M(GPIOD_PIN2) | PIN_OSPEED_100M(GPIOD_PIN3) | PIN_OSPEED_100M(GPIOD_PIN4) | PIN_OSPEED_100M(GPIOD_PIN5) | PIN_OSPEED_100M(GPIOD_PIN6) | PIN_OSPEED_100M(GPIOD_PIN7) | PIN_OSPEED_100M(GPIOD_PIN8) | PIN_OSPEED_100M(GPIOD_PIN9) | PIN_OSPEED_100M(GPIOD_PIN10) | PIN_OSPEED_100M(GPIOD_PIN11) | PIN_OSPEED_100M(GPIOD_PIN12) | PIN_OSPEED_100M(GPIOD_PIN13) | PIN_OSPEED_100M(GPIOD_PIN14) | PIN_OSPEED_100M(GPIOD_PIN15)) 265 | #define VAL_GPIOD_PUPDR (PIN_PUPDR_PULLUP(GPIOD_PIN0) | PIN_PUPDR_PULLUP(GPIOD_PIN1) | PIN_PUPDR_PULLUP(GPIOD_PIN2) | PIN_PUPDR_PULLUP(GPIOD_PIN3) | PIN_PUPDR_PULLUP(GPIOD_PIN4) | PIN_PUPDR_PULLUP(GPIOD_PIN5) | PIN_PUPDR_PULLUP(GPIOD_PIN6) | PIN_PUPDR_PULLUP(GPIOD_PIN7) | PIN_PUPDR_PULLUP(GPIOD_PIN8) | PIN_PUPDR_PULLUP(GPIOD_PIN9) | PIN_PUPDR_PULLUP(GPIOD_PIN10) | PIN_PUPDR_PULLUP(GPIOD_PIN11) | PIN_PUPDR_PULLUP(GPIOD_PIN12) | PIN_PUPDR_PULLUP(GPIOD_PIN13) | PIN_PUPDR_PULLUP(GPIOD_PIN14) | PIN_PUPDR_PULLUP(GPIOD_PIN15)) 266 | #define VAL_GPIOD_ODR (PIN_ODR_HIGH(GPIOD_PIN0) | PIN_ODR_HIGH(GPIOD_PIN1) | PIN_ODR_HIGH(GPIOD_PIN2) | PIN_ODR_HIGH(GPIOD_PIN3) | PIN_ODR_HIGH(GPIOD_PIN4) | PIN_ODR_HIGH(GPIOD_PIN5) | PIN_ODR_HIGH(GPIOD_PIN6) | PIN_ODR_HIGH(GPIOD_PIN7) | PIN_ODR_HIGH(GPIOD_PIN8) | PIN_ODR_HIGH(GPIOD_PIN9) | PIN_ODR_HIGH(GPIOD_PIN10) | PIN_ODR_HIGH(GPIOD_PIN11) | PIN_ODR_HIGH(GPIOD_PIN12) | PIN_ODR_HIGH(GPIOD_PIN13) | PIN_ODR_HIGH(GPIOD_PIN14) | PIN_ODR_HIGH(GPIOD_PIN15)) 267 | #define VAL_GPIOD_AFRL (PIN_AFIO_AF(GPIOD_PIN0, 0) | PIN_AFIO_AF(GPIOD_PIN1, 0) | PIN_AFIO_AF(GPIOD_PIN2, 0) | PIN_AFIO_AF(GPIOD_PIN3, 0) | PIN_AFIO_AF(GPIOD_PIN4, 0) | PIN_AFIO_AF(GPIOD_PIN5, 0) | PIN_AFIO_AF(GPIOD_PIN6, 0) | PIN_AFIO_AF(GPIOD_PIN7, 0)) 268 | #define VAL_GPIOD_AFRH (PIN_AFIO_AF(GPIOD_PIN8, 0) | PIN_AFIO_AF(GPIOD_PIN9, 0) | PIN_AFIO_AF(GPIOD_PIN10, 0) | PIN_AFIO_AF(GPIOD_PIN11, 0) | PIN_AFIO_AF(GPIOD_PIN12, 0) | PIN_AFIO_AF(GPIOD_PIN13, 0) | PIN_AFIO_AF(GPIOD_PIN14, 0) | PIN_AFIO_AF(GPIOD_PIN15, 0)) 269 | 270 | /* 271 | * GPIOE setup: 272 | * 273 | * PE0 - PIN0 (input floating). 274 | * PE1 - PIN1 (input floating). 275 | * PE2 - PIN2 (input floating). 276 | * PE3 - PIN3 (input floating). 277 | * PE4 - PIN4 (input floating). 278 | * PE5 - PIN5 (input floating). 279 | * PE6 - PIN6 (input floating). 280 | * PE7 - PIN7 (input floating). 281 | * PE8 - PIN8 (input floating). 282 | * PE9 - PIN9 (input floating). 283 | * PE10 - PIN10 (input floating). 284 | * PE11 - PIN11 (input floating). 285 | * PE12 - PIN12 (input floating). 286 | * PE13 - PIN13 (input floating). 287 | * PE14 - PIN14 (input floating). 288 | * PE15 - PIN15 (input floating). 289 | */ 290 | #define VAL_GPIOE_MODER (PIN_MODE_INPUT(GPIOE_PIN0) | PIN_MODE_INPUT(GPIOE_PIN1) | PIN_MODE_INPUT(GPIOE_PIN2) | PIN_MODE_INPUT(GPIOE_PIN3) | PIN_MODE_INPUT(GPIOE_PIN4) | PIN_MODE_INPUT(GPIOE_PIN5) | PIN_MODE_INPUT(GPIOE_PIN6) | PIN_MODE_INPUT(GPIOE_PIN7) | PIN_MODE_INPUT(GPIOE_PIN8) | PIN_MODE_INPUT(GPIOE_PIN9) | PIN_MODE_INPUT(GPIOE_PIN10) | PIN_MODE_INPUT(GPIOE_PIN11) | PIN_MODE_INPUT(GPIOE_PIN12) | PIN_MODE_INPUT(GPIOE_PIN13) | PIN_MODE_INPUT(GPIOE_PIN14) | PIN_MODE_INPUT(GPIOE_PIN15)) 291 | #define VAL_GPIOE_OTYPER (PIN_OTYPE_PUSHPULL(GPIOE_PIN0) | PIN_OTYPE_PUSHPULL(GPIOE_PIN1) | PIN_OTYPE_PUSHPULL(GPIOE_PIN2) | PIN_OTYPE_PUSHPULL(GPIOE_PIN3) | PIN_OTYPE_PUSHPULL(GPIOE_PIN4) | PIN_OTYPE_PUSHPULL(GPIOE_PIN5) | PIN_OTYPE_PUSHPULL(GPIOE_PIN6) | PIN_OTYPE_PUSHPULL(GPIOE_PIN7) | PIN_OTYPE_PUSHPULL(GPIOE_PIN8) | PIN_OTYPE_PUSHPULL(GPIOE_PIN9) | PIN_OTYPE_PUSHPULL(GPIOE_PIN10) | PIN_OTYPE_PUSHPULL(GPIOE_PIN11) | PIN_OTYPE_PUSHPULL(GPIOE_PIN12) | PIN_OTYPE_PUSHPULL(GPIOE_PIN13) | PIN_OTYPE_PUSHPULL(GPIOE_PIN14) | PIN_OTYPE_PUSHPULL(GPIOE_PIN15)) 292 | #define VAL_GPIOE_OSPEEDR (PIN_OSPEED_100M(GPIOE_PIN0) | PIN_OSPEED_100M(GPIOE_PIN1) | PIN_OSPEED_100M(GPIOE_PIN2) | PIN_OSPEED_100M(GPIOE_PIN3) | PIN_OSPEED_100M(GPIOE_PIN4) | PIN_OSPEED_100M(GPIOE_PIN5) | PIN_OSPEED_100M(GPIOE_PIN6) | PIN_OSPEED_100M(GPIOE_PIN7) | PIN_OSPEED_100M(GPIOE_PIN8) | PIN_OSPEED_100M(GPIOE_PIN9) | PIN_OSPEED_100M(GPIOE_PIN10) | PIN_OSPEED_100M(GPIOE_PIN11) | PIN_OSPEED_100M(GPIOE_PIN12) | PIN_OSPEED_100M(GPIOE_PIN13) | PIN_OSPEED_100M(GPIOE_PIN14) | PIN_OSPEED_100M(GPIOE_PIN15)) 293 | #define VAL_GPIOE_PUPDR (PIN_PUPDR_FLOATING(GPIOE_PIN0) | PIN_PUPDR_FLOATING(GPIOE_PIN1) | PIN_PUPDR_FLOATING(GPIOE_PIN2) | PIN_PUPDR_FLOATING(GPIOE_PIN3) | PIN_PUPDR_FLOATING(GPIOE_PIN4) | PIN_PUPDR_FLOATING(GPIOE_PIN5) | PIN_PUPDR_FLOATING(GPIOE_PIN6) | PIN_PUPDR_FLOATING(GPIOE_PIN7) | PIN_PUPDR_FLOATING(GPIOE_PIN8) | PIN_PUPDR_FLOATING(GPIOE_PIN9) | PIN_PUPDR_FLOATING(GPIOE_PIN10) | PIN_PUPDR_FLOATING(GPIOE_PIN11) | PIN_PUPDR_FLOATING(GPIOE_PIN12) | PIN_PUPDR_FLOATING(GPIOE_PIN13) | PIN_PUPDR_FLOATING(GPIOE_PIN14) | PIN_PUPDR_FLOATING(GPIOE_PIN15)) 294 | #define VAL_GPIOE_ODR (PIN_ODR_HIGH(GPIOE_PIN0) | PIN_ODR_HIGH(GPIOE_PIN1) | PIN_ODR_HIGH(GPIOE_PIN2) | PIN_ODR_HIGH(GPIOE_PIN3) | PIN_ODR_HIGH(GPIOE_PIN4) | PIN_ODR_HIGH(GPIOE_PIN5) | PIN_ODR_HIGH(GPIOE_PIN6) | PIN_ODR_HIGH(GPIOE_PIN7) | PIN_ODR_HIGH(GPIOE_PIN8) | PIN_ODR_HIGH(GPIOE_PIN9) | PIN_ODR_HIGH(GPIOE_PIN10) | PIN_ODR_HIGH(GPIOE_PIN11) | PIN_ODR_HIGH(GPIOE_PIN12) | PIN_ODR_HIGH(GPIOE_PIN13) | PIN_ODR_HIGH(GPIOE_PIN14) | PIN_ODR_HIGH(GPIOE_PIN15)) 295 | #define VAL_GPIOE_AFRL (PIN_AFIO_AF(GPIOE_PIN0, 0) | PIN_AFIO_AF(GPIOE_PIN1, 0) | PIN_AFIO_AF(GPIOE_PIN2, 0) | PIN_AFIO_AF(GPIOE_PIN3, 0) | PIN_AFIO_AF(GPIOE_PIN4, 0) | PIN_AFIO_AF(GPIOE_PIN5, 0) | PIN_AFIO_AF(GPIOE_PIN6, 0) | PIN_AFIO_AF(GPIOE_PIN7, 0)) 296 | #define VAL_GPIOE_AFRH (PIN_AFIO_AF(GPIOE_PIN8, 0) | PIN_AFIO_AF(GPIOE_PIN9, 0) | PIN_AFIO_AF(GPIOE_PIN10, 0) | PIN_AFIO_AF(GPIOE_PIN11, 0) | PIN_AFIO_AF(GPIOE_PIN12, 0) | PIN_AFIO_AF(GPIOE_PIN13, 0) | PIN_AFIO_AF(GPIOE_PIN14, 0) | PIN_AFIO_AF(GPIOE_PIN15, 0)) 297 | 298 | /* 299 | * GPIOF setup: 300 | * 301 | * PF0 - PIN0 (input floating). 302 | * PF1 - PIN1 (input floating). 303 | * PF2 - PIN2 (input floating). 304 | * PF3 - PIN3 (input floating). 305 | * PF4 - PIN4 (input floating). 306 | * PF5 - PIN5 (input floating). 307 | * PF6 - PIN6 (input floating). 308 | * PF7 - PIN7 (input floating). 309 | * PF8 - PIN8 (input floating). 310 | * PF9 - PIN9 (input floating). 311 | * PF10 - PIN10 (input floating). 312 | * PF11 - PIN11 (input floating). 313 | * PF12 - PIN12 (input floating). 314 | * PF13 - PIN13 (input floating). 315 | * PF14 - PIN14 (input floating). 316 | * PF15 - PIN15 (input floating). 317 | */ 318 | #define VAL_GPIOF_MODER (PIN_MODE_INPUT(GPIOF_PIN0) | PIN_MODE_INPUT(GPIOF_PIN1) | PIN_MODE_INPUT(GPIOF_PIN2) | PIN_MODE_INPUT(GPIOF_PIN3) | PIN_MODE_INPUT(GPIOF_PIN4) | PIN_MODE_INPUT(GPIOF_PIN5) | PIN_MODE_INPUT(GPIOF_PIN6) | PIN_MODE_INPUT(GPIOF_PIN7) | PIN_MODE_INPUT(GPIOF_PIN8) | PIN_MODE_INPUT(GPIOF_PIN9) | PIN_MODE_INPUT(GPIOF_PIN10) | PIN_MODE_INPUT(GPIOF_PIN11) | PIN_MODE_INPUT(GPIOF_PIN12) | PIN_MODE_INPUT(GPIOF_PIN13) | PIN_MODE_INPUT(GPIOF_PIN14) | PIN_MODE_INPUT(GPIOF_PIN15)) 319 | #define VAL_GPIOF_OTYPER (PIN_OTYPE_PUSHPULL(GPIOF_PIN0) | PIN_OTYPE_PUSHPULL(GPIOF_PIN1) | PIN_OTYPE_PUSHPULL(GPIOF_PIN2) | PIN_OTYPE_PUSHPULL(GPIOF_PIN3) | PIN_OTYPE_PUSHPULL(GPIOF_PIN4) | PIN_OTYPE_PUSHPULL(GPIOF_PIN5) | PIN_OTYPE_PUSHPULL(GPIOF_PIN6) | PIN_OTYPE_PUSHPULL(GPIOF_PIN7) | PIN_OTYPE_PUSHPULL(GPIOF_PIN8) | PIN_OTYPE_PUSHPULL(GPIOF_PIN9) | PIN_OTYPE_PUSHPULL(GPIOF_PIN10) | PIN_OTYPE_PUSHPULL(GPIOF_PIN11) | PIN_OTYPE_PUSHPULL(GPIOF_PIN12) | PIN_OTYPE_PUSHPULL(GPIOF_PIN13) | PIN_OTYPE_PUSHPULL(GPIOF_PIN14) | PIN_OTYPE_PUSHPULL(GPIOF_PIN15)) 320 | #define VAL_GPIOF_OSPEEDR (PIN_OSPEED_100M(GPIOF_PIN0) | PIN_OSPEED_100M(GPIOF_PIN1) | PIN_OSPEED_100M(GPIOF_PIN2) | PIN_OSPEED_100M(GPIOF_PIN3) | PIN_OSPEED_100M(GPIOF_PIN4) | PIN_OSPEED_100M(GPIOF_PIN5) | PIN_OSPEED_100M(GPIOF_PIN6) | PIN_OSPEED_100M(GPIOF_PIN7) | PIN_OSPEED_100M(GPIOF_PIN8) | PIN_OSPEED_100M(GPIOF_PIN9) | PIN_OSPEED_100M(GPIOF_PIN10) | PIN_OSPEED_100M(GPIOF_PIN11) | PIN_OSPEED_100M(GPIOF_PIN12) | PIN_OSPEED_100M(GPIOF_PIN13) | PIN_OSPEED_100M(GPIOF_PIN14) | PIN_OSPEED_100M(GPIOF_PIN15)) 321 | #define VAL_GPIOF_PUPDR (PIN_PUPDR_FLOATING(GPIOF_PIN0) | PIN_PUPDR_FLOATING(GPIOF_PIN1) | PIN_PUPDR_FLOATING(GPIOF_PIN2) | PIN_PUPDR_FLOATING(GPIOF_PIN3) | PIN_PUPDR_FLOATING(GPIOF_PIN4) | PIN_PUPDR_FLOATING(GPIOF_PIN5) | PIN_PUPDR_FLOATING(GPIOF_PIN6) | PIN_PUPDR_FLOATING(GPIOF_PIN7) | PIN_PUPDR_FLOATING(GPIOF_PIN8) | PIN_PUPDR_FLOATING(GPIOF_PIN9) | PIN_PUPDR_FLOATING(GPIOF_PIN10) | PIN_PUPDR_FLOATING(GPIOF_PIN11) | PIN_PUPDR_FLOATING(GPIOF_PIN12) | PIN_PUPDR_FLOATING(GPIOF_PIN13) | PIN_PUPDR_FLOATING(GPIOF_PIN14) | PIN_PUPDR_FLOATING(GPIOF_PIN15)) 322 | #define VAL_GPIOF_ODR (PIN_ODR_HIGH(GPIOF_PIN0) | PIN_ODR_HIGH(GPIOF_PIN1) | PIN_ODR_HIGH(GPIOF_PIN2) | PIN_ODR_HIGH(GPIOF_PIN3) | PIN_ODR_HIGH(GPIOF_PIN4) | PIN_ODR_HIGH(GPIOF_PIN5) | PIN_ODR_HIGH(GPIOF_PIN6) | PIN_ODR_HIGH(GPIOF_PIN7) | PIN_ODR_HIGH(GPIOF_PIN8) | PIN_ODR_HIGH(GPIOF_PIN9) | PIN_ODR_HIGH(GPIOF_PIN10) | PIN_ODR_HIGH(GPIOF_PIN11) | PIN_ODR_HIGH(GPIOF_PIN12) | PIN_ODR_HIGH(GPIOF_PIN13) | PIN_ODR_HIGH(GPIOF_PIN14) | PIN_ODR_HIGH(GPIOF_PIN15)) 323 | #define VAL_GPIOF_AFRL (PIN_AFIO_AF(GPIOF_PIN0, 0) | PIN_AFIO_AF(GPIOF_PIN1, 0) | PIN_AFIO_AF(GPIOF_PIN2, 0) | PIN_AFIO_AF(GPIOF_PIN3, 0) | PIN_AFIO_AF(GPIOF_PIN4, 0) | PIN_AFIO_AF(GPIOF_PIN5, 0) | PIN_AFIO_AF(GPIOF_PIN6, 0) | PIN_AFIO_AF(GPIOF_PIN7, 0)) 324 | #define VAL_GPIOF_AFRH (PIN_AFIO_AF(GPIOF_PIN8, 0) | PIN_AFIO_AF(GPIOF_PIN9, 0) | PIN_AFIO_AF(GPIOF_PIN10, 0) | PIN_AFIO_AF(GPIOF_PIN11, 0) | PIN_AFIO_AF(GPIOF_PIN12, 0) | PIN_AFIO_AF(GPIOF_PIN13, 0) | PIN_AFIO_AF(GPIOF_PIN14, 0) | PIN_AFIO_AF(GPIOF_PIN15, 0)) 325 | 326 | #define STATUS_LED (1 << 0) 327 | #define CAN1_STATUS_LED (1 << 1) 328 | #define CAN1_PWR_LED (1 << 2) 329 | 330 | #define ADC_CHANNEL_VBUS ADC_CHANNEL_IN3 331 | 332 | #if !defined(_FROM_ASM_) 333 | #ifdef __cplusplus 334 | extern "C" { 335 | #endif 336 | #include "board/board_functions.h" 337 | #ifdef __cplusplus 338 | } 339 | #endif 340 | #endif /* _FROM_ASM_ */ 341 | 342 | #endif /* _BOARD_H_ */ 343 | -------------------------------------------------------------------------------- /src/board/CAN-USB-dongle/RevA/board.mk: -------------------------------------------------------------------------------- 1 | # List of all the board related files. 2 | BOARDSRC = src/board/CAN-USB-dongle/RevA/board.c 3 | 4 | # Required include directories 5 | BOARDINC = src/board/CAN-USB-dongle/RevA -------------------------------------------------------------------------------- /src/board/CAN-USB-dongle/RevC/board.c: -------------------------------------------------------------------------------- 1 | /* 2 | ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #include "hal.h" 18 | 19 | #if HAL_USE_PAL || defined(__DOXYGEN__) 20 | /** 21 | * @brief PAL setup. 22 | * @details Digital I/O ports static configuration as defined in @p board.h. 23 | * This variable is used by the HAL when initializing the PAL driver. 24 | */ 25 | const PALConfig pal_default_config = { 26 | #if STM32_HAS_GPIOA 27 | {VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR, 28 | VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH}, 29 | #endif 30 | #if STM32_HAS_GPIOB 31 | {VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR, 32 | VAL_GPIOB_ODR, VAL_GPIOB_AFRL, VAL_GPIOB_AFRH}, 33 | #endif 34 | #if STM32_HAS_GPIOC 35 | {VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR, 36 | VAL_GPIOC_ODR, VAL_GPIOC_AFRL, VAL_GPIOC_AFRH}, 37 | #endif 38 | #if STM32_HAS_GPIOD 39 | {VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR, 40 | VAL_GPIOD_ODR, VAL_GPIOD_AFRL, VAL_GPIOD_AFRH}, 41 | #endif 42 | #if STM32_HAS_GPIOE 43 | {VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR, 44 | VAL_GPIOE_ODR, VAL_GPIOE_AFRL, VAL_GPIOE_AFRH}, 45 | #endif 46 | #if STM32_HAS_GPIOF 47 | {VAL_GPIOF_MODER, VAL_GPIOF_OTYPER, VAL_GPIOF_OSPEEDR, VAL_GPIOF_PUPDR, 48 | VAL_GPIOF_ODR, VAL_GPIOF_AFRL, VAL_GPIOF_AFRH}, 49 | #endif 50 | #if STM32_HAS_GPIOG 51 | {VAL_GPIOG_MODER, VAL_GPIOG_OTYPER, VAL_GPIOG_OSPEEDR, VAL_GPIOG_PUPDR, 52 | VAL_GPIOG_ODR, VAL_GPIOG_AFRL, VAL_GPIOG_AFRH}, 53 | #endif 54 | #if STM32_HAS_GPIOH 55 | {VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR, 56 | VAL_GPIOH_ODR, VAL_GPIOH_AFRL, VAL_GPIOH_AFRH}, 57 | #endif 58 | #if STM32_HAS_GPIOI 59 | {VAL_GPIOI_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR, 60 | VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH} 61 | #endif 62 | }; 63 | #endif 64 | 65 | /** 66 | * @brief Early initialization code. 67 | * @details This initialization must be performed just after stack setup 68 | * and before any other initialization. 69 | */ 70 | void __early_init(void) 71 | { 72 | stm32_clock_init(); 73 | } 74 | 75 | #if HAL_USE_SDC || defined(__DOXYGEN__) 76 | /** 77 | * @brief SDC card detection. 78 | */ 79 | bool sdc_lld_is_card_inserted(SDCDriver* sdcp) 80 | { 81 | (void)sdcp; 82 | /* TODO: Fill the implementation.*/ 83 | return true; 84 | } 85 | 86 | /** 87 | * @brief SDC card write protection detection. 88 | */ 89 | bool sdc_lld_is_write_protected(SDCDriver* sdcp) 90 | { 91 | (void)sdcp; 92 | /* TODO: Fill the implementation.*/ 93 | return false; 94 | } 95 | #endif /* HAL_USE_SDC */ 96 | 97 | #if HAL_USE_MMC_SPI || defined(__DOXYGEN__) 98 | /** 99 | * @brief MMC_SPI card detection. 100 | */ 101 | bool mmc_lld_is_card_inserted(MMCDriver* mmcp) 102 | { 103 | (void)mmcp; 104 | /* TODO: Fill the implementation.*/ 105 | return true; 106 | } 107 | 108 | /** 109 | * @brief MMC_SPI card write protection detection. 110 | */ 111 | bool mmc_lld_is_write_protected(MMCDriver* mmcp) 112 | { 113 | (void)mmcp; 114 | /* TODO: Fill the implementation.*/ 115 | return false; 116 | } 117 | #endif 118 | 119 | /** 120 | * @brief Board-specific initialization code. 121 | * @todo Add your board-specific code, if any. 122 | */ 123 | void boardInit(void) {} 124 | 125 | #if HAL_USE_USB 126 | void usb_lld_disconnect_bus(void* arg) 127 | { 128 | (void)arg; 129 | palSetPadMode(GPIOA, GPIOA_OTG_FS_DM, PAL_MODE_OUTPUT_OPENDRAIN); 130 | palSetPadMode(GPIOA, GPIOA_OTG_FS_DP, PAL_MODE_OUTPUT_OPENDRAIN); 131 | palClearPort(GPIOA, (1 << GPIOA_OTG_FS_DM) | (1 << GPIOA_OTG_FS_DP)); 132 | } 133 | 134 | void usb_lld_connect_bus(void* arg) 135 | { 136 | (void)arg; 137 | palSetPadMode(GPIOA, GPIOA_OTG_FS_DM, PAL_MODE_ALTERNATE(10)); 138 | palSetPadMode(GPIOA, GPIOA_OTG_FS_DP, PAL_MODE_ALTERNATE(10)); 139 | } 140 | #endif 141 | 142 | void led_toggle(unsigned int led) 143 | { 144 | if (led & STATUS_LED) { 145 | palTogglePad(GPIOB, GPIOB_STATUS_LED); 146 | } 147 | if (led & CAN1_STATUS_LED) { 148 | palTogglePad(GPIOB, GPIOB_CAN1_STATUS_LED); 149 | } 150 | if (led & CAN1_PWR_LED) { 151 | palTogglePad(GPIOB, GPIOB_CAN1_PWR_LED); 152 | } 153 | } 154 | 155 | void led_set(unsigned int led) 156 | { 157 | if (led & STATUS_LED) { 158 | palSetPad(GPIOB, GPIOB_STATUS_LED); 159 | } 160 | if (led & CAN1_STATUS_LED) { 161 | palSetPad(GPIOB, GPIOB_CAN1_STATUS_LED); 162 | } 163 | if (led & CAN1_PWR_LED) { 164 | palSetPad(GPIOB, GPIOB_CAN1_PWR_LED); 165 | } 166 | } 167 | 168 | void led_clear(unsigned int led) 169 | { 170 | if (led & STATUS_LED) { 171 | palClearPad(GPIOB, GPIOB_STATUS_LED); 172 | } 173 | if (led & CAN1_STATUS_LED) { 174 | palClearPad(GPIOB, GPIOB_CAN1_STATUS_LED); 175 | } 176 | if (led & CAN1_PWR_LED) { 177 | palClearPad(GPIOB, GPIOB_CAN1_PWR_LED); 178 | } 179 | } 180 | 181 | void can_set_silent_mode(int silent) 182 | { 183 | // The CAN transceiver used on the RevC board has no support for silent 184 | // mode, this is handled by the STM32 CAN hardware instead. 185 | (void)silent; 186 | } 187 | 188 | int user_button_pressed(void) 189 | { 190 | return palReadPad(GPIOA, GPIOA_USER_BUTTON); 191 | } 192 | 193 | void can_bus_power_enable(int enabled) 194 | { 195 | palWritePad(GPIOA, GPIOA_V_BUS_ENABLE, enabled); 196 | } 197 | -------------------------------------------------------------------------------- /src/board/CAN-USB-dongle/RevC/board.mk: -------------------------------------------------------------------------------- 1 | # List of all the board related files. 2 | BOARDSRC = src/board/CAN-USB-dongle/RevC/board.c 3 | 4 | # Required include directories 5 | BOARDINC = src/board/CAN-USB-dongle/RevC 6 | -------------------------------------------------------------------------------- /src/board/board_functions.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARD_FUNCTIONS_H 2 | #define BOARD_FUNCTIONS_H 3 | 4 | void usb_lld_connect_bus(void*); 5 | void usb_lld_disconnect_bus(void*); 6 | void boardInit(void); 7 | 8 | void led_toggle(unsigned int led); 9 | void led_set(unsigned int led); 10 | void led_clear(unsigned int led); 11 | void can_set_silent_mode(int silent); 12 | int user_button_pressed(void); 13 | void can_bus_power_enable(int enabled); 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /src/board/nucleo/board.c: -------------------------------------------------------------------------------- 1 | /* 2 | ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #include "hal.h" 18 | 19 | #if HAL_USE_PAL || defined(__DOXYGEN__) 20 | /** 21 | * @brief PAL setup. 22 | * @details Digital I/O ports static configuration as defined in @p board.h. 23 | * This variable is used by the HAL when initializing the PAL driver. 24 | */ 25 | const PALConfig pal_default_config = { 26 | #if STM32_HAS_GPIOA 27 | {VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR, 28 | VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH}, 29 | #endif 30 | #if STM32_HAS_GPIOB 31 | {VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR, 32 | VAL_GPIOB_ODR, VAL_GPIOB_AFRL, VAL_GPIOB_AFRH}, 33 | #endif 34 | #if STM32_HAS_GPIOC 35 | {VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR, 36 | VAL_GPIOC_ODR, VAL_GPIOC_AFRL, VAL_GPIOC_AFRH}, 37 | #endif 38 | #if STM32_HAS_GPIOD 39 | {VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR, 40 | VAL_GPIOD_ODR, VAL_GPIOD_AFRL, VAL_GPIOD_AFRH}, 41 | #endif 42 | #if STM32_HAS_GPIOE 43 | {VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR, 44 | VAL_GPIOE_ODR, VAL_GPIOE_AFRL, VAL_GPIOE_AFRH}, 45 | #endif 46 | #if STM32_HAS_GPIOF 47 | {VAL_GPIOF_MODER, VAL_GPIOF_OTYPER, VAL_GPIOF_OSPEEDR, VAL_GPIOF_PUPDR, 48 | VAL_GPIOF_ODR, VAL_GPIOF_AFRL, VAL_GPIOF_AFRH}, 49 | #endif 50 | #if STM32_HAS_GPIOG 51 | {VAL_GPIOG_MODER, VAL_GPIOG_OTYPER, VAL_GPIOG_OSPEEDR, VAL_GPIOG_PUPDR, 52 | VAL_GPIOG_ODR, VAL_GPIOG_AFRL, VAL_GPIOG_AFRH}, 53 | #endif 54 | #if STM32_HAS_GPIOH 55 | {VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR, 56 | VAL_GPIOH_ODR, VAL_GPIOH_AFRL, VAL_GPIOH_AFRH}, 57 | #endif 58 | #if STM32_HAS_GPIOI 59 | {VAL_GPIOI_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR, 60 | VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH} 61 | #endif 62 | }; 63 | #endif 64 | 65 | /** 66 | * @brief Early initialization code. 67 | * @details This initialization must be performed just after stack setup 68 | * and before any other initialization. 69 | */ 70 | void __early_init(void) 71 | { 72 | stm32_clock_init(); 73 | } 74 | 75 | #if HAL_USE_SDC || defined(__DOXYGEN__) 76 | /** 77 | * @brief SDC card detection. 78 | */ 79 | bool sdc_lld_is_card_inserted(SDCDriver* sdcp) 80 | { 81 | (void)sdcp; 82 | /* TODO: Fill the implementation.*/ 83 | return true; 84 | } 85 | 86 | /** 87 | * @brief SDC card write protection detection. 88 | */ 89 | bool sdc_lld_is_write_protected(SDCDriver* sdcp) 90 | { 91 | (void)sdcp; 92 | /* TODO: Fill the implementation.*/ 93 | return false; 94 | } 95 | #endif /* HAL_USE_SDC */ 96 | 97 | #if HAL_USE_MMC_SPI || defined(__DOXYGEN__) 98 | /** 99 | * @brief MMC_SPI card detection. 100 | */ 101 | bool mmc_lld_is_card_inserted(MMCDriver* mmcp) 102 | { 103 | (void)mmcp; 104 | /* TODO: Fill the implementation.*/ 105 | return true; 106 | } 107 | 108 | /** 109 | * @brief MMC_SPI card write protection detection. 110 | */ 111 | bool mmc_lld_is_write_protected(MMCDriver* mmcp) 112 | { 113 | (void)mmcp; 114 | /* TODO: Fill the implementation.*/ 115 | return false; 116 | } 117 | #endif 118 | 119 | /** 120 | * @brief Board-specific initialization code. 121 | * @todo Add your board-specific code, if any. 122 | */ 123 | void boardInit(void) 124 | { 125 | } 126 | 127 | #if HAL_USE_USB 128 | void usb_lld_disconnect_bus(void* arg) 129 | { 130 | (void)arg; 131 | palSetPadMode(GPIOA, GPIOA_OTG_FS_DM, PAL_MODE_OUTPUT_OPENDRAIN); 132 | palSetPadMode(GPIOA, GPIOA_OTG_FS_DP, PAL_MODE_OUTPUT_OPENDRAIN); 133 | palClearPort(GPIOA, (1 << GPIOA_OTG_FS_DM) | (1 << GPIOA_OTG_FS_DP)); 134 | } 135 | 136 | void usb_lld_connect_bus(void* arg) 137 | { 138 | (void)arg; 139 | palSetPadMode(GPIOA, GPIOA_OTG_FS_DM, PAL_MODE_ALTERNATE(10)); 140 | palSetPadMode(GPIOA, GPIOA_OTG_FS_DP, PAL_MODE_ALTERNATE(10)); 141 | } 142 | #endif 143 | 144 | void led_toggle(unsigned int led) 145 | { 146 | if (led & STATUS_LED) { 147 | palTogglePad(GPIOB, GPIOB_STATUS_LED); 148 | } 149 | if (led & CAN1_STATUS_LED) { 150 | palTogglePad(GPIOB, GPIOB_CAN1_STATUS_LED); 151 | } 152 | if (led & CAN1_PWR_LED) { 153 | palTogglePad(GPIOA, GPIOA_CAN1_PWR_LED); 154 | } 155 | } 156 | 157 | void led_set(unsigned int led) 158 | { 159 | if (led & STATUS_LED) { 160 | palSetPad(GPIOB, GPIOB_STATUS_LED); 161 | } 162 | if (led & CAN1_STATUS_LED) { 163 | palSetPad(GPIOB, GPIOB_CAN1_STATUS_LED); 164 | } 165 | if (led & CAN1_PWR_LED) { 166 | palSetPad(GPIOA, GPIOA_CAN1_PWR_LED); 167 | } 168 | } 169 | 170 | void led_clear(unsigned int led) 171 | { 172 | if (led & STATUS_LED) { 173 | palClearPad(GPIOB, GPIOB_STATUS_LED); 174 | } 175 | if (led & CAN1_STATUS_LED) { 176 | palClearPad(GPIOB, GPIOB_CAN1_STATUS_LED); 177 | } 178 | if (led & CAN1_PWR_LED) { 179 | palClearPad(GPIOA, GPIOA_CAN1_PWR_LED); 180 | } 181 | } 182 | 183 | void can_set_silent_mode(int silent) 184 | { 185 | palWritePad(GPIOA, GPIOA_CAN_SILENT, silent); 186 | } 187 | 188 | int user_button_pressed(void) 189 | { 190 | return palReadPad(GPIOA, GPIOA_USER_BUTTON); 191 | } 192 | 193 | void can_bus_power_enable(int enabled) 194 | { 195 | palWritePad(GPIOB, GPIOB_V_BUS_ENABLE, enabled); 196 | } 197 | -------------------------------------------------------------------------------- /src/board/nucleo/board.mk: -------------------------------------------------------------------------------- 1 | # List of all the board related files. 2 | BOARDSRC = src/board/nucleo/board.c 3 | 4 | # Required include directories 5 | BOARDINC = src/board/nucleo -------------------------------------------------------------------------------- /src/board/nucleo/nucleo-f302r8-prototype.md: -------------------------------------------------------------------------------- 1 | # ST Nucleo STM32F302R8 prototype modifications 2 | ## CAN 3 | CAN_RX: PB8 4 | CAN_TX: PB9 5 | 6 | ## USB 7 | USB_DM: PA11 8 | USB_DP: PA12 9 | 10 | Add a 1.5K Pullup to USB_DP (see AN2606 "STM32 microcontroller system memory boot mode") 11 | 12 | For booting into DFU connect BOOT0 pin to VCC with a jumper. 13 | 14 | ## Clock source 15 | For USB to work an external clock source is required. 16 | Use MCO clock output from ST-link: 17 | - SB54, SB55 OFF 18 | - R35,R37 removed 19 | - SB16, SB50 ON 20 | 21 | Alternatively, mount the cristal (see Nucleo User Manual for modifications). 22 | -------------------------------------------------------------------------------- /src/bus_power.c: -------------------------------------------------------------------------------- 1 | #include "bus_power.h" 2 | #include 3 | #include 4 | 5 | uint16_t bus_voltage = 0; 6 | #define ADC_NUM_CHANNELS 1 7 | #define ADC_BUF_DEPTH 1 8 | static adcsample_t adc_samples[ADC_NUM_CHANNELS * ADC_BUF_DEPTH]; 9 | binary_semaphore_t adc_wait; 10 | static bool bus_power_enabled = false; 11 | 12 | static void adc_callback(ADCDriver* adcp, adcsample_t* buffer, size_t n) 13 | { 14 | (void)adcp; 15 | (void)n; 16 | bus_voltage = buffer[0]; 17 | chSysLockFromISR(); 18 | chBSemSignalI(&adc_wait); 19 | chSysUnlockFromISR(); 20 | } 21 | 22 | static void adc_error_callback(ADCDriver* adcp, adcerror_t err) 23 | { 24 | (void)adcp; 25 | (void)err; 26 | chSysHalt("ADC error"); 27 | } 28 | 29 | /* 30 | * ADC conversion group. 31 | * Mode: Continuous, 1 sample of 1 channel, SW triggered. 32 | * Channels: VBus 33 | */ 34 | static const ADCConversionGroup adcgrpcfg = { 35 | false, 36 | ADC_NUM_CHANNELS, 37 | adc_callback, 38 | adc_error_callback, 39 | ADC_CFGR_CONT | ADC_CFGR_RES_12BITS, /* CFGR */ 40 | ADC_TR(0, 4095), /* TR1 */ 41 | 0, /* CCR */ 42 | {/* SMPR[2] */ 43 | ADC_SMPR1_SMP_AN3(ADC_SMPR_SMP_601P5) | ADC_SMPR1_SMP_AN5(ADC_SMPR_SMP_601P5), 44 | 0}, 45 | {/* SQR[4] */ 46 | ADC_SQR1_SQ1_N(ADC_CHANNEL_VBUS), 47 | 0, 48 | 0, 49 | 0}}; 50 | 51 | float bus_voltage_get(void) 52 | { 53 | return ((float)bus_voltage) / ((1 << 12) - 1) * 3.3 * 2; 54 | } 55 | 56 | void bus_voltage_adc_conversion(void) 57 | { 58 | // read bus voltage 59 | adcStartConversion(&ADCD1, &adcgrpcfg, adc_samples, ADC_BUF_DEPTH); 60 | chBSemWait(&adc_wait); 61 | 62 | // Set LED if there is bus power 63 | float voltage = bus_voltage_get(); 64 | if (voltage > 4.5f && voltage < 5.5f) { 65 | led_set(CAN1_PWR_LED); 66 | } else if (voltage > 0.5f || voltage > 5.5f) { 67 | // voltage warning 68 | led_toggle(CAN1_PWR_LED); 69 | } else { 70 | led_clear(CAN1_PWR_LED); 71 | } 72 | } 73 | 74 | bool bus_power(bool enable) 75 | { 76 | if (enable) { 77 | if (bus_voltage_get() > 0.5 && !bus_power_enabled) { 78 | return false; 79 | } 80 | can_bus_power_enable(true); 81 | bus_power_enabled = true; 82 | } else { 83 | can_bus_power_enable(false); 84 | bus_power_enabled = false; 85 | } 86 | return true; 87 | } 88 | 89 | void bus_power_toggle(void) 90 | { 91 | if (bus_power_enabled) { 92 | bus_power(false); 93 | } else { 94 | bus_power(true); 95 | } 96 | } 97 | 98 | void bus_power_init(void) 99 | { 100 | chBSemObjectInit(&adc_wait, true); 101 | adcStart(&ADCD1, NULL); 102 | } 103 | -------------------------------------------------------------------------------- /src/bus_power.h: -------------------------------------------------------------------------------- 1 | #ifndef BUS_POWER_H 2 | #define BUS_POWER_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | 10 | float bus_voltage_get(void); 11 | void bus_voltage_adc_conversion(void); 12 | bool bus_power(bool enable); 13 | void bus_power_toggle(void); 14 | void bus_power_init(void); 15 | 16 | #ifdef __cplusplus 17 | } 18 | #endif 19 | 20 | #endif /* BUS_POWER_H */ 21 | -------------------------------------------------------------------------------- /src/can_driver.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "can_driver.h" 7 | 8 | #define CAN_RX_BUFFER_SIZE 100 9 | 10 | // size+2 for the 2 threads handling CAN frames from can_rx_pool 11 | #define CAN_RX_POOL_SIZE CAN_RX_BUFFER_SIZE + 2 12 | 13 | #define CAN_BTR_BRP_MASK 0x000003FF 14 | #define CAN_BTR_TS1_MASK 0x000F0000 15 | #define CAN_BTR_TS2_MASK 0x00700000 16 | #define CAN_BTR_TIMING_MASK (CAN_BTR_BRP_MASK | CAN_BTR_TS1_MASK | CAN_BTR_TS2_MASK) 17 | 18 | #if !defined(CAN_DEFAULT_BITRATE) 19 | #define CAN_DEFAULT_BITRATE 1000000 20 | #endif 21 | 22 | #define CAN_BASE_CLOCK STM32_PCLK1 // APB1 clock = 36MHz 23 | #if CAN_BASE_CLOCK != 36000000 24 | #error "CAN peripheral clock" 25 | #endif 26 | #define BTR_TS1 6 27 | #define BTR_TS2 5 28 | #define CAN_BASE_BIT_RATE CAN_BASE_CLOCK / (1 + BTR_TS1 + BTR_TS2) 29 | 30 | static bool can_btr_from_bitrate(uint32_t bitrate, uint32_t* btr_value); 31 | static void wait_on_request(void); 32 | static void can_rx_queue_post(struct can_frame_s* fp); 33 | static void can_rx_queue_flush(void); 34 | 35 | bool can_is_running = false; 36 | 37 | static CANConfig can_config = { 38 | .mcr = (1 << 6) // Automatic bus-off management enabled 39 | | (1 << 2), // Message are prioritized by order of arrival 40 | .btr = CAN_BTR_SILM // Silent mode 41 | | CAN_BTR_SJW_0 // 2tq resynchronization jump width 42 | }; 43 | 44 | // searches CAN bit rate register value 45 | static bool can_btr_from_bitrate(uint32_t bitrate, uint32_t* btr_value) 46 | { 47 | if (bitrate > 1000000 || CAN_BASE_BIT_RATE % bitrate != 0 || CAN_BASE_BIT_RATE / bitrate > 1024) { 48 | // bad range or no exact bitrate possible 49 | return false; 50 | } 51 | uint32_t prescaler = CAN_BASE_BIT_RATE / bitrate; 52 | *btr_value = ((prescaler - 1) << 0) | ((BTR_TS1 - 1) << 16) | ((BTR_TS2 - 1) << 20); 53 | return true; 54 | } 55 | 56 | // synchronize between recevier and sender thread 57 | SEMAPHORE_DECL(can_config_wait, 1); 58 | 59 | static void wait_on_request(void) 60 | { 61 | cnt_t count; 62 | chSysLock(); 63 | count = chSemGetCounterI(&can_config_wait); 64 | chSysUnlock(); 65 | if (count == -1) { 66 | chSemSignal(&can_config_wait); 67 | chSemWait(&can_config_wait); 68 | } 69 | } 70 | 71 | memory_pool_t can_rx_pool; 72 | mailbox_t can_rx_queue; 73 | msg_t rx_mbox_buf[CAN_RX_BUFFER_SIZE]; 74 | struct can_frame_s rx_pool_buf[CAN_RX_POOL_SIZE]; 75 | 76 | bool can_send(uint32_t id, bool extended, bool remote, uint8_t* data, size_t length) 77 | { 78 | led_set(CAN1_STATUS_LED); 79 | CANTxFrame txf; 80 | if (extended) { 81 | txf.EID = id; 82 | txf.IDE = 1; 83 | } else { 84 | txf.SID = id; 85 | txf.IDE = 0; 86 | } 87 | txf.DLC = length; 88 | if (remote) { 89 | txf.RTR = 1; 90 | } else { 91 | txf.RTR = 0; 92 | memcpy(&txf.data8[0], data, length); 93 | } 94 | msg_t m = canTransmit(&CAND1, CAN_ANY_MAILBOX, &txf, MS2ST(100)); 95 | if (m != MSG_OK) { 96 | return false; 97 | } 98 | return true; 99 | } 100 | 101 | static THD_WORKING_AREA(can_rx_thread_wa, 256); 102 | static THD_FUNCTION(can_rx_thread, arg) 103 | { 104 | (void)arg; 105 | chRegSetThreadName("CAN rx"); 106 | while (1) { 107 | wait_on_request(); 108 | CANRxFrame rxf; 109 | msg_t m = canReceive(&CAND1, CAN_ANY_MAILBOX, &rxf, MS2ST(10)); 110 | if (m != MSG_OK) { 111 | continue; 112 | } 113 | led_set(CAN1_STATUS_LED); 114 | struct can_frame_s* fp = (struct can_frame_s*)chPoolAlloc(&can_rx_pool); 115 | if (fp == NULL) { 116 | chSysHalt("CAN driver out of memory"); 117 | } 118 | fp->timestamp = timestamp_get() / 1000; 119 | if (rxf.IDE) { 120 | fp->id = rxf.EID; 121 | fp->extended = 1; 122 | } else { 123 | fp->id = rxf.SID; 124 | fp->extended = 0; 125 | } 126 | if (rxf.RTR) { 127 | fp->remote = 1; 128 | } else { 129 | fp->remote = 0; 130 | } 131 | fp->length = rxf.DLC; 132 | memcpy(&fp->data[0], &rxf.data8[0], rxf.DLC); 133 | can_rx_queue_post(fp); 134 | } 135 | } 136 | 137 | static void can_rx_queue_post(struct can_frame_s* fp) 138 | { 139 | msg_t m = chMBPost(&can_rx_queue, (msg_t)fp, TIME_IMMEDIATE); 140 | if (m != MSG_OK) { 141 | chPoolFree(&can_rx_pool, fp); 142 | can_rx_queue_flush(); 143 | } 144 | } 145 | 146 | static void can_rx_queue_flush(void) 147 | { 148 | struct can_frame_s* fp; 149 | while (1) { 150 | msg_t m = chMBFetch(&can_rx_queue, (msg_t*)&fp, TIME_IMMEDIATE); 151 | if (m == MSG_OK) { 152 | chPoolFree(&can_rx_pool, fp); 153 | } else { 154 | break; 155 | } 156 | } 157 | } 158 | 159 | void can_frame_delete(struct can_frame_s* f) 160 | { 161 | chPoolFree(&can_rx_pool, f); 162 | } 163 | 164 | struct can_frame_s* can_receive(void) 165 | { 166 | struct can_frame_s* fp; 167 | msg_t m = chMBFetch(&can_rx_queue, (msg_t*)&fp, MS2ST(100)); 168 | if (m == MSG_OK) { 169 | return fp; 170 | } 171 | return NULL; 172 | } 173 | 174 | bool can_set_bitrate(uint32_t bitrate) 175 | { 176 | if (can_is_running) { 177 | return false; 178 | } 179 | 180 | uint32_t btr; 181 | if (can_btr_from_bitrate(bitrate, &btr)) { 182 | can_config.btr = (can_config.btr & ~CAN_BTR_TIMING_MASK) | btr; 183 | return true; 184 | } else { 185 | return false; 186 | } 187 | } 188 | 189 | bool can_open(int mode) 190 | { 191 | if (can_is_running) { 192 | return false; 193 | } 194 | 195 | // CAN_MODE_NORMAL 196 | can_set_silent_mode(false); 197 | can_config.btr &= ~CAN_BTR_LBKM; 198 | can_config.btr &= ~CAN_BTR_SILM; 199 | 200 | switch (mode) { 201 | case CAN_MODE_LOOPBACK: 202 | can_config.btr |= CAN_BTR_LBKM; 203 | break; 204 | case CAN_MODE_SILENT: 205 | can_config.btr |= CAN_BTR_SILM; 206 | can_set_silent_mode(true); 207 | break; 208 | }; 209 | 210 | can_is_running = true; 211 | canStart(&CAND1, &can_config); 212 | chSemSignal(&can_config_wait); 213 | 214 | return true; 215 | } 216 | 217 | void can_close(void) 218 | { 219 | if (can_is_running) { 220 | chSemWait(&can_config_wait); 221 | canStop(&CAND1); 222 | can_is_running = false; 223 | can_rx_queue_flush(); 224 | } 225 | } 226 | 227 | void can_init(void) 228 | { 229 | chMBObjectInit(&can_rx_queue, rx_mbox_buf, sizeof(rx_mbox_buf) / sizeof(rx_mbox_buf[0])); 230 | chPoolObjectInit(&can_rx_pool, sizeof(rx_pool_buf[0]), NULL); 231 | chPoolLoadArray(&can_rx_pool, rx_pool_buf, sizeof(rx_pool_buf) / sizeof(rx_pool_buf[0])); 232 | 233 | chSemObjectInit(&can_config_wait, 1); 234 | 235 | uint32_t btr; 236 | if (!can_btr_from_bitrate(CAN_DEFAULT_BITRATE, &btr)) { 237 | chSysHalt("CAN default bitrate"); 238 | } 239 | can_config.btr |= btr; 240 | 241 | chThdCreateStatic(can_rx_thread_wa, sizeof(can_rx_thread_wa), NORMALPRIO, can_rx_thread, NULL); 242 | } 243 | -------------------------------------------------------------------------------- /src/can_driver.h: -------------------------------------------------------------------------------- 1 | #ifndef CAN_DRIVER_H 2 | #define CAN_DRIVER_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | struct can_frame_s { 13 | uint32_t timestamp; 14 | uint32_t id : 29; 15 | uint32_t extended : 1; 16 | uint32_t remote : 1; 17 | uint8_t length; 18 | uint8_t data[8]; 19 | }; 20 | 21 | enum { 22 | CAN_MODE_NORMAL, 23 | CAN_MODE_LOOPBACK, 24 | CAN_MODE_SILENT 25 | }; 26 | 27 | /* non-blocking CAN frame receive, NULL if nothing received */ 28 | struct can_frame_s* can_receive(void); 29 | void can_frame_delete(struct can_frame_s* f); 30 | 31 | /* blocking CAN frame send */ 32 | bool can_send(uint32_t id, bool extended, bool remote, uint8_t* data, size_t length); 33 | 34 | /* returns true on success, must be called before can_open */ 35 | bool can_set_bitrate(uint32_t bitrate); 36 | 37 | /* returns true on success */ 38 | bool can_open(int mode); 39 | void can_close(void); 40 | void can_init(void); 41 | 42 | #ifdef __cplusplus 43 | } 44 | #endif 45 | 46 | #endif /* CAN_DRIVER_H */ 47 | -------------------------------------------------------------------------------- /src/chconf.h: -------------------------------------------------------------------------------- 1 | /* 2 | ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | /** 18 | * @file templates/chconf.h 19 | * @brief Configuration file template. 20 | * @details A copy of this file must be placed in each project directory, it 21 | * contains the application specific kernel settings. 22 | * 23 | * @addtogroup config 24 | * @details Kernel related settings and hooks. 25 | * @{ 26 | */ 27 | 28 | #ifndef _CHCONF_H_ 29 | #define _CHCONF_H_ 30 | 31 | /*===========================================================================*/ 32 | /** 33 | * @name System timers settings 34 | * @{ 35 | */ 36 | /*===========================================================================*/ 37 | 38 | /** 39 | * @brief System time counter resolution. 40 | * @note Allowed values are 16 or 32 bits. 41 | */ 42 | #define CH_CFG_ST_RESOLUTION 32 43 | 44 | /** 45 | * @brief System tick frequency. 46 | * @details Frequency of the system timer that drives the system ticks. This 47 | * setting also defines the system tick time unit. 48 | */ 49 | #define CH_CFG_ST_FREQUENCY 10000 50 | 51 | /** 52 | * @brief Time delta constant for the tick-less mode. 53 | * @note If this value is zero then the system uses the classic 54 | * periodic tick. This value represents the minimum number 55 | * of ticks that is safe to specify in a timeout directive. 56 | * The value one is not valid, timeouts are rounded up to 57 | * this value. 58 | */ 59 | #define CH_CFG_ST_TIMEDELTA 0 60 | 61 | /** @} */ 62 | 63 | /*===========================================================================*/ 64 | /** 65 | * @name Kernel parameters and options 66 | * @{ 67 | */ 68 | /*===========================================================================*/ 69 | 70 | /** 71 | * @brief Round robin interval. 72 | * @details This constant is the number of system ticks allowed for the 73 | * threads before preemption occurs. Setting this value to zero 74 | * disables the preemption for threads with equal priority and the 75 | * round robin becomes cooperative. Note that higher priority 76 | * threads can still preempt, the kernel is always preemptive. 77 | * @note Disabling the round robin preemption makes the kernel more compact 78 | * and generally faster. 79 | * @note The round robin preemption is not supported in tickless mode and 80 | * must be set to zero in that case. 81 | */ 82 | #define CH_CFG_TIME_QUANTUM 0 83 | 84 | /** 85 | * @brief Managed RAM size. 86 | * @details Size of the RAM area to be managed by the OS. If set to zero 87 | * then the whole available RAM is used. The core memory is made 88 | * available to the heap allocator and/or can be used directly through 89 | * the simplified core memory allocator. 90 | * 91 | * @note In order to let the OS manage the whole RAM the linker script must 92 | * provide the @p __heap_base__ and @p __heap_end__ symbols. 93 | * @note Requires @p CH_CFG_USE_MEMCORE. 94 | */ 95 | #define CH_CFG_MEMCORE_SIZE 0 96 | 97 | /** 98 | * @brief Idle thread automatic spawn suppression. 99 | * @details When this option is activated the function @p chSysInit() 100 | * does not spawn the idle thread. The application @p main() 101 | * function becomes the idle thread and must implement an 102 | * infinite loop. 103 | */ 104 | #define CH_CFG_NO_IDLE_THREAD FALSE 105 | 106 | /** @} */ 107 | 108 | /*===========================================================================*/ 109 | /** 110 | * @name Performance options 111 | * @{ 112 | */ 113 | /*===========================================================================*/ 114 | 115 | /** 116 | * @brief OS optimization. 117 | * @details If enabled then time efficient rather than space efficient code 118 | * is used when two possible implementations exist. 119 | * 120 | * @note This is not related to the compiler optimization options. 121 | * @note The default is @p TRUE. 122 | */ 123 | #define CH_CFG_OPTIMIZE_SPEED TRUE 124 | 125 | /** @} */ 126 | 127 | /*===========================================================================*/ 128 | /** 129 | * @name Subsystem options 130 | * @{ 131 | */ 132 | /*===========================================================================*/ 133 | 134 | /** 135 | * @brief Time Measurement APIs. 136 | * @details If enabled then the time measurement APIs are included in 137 | * the kernel. 138 | * 139 | * @note The default is @p TRUE. 140 | */ 141 | #define CH_CFG_USE_TM TRUE 142 | 143 | /** 144 | * @brief Threads registry APIs. 145 | * @details If enabled then the registry APIs are included in the kernel. 146 | * 147 | * @note The default is @p TRUE. 148 | */ 149 | #define CH_CFG_USE_REGISTRY TRUE 150 | 151 | /** 152 | * @brief Threads synchronization APIs. 153 | * @details If enabled then the @p chThdWait() function is included in 154 | * the kernel. 155 | * 156 | * @note The default is @p TRUE. 157 | */ 158 | #define CH_CFG_USE_WAITEXIT TRUE 159 | 160 | /** 161 | * @brief Semaphores APIs. 162 | * @details If enabled then the Semaphores APIs are included in the kernel. 163 | * 164 | * @note The default is @p TRUE. 165 | */ 166 | #define CH_CFG_USE_SEMAPHORES TRUE 167 | 168 | /** 169 | * @brief Semaphores queuing mode. 170 | * @details If enabled then the threads are enqueued on semaphores by 171 | * priority rather than in FIFO order. 172 | * 173 | * @note The default is @p FALSE. Enable this if you have special 174 | * requirements. 175 | * @note Requires @p CH_CFG_USE_SEMAPHORES. 176 | */ 177 | #define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE 178 | 179 | /** 180 | * @brief Mutexes APIs. 181 | * @details If enabled then the mutexes APIs are included in the kernel. 182 | * 183 | * @note The default is @p TRUE. 184 | */ 185 | #define CH_CFG_USE_MUTEXES TRUE 186 | 187 | /** 188 | * @brief Enables recursive behavior on mutexes. 189 | * @note Recursive mutexes are heavier and have an increased 190 | * memory footprint. 191 | * 192 | * @note The default is @p FALSE. 193 | * @note Requires @p CH_CFG_USE_MUTEXES. 194 | */ 195 | #define CH_CFG_USE_MUTEXES_RECURSIVE FALSE 196 | 197 | /** 198 | * @brief Conditional Variables APIs. 199 | * @details If enabled then the conditional variables APIs are included 200 | * in the kernel. 201 | * 202 | * @note The default is @p TRUE. 203 | * @note Requires @p CH_CFG_USE_MUTEXES. 204 | */ 205 | #define CH_CFG_USE_CONDVARS TRUE 206 | 207 | /** 208 | * @brief Conditional Variables APIs with timeout. 209 | * @details If enabled then the conditional variables APIs with timeout 210 | * specification are included in the kernel. 211 | * 212 | * @note The default is @p TRUE. 213 | * @note Requires @p CH_CFG_USE_CONDVARS. 214 | */ 215 | #define CH_CFG_USE_CONDVARS_TIMEOUT TRUE 216 | 217 | /** 218 | * @brief Events Flags APIs. 219 | * @details If enabled then the event flags APIs are included in the kernel. 220 | * 221 | * @note The default is @p TRUE. 222 | */ 223 | #define CH_CFG_USE_EVENTS TRUE 224 | 225 | /** 226 | * @brief Events Flags APIs with timeout. 227 | * @details If enabled then the events APIs with timeout specification 228 | * are included in the kernel. 229 | * 230 | * @note The default is @p TRUE. 231 | * @note Requires @p CH_CFG_USE_EVENTS. 232 | */ 233 | #define CH_CFG_USE_EVENTS_TIMEOUT TRUE 234 | 235 | /** 236 | * @brief Synchronous Messages APIs. 237 | * @details If enabled then the synchronous messages APIs are included 238 | * in the kernel. 239 | * 240 | * @note The default is @p TRUE. 241 | */ 242 | #define CH_CFG_USE_MESSAGES TRUE 243 | 244 | /** 245 | * @brief Synchronous Messages queuing mode. 246 | * @details If enabled then messages are served by priority rather than in 247 | * FIFO order. 248 | * 249 | * @note The default is @p FALSE. Enable this if you have special 250 | * requirements. 251 | * @note Requires @p CH_CFG_USE_MESSAGES. 252 | */ 253 | #define CH_CFG_USE_MESSAGES_PRIORITY FALSE 254 | 255 | /** 256 | * @brief Mailboxes APIs. 257 | * @details If enabled then the asynchronous messages (mailboxes) APIs are 258 | * included in the kernel. 259 | * 260 | * @note The default is @p TRUE. 261 | * @note Requires @p CH_CFG_USE_SEMAPHORES. 262 | */ 263 | #define CH_CFG_USE_MAILBOXES TRUE 264 | 265 | /** 266 | * @brief I/O Queues APIs. 267 | * @details If enabled then the I/O queues APIs are included in the kernel. 268 | * 269 | * @note The default is @p TRUE. 270 | */ 271 | #define CH_CFG_USE_QUEUES TRUE 272 | 273 | /** 274 | * @brief Core Memory Manager APIs. 275 | * @details If enabled then the core memory manager APIs are included 276 | * in the kernel. 277 | * 278 | * @note The default is @p TRUE. 279 | */ 280 | #define CH_CFG_USE_MEMCORE TRUE 281 | 282 | /** 283 | * @brief Heap Allocator APIs. 284 | * @details If enabled then the memory heap allocator APIs are included 285 | * in the kernel. 286 | * 287 | * @note The default is @p TRUE. 288 | * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or 289 | * @p CH_CFG_USE_SEMAPHORES. 290 | * @note Mutexes are recommended. 291 | */ 292 | #define CH_CFG_USE_HEAP TRUE 293 | 294 | /** 295 | * @brief Memory Pools Allocator APIs. 296 | * @details If enabled then the memory pools allocator APIs are included 297 | * in the kernel. 298 | * 299 | * @note The default is @p TRUE. 300 | */ 301 | #define CH_CFG_USE_MEMPOOLS TRUE 302 | 303 | /** 304 | * @brief Dynamic Threads APIs. 305 | * @details If enabled then the dynamic threads creation APIs are included 306 | * in the kernel. 307 | * 308 | * @note The default is @p TRUE. 309 | * @note Requires @p CH_CFG_USE_WAITEXIT. 310 | * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. 311 | */ 312 | #define CH_CFG_USE_DYNAMIC TRUE 313 | 314 | /** @} */ 315 | 316 | /*===========================================================================*/ 317 | /** 318 | * @name Debug options 319 | * @{ 320 | */ 321 | /*===========================================================================*/ 322 | 323 | /** 324 | * @brief Debug option, kernel statistics. 325 | * 326 | * @note The default is @p FALSE. 327 | */ 328 | #define CH_DBG_STATISTICS FALSE 329 | 330 | /** 331 | * @brief Debug option, system state check. 332 | * @details If enabled the correct call protocol for system APIs is checked 333 | * at runtime. 334 | * 335 | * @note The default is @p FALSE. 336 | */ 337 | #define CH_DBG_SYSTEM_STATE_CHECK FALSE 338 | 339 | /** 340 | * @brief Debug option, parameters checks. 341 | * @details If enabled then the checks on the API functions input 342 | * parameters are activated. 343 | * 344 | * @note The default is @p FALSE. 345 | */ 346 | #define CH_DBG_ENABLE_CHECKS FALSE 347 | 348 | /** 349 | * @brief Debug option, consistency checks. 350 | * @details If enabled then all the assertions in the kernel code are 351 | * activated. This includes consistency checks inside the kernel, 352 | * runtime anomalies and port-defined checks. 353 | * 354 | * @note The default is @p FALSE. 355 | */ 356 | #define CH_DBG_ENABLE_ASSERTS FALSE 357 | 358 | /** 359 | * @brief Debug option, trace buffer. 360 | * @details If enabled then the context switch circular trace buffer is 361 | * activated. 362 | * 363 | * @note The default is @p FALSE. 364 | */ 365 | #define CH_DBG_ENABLE_TRACE FALSE 366 | 367 | /** 368 | * @brief Debug option, stack checks. 369 | * @details If enabled then a runtime stack check is performed. 370 | * 371 | * @note The default is @p FALSE. 372 | * @note The stack check is performed in a architecture/port dependent way. 373 | * It may not be implemented or some ports. 374 | * @note The default failure mode is to halt the system with the global 375 | * @p panic_msg variable set to @p NULL. 376 | */ 377 | #define CH_DBG_ENABLE_STACK_CHECK FALSE 378 | 379 | /** 380 | * @brief Debug option, stacks initialization. 381 | * @details If enabled then the threads working area is filled with a byte 382 | * value when a thread is created. This can be useful for the 383 | * runtime measurement of the used stack. 384 | * 385 | * @note The default is @p FALSE. 386 | */ 387 | #define CH_DBG_FILL_THREADS FALSE 388 | 389 | /** 390 | * @brief Debug option, threads profiling. 391 | * @details If enabled then a field is added to the @p thread_t structure that 392 | * counts the system ticks occurred while executing the thread. 393 | * 394 | * @note The default is @p FALSE. 395 | * @note This debug option is not currently compatible with the 396 | * tickless mode. 397 | */ 398 | #define CH_DBG_THREADS_PROFILING FALSE 399 | 400 | /** @} */ 401 | 402 | /*===========================================================================*/ 403 | /** 404 | * @name Kernel hooks 405 | * @{ 406 | */ 407 | /*===========================================================================*/ 408 | 409 | /** 410 | * @brief Threads descriptor structure extension. 411 | * @details User fields added to the end of the @p thread_t structure. 412 | */ 413 | #define CH_CFG_THREAD_EXTRA_FIELDS \ 414 | /* Add threads custom fields here.*/ 415 | 416 | /** 417 | * @brief Threads initialization hook. 418 | * @details User initialization code added to the @p chThdInit() API. 419 | * 420 | * @note It is invoked from within @p chThdInit() and implicitly from all 421 | * the threads creation APIs. 422 | */ 423 | #define CH_CFG_THREAD_INIT_HOOK(tp) \ 424 | { \ 425 | /* Add threads initialization code here.*/ \ 426 | } 427 | 428 | /** 429 | * @brief Threads finalization hook. 430 | * @details User finalization code added to the @p chThdExit() API. 431 | * 432 | * @note It is inserted into lock zone. 433 | * @note It is also invoked when the threads simply return in order to 434 | * terminate. 435 | */ 436 | #define CH_CFG_THREAD_EXIT_HOOK(tp) \ 437 | { \ 438 | /* Add threads finalization code here.*/ \ 439 | } 440 | 441 | /** 442 | * @brief Context switch hook. 443 | * @details This hook is invoked just before switching between threads. 444 | */ 445 | #define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) \ 446 | { \ 447 | /* Context switch code here.*/ \ 448 | } 449 | 450 | /** 451 | * @brief Idle thread enter hook. 452 | * @note This hook is invoked within a critical zone, no OS functions 453 | * should be invoked from here. 454 | * @note This macro can be used to activate a power saving mode. 455 | */ 456 | #define CH_CFG_IDLE_ENTER_HOOK() \ 457 | { \ 458 | } 459 | 460 | /** 461 | * @brief Idle thread leave hook. 462 | * @note This hook is invoked within a critical zone, no OS functions 463 | * should be invoked from here. 464 | * @note This macro can be used to deactivate a power saving mode. 465 | */ 466 | #define CH_CFG_IDLE_LEAVE_HOOK() \ 467 | { \ 468 | } 469 | 470 | /** 471 | * @brief Idle Loop hook. 472 | * @details This hook is continuously invoked by the idle thread loop. 473 | */ 474 | #define CH_CFG_IDLE_LOOP_HOOK() \ 475 | { \ 476 | /* Idle loop code here.*/ \ 477 | } 478 | 479 | /** 480 | * @brief System tick event hook. 481 | * @details This hook is invoked in the system tick handler immediately 482 | * after processing the virtual timers queue. 483 | */ 484 | #define CH_CFG_SYSTEM_TICK_HOOK() \ 485 | { \ 486 | /* System tick event code here.*/ \ 487 | } 488 | 489 | /** 490 | * @brief System halt hook. 491 | * @details This hook is invoked in case to a system halting error before 492 | * the system is halted. 493 | */ 494 | #define CH_CFG_SYSTEM_HALT_HOOK(reason) \ 495 | { \ 496 | /* System halt code here.*/ \ 497 | void panic(const char*); \ 498 | panic(reason); \ 499 | } 500 | 501 | /** @} */ 502 | 503 | /*===========================================================================*/ 504 | /* Port-specific settings (override port settings defaulted in chcore.h). */ 505 | /*===========================================================================*/ 506 | 507 | #endif /* _CHCONF_H_ */ 508 | 509 | /** @} */ 510 | -------------------------------------------------------------------------------- /src/halconf.h: -------------------------------------------------------------------------------- 1 | /* 2 | ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | /** 18 | * @file templates/halconf.h 19 | * @brief HAL configuration header. 20 | * @details HAL configuration file, this file allows to enable or disable the 21 | * various device drivers from your application. You may also use 22 | * this file in order to override the device drivers default settings. 23 | * 24 | * @addtogroup HAL_CONF 25 | * @{ 26 | */ 27 | 28 | #ifndef _HALCONF_H_ 29 | #define _HALCONF_H_ 30 | 31 | #include "mcuconf.h" 32 | 33 | /** 34 | * @brief Enables the PAL subsystem. 35 | */ 36 | #if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) 37 | #define HAL_USE_PAL TRUE 38 | #endif 39 | 40 | /** 41 | * @brief Enables the ADC subsystem. 42 | */ 43 | #if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) 44 | #define HAL_USE_ADC TRUE 45 | #endif 46 | 47 | /** 48 | * @brief Enables the CAN subsystem. 49 | */ 50 | #if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) 51 | #define HAL_USE_CAN TRUE 52 | #endif 53 | 54 | /** 55 | * @brief Enables the DAC subsystem. 56 | */ 57 | #if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) 58 | #define HAL_USE_DAC FALSE 59 | #endif 60 | 61 | /** 62 | * @brief Enables the EXT subsystem. 63 | */ 64 | #if !defined(HAL_USE_EXT) || defined(__DOXYGEN__) 65 | #define HAL_USE_EXT FALSE 66 | #endif 67 | 68 | /** 69 | * @brief Enables the GPT subsystem. 70 | */ 71 | #if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) 72 | #define HAL_USE_GPT FALSE 73 | #endif 74 | 75 | /** 76 | * @brief Enables the I2C subsystem. 77 | */ 78 | #if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) 79 | #define HAL_USE_I2C FALSE 80 | #endif 81 | 82 | /** 83 | * @brief Enables the I2S subsystem. 84 | */ 85 | #if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) 86 | #define HAL_USE_I2S FALSE 87 | #endif 88 | 89 | /** 90 | * @brief Enables the ICU subsystem. 91 | */ 92 | #if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) 93 | #define HAL_USE_ICU FALSE 94 | #endif 95 | 96 | /** 97 | * @brief Enables the MAC subsystem. 98 | */ 99 | #if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) 100 | #define HAL_USE_MAC FALSE 101 | #endif 102 | 103 | /** 104 | * @brief Enables the MMC_SPI subsystem. 105 | */ 106 | #if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) 107 | #define HAL_USE_MMC_SPI FALSE 108 | #endif 109 | 110 | /** 111 | * @brief Enables the PWM subsystem. 112 | */ 113 | #if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) 114 | #define HAL_USE_PWM FALSE 115 | #endif 116 | 117 | /** 118 | * @brief Enables the RTC subsystem. 119 | */ 120 | #if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) 121 | #define HAL_USE_RTC FALSE 122 | #endif 123 | 124 | /** 125 | * @brief Enables the SDC subsystem. 126 | */ 127 | #if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) 128 | #define HAL_USE_SDC FALSE 129 | #endif 130 | 131 | /** 132 | * @brief Enables the SERIAL subsystem. 133 | */ 134 | #if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) 135 | #define HAL_USE_SERIAL TRUE 136 | #endif 137 | 138 | /** 139 | * @brief Enables the SERIAL over USB subsystem. 140 | */ 141 | #if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) 142 | #define HAL_USE_SERIAL_USB TRUE 143 | #endif 144 | 145 | /** 146 | * @brief Enables the SPI subsystem. 147 | */ 148 | #if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) 149 | #define HAL_USE_SPI FALSE 150 | #endif 151 | 152 | /** 153 | * @brief Enables the UART subsystem. 154 | */ 155 | #if !defined(HAL_USE_UART) || defined(__DOXYGEN__) 156 | #define HAL_USE_UART FALSE 157 | #endif 158 | 159 | /** 160 | * @brief Enables the USB subsystem. 161 | */ 162 | #if !defined(HAL_USE_USB) || defined(__DOXYGEN__) 163 | #define HAL_USE_USB TRUE 164 | #endif 165 | 166 | /*===========================================================================*/ 167 | /* ADC driver related settings. */ 168 | /*===========================================================================*/ 169 | 170 | /** 171 | * @brief Enables synchronous APIs. 172 | * @note Disabling this option saves both code and data space. 173 | */ 174 | #if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) 175 | #define ADC_USE_WAIT TRUE 176 | #endif 177 | 178 | /** 179 | * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. 180 | * @note Disabling this option saves both code and data space. 181 | */ 182 | #if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) 183 | #define ADC_USE_MUTUAL_EXCLUSION TRUE 184 | #endif 185 | 186 | /*===========================================================================*/ 187 | /* CAN driver related settings. */ 188 | /*===========================================================================*/ 189 | 190 | /** 191 | * @brief Sleep mode related APIs inclusion switch. 192 | */ 193 | #if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) 194 | #define CAN_USE_SLEEP_MODE TRUE 195 | #endif 196 | 197 | /*===========================================================================*/ 198 | /* I2C driver related settings. */ 199 | /*===========================================================================*/ 200 | 201 | /** 202 | * @brief Enables the mutual exclusion APIs on the I2C bus. 203 | */ 204 | #if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) 205 | #define I2C_USE_MUTUAL_EXCLUSION TRUE 206 | #endif 207 | 208 | /*===========================================================================*/ 209 | /* MAC driver related settings. */ 210 | /*===========================================================================*/ 211 | 212 | /** 213 | * @brief Enables an event sources for incoming packets. 214 | */ 215 | #if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) 216 | #define MAC_USE_ZERO_COPY FALSE 217 | #endif 218 | 219 | /** 220 | * @brief Enables an event sources for incoming packets. 221 | */ 222 | #if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) 223 | #define MAC_USE_EVENTS TRUE 224 | #endif 225 | 226 | /*===========================================================================*/ 227 | /* MMC_SPI driver related settings. */ 228 | /*===========================================================================*/ 229 | 230 | /** 231 | * @brief Delays insertions. 232 | * @details If enabled this options inserts delays into the MMC waiting 233 | * routines releasing some extra CPU time for the threads with 234 | * lower priority, this may slow down the driver a bit however. 235 | * This option is recommended also if the SPI driver does not 236 | * use a DMA channel and heavily loads the CPU. 237 | */ 238 | #if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) 239 | #define MMC_NICE_WAITING TRUE 240 | #endif 241 | 242 | /*===========================================================================*/ 243 | /* SDC driver related settings. */ 244 | /*===========================================================================*/ 245 | 246 | /** 247 | * @brief Number of initialization attempts before rejecting the card. 248 | * @note Attempts are performed at 10mS intervals. 249 | */ 250 | #if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) 251 | #define SDC_INIT_RETRY 100 252 | #endif 253 | 254 | /** 255 | * @brief Include support for MMC cards. 256 | * @note MMC support is not yet implemented so this option must be kept 257 | * at @p FALSE. 258 | */ 259 | #if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) 260 | #define SDC_MMC_SUPPORT FALSE 261 | #endif 262 | 263 | /** 264 | * @brief Delays insertions. 265 | * @details If enabled this options inserts delays into the MMC waiting 266 | * routines releasing some extra CPU time for the threads with 267 | * lower priority, this may slow down the driver a bit however. 268 | */ 269 | #if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) 270 | #define SDC_NICE_WAITING TRUE 271 | #endif 272 | 273 | /*===========================================================================*/ 274 | /* SERIAL driver related settings. */ 275 | /*===========================================================================*/ 276 | 277 | /** 278 | * @brief Default bit rate. 279 | * @details Configuration parameter, this is the baud rate selected for the 280 | * default configuration. 281 | */ 282 | #if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) 283 | #define SERIAL_DEFAULT_BITRATE 38400 284 | #endif 285 | 286 | /** 287 | * @brief Serial buffers size. 288 | * @details Configuration parameter, you can change the depth of the queue 289 | * buffers depending on the requirements of your application. 290 | * @note The default is 64 bytes for both the transmission and receive 291 | * buffers. 292 | */ 293 | #if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) 294 | #define SERIAL_BUFFERS_SIZE 16 295 | #endif 296 | 297 | /*===========================================================================*/ 298 | /* SERIAL_USB driver related setting. */ 299 | /*===========================================================================*/ 300 | 301 | /** 302 | * @brief Serial over USB buffers size. 303 | * @details Configuration parameter, the buffer size must be a multiple of 304 | * the USB data endpoint maximum packet size. 305 | * @note The default is 64 bytes for both the transmission and receive 306 | * buffers. 307 | */ 308 | #if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) 309 | #define SERIAL_USB_BUFFERS_SIZE 256 310 | #endif 311 | 312 | /*===========================================================================*/ 313 | /* SPI driver related settings. */ 314 | /*===========================================================================*/ 315 | 316 | /** 317 | * @brief Enables synchronous APIs. 318 | * @note Disabling this option saves both code and data space. 319 | */ 320 | #if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) 321 | #define SPI_USE_WAIT TRUE 322 | #endif 323 | 324 | /** 325 | * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. 326 | * @note Disabling this option saves both code and data space. 327 | */ 328 | #if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) 329 | #define SPI_USE_MUTUAL_EXCLUSION TRUE 330 | #endif 331 | 332 | #endif /* _HALCONF_H_ */ 333 | 334 | /** @} */ 335 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "usbcfg2.h" 4 | #include "bus_power.h" 5 | #include "can_driver.h" 6 | #include "slcan.h" 7 | #include "slcan_thread.h" 8 | #include 9 | #include 10 | 11 | void panic(const char* reason) 12 | { 13 | (void)reason; 14 | led_set(STATUS_LED | CAN1_STATUS_LED | CAN1_PWR_LED); 15 | can_set_silent_mode(true); 16 | can_bus_power_enable(false); 17 | while (1) { 18 | } 19 | } 20 | 21 | void user_button_poll(void) 22 | { 23 | static timestamp_t last_press = 0; 24 | static bool active = false; 25 | if (user_button_pressed()) { 26 | if (active && 1.0f < timestamp_duration_s(last_press, timestamp_get())) { 27 | bus_power_toggle(); 28 | active = false; 29 | } else if (!active) { 30 | active = true; 31 | last_press = timestamp_get(); 32 | } 33 | } else { 34 | active = false; 35 | } 36 | } 37 | 38 | int main(void) 39 | { 40 | halInit(); 41 | chSysInit(); 42 | 43 | chSysLock(); 44 | timestamp_stm32_init(); 45 | chSysUnlock(); 46 | 47 | bus_power_init(); 48 | 49 | // USB CDC 50 | sduObjectInit(&SDU1); 51 | sduStart(&SDU1, &serusbcfg); 52 | 53 | usbDisconnectBus(serusbcfg.usbp); 54 | chThdSleepMilliseconds(1500); 55 | usbStart(serusbcfg.usbp, &usbcfg); 56 | usbConnectBus(serusbcfg.usbp); 57 | 58 | while (SDU1.config->usbp->state != USB_ACTIVE) { 59 | chThdSleepMilliseconds(10); 60 | } 61 | 62 | slcan_start((BaseChannel*)&SDU1); 63 | 64 | while (1) { 65 | user_button_poll(); 66 | bus_voltage_adc_conversion(); 67 | chThdSleepMilliseconds(100); 68 | led_clear(STATUS_LED); 69 | led_clear(CAN1_STATUS_LED); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/mcuconf.h: -------------------------------------------------------------------------------- 1 | /* 2 | ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #ifndef _MCUCONF_H_ 18 | #define _MCUCONF_H_ 19 | 20 | /* 21 | * STM32F3xx drivers configuration. 22 | * The following settings override the default settings present in 23 | * the various device driver implementation headers. 24 | * Note that the settings for each driver only have effect if the whole 25 | * driver is enabled in halconf.h. 26 | * 27 | * IRQ priorities: 28 | * 15...0 Lowest...Highest. 29 | * 30 | * DMA priorities: 31 | * 0...3 Lowest...Highest. 32 | */ 33 | 34 | #define STM32F3xx_MCUCONF 35 | 36 | /* 37 | * HAL driver system settings. 38 | */ 39 | #define STM32_NO_INIT FALSE 40 | #define STM32_PVD_ENABLE FALSE 41 | #define STM32_PLS STM32_PLS_LEV0 42 | #define STM32_HSI_ENABLED TRUE 43 | #define STM32_LSI_ENABLED TRUE 44 | #define STM32_HSE_ENABLED TRUE 45 | #define STM32_LSE_ENABLED FALSE 46 | #define STM32_SW STM32_SW_PLL 47 | #define STM32_PLLSRC STM32_PLLSRC_HSE 48 | #if (STM32_HSECLK == 16000000U) 49 | #define STM32_PREDIV_VALUE 2 50 | #elif (STM32_HSECLK == 8000000U) 51 | #define STM32_PREDIV_VALUE 1 52 | #endif 53 | #define STM32_PLLMUL_VALUE 9 54 | #define STM32_HPRE STM32_HPRE_DIV1 55 | #define STM32_PPRE1 STM32_PPRE1_DIV2 56 | #define STM32_PPRE2 STM32_PPRE2_DIV1 57 | #define STM32_MCOSEL STM32_MCOSEL_NOCLOCK 58 | #define STM32_ADC12PRES STM32_ADC12PRES_DIV1 59 | #define STM32_USART1SW STM32_USART1SW_PCLK 60 | #define STM32_USART2SW STM32_USART2SW_PCLK 61 | #define STM32_USART3SW STM32_USART3SW_PCLK 62 | #define STM32_I2C1SW STM32_I2C1SW_SYSCLK 63 | #define STM32_TIM1SW STM32_TIM1SW_PCLK2 64 | #define STM32_RTCSEL STM32_RTCSEL_LSI 65 | #define STM32_USBPRE STM32_USBPRE_DIV1P5 66 | 67 | /* 68 | * ADC driver system settings. 69 | */ 70 | #define STM32_ADC_USE_ADC1 TRUE 71 | #define STM32_ADC_ADC12_DMA_PRIORITY 2 72 | #define STM32_ADC_ADC12_IRQ_PRIORITY 5 73 | #define STM32_ADC_ADC12_DMA_IRQ_PRIORITY 5 74 | #define STM32_ADC_ADC12_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV1 75 | #define STM32_ADC_DUAL_MODE FALSE 76 | 77 | /* 78 | * CAN driver system settings. 79 | */ 80 | #define STM32_CAN_USE_CAN1 TRUE 81 | #define STM32_CAN_CAN1_IRQ_PRIORITY 11 82 | 83 | /* 84 | * EXT driver system settings. 85 | */ 86 | #define STM32_EXT_EXTI0_IRQ_PRIORITY 6 87 | #define STM32_EXT_EXTI1_IRQ_PRIORITY 6 88 | #define STM32_EXT_EXTI2_IRQ_PRIORITY 6 89 | #define STM32_EXT_EXTI3_IRQ_PRIORITY 6 90 | #define STM32_EXT_EXTI4_IRQ_PRIORITY 6 91 | #define STM32_EXT_EXTI5_9_IRQ_PRIORITY 6 92 | #define STM32_EXT_EXTI10_15_IRQ_PRIORITY 6 93 | #define STM32_EXT_EXTI16_IRQ_PRIORITY 6 94 | #define STM32_EXT_EXTI17_IRQ_PRIORITY 6 95 | #define STM32_EXT_EXTI18_IRQ_PRIORITY 6 96 | #define STM32_EXT_EXTI19_IRQ_PRIORITY 6 97 | #define STM32_EXT_EXTI20_IRQ_PRIORITY 6 98 | #define STM32_EXT_EXTI21_22_29_IRQ_PRIORITY 6 99 | #define STM32_EXT_EXTI30_32_IRQ_PRIORITY 6 100 | #define STM32_EXT_EXTI33_IRQ_PRIORITY 6 101 | 102 | /* 103 | * GPT driver system settings. 104 | */ 105 | #define STM32_GPT_USE_TIM1 FALSE 106 | #define STM32_GPT_USE_TIM2 FALSE 107 | #define STM32_GPT_USE_TIM3 FALSE 108 | #define STM32_GPT_USE_TIM6 FALSE 109 | #define STM32_GPT_USE_TIM7 FALSE 110 | #define STM32_GPT_TIM1_IRQ_PRIORITY 7 111 | #define STM32_GPT_TIM2_IRQ_PRIORITY 7 112 | #define STM32_GPT_TIM3_IRQ_PRIORITY 7 113 | #define STM32_GPT_TIM6_IRQ_PRIORITY 7 114 | #define STM32_GPT_TIM7_IRQ_PRIORITY 7 115 | 116 | /* 117 | * I2C driver system settings. 118 | */ 119 | #define STM32_I2C_USE_I2C1 FALSE 120 | #define STM32_I2C_BUSY_TIMEOUT 50 121 | #define STM32_I2C_I2C1_IRQ_PRIORITY 10 122 | #define STM32_I2C_USE_DMA TRUE 123 | #define STM32_I2C_I2C1_DMA_PRIORITY 1 124 | #define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") 125 | 126 | /* 127 | * ICU driver system settings. 128 | */ 129 | #define STM32_ICU_USE_TIM1 FALSE 130 | #define STM32_ICU_USE_TIM2 FALSE 131 | #define STM32_ICU_USE_TIM3 FALSE 132 | #define STM32_ICU_TIM1_IRQ_PRIORITY 7 133 | #define STM32_ICU_TIM2_IRQ_PRIORITY 7 134 | #define STM32_ICU_TIM3_IRQ_PRIORITY 7 135 | 136 | /* 137 | * PWM driver system settings. 138 | */ 139 | #define STM32_PWM_USE_ADVANCED FALSE 140 | #define STM32_PWM_USE_TIM1 FALSE 141 | #define STM32_PWM_USE_TIM2 FALSE 142 | #define STM32_PWM_USE_TIM3 FALSE 143 | #define STM32_PWM_TIM1_IRQ_PRIORITY 7 144 | #define STM32_PWM_TIM2_IRQ_PRIORITY 7 145 | #define STM32_PWM_TIM3_IRQ_PRIORITY 7 146 | 147 | /* 148 | * SERIAL driver system settings. 149 | */ 150 | #define STM32_SERIAL_USE_USART1 TRUE 151 | #define STM32_SERIAL_USE_USART2 FALSE 152 | #define STM32_SERIAL_USE_USART3 FALSE 153 | #define STM32_SERIAL_USART1_PRIORITY 12 154 | #define STM32_SERIAL_USART2_PRIORITY 12 155 | #define STM32_SERIAL_USART3_PRIORITY 12 156 | 157 | /* 158 | * SPI driver system settings. 159 | */ 160 | #define STM32_SPI_USE_SPI1 FALSE 161 | #define STM32_SPI_SPI1_DMA_PRIORITY 1 162 | #define STM32_SPI_SPI1_IRQ_PRIORITY 10 163 | #define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") 164 | 165 | /* 166 | * ST driver system settings. 167 | */ 168 | #define STM32_ST_IRQ_PRIORITY 8 169 | #define STM32_ST_USE_TIMER 2 170 | 171 | /* 172 | * UART driver system settings. 173 | */ 174 | #define STM32_UART_USE_USART1 FALSE 175 | #define STM32_UART_USE_USART2 FALSE 176 | #define STM32_UART_USE_USART3 FALSE 177 | #define STM32_UART_USART1_IRQ_PRIORITY 12 178 | #define STM32_UART_USART2_IRQ_PRIORITY 12 179 | #define STM32_UART_USART3_IRQ_PRIORITY 12 180 | #define STM32_UART_USART1_DMA_PRIORITY 0 181 | #define STM32_UART_USART2_DMA_PRIORITY 0 182 | #define STM32_UART_USART3_DMA_PRIORITY 0 183 | #define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") 184 | 185 | /* 186 | * USB driver system settings. 187 | */ 188 | #define STM32_USB_USE_USB1 TRUE 189 | #define STM32_USB_LOW_POWER_ON_SUSPEND FALSE 190 | #define STM32_USB_USB1_HP_IRQ_PRIORITY 13 191 | #define STM32_USB_USB1_LP_IRQ_PRIORITY 14 192 | 193 | #endif /* _MCUCONF_H_ */ 194 | -------------------------------------------------------------------------------- /src/slcan.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "version.h" 6 | #include "can_driver.h" 7 | #include "slcan.h" 8 | #include "bus_power.h" 9 | 10 | #define MAX_FRAME_LEN (sizeof("T1111222281122334455667788EA5F\r") + 1) 11 | 12 | int slcan_serial_write(void* arg, const char* buf, size_t len); 13 | char* slcan_getline(void* arg); 14 | 15 | static void slcan_ack(char* buf); 16 | static void slcan_nack(char* buf); 17 | 18 | static char hex_digit(const uint8_t b) 19 | { 20 | static const char* hex_tbl = "0123456789abcdef"; 21 | return hex_tbl[b & 0x0f]; 22 | } 23 | 24 | static void hex_write(char** p, const uint8_t* data, uint8_t len) 25 | { 26 | unsigned int i; 27 | for (i = 0; i < len; i++) { 28 | *(*p)++ = hex_digit(data[i] >> 4); 29 | *(*p)++ = hex_digit(data[i]); 30 | } 31 | } 32 | 33 | static uint8_t hex_val(char c) 34 | { 35 | if (c >= 'A' && c <= 'F') { 36 | return c - 'A' + 0xA; 37 | } else if (c >= 'a' && c <= 'f') { 38 | return c - 'a' + 0xa; 39 | } else { 40 | return (c - '0') & 0xf; 41 | } 42 | } 43 | 44 | static uint32_t hex_to_u32(const char* str, uint8_t len) 45 | { 46 | uint32_t val = 0; 47 | unsigned int i; 48 | for (i = 0; i < len; i++) { 49 | val = (val << 4) | hex_val(str[i]); 50 | } 51 | return val; 52 | } 53 | 54 | static uint8_t hex_to_u8(const char* str) 55 | { 56 | uint8_t val; 57 | val = hex_val(*str++); 58 | val = (val << 4) | hex_val(*str); 59 | return val; 60 | } 61 | 62 | void hex_to_u8_array(const char* str, uint8_t* buf, size_t len) 63 | { 64 | while (len-- > 0) { 65 | *buf++ = hex_to_u8(str); 66 | str += 2; 67 | } 68 | } 69 | 70 | size_t slcan_frame_to_ascii(char* buf, const struct can_frame_s* f, bool timestamp) 71 | { 72 | char* p = buf; 73 | uint32_t id = f->id; 74 | 75 | // type 76 | if (f->remote) { 77 | if (f->extended) { 78 | *p++ = 'R'; 79 | } else { 80 | *p++ = 'r'; 81 | } 82 | } else { 83 | if (f->extended) { 84 | *p++ = 'T'; 85 | } else { 86 | *p++ = 't'; 87 | } 88 | } 89 | 90 | // ID 91 | if (f->extended) { 92 | int i; 93 | for (i = 3; i >= 0; i--) { 94 | uint8_t b = id >> (8 * i); 95 | hex_write(&p, &b, 1); 96 | } 97 | } else { 98 | *p++ = hex_digit(id >> 8); 99 | *p++ = hex_digit(id >> 4); 100 | *p++ = hex_digit(id); 101 | } 102 | 103 | // DLC 104 | *p++ = hex_digit(f->length); 105 | 106 | // data 107 | if (!f->remote) { 108 | hex_write(&p, f->data, f->length); 109 | } 110 | 111 | // timestamp 112 | if (timestamp) { 113 | uint16_t t = f->timestamp; 114 | uint8_t b[2] = {t >> 8, t}; 115 | hex_write(&p, b, 2); 116 | } 117 | 118 | *p++ = '\r'; 119 | *p = 0; 120 | 121 | return (size_t)(p - buf); 122 | } 123 | 124 | #define SLC_STD_ID_LEN 3 125 | #define SLC_EXT_ID_LEN 8 126 | 127 | void slcan_send_frame(char* line) 128 | { 129 | char* out = line; 130 | uint8_t data[8]; 131 | uint8_t len; 132 | uint32_t id; 133 | bool remote = false; 134 | bool extended = false; 135 | 136 | switch (*line++) { 137 | case 'r': 138 | remote = true; 139 | /* fallthrought */ 140 | case 't': 141 | id = hex_to_u32(line, SLC_STD_ID_LEN); 142 | line += SLC_STD_ID_LEN; 143 | break; 144 | case 'R': 145 | remote = true; 146 | /* fallthrought */ 147 | case 'T': 148 | extended = true; 149 | id = hex_to_u32(line, SLC_EXT_ID_LEN); 150 | line += SLC_EXT_ID_LEN; 151 | break; 152 | default: 153 | slcan_nack(out); 154 | return; 155 | }; 156 | 157 | len = hex_val(*line++); 158 | 159 | if (len > 8) { 160 | slcan_nack(out); 161 | return; 162 | } 163 | 164 | if (!remote) { 165 | hex_to_u8_array(line, data, len); 166 | } 167 | 168 | if (can_send(id, extended, remote, data, len)) { 169 | slcan_ack(out); 170 | } else { 171 | slcan_nack(out); 172 | } 173 | } 174 | 175 | static void set_bitrate(char* line) 176 | { 177 | static const uint32_t br_tbl[10] = {10000, 20000, 50000, 100000, 125000, 178 | 250000, 500000, 800000, 1000000}; 179 | unsigned char i = line[1]; 180 | if (i < '0' || i > '8') { 181 | slcan_nack(line); 182 | return; 183 | } 184 | i -= '0'; 185 | if (can_set_bitrate(br_tbl[i])) { 186 | slcan_ack(line); 187 | } else { 188 | slcan_nack(line); 189 | } 190 | } 191 | 192 | static void slcan_open(char* line, int mode) 193 | { 194 | if (can_open(mode)) { 195 | slcan_ack(line); 196 | } else { 197 | slcan_nack(line); 198 | } 199 | } 200 | 201 | static void slcan_close(char* line) 202 | { 203 | can_close(); 204 | slcan_ack(line); 205 | } 206 | 207 | /** wirtes a NULL terminated ACK response */ 208 | static void slcan_ack(char* buf) 209 | { 210 | *buf++ = '\r'; // CR 211 | *buf = 0; 212 | } 213 | 214 | /** wirtes a NULL terminated NACK response */ 215 | static void slcan_nack(char* buf) 216 | { 217 | *buf++ = '\a'; // BELL 218 | *buf = 0; 219 | } 220 | 221 | /* 222 | reference: 223 | http://www.fischl.de/usbtin/ 224 | http://www.can232.com/docs/canusb_manual.pdf 225 | */ 226 | void slcan_decode_line(char* line) 227 | { 228 | switch (*line) { 229 | case 'T': // extended frame 230 | case 't': // standard frame 231 | case 'R': // extended remote frame 232 | case 'r': // standard remote frame 233 | slcan_send_frame(line); 234 | break; 235 | case 'S': // set baud rate, S0-S9 236 | set_bitrate(line); 237 | break; 238 | case 'O': // open CAN channel 239 | slcan_open(line, CAN_MODE_NORMAL); 240 | break; 241 | case 'l': // open in loop back mode 242 | slcan_open(line, CAN_MODE_LOOPBACK); 243 | break; 244 | case 'L': // open in silent mode (listen only) 245 | slcan_open(line, CAN_MODE_SILENT); 246 | break; 247 | case 'C': // close CAN channel 248 | slcan_close(line); 249 | break; 250 | case 'V': // hardware version 251 | line = stpcpy(line, hardware_version_str); 252 | slcan_ack(line); 253 | break; 254 | case 'v': // firmware version 255 | line = stpcpy(line, software_version_str); 256 | slcan_ack(line); 257 | break; 258 | case 'F': // read & clear status/error flags 259 | line[1] = '0'; // no error 260 | line[2] = '0'; 261 | slcan_ack(line); 262 | break; 263 | case '\0': // Empty line, requires an ACK to be sent back 264 | slcan_ack(line); 265 | break; 266 | // 'N': // serial number 267 | // 'F': // read status byte 268 | // 'Z': // timestamp on/off, Zx[CR] 269 | // 'm': // acceptance mask, mxxxxxxxx[CR] 270 | // 'M': // acceptance code, Mxxxxxxxx[CR] 271 | 272 | /* CVRA Proprietary extensions */ 273 | case 'P': // Enable bus power 274 | bus_power(true); 275 | slcan_ack(line); 276 | break; 277 | case 'p': // Disable bus power 278 | bus_power(false); 279 | slcan_ack(line); 280 | break; 281 | default: 282 | slcan_nack(line); 283 | break; 284 | }; 285 | } 286 | 287 | void slcan_spin(void* arg) 288 | { 289 | char* line = slcan_getline(arg); 290 | if (line) { 291 | slcan_decode_line(line); 292 | slcan_serial_write(arg, line, strlen(line)); 293 | } 294 | } 295 | 296 | void slcan_rx_spin(void* arg) 297 | { 298 | struct can_frame_s* rxf; 299 | while ((rxf = can_receive()) != NULL) { 300 | static char txbuf[MAX_FRAME_LEN]; 301 | size_t len; 302 | len = slcan_frame_to_ascii(txbuf, rxf, false); 303 | can_frame_delete(rxf); 304 | slcan_serial_write(arg, txbuf, len); 305 | } 306 | } 307 | -------------------------------------------------------------------------------- /src/slcan.h: -------------------------------------------------------------------------------- 1 | #ifndef SLCAN_H 2 | #define SLCAN_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | void slcan_spin(void* arg); 9 | 10 | #ifdef __cplusplus 11 | } 12 | #endif 13 | 14 | #endif /* SLCAN_H */ 15 | -------------------------------------------------------------------------------- /src/slcan_thread.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "can_driver.h" 5 | #include "slcan.h" 6 | #include "slcan_thread.h" 7 | 8 | char* slcan_getline(void* arg) 9 | { 10 | static char line_buffer[500]; 11 | static size_t pos = 0; 12 | size_t i; 13 | for (i = pos; i < sizeof(line_buffer); i++) { 14 | int c = chnGetTimeout((BaseChannel*)arg, TIME_INFINITE); 15 | if (c == STM_TIMEOUT) { 16 | /* no more data, continue */ 17 | pos = i; 18 | return NULL; 19 | } 20 | if (c == '\n' || c == '\r' || c == '\0') { 21 | /* line found */ 22 | line_buffer[i] = 0; 23 | pos = 0; 24 | led_set(STATUS_LED); // show USB activity 25 | return line_buffer; 26 | } else { 27 | line_buffer[i] = c; 28 | } 29 | } 30 | 31 | /* reset */ 32 | pos = 0; 33 | return NULL; 34 | } 35 | 36 | MUTEX_DECL(serial_lock); 37 | 38 | int slcan_serial_write(void* arg, const char* buf, size_t len) 39 | { 40 | if (len == 0) { 41 | return 0; 42 | } 43 | chMtxLock(&serial_lock); 44 | int ret = chnWriteTimeout((BaseChannel*)arg, (const uint8_t*)buf, len, MS2ST(100)); 45 | chMtxUnlock(&serial_lock); 46 | return ret; 47 | } 48 | 49 | THD_WORKING_AREA(slcan_thread, 1000); 50 | void slcan_thread_main(void* arg) 51 | { 52 | chRegSetThreadName("USB receiver"); 53 | while (1) { 54 | slcan_spin(arg); 55 | } 56 | } 57 | 58 | void slcan_rx_spin(void* arg); 59 | 60 | THD_WORKING_AREA(slcan_rx_thread, 1000); 61 | void slcan_rx_thread_main(void* arg) 62 | { 63 | chRegSetThreadName("CAN receiver"); 64 | while (1) { 65 | slcan_rx_spin(arg); 66 | } 67 | } 68 | 69 | void slcan_start(BaseChannel* ch) 70 | { 71 | can_init(); 72 | chThdCreateStatic(slcan_thread, sizeof(slcan_thread), NORMALPRIO, slcan_thread_main, ch); 73 | chThdCreateStatic(slcan_rx_thread, sizeof(slcan_rx_thread), NORMALPRIO, slcan_rx_thread_main, ch); 74 | } 75 | -------------------------------------------------------------------------------- /src/slcan_thread.h: -------------------------------------------------------------------------------- 1 | #ifndef SLCAN_THREAD_H 2 | #define SLCAN_THREAD_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | 10 | void slcan_start(BaseChannel* ch); 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | 16 | #endif /* SLCAN_THREAD_H */ 17 | -------------------------------------------------------------------------------- /src/timestamp/timestamp.c: -------------------------------------------------------------------------------- 1 | #include "timestamp.h" 2 | 3 | int32_t timestamp_duration_us(timestamp_t t1, timestamp_t t2) 4 | { 5 | return (t2 - t1); 6 | } 7 | 8 | float timestamp_duration_s(timestamp_t t1, timestamp_t t2) 9 | { 10 | return (float)timestamp_duration_us(t1, t2) / 1000000.f; 11 | } 12 | 13 | int64_t ltimestamp_duration_us(ltimestamp_t t1, ltimestamp_t t2) 14 | { 15 | return (t2 - t1); 16 | } 17 | 18 | float ltimestamp_duration_s(ltimestamp_t t1, ltimestamp_t t2) 19 | { 20 | return (float)ltimestamp_duration_us(t1, t2) / 1000000.f; 21 | } 22 | -------------------------------------------------------------------------------- /src/timestamp/timestamp.h: -------------------------------------------------------------------------------- 1 | #ifndef TIMESTAMP_H 2 | #define TIMESTAMP_H 3 | 4 | #include 5 | 6 | /* Timestamp 7 | * monotonic, provides us resolution, overflows every 1.19 hours 8 | */ 9 | typedef uint32_t timestamp_t; 10 | 11 | /* Long Timestamp 12 | * monotonic, provides us resolution, never overflows (every 593066 years) 13 | */ 14 | typedef uint64_t ltimestamp_t; 15 | 16 | #ifdef __cplusplus 17 | extern "C" { 18 | #endif 19 | 20 | /* 21 | * Obtain current timestamp 22 | */ 23 | timestamp_t timestamp_get(void); 24 | ltimestamp_t ltimestamp_get(void); 25 | 26 | /* 27 | * Compute duration between two timestamps 28 | * The duration from the first timestamp (t1) to the second (t2) can be 29 | * positive or negative. It is positive when t1 was taken before t2. 30 | * Overflow handling: 31 | * Overflows of the internal integer representation are correctly handled. 32 | * To distinguish between positive and negative durations, the shorter of the 33 | * possible intervals is chosen. 34 | */ 35 | int32_t timestamp_duration_us(timestamp_t t1, timestamp_t t2); 36 | float timestamp_duration_s(timestamp_t t1, timestamp_t t2); 37 | 38 | int64_t ltimestamp_duration_us(ltimestamp_t t1, ltimestamp_t t2); 39 | float ltimestamp_duration_s(ltimestamp_t t1, ltimestamp_t t2); 40 | 41 | #ifdef __cplusplus 42 | } 43 | #endif 44 | 45 | #endif /* TIMESTAMP_H */ 46 | -------------------------------------------------------------------------------- /src/timestamp/timestamp_stm32.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | static volatile uint32_t time_us_low; 5 | static volatile uint32_t time_us_high; 6 | 7 | // ChibiOS specific begin 8 | #include 9 | #include 10 | #include "timestamp.h" 11 | 12 | // settings 13 | #include 14 | 15 | static inline uint32_t timer_read(void) 16 | { 17 | uint32_t tim_reg = TIMER_REG->CNT; 18 | while (TIMER_REG->SR & STM32_TIM_SR_UIF) 19 | ; // make sure there is no interrupt pending TODO won't work in interrupts 20 | return tim_reg; 21 | } 22 | 23 | CH_FAST_IRQ_HANDLER(TIMER_IRQ_NAME) 24 | { 25 | TIMER_REG->SR &= ~STM32_TIM_SR_UIF; // clear interrupt flag 26 | time_us_low += COUNTER_MAX; 27 | // todo 28 | } 29 | 30 | void timestamp_stm32_init(void) 31 | { 32 | time_us_low = 0; 33 | time_us_high = 0; 34 | RCC_EN(); 35 | RCC_RESET(); 36 | nvicEnableVector(NVIC_NB, INTERRUPT_PRIO); 37 | TIMER_REG->ARR = COUNTER_MAX; 38 | TIMER_REG->PSC = PRESCALER; 39 | TIMER_REG->DIER = STM32_TIM_DIER_UIE; // enable update interrupt 40 | TIMER_REG->CR1 |= STM32_TIM_CR1_CEN; // enable timer 41 | } 42 | // ChibiOS specific end 43 | 44 | timestamp_t timestamp_get() 45 | { 46 | uint32_t t1 = time_us_low; 47 | uint32_t tim = timer_read(); 48 | uint32_t t2 = time_us_low; 49 | if (t2 != t1) { 50 | return t2; 51 | } 52 | return t1 + tim; 53 | } 54 | 55 | ltimestamp_t ltimestamp_get() 56 | { 57 | uint32_t t1 = time_us_low; 58 | uint32_t th = time_us_high; 59 | uint32_t tim = timer_read(); 60 | uint32_t t2 = time_us_low; 61 | if (t2 != t1) { 62 | if (t2 < t1) { // time_us_low overflow 63 | return ((uint64_t)(th + 1) << 32) + t2; 64 | } else { 65 | return ((uint64_t)th << 32) + t2; 66 | } 67 | } 68 | return ((uint64_t)th << 32) + t1 + tim; 69 | } 70 | 71 | // test to make sure timestamps are monotonic 72 | bool _timestamp_test(void) 73 | { 74 | timestamp_t t = timestamp_get(); 75 | while (1) { 76 | timestamp_t t_now = timestamp_get(); 77 | if (timestamp_duration_us(t, t_now) < 0) { 78 | return false; 79 | } 80 | t = t_now; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/timestamp/timestamp_stm32.h: -------------------------------------------------------------------------------- 1 | #ifndef TIMESTAMP_STM32_H 2 | #define TIMESTAMP_STM32_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | void timestamp_stm32_init(void); 9 | 10 | #ifdef __cplusplus 11 | } 12 | #endif 13 | 14 | #endif /* TIMESTAMP_STM32_H */ -------------------------------------------------------------------------------- /src/timestamp/timestamp_stm32_settings.h: -------------------------------------------------------------------------------- 1 | #ifndef TIMESTAMP_STM32_SETTINGS_H 2 | #define TIMESTAMP_STM32_SETTINGS_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | 10 | // settings 11 | #define TIMESTAMP_TIMER TIM7 12 | #define TIMER_REG STM32_TIM7 13 | #define TIMER_IRQ_NAME STM32_TIM7_HANDLER 14 | #define RCC_EN() rccEnableTIM7(FALSE) 15 | #define RCC_RESET() rccResetTIM7() 16 | #define NVIC_NB STM32_TIM7_NUMBER 17 | 18 | #define COUNTER_MAX 0xffff 19 | 20 | // CK_CNT = CK_INT / (PSC[15:0] + 1) 21 | #if STM32_PPRE1 == STM32_PPRE1_DIV1 22 | #define PRESCALER (STM32_PCLK1 / 1000000 - 1) 23 | #else 24 | #define PRESCALER (2 * STM32_PCLK1 / 1000000 - 1) 25 | #endif 26 | #define INTERRUPT_PRIO 5 27 | 28 | #ifdef __cplusplus 29 | } 30 | #endif 31 | 32 | #endif /* TIMESTAMP_STM32_SETTINGS_H */ 33 | -------------------------------------------------------------------------------- /src/timestamp_stm32_settings.h: -------------------------------------------------------------------------------- 1 | #ifndef TIMESTAMP_STM32_SETTINGS_H 2 | #define TIMESTAMP_STM32_SETTINGS_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | 10 | // settings 11 | #define TIMESTAMP_TIMER TIM6 12 | #define TIMER_REG STM32_TIM6 13 | #define TIMER_IRQ_NAME STM32_TIM6_HANDLER 14 | #define RCC_EN() rccEnableTIM6(FALSE) 15 | #define RCC_RESET() rccResetTIM6() 16 | #define NVIC_NB STM32_TIM6_NUMBER 17 | 18 | #define COUNTER_MAX 0xffff 19 | 20 | // CK_CNT = CK_INT / (PSC[15:0] + 1) 21 | #if STM32_PPRE1 == STM32_PPRE1_DIV1 22 | #define PRESCALER (STM32_PCLK1 / 1000000 - 1) 23 | #else 24 | #define PRESCALER (2 * STM32_PCLK1 / 1000000 - 1) 25 | #endif 26 | #define INTERRUPT_PRIO 5 27 | 28 | #ifdef __cplusplus 29 | } 30 | #endif 31 | 32 | #endif /* TIMESTAMP_STM32_SETTINGS_H */ 33 | -------------------------------------------------------------------------------- /src/uart_bridge.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "usbcfg.h" 5 | #include 6 | 7 | volatile bool uart1_needs_reconfig = false; 8 | binary_semaphore_t uart1_config_lock; 9 | 10 | static THD_WORKING_AREA(uart_rx_wa, 300); 11 | static THD_FUNCTION(uart_rx, arg) 12 | { 13 | chRegSetThreadName("uart_rx"); 14 | BaseChannel* io = (BaseChannel*)arg; 15 | size_t len; 16 | static uint8_t buf[32]; 17 | while (true) { 18 | len = sdReadTimeout(&SD1, &buf[0], sizeof(buf), MS2ST(1)); 19 | if (len > 0) { 20 | led_set(STATUS_LED); 21 | chnWrite(io, &buf[0], len); 22 | } 23 | if (uart1_needs_reconfig) { 24 | // wait until uart is reconfigured 25 | chBSemWait(&uart1_config_lock); 26 | } 27 | } 28 | } 29 | 30 | static THD_WORKING_AREA(uart_tx_wa, 300); 31 | static THD_FUNCTION(uart_tx, arg) 32 | { 33 | chRegSetThreadName("uart_tx"); 34 | BaseChannel* io = (BaseChannel*)arg; 35 | static SerialConfig uart1_config = { 36 | SERIAL_DEFAULT_BITRATE, 37 | 0, 38 | USART_CR2_STOP1_BITS | USART_CR2_LINEN, 39 | 0}; 40 | uart1_config.speed = serial_usb_get_baudrate(); 41 | uart1_config.speed *= 2; 42 | sdStart(&SD1, &uart1_config); 43 | // start uart receive thread 44 | chBSemObjectInit(&uart1_config_lock, true); 45 | chThdCreateStatic(uart_rx_wa, sizeof(uart_rx_wa), NORMALPRIO, uart_rx, io); 46 | while (true) { 47 | size_t len; 48 | static uint8_t buf[32]; 49 | len = chnReadTimeout(io, &buf[0], sizeof(buf), MS2ST(1)); 50 | if (len > 0) { 51 | led_set(STATUS_LED); 52 | sdWrite(&SD1, &buf[0], len); 53 | } else { 54 | // check if uart baudrate has changed 55 | uint32_t speed = serial_usb_get_baudrate(); 56 | speed *= 2; // workaround: uart1 clock is off by a factor of 2 for some reason 57 | if (speed != uart1_config.speed) { 58 | // wait until receiver thread is halted 59 | uart1_needs_reconfig = true; 60 | while (!chBSemGetStateI(&uart1_config_lock)) { 61 | chThdSleepMilliseconds(1); 62 | } 63 | // reconfigure uart 64 | sdStop(&SD1); 65 | uart1_config.speed = speed; 66 | sdStart(&SD1, &uart1_config); 67 | uart1_needs_reconfig = false; 68 | chBSemSignal(&uart1_config_lock); 69 | } 70 | } 71 | } 72 | } 73 | 74 | void uart_bridge_start(BaseChannel* ch) 75 | { 76 | chThdCreateStatic(uart_tx_wa, sizeof(uart_tx_wa), NORMALPRIO, uart_tx, ch); 77 | } 78 | -------------------------------------------------------------------------------- /src/uart_bridge.h: -------------------------------------------------------------------------------- 1 | #ifndef UART_BRIDGE_H 2 | #define UART_BRIDGE_H 3 | 4 | #include 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | void uart_bridge_start(BaseChannel* ch); 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | 16 | #endif /* UART_BRIDGE_H */ 17 | -------------------------------------------------------------------------------- /src/usbcfg.c: -------------------------------------------------------------------------------- 1 | /* 2 | ChibiOS - Copyright (C) 2006-2014 Giovanni Di Sirio 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #include "ch.h" 18 | #include "hal.h" 19 | 20 | /* 21 | * Endpoints to be used for USBD1. 22 | */ 23 | #define USBD1_CDC1_DATA_REQUEST_EP 1 24 | #define USBD1_CDC1_DATA_AVAILABLE_EP 1 25 | #define USBD1_CDC1_INTERRUPT_REQUEST_EP 2 26 | 27 | #define USBD1_CDC2_DATA_REQUEST_EP 3 28 | #define USBD1_CDC2_DATA_AVAILABLE_EP 3 29 | #define USBD1_CDC2_INTERRUPT_REQUEST_EP 4 30 | 31 | /* 32 | * USB Device Descriptor. 33 | */ 34 | static const uint8_t vcom_device_descriptor_data[18] = { 35 | USB_DESC_DEVICE(0x0110, /* bcdUSB (1.1). */ 36 | 0x02, /* bDeviceClass (CDC). */ 37 | 0x00, /* bDeviceSubClass. */ 38 | 0x00, /* bDeviceProtocol. */ 39 | 0x40, /* bMaxPacketSize. */ 40 | 0x0483, /* idVendor (ST). */ 41 | 0x5740, /* idProduct. */ 42 | 0x0200, /* bcdDevice. */ 43 | 1, /* iManufacturer. */ 44 | 2, /* iProduct. */ 45 | 3, /* iSerialNumber. */ 46 | 1) /* bNumConfigurations. */ 47 | }; 48 | 49 | /* 50 | * Device Descriptor wrapper. 51 | */ 52 | static const USBDescriptor vcom_device_descriptor = { 53 | sizeof vcom_device_descriptor_data, 54 | vcom_device_descriptor_data}; 55 | 56 | /* Configuration Descriptor tree for a CDC.*/ 57 | static const uint8_t vcom_configuration_descriptor_data[141] = { 58 | /* Configuration Descriptor.*/ 59 | USB_DESC_CONFIGURATION(141, /* wTotalLength. */ 60 | 0x04, /* bNumInterfaces. */ 61 | 0x01, /* bConfigurationValue. */ 62 | 0, /* iConfiguration. */ 63 | 0xC0, /* bmAttributes (self powered). */ 64 | 50), /* bMaxPower (100mA). */ 65 | /* CDC1 */ 66 | /* Interface Association Descriptor. */ 67 | USB_DESC_INTERFACE_ASSOCIATION(0x00, /* bFirstInterface */ 68 | 0x02, /* bInterfaceCount */ 69 | 0x02, /* bFunctionClass */ 70 | 0x00, /* bFunctionSubClass */ 71 | 0x01, /* bFunctionProcotol */ 72 | 0), /* iInterface */ 73 | /* Interface Descriptor.*/ 74 | USB_DESC_INTERFACE(0x00, /* bInterfaceNumber. */ 75 | 0x00, /* bAlternateSetting. */ 76 | 0x01, /* bNumEndpoints. */ 77 | 0x02, /* bInterfaceClass (Communications 78 | Interface Class, CDC section 79 | 4.2). */ 80 | 0x02, /* bInterfaceSubClass (Abstract 81 | Control Model, CDC section 4.3). */ 82 | 0x01, /* bInterfaceProtocol (AT commands, 83 | CDC section 4.4). */ 84 | 0), /* iInterface. */ 85 | /* Header Functional Descriptor (CDC section 5.2.3).*/ 86 | USB_DESC_BYTE(5), /* bLength. */ 87 | USB_DESC_BYTE(0x24), /* bDescriptorType (CS_INTERFACE). */ 88 | USB_DESC_BYTE(0x00), /* bDescriptorSubtype (Header 89 | Functional Descriptor. */ 90 | USB_DESC_BCD(0x0110), /* bcdCDC. */ 91 | /* Call Management Functional Descriptor. */ 92 | USB_DESC_BYTE(5), /* bFunctionLength. */ 93 | USB_DESC_BYTE(0x24), /* bDescriptorType (CS_INTERFACE). */ 94 | USB_DESC_BYTE(0x01), /* bDescriptorSubtype (Call Management 95 | Functional Descriptor). */ 96 | USB_DESC_BYTE(0x00), /* bmCapabilities (D0+D1). */ 97 | USB_DESC_BYTE(0x01), /* bDataInterface. */ 98 | /* ACM Functional Descriptor.*/ 99 | USB_DESC_BYTE(4), /* bFunctionLength. */ 100 | USB_DESC_BYTE(0x24), /* bDescriptorType (CS_INTERFACE). */ 101 | USB_DESC_BYTE(0x02), /* bDescriptorSubtype (Abstract 102 | Control Management Descriptor). */ 103 | USB_DESC_BYTE(0x02), /* bmCapabilities. */ 104 | /* Union Functional Descriptor.*/ 105 | USB_DESC_BYTE(5), /* bFunctionLength. */ 106 | USB_DESC_BYTE(0x24), /* bDescriptorType (CS_INTERFACE). */ 107 | USB_DESC_BYTE(0x06), /* bDescriptorSubtype (Union 108 | Functional Descriptor). */ 109 | USB_DESC_BYTE(0x00), /* bMasterInterface (Communication 110 | Class Interface). */ 111 | USB_DESC_BYTE(0x01), /* bSlaveInterface0 (Data Class 112 | Interface). */ 113 | /* Endpoint 2 Descriptor.*/ 114 | USB_DESC_ENDPOINT(USBD1_CDC1_INTERRUPT_REQUEST_EP | 0x80, 115 | 0x03, /* bmAttributes (Interrupt). */ 116 | 0x0008, /* wMaxPacketSize. */ 117 | 0xFF), /* bInterval. */ 118 | /* Interface Descriptor.*/ 119 | USB_DESC_INTERFACE(0x01, /* bInterfaceNumber. */ 120 | 0x00, /* bAlternateSetting. */ 121 | 0x02, /* bNumEndpoints. */ 122 | 0x0A, /* bInterfaceClass (Data Class 123 | Interface, CDC section 4.5). */ 124 | 0x00, /* bInterfaceSubClass (CDC section 125 | 4.6). */ 126 | 0x00, /* bInterfaceProtocol (CDC section 127 | 4.7). */ 128 | 0x00), /* iInterface. */ 129 | /* Endpoint 3 Descriptor.*/ 130 | USB_DESC_ENDPOINT(USBD1_CDC1_DATA_AVAILABLE_EP, /* bEndpointAddress.*/ 131 | 0x02, /* bmAttributes (Bulk). */ 132 | 0x0040, /* wMaxPacketSize. */ 133 | 0x00), /* bInterval. */ 134 | /* Endpoint 1 Descriptor.*/ 135 | USB_DESC_ENDPOINT(USBD1_CDC1_DATA_REQUEST_EP | 0x80, /* bEndpointAddress.*/ 136 | 0x02, /* bmAttributes (Bulk). */ 137 | 0x0040, /* wMaxPacketSize. */ 138 | 0x00), /* bInterval. */ 139 | 140 | /* CDC2 */ 141 | /* Interface Association Descriptor. */ 142 | USB_DESC_INTERFACE_ASSOCIATION(0x02, /* bFirstInterface */ 143 | 0x02, /* bInterfaceCount */ 144 | 0x02, /* bFunctionClass */ 145 | 0x00, /* bFunctionSubClass */ 146 | 0x01, /* bFunctionProcotol */ 147 | 0), /* iInterface */ 148 | /* Interface Descriptor.*/ 149 | USB_DESC_INTERFACE(0x02, /* bInterfaceNumber. */ 150 | 0x00, /* bAlternateSetting. */ 151 | 0x01, /* bNumEndpoints. */ 152 | 0x02, /* bInterfaceClass (Communications 153 | Interface Class, CDC section 154 | 4.2). */ 155 | 0x02, /* bInterfaceSubClass (Abstract 156 | Control Model, CDC section 4.3). */ 157 | 0x01, /* bInterfaceProtocol (AT commands, 158 | CDC section 4.4). */ 159 | 0), /* iInterface. */ 160 | /* Header Functional Descriptor (CDC section 5.2.3).*/ 161 | USB_DESC_BYTE(5), /* bLength. */ 162 | USB_DESC_BYTE(0x24), /* bDescriptorType (CS_INTERFACE). */ 163 | USB_DESC_BYTE(0x00), /* bDescriptorSubtype (Header 164 | Functional Descriptor. */ 165 | USB_DESC_BCD(0x0110), /* bcdCDC. */ 166 | /* Call Management Functional Descriptor. */ 167 | USB_DESC_BYTE(5), /* bFunctionLength. */ 168 | USB_DESC_BYTE(0x24), /* bDescriptorType (CS_INTERFACE). */ 169 | USB_DESC_BYTE(0x01), /* bDescriptorSubtype (Call Management 170 | Functional Descriptor). */ 171 | USB_DESC_BYTE(0x00), /* bmCapabilities (D0+D1). */ 172 | USB_DESC_BYTE(0x03), /* bDataInterface. */ 173 | /* ACM Functional Descriptor.*/ 174 | USB_DESC_BYTE(4), /* bFunctionLength. */ 175 | USB_DESC_BYTE(0x24), /* bDescriptorType (CS_INTERFACE). */ 176 | USB_DESC_BYTE(0x02), /* bDescriptorSubtype (Abstract 177 | Control Management Descriptor). */ 178 | USB_DESC_BYTE(0x02), /* bmCapabilities. */ 179 | /* Union Functional Descriptor.*/ 180 | USB_DESC_BYTE(5), /* bFunctionLength. */ 181 | USB_DESC_BYTE(0x24), /* bDescriptorType (CS_INTERFACE). */ 182 | USB_DESC_BYTE(0x06), /* bDescriptorSubtype (Union 183 | Functional Descriptor). */ 184 | USB_DESC_BYTE(0x02), /* bMasterInterface (Communication 185 | Class Interface). */ 186 | USB_DESC_BYTE(0x03), /* bSlaveInterface0 (Data Class 187 | Interface). */ 188 | /* Endpoint INTERRUPT_REQUEST Descriptor.*/ 189 | USB_DESC_ENDPOINT(USBD1_CDC2_INTERRUPT_REQUEST_EP | 0x80, 190 | 0x03, /* bmAttributes (Interrupt). */ 191 | 0x0008, /* wMaxPacketSize. */ 192 | 0xFF), /* bInterval. */ 193 | /* Interface Descriptor.*/ 194 | USB_DESC_INTERFACE(0x03, /* bInterfaceNumber. */ 195 | 0x00, /* bAlternateSetting. */ 196 | 0x02, /* bNumEndpoints. */ 197 | 0x0A, /* bInterfaceClass (Data Class 198 | Interface, CDC section 4.5). */ 199 | 0x00, /* bInterfaceSubClass (CDC section 200 | 4.6). */ 201 | 0x00, /* bInterfaceProtocol (CDC section 202 | 4.7). */ 203 | 0x00), /* iInterface. */ 204 | /* Endpoint DATA_AVAILABLE Descriptor.*/ 205 | USB_DESC_ENDPOINT(USBD1_CDC2_DATA_AVAILABLE_EP, /* bEndpointAddress.*/ 206 | 0x02, /* bmAttributes (Bulk). */ 207 | 0x0040, /* wMaxPacketSize. */ 208 | 0x00), /* bInterval. */ 209 | /* Endpoint DATA_REQUEST Descriptor.*/ 210 | USB_DESC_ENDPOINT(USBD1_CDC2_DATA_REQUEST_EP | 0x80, /* bEndpointAddress.*/ 211 | 0x02, /* bmAttributes (Bulk). */ 212 | 0x0040, /* wMaxPacketSize. */ 213 | 0x00) /* bInterval. */ 214 | }; 215 | 216 | /* 217 | * Configuration Descriptor wrapper. 218 | */ 219 | static const USBDescriptor vcom_configuration_descriptor = { 220 | sizeof vcom_configuration_descriptor_data, 221 | vcom_configuration_descriptor_data}; 222 | 223 | /* 224 | * U.S. English language identifier. 225 | */ 226 | static const uint8_t vcom_string0[] = { 227 | USB_DESC_BYTE(4), /* bLength. */ 228 | USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */ 229 | USB_DESC_WORD(0x0409) /* wLANGID (U.S. English). */ 230 | }; 231 | 232 | /* 233 | * Vendor string. 234 | */ 235 | static const uint8_t vcom_string1[] = { 236 | USB_DESC_BYTE(10), /* bLength. */ 237 | USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */ 238 | 'C', 0, 'V', 0, 'R', 0, 'A', 0}; 239 | 240 | /* 241 | * Device Description string. 242 | */ 243 | static const uint8_t vcom_string2[] = { 244 | USB_DESC_BYTE(16), /* bLength. */ 245 | USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */ 246 | 'C', 0, 'A', 0, 'N', 0, '2', 0, 'U', 0, 'S', 0, 'B', 0}; 247 | 248 | /* 249 | * Serial Number string. 250 | */ 251 | static const uint8_t vcom_string3[] = { 252 | USB_DESC_BYTE(8), /* bLength. */ 253 | USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */ 254 | '0' + CH_KERNEL_MAJOR, 0, 255 | '0' + CH_KERNEL_MINOR, 0, 256 | '0' + CH_KERNEL_PATCH, 0}; 257 | 258 | /* 259 | * Strings wrappers array. 260 | */ 261 | static const USBDescriptor vcom_strings[] = { 262 | {sizeof vcom_string0, vcom_string0}, 263 | {sizeof vcom_string1, vcom_string1}, 264 | {sizeof vcom_string2, vcom_string2}, 265 | {sizeof vcom_string3, vcom_string3}}; 266 | 267 | /* 268 | * Handles the GET_DESCRIPTOR callback. All required descriptors must be 269 | * handled here. 270 | */ 271 | static const USBDescriptor* get_descriptor(USBDriver* usbp, 272 | uint8_t dtype, 273 | uint8_t dindex, 274 | uint16_t lang) 275 | { 276 | (void)usbp; 277 | (void)lang; 278 | switch (dtype) { 279 | case USB_DESCRIPTOR_DEVICE: 280 | return &vcom_device_descriptor; 281 | case USB_DESCRIPTOR_CONFIGURATION: 282 | return &vcom_configuration_descriptor; 283 | case USB_DESCRIPTOR_STRING: 284 | if (dindex < 4) 285 | return &vcom_strings[dindex]; 286 | } 287 | return NULL; 288 | } 289 | 290 | /** 291 | * @brief IN EP1 state. 292 | */ 293 | static USBInEndpointState ep1instate; 294 | 295 | /** 296 | * @brief OUT EP1 state. 297 | */ 298 | static USBOutEndpointState ep1outstate; 299 | 300 | /** 301 | * @brief EP1 initialization structure (both IN and OUT). 302 | */ 303 | static const USBEndpointConfig ep1config = { 304 | USB_EP_MODE_TYPE_BULK, 305 | NULL, 306 | sduDataTransmitted, 307 | sduDataReceived, 308 | 0x0040, 309 | 0x0040, 310 | &ep1instate, 311 | &ep1outstate, 312 | 2, 313 | NULL}; 314 | 315 | /** 316 | * @brief IN EP2 state. 317 | */ 318 | static USBInEndpointState ep2instate; 319 | 320 | /** 321 | * @brief EP2 initialization structure (IN only). 322 | */ 323 | static const USBEndpointConfig ep2config = { 324 | USB_EP_MODE_TYPE_INTR, 325 | NULL, 326 | sduInterruptTransmitted, 327 | NULL, 328 | 0x0010, 329 | 0x0000, 330 | &ep2instate, 331 | NULL, 332 | 1, 333 | NULL}; 334 | 335 | /** 336 | * @brief IN EP3 state. 337 | */ 338 | static USBInEndpointState ep3instate; 339 | 340 | /** 341 | * @brief OUT EP3 state. 342 | */ 343 | static USBOutEndpointState ep3outstate; 344 | 345 | /** 346 | * @brief EP3 initialization structure (both IN and OUT). 347 | */ 348 | static const USBEndpointConfig ep3config = { 349 | USB_EP_MODE_TYPE_BULK, 350 | NULL, 351 | sduDataTransmitted, 352 | sduDataReceived, 353 | 0x0040, 354 | 0x0040, 355 | &ep3instate, 356 | &ep3outstate, 357 | 2, 358 | NULL}; 359 | 360 | /** 361 | * @brief IN EP4 state. 362 | */ 363 | static USBInEndpointState ep4instate; 364 | 365 | /** 366 | * @brief EP4 initialization structure (IN only). 367 | */ 368 | static const USBEndpointConfig ep4config = { 369 | USB_EP_MODE_TYPE_INTR, 370 | NULL, 371 | sduInterruptTransmitted, 372 | NULL, 373 | 0x0010, 374 | 0x0000, 375 | &ep4instate, 376 | NULL, 377 | 1, 378 | NULL}; 379 | 380 | /* 381 | * Handles the USB driver global events. 382 | */ 383 | static void usb_event(USBDriver* usbp, usbevent_t event) 384 | { 385 | extern SerialUSBDriver SDU1, SDU2; 386 | 387 | switch (event) { 388 | case USB_EVENT_RESET: 389 | return; 390 | case USB_EVENT_ADDRESS: 391 | return; 392 | case USB_EVENT_CONFIGURED: 393 | chSysLockFromISR(); 394 | 395 | /* Enables the endpoints specified into the configuration. */ 396 | usbInitEndpointI(usbp, USBD1_CDC1_DATA_REQUEST_EP, &ep1config); 397 | usbInitEndpointI(usbp, USBD1_CDC1_INTERRUPT_REQUEST_EP, &ep2config); 398 | /* Resetting the state of the CDC subsystem.*/ 399 | sduConfigureHookI(&SDU1); 400 | 401 | /* Enables the endpoints specified into the configuration. */ 402 | usbInitEndpointI(usbp, USBD1_CDC2_DATA_REQUEST_EP, &ep3config); 403 | usbInitEndpointI(usbp, USBD1_CDC2_INTERRUPT_REQUEST_EP, &ep4config); 404 | /* Resetting the state of the CDC subsystem.*/ 405 | sduConfigureHookI(&SDU2); 406 | 407 | chSysUnlockFromISR(); 408 | return; 409 | case USB_EVENT_SUSPEND: 410 | return; 411 | case USB_EVENT_WAKEUP: 412 | return; 413 | case USB_EVENT_STALLED: 414 | return; 415 | } 416 | return; 417 | } 418 | 419 | static cdc_linecoding_t cdc_linecoding = { 420 | {0x00, 0x96, 0x00, 0x00}, // 38400 421 | LC_STOP_1, 422 | LC_PARITY_NONE, 423 | 8}; 424 | 425 | static uint32_t serial_baudrate = SERIAL_DEFAULT_BITRATE; 426 | 427 | static void linecoding_callback(USBDriver* usbp) 428 | { 429 | (void)usbp; 430 | chSysLockFromISR(); 431 | serial_baudrate = cdc_linecoding.dwDTERate[0] | cdc_linecoding.dwDTERate[1] << 8 | cdc_linecoding.dwDTERate[2] << 16 | cdc_linecoding.dwDTERate[3] << 24; 432 | chSysUnlockFromISR(); 433 | } 434 | 435 | uint32_t serial_usb_get_baudrate(void) 436 | { 437 | uint32_t br; 438 | chSysLock(); 439 | br = serial_baudrate; 440 | chSysUnlock(); 441 | return br; 442 | } 443 | 444 | // copied from serial_usb.c driver to have direct access to linecoding. 445 | bool my_sduRequestsHook(USBDriver* usbp) 446 | { 447 | if ((usbp->setup[0] & USB_RTYPE_TYPE_MASK) == USB_RTYPE_TYPE_CLASS) { 448 | usbcallback_t callback = NULL; 449 | switch (usbp->setup[1]) { 450 | case CDC_GET_LINE_CODING: 451 | usbSetupTransfer(usbp, (uint8_t*)&cdc_linecoding, sizeof(cdc_linecoding), NULL); 452 | return true; 453 | case CDC_SET_LINE_CODING: 454 | if (usbp->setup[4] == 0x02) { // wIndex field indicatedes the addressed interface 455 | // if second interface then we actually care about the linecoding 456 | callback = linecoding_callback; 457 | } 458 | usbSetupTransfer(usbp, (uint8_t*)&cdc_linecoding, sizeof(cdc_linecoding), callback); 459 | return true; 460 | case CDC_SET_CONTROL_LINE_STATE: 461 | /* Nothing to do, there are no control lines.*/ 462 | usbSetupTransfer(usbp, NULL, 0, NULL); 463 | return true; 464 | default: 465 | return false; 466 | } 467 | } 468 | return false; 469 | } 470 | 471 | /* 472 | * USB driver configuration. 473 | */ 474 | const USBConfig usbcfg = { 475 | usb_event, 476 | get_descriptor, 477 | my_sduRequestsHook, 478 | NULL}; 479 | 480 | /* 481 | * Serial over USB driver configuration. 482 | */ 483 | const SerialUSBConfig serusbcfg1 = { 484 | &USBD1, 485 | USBD1_CDC1_DATA_REQUEST_EP, 486 | USBD1_CDC1_DATA_AVAILABLE_EP, 487 | USBD1_CDC1_INTERRUPT_REQUEST_EP}; 488 | 489 | const SerialUSBConfig serusbcfg2 = { 490 | &USBD1, 491 | USBD1_CDC2_DATA_REQUEST_EP, 492 | USBD1_CDC2_DATA_AVAILABLE_EP, 493 | USBD1_CDC2_INTERRUPT_REQUEST_EP}; 494 | -------------------------------------------------------------------------------- /src/usbcfg.h: -------------------------------------------------------------------------------- 1 | /* 2 | ChibiOS - Copyright (C) 2006-2014 Giovanni Di Sirio 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #ifndef _USBCFG_H_ 18 | #define _USBCFG_H_ 19 | 20 | #include 21 | 22 | uint32_t serial_usb_get_baudrate(void); 23 | extern const USBConfig usbcfg; 24 | extern SerialUSBConfig serusbcfg1; 25 | extern SerialUSBConfig serusbcfg2; 26 | 27 | #endif /* _USBCFG_H_ */ 28 | 29 | /** @} */ 30 | -------------------------------------------------------------------------------- /src/usbcfg2.c: -------------------------------------------------------------------------------- 1 | #include "usbcfg2.h" 2 | 3 | /*Endpoints to be used for USBD1. */ 4 | #define USBD1_DATA_REQUEST_EP 1 5 | #define USBD1_DATA_AVAILABLE_EP 1 6 | #define USBD1_INTERRUPT_REQUEST_EP 2 7 | 8 | /* USB Device Descriptor. */ 9 | static const uint8_t vcom_device_descriptor_data[18] = { 10 | USB_DESC_DEVICE(0x0110, /* bcdUSB (1.1). */ 11 | 0x02, /* bDeviceClass (CDC). */ 12 | 0x00, /* bDeviceSubClass. */ 13 | 0x00, /* bDeviceProtocol. */ 14 | 0x40, /* bMaxPacketSize. */ 15 | 0x0483, /* idVendor (ST). */ 16 | 0x5740, /* idProduct. */ 17 | 0x0200, /* bcdDevice. */ 18 | 1, /* iManufacturer. */ 19 | 2, /* iProduct. */ 20 | 3, /* iSerialNumber. */ 21 | 1) /* bNumConfigurations. */ 22 | }; 23 | 24 | /* Device Descriptor wrapper. */ 25 | static const USBDescriptor vcom_device_descriptor = { 26 | sizeof vcom_device_descriptor_data, 27 | vcom_device_descriptor_data}; 28 | 29 | /* Configuration Descriptor tree for a CDC.*/ 30 | static const uint8_t vcom_configuration_descriptor_data[67] = { 31 | /* Configuration Descriptor.*/ 32 | USB_DESC_CONFIGURATION(67, /* wTotalLength. */ 33 | 0x02, /* bNumInterfaces. */ 34 | 0x01, /* bConfigurationValue. */ 35 | 0, /* iConfiguration. */ 36 | 0xC0, /* bmAttributes (self powered). */ 37 | 50), /* bMaxPower (100mA). */ 38 | /* Interface Descriptor.*/ 39 | USB_DESC_INTERFACE(0x00, /* bInterfaceNumber. */ 40 | 0x00, /* bAlternateSetting. */ 41 | 0x01, /* bNumEndpoints. */ 42 | 0x02, /* bInterfaceClass (Communications 43 | Interface Class, CDC section 44 | 4.2). */ 45 | 0x02, /* bInterfaceSubClass (Abstract 46 | Control Model, CDC section 4.3). */ 47 | 0x01, /* bInterfaceProtocol (AT commands, 48 | CDC section 4.4). */ 49 | 0), /* iInterface. */ 50 | /* Header Functional Descriptor (CDC section 5.2.3).*/ 51 | USB_DESC_BYTE(5), /* bLength. */ 52 | USB_DESC_BYTE(0x24), /* bDescriptorType (CS_INTERFACE). */ 53 | USB_DESC_BYTE(0x00), /* bDescriptorSubtype (Header 54 | Functional Descriptor. */ 55 | USB_DESC_BCD(0x0110), /* bcdCDC. */ 56 | /* Call Management Functional Descriptor. */ 57 | USB_DESC_BYTE(5), /* bFunctionLength. */ 58 | USB_DESC_BYTE(0x24), /* bDescriptorType (CS_INTERFACE). */ 59 | USB_DESC_BYTE(0x01), /* bDescriptorSubtype (Call Management 60 | Functional Descriptor). */ 61 | USB_DESC_BYTE(0x00), /* bmCapabilities (D0+D1). */ 62 | USB_DESC_BYTE(0x01), /* bDataInterface. */ 63 | /* ACM Functional Descriptor.*/ 64 | USB_DESC_BYTE(4), /* bFunctionLength. */ 65 | USB_DESC_BYTE(0x24), /* bDescriptorType (CS_INTERFACE). */ 66 | USB_DESC_BYTE(0x02), /* bDescriptorSubtype (Abstract 67 | Control Management Descriptor). */ 68 | USB_DESC_BYTE(0x02), /* bmCapabilities. */ 69 | /* Union Functional Descriptor.*/ 70 | USB_DESC_BYTE(5), /* bFunctionLength. */ 71 | USB_DESC_BYTE(0x24), /* bDescriptorType (CS_INTERFACE). */ 72 | USB_DESC_BYTE(0x06), /* bDescriptorSubtype (Union 73 | Functional Descriptor). */ 74 | USB_DESC_BYTE(0x00), /* bMasterInterface (Communication 75 | Class Interface). */ 76 | USB_DESC_BYTE(0x01), /* bSlaveInterface0 (Data Class 77 | Interface). */ 78 | /* Endpoint 2 Descriptor.*/ 79 | USB_DESC_ENDPOINT(USBD1_INTERRUPT_REQUEST_EP | 0x80, 80 | 0x03, /* bmAttributes (Interrupt). */ 81 | 0x0008, /* wMaxPacketSize. */ 82 | 0xFF), /* bInterval. */ 83 | /* Interface Descriptor.*/ 84 | USB_DESC_INTERFACE(0x01, /* bInterfaceNumber. */ 85 | 0x00, /* bAlternateSetting. */ 86 | 0x02, /* bNumEndpoints. */ 87 | 0x0A, /* bInterfaceClass (Data Class 88 | Interface, CDC section 4.5). */ 89 | 0x00, /* bInterfaceSubClass (CDC section 90 | 4.6). */ 91 | 0x00, /* bInterfaceProtocol (CDC section 92 | 4.7). */ 93 | 0x00), /* iInterface. */ 94 | /* Endpoint 3 Descriptor.*/ 95 | USB_DESC_ENDPOINT(USBD1_DATA_AVAILABLE_EP, /* bEndpointAddress.*/ 96 | 0x02, /* bmAttributes (Bulk). */ 97 | 0x0040, /* wMaxPacketSize. */ 98 | 0x00), /* bInterval. */ 99 | /* Endpoint 1 Descriptor.*/ 100 | USB_DESC_ENDPOINT(USBD1_DATA_REQUEST_EP | 0x80, /* bEndpointAddress.*/ 101 | 0x02, /* bmAttributes (Bulk). */ 102 | 0x0040, /* wMaxPacketSize. */ 103 | 0x00) /* bInterval. */ 104 | }; 105 | 106 | /* Configuration Descriptor wrapper. */ 107 | static const USBDescriptor vcom_configuration_descriptor = { 108 | sizeof vcom_configuration_descriptor_data, 109 | vcom_configuration_descriptor_data}; 110 | 111 | /* U.S. English language identifier. */ 112 | static const uint8_t vcom_string0[] = { 113 | USB_DESC_BYTE(4), /* bLength. */ 114 | USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */ 115 | USB_DESC_WORD(0x0409) /* wLANGID (U.S. English). */ 116 | }; 117 | 118 | /* Vendor string. */ 119 | static const uint8_t vcom_string1[] = { 120 | USB_DESC_BYTE(38), /* bLength. */ 121 | USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */ 122 | 'C', 123 | 0, 124 | 'V', 125 | 0, 126 | 'R', 127 | 0, 128 | 'A', 129 | 0, 130 | }; 131 | 132 | /* Device Description string. */ 133 | static const uint8_t vcom_string2[] = { 134 | USB_DESC_BYTE(26), /* bLength. */ 135 | USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */ 136 | 'C', 0, 'V', 0, 'R', 0, 'A', 0, ' ', 0, 137 | 'C', 0, 'A', 0, 'N', 0, '2', 0, 'U', 0, 'S', 0, 'B', 0}; 138 | 139 | /* Serial Number string. */ 140 | static const uint8_t vcom_string3[] = { 141 | USB_DESC_BYTE(8), /* bLength. */ 142 | USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */ 143 | '0' + CH_KERNEL_MAJOR, 0, 144 | '0' + CH_KERNEL_MINOR, 0, 145 | '0' + CH_KERNEL_PATCH, 0}; 146 | 147 | /* Strings wrappers array. */ 148 | static const USBDescriptor vcom_strings[] = { 149 | {sizeof vcom_string0, vcom_string0}, 150 | {sizeof vcom_string1, vcom_string1}, 151 | {sizeof vcom_string2, vcom_string2}, 152 | {sizeof vcom_string3, vcom_string3}}; 153 | 154 | /* Handles the GET_DESCRIPTOR callback. All required descriptors must be 155 | * handled here. */ 156 | static const USBDescriptor* get_descriptor(USBDriver* usbp, 157 | uint8_t dtype, 158 | uint8_t dindex, 159 | uint16_t lang) 160 | { 161 | (void)usbp; 162 | (void)lang; 163 | switch (dtype) { 164 | case USB_DESCRIPTOR_DEVICE: 165 | return &vcom_device_descriptor; 166 | case USB_DESCRIPTOR_CONFIGURATION: 167 | return &vcom_configuration_descriptor; 168 | case USB_DESCRIPTOR_STRING: 169 | if (dindex < 4) 170 | return &vcom_strings[dindex]; 171 | } 172 | return NULL; 173 | } 174 | 175 | static USBInEndpointState ep1instate; 176 | static USBOutEndpointState ep1outstate; 177 | 178 | /** @brief EP1 initialization structure (both IN and OUT). */ 179 | static const USBEndpointConfig ep1config = { 180 | USB_EP_MODE_TYPE_BULK, 181 | NULL, 182 | sduDataTransmitted, 183 | sduDataReceived, 184 | 0x0040, 185 | 0x0040, 186 | &ep1instate, 187 | &ep1outstate, 188 | 2, 189 | NULL}; 190 | 191 | static USBInEndpointState ep2instate; 192 | 193 | static const USBEndpointConfig ep2config = { 194 | USB_EP_MODE_TYPE_INTR, 195 | NULL, 196 | sduInterruptTransmitted, 197 | NULL, 198 | 0x0010, 199 | 0x0000, 200 | &ep2instate, 201 | NULL, 202 | 1, 203 | NULL}; 204 | 205 | /** Handles the USB driver global events. */ 206 | static void usb_event(USBDriver* usbp, usbevent_t event) 207 | { 208 | switch (event) { 209 | case USB_EVENT_RESET: 210 | return; 211 | case USB_EVENT_ADDRESS: 212 | return; 213 | case USB_EVENT_CONFIGURED: 214 | chSysLockFromISR(); 215 | 216 | /* Enables the endpoints specified into the configuration. 217 | Note, this callback is invoked from an ISR so I-Class functions 218 | must be used.*/ 219 | usbInitEndpointI(usbp, USBD1_DATA_REQUEST_EP, &ep1config); 220 | usbInitEndpointI(usbp, USBD1_INTERRUPT_REQUEST_EP, &ep2config); 221 | 222 | /* Resetting the state of the CDC subsystem.*/ 223 | sduConfigureHookI(&SDU1); 224 | 225 | chSysUnlockFromISR(); 226 | return; 227 | case USB_EVENT_SUSPEND: 228 | return; 229 | case USB_EVENT_WAKEUP: 230 | return; 231 | case USB_EVENT_STALLED: 232 | return; 233 | } 234 | return; 235 | } 236 | 237 | /** USB driver configuration. */ 238 | const USBConfig usbcfg = { 239 | usb_event, 240 | get_descriptor, 241 | sduRequestsHook, 242 | NULL}; 243 | 244 | /** Serial over USB driver configuration. */ 245 | const SerialUSBConfig serusbcfg = { 246 | &USBD1, 247 | USBD1_DATA_REQUEST_EP, 248 | USBD1_DATA_AVAILABLE_EP, 249 | USBD1_INTERRUPT_REQUEST_EP}; 250 | 251 | /* Serial over USB Driver structure. */ 252 | SerialUSBDriver SDU1; 253 | -------------------------------------------------------------------------------- /src/usbcfg2.h: -------------------------------------------------------------------------------- 1 | #ifndef USBCONF_H 2 | #define USBCONF_H 3 | 4 | #include 5 | 6 | extern const USBConfig usbcfg; 7 | extern const SerialUSBConfig serusbcfg; 8 | extern SerialUSBDriver SDU1; 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /src/version.h: -------------------------------------------------------------------------------- 1 | #ifndef VERSION_H 2 | #define VERSION_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | extern const char* software_version_str; 9 | extern const char* hardware_version_str; 10 | 11 | #ifdef __cplusplus 12 | } 13 | #endif 14 | 15 | #endif /* VERSION_H */ 16 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | 3 | project(slcan_adapter) 4 | set(CMAKE_BUILD_TYPE Debug) 5 | 6 | include_directories(../src) 7 | 8 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -Wall -Wextra") 9 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -Wall -Wextra -Wno-char-subscripts") 10 | 11 | add_executable( 12 | tests 13 | ../src/slcan.c 14 | ../src/timestamp/timestamp.c 15 | slcan_test.cpp 16 | timestamp_test.cpp 17 | ) 18 | 19 | target_link_libraries( 20 | tests 21 | CppUTest 22 | CppUTestExt 23 | ) 24 | 25 | # Run unit tests 26 | add_custom_target(check ./tests -c DEPENDS tests) 27 | -------------------------------------------------------------------------------- /tests/slcan_test.cpp: -------------------------------------------------------------------------------- 1 | #include "CppUTest/TestHarness.h" 2 | #include "CppUTestExt/MockSupport.h" 3 | #include "CppUTest/CommandLineTestRunner.h" 4 | #include 5 | #include "../src/slcan.h" 6 | #include "../src/can_driver.h" 7 | #include "../src/bus_power.h" 8 | 9 | extern "C" { 10 | #include 11 | size_t slcan_frame_to_ascii(char* buf, const struct can_frame_s* f, bool timestamp); 12 | void slcan_send_frame(char* line); 13 | void slcan_decode_line(char* line); 14 | } 15 | 16 | TEST_GROUP (SlcanTestGroup) { 17 | char line[100]; 18 | 19 | void setup() 20 | { 21 | memset(line, 0, sizeof(line)); 22 | } 23 | 24 | void teardown() 25 | { 26 | mock().checkExpectations(); 27 | mock().clear(); 28 | } 29 | }; 30 | 31 | TEST(SlcanTestGroup, CanEncodeStandardFrame) 32 | { 33 | struct can_frame_s frame = { 34 | .timestamp = 0, 35 | .id = 0x72a, 36 | .extended = false, 37 | .remote = false, 38 | .length = 4, 39 | .data = {0x12, 0x89, 0xab, 0xef}}; 40 | size_t len = slcan_frame_to_ascii(line, &frame, false); 41 | const char* expect = "t72a41289abef\r"; 42 | STRCMP_EQUAL(expect, line); 43 | CHECK_EQUAL(strlen(expect), len); 44 | } 45 | 46 | TEST(SlcanTestGroup, CanEncodeExtendedFrame) 47 | { 48 | struct can_frame_s frame = { 49 | .timestamp = 0, 50 | .id = 0x1234abcd, 51 | .extended = true, 52 | .remote = false, 53 | .length = 8, 54 | .data = {0, 1, 2, 3, 4, 5, 6, 7}}; 55 | size_t len = slcan_frame_to_ascii(line, &frame, false); 56 | const char* expect = "T1234abcd80001020304050607\r"; 57 | STRCMP_EQUAL(expect, line); 58 | CHECK_EQUAL(strlen(expect), len); 59 | } 60 | 61 | TEST(SlcanTestGroup, CanEncodeStandardRemoteFrame) 62 | { 63 | struct can_frame_s frame = { 64 | .timestamp = 0, 65 | .id = 0x72a, 66 | .extended = false, 67 | .remote = true, 68 | .length = 8, 69 | .data = {0}}; 70 | size_t len = slcan_frame_to_ascii(line, &frame, false); 71 | const char* expect = "r72a8\r"; 72 | STRCMP_EQUAL(expect, line); 73 | CHECK_EQUAL(strlen(expect), len); 74 | } 75 | 76 | TEST(SlcanTestGroup, CanEncodeExtendedRemoteFrame) 77 | { 78 | struct can_frame_s frame = { 79 | .timestamp = 0, 80 | .id = 0x1234abcd, 81 | .extended = true, 82 | .remote = true, 83 | .length = 4, 84 | .data = {0}}; 85 | size_t len = slcan_frame_to_ascii(line, &frame, false); 86 | const char* expect = "R1234abcd4\r"; 87 | STRCMP_EQUAL(expect, line); 88 | CHECK_EQUAL(strlen(expect), len); 89 | } 90 | 91 | TEST(SlcanTestGroup, CanEncodeFrameWithTimestamp) 92 | { 93 | struct can_frame_s frame = { 94 | .timestamp = 0xdead, 95 | .id = 0x100, 96 | .extended = false, 97 | .remote = false, 98 | .length = 1, 99 | .data = {0x2a}, 100 | }; 101 | size_t len = slcan_frame_to_ascii(line, &frame, true); 102 | const char* expect = "t10012adead\r"; 103 | STRCMP_EQUAL(expect, line); 104 | CHECK_EQUAL(strlen(expect), len); 105 | } 106 | 107 | TEST(SlcanTestGroup, CanDecodeStandardFrame) 108 | { 109 | uint8_t data[] = {0x2a}; 110 | mock().expectOneCall("can_send").withParameter("id", 0x100).withParameter("extended", false).withParameter("remote", false).withMemoryBufferParameter("data", data, sizeof(data)).withParameter("length", sizeof(data)); 111 | 112 | strcpy(line, "t10012a\r"); 113 | slcan_send_frame(line); 114 | 115 | STRCMP_EQUAL("\r", line); 116 | } 117 | 118 | TEST(SlcanTestGroup, CanDecodeExtendedFrame) 119 | { 120 | uint8_t data[] = {1, 2, 3, 4, 5, 6, 7, 8}; 121 | mock().expectOneCall("can_send").withParameter("id", 0xabcdef).withParameter("extended", true).withParameter("remote", false).withMemoryBufferParameter("data", data, sizeof(data)).withParameter("length", sizeof(data)); 122 | 123 | strcpy(line, "T00abcdef80102030405060708\r"); 124 | slcan_send_frame(line); 125 | 126 | STRCMP_EQUAL("\r", line); 127 | } 128 | 129 | TEST(SlcanTestGroup, CanDecodeExtendedRemoteFrame) 130 | { 131 | uint8_t data[] = {}; 132 | mock().expectOneCall("can_send").withParameter("id", 0x1000).withParameter("extended", true).withParameter("remote", true).withMemoryBufferParameter("data", data, 0).withParameter("length", 8); 133 | 134 | strcpy(line, "R000010008\r"); 135 | slcan_send_frame(line); 136 | 137 | STRCMP_EQUAL("\r", line); 138 | } 139 | 140 | TEST(SlcanTestGroup, CanDecodeStandardRemoteFrame) 141 | { 142 | uint8_t data[] = {}; 143 | mock().expectOneCall("can_send").withParameter("id", 0x100).withParameter("extended", false).withParameter("remote", true).withMemoryBufferParameter("data", data, 0).withParameter("length", 2); 144 | 145 | strcpy(line, "r1002\r"); 146 | slcan_send_frame(line); 147 | 148 | STRCMP_EQUAL("\r", line); 149 | } 150 | 151 | TEST(SlcanTestGroup, OpenCommand) 152 | { 153 | mock().expectOneCall("can_open").withParameter("mode", CAN_MODE_NORMAL); 154 | strcpy(line, "O\r"); 155 | slcan_decode_line(line); 156 | STRCMP_EQUAL("\r", line); 157 | } 158 | 159 | TEST(SlcanTestGroup, OpenLoopbackCommand) 160 | { 161 | mock().expectOneCall("can_open").withParameter("mode", CAN_MODE_LOOPBACK); 162 | strcpy(line, "l\r"); 163 | slcan_decode_line(line); 164 | STRCMP_EQUAL("\r", line); 165 | } 166 | 167 | TEST(SlcanTestGroup, OpenSilentCommand) 168 | { 169 | mock().expectOneCall("can_open").withParameter("mode", CAN_MODE_SILENT); 170 | strcpy(line, "L\r"); 171 | slcan_decode_line(line); 172 | STRCMP_EQUAL("\r", line); 173 | } 174 | 175 | TEST(SlcanTestGroup, SetBitrateCommand) 176 | { 177 | mock().expectOneCall("can_set_bitrate").withParameter("bitrate", 1000000); 178 | strcpy(line, "S8\r"); 179 | slcan_decode_line(line); 180 | STRCMP_EQUAL("\r", line); 181 | } 182 | 183 | TEST(SlcanTestGroup, CloseCommand) 184 | { 185 | mock().expectOneCall("can_close"); 186 | strcpy(line, "C\r"); 187 | slcan_decode_line(line); 188 | STRCMP_EQUAL("\r", line); 189 | } 190 | 191 | TEST(SlcanTestGroup, HardwareVersionCommand) 192 | { 193 | strcpy(line, "V\r"); 194 | slcan_decode_line(line); 195 | STRCMP_EQUAL("hardware version str\r", line); 196 | } 197 | 198 | TEST(SlcanTestGroup, SoftwareVersionCommand) 199 | { 200 | strcpy(line, "v\r"); 201 | slcan_decode_line(line); 202 | STRCMP_EQUAL("software version str\r", line); 203 | } 204 | 205 | TEST(SlcanTestGroup, PowerOnBusCommand) 206 | { 207 | mock().expectOneCall("bus_power").withParameter("enable", true); 208 | strcpy(line, "P\r"); 209 | slcan_decode_line(line); 210 | STRCMP_EQUAL("\r", line); 211 | } 212 | 213 | TEST(SlcanTestGroup, PowerOffBusCommand) 214 | { 215 | mock().expectOneCall("bus_power").withParameter("enable", false); 216 | strcpy(line, "p\r"); 217 | slcan_decode_line(line); 218 | STRCMP_EQUAL("\r", line); 219 | } 220 | 221 | int main(int ac, char** av) 222 | { 223 | return CommandLineTestRunner::RunAllTests(ac, av); 224 | } 225 | 226 | // mocks 227 | extern "C" { 228 | 229 | const char* software_version_str = "software version str"; 230 | const char* hardware_version_str = "hardware version str"; 231 | 232 | bool can_send(uint32_t id, bool extended, bool remote, uint8_t* data, size_t length) 233 | { 234 | size_t data_length = remote ? 0 : length; 235 | mock().actualCall("can_send").withParameter("id", id).withParameter("extended", extended).withParameter("remote", remote).withMemoryBufferParameter("data", data, data_length).withParameter("length", length); 236 | return true; 237 | } 238 | 239 | bool can_set_bitrate(uint32_t bitrate) 240 | { 241 | mock().actualCall("can_set_bitrate").withParameter("bitrate", bitrate); 242 | return true; 243 | } 244 | 245 | bool can_open(int mode) 246 | { 247 | mock().actualCall("can_open").withParameter("mode", mode); 248 | return true; 249 | } 250 | 251 | void can_close(void) 252 | { 253 | mock().actualCall("can_close"); 254 | } 255 | 256 | /* dummy functions */ 257 | 258 | int slcan_serial_write(void* arg, const char* buf, size_t len) 259 | { 260 | (void)arg; 261 | (void)buf; 262 | (void)len; 263 | return 0; 264 | } 265 | 266 | struct can_frame_s* can_receive(void) 267 | { 268 | return NULL; 269 | } 270 | 271 | void can_frame_delete(struct can_frame_s* f) 272 | { 273 | (void)f; 274 | } 275 | 276 | char* slcan_getline(void* arg) 277 | { 278 | (void)arg; 279 | return NULL; 280 | } 281 | 282 | bool bus_power(bool enable) 283 | { 284 | mock().actualCall("bus_power").withParameter("enable", enable); 285 | return true; 286 | } 287 | } 288 | -------------------------------------------------------------------------------- /tests/timestamp_test.cpp: -------------------------------------------------------------------------------- 1 | #include "CppUTest/TestHarness.h" 2 | #include "timestamp/timestamp.h" 3 | 4 | TEST_GROUP (Timestamp) { 5 | }; 6 | 7 | TEST(Timestamp, DurationPositive) 8 | { 9 | timestamp_t t1 = 10; 10 | timestamp_t t2 = 22; 11 | CHECK_EQUAL(12, timestamp_duration_us(t1, t2)); 12 | } 13 | 14 | TEST(Timestamp, DurationNegative) 15 | { 16 | timestamp_t t1 = 22; 17 | timestamp_t t2 = 10; 18 | CHECK_EQUAL(-12, timestamp_duration_us(t1, t2)); 19 | } 20 | 21 | TEST(Timestamp, DurationOverflow) 22 | { 23 | timestamp_t t1 = UINT32_MAX - 5; 24 | timestamp_t t2 = 10; 25 | CHECK_EQUAL(16, timestamp_duration_us(t1, t2)); 26 | } 27 | 28 | TEST(Timestamp, DurationNegativeOverflow) 29 | { 30 | timestamp_t t1 = 10; 31 | timestamp_t t2 = UINT32_MAX - 5; 32 | CHECK_EQUAL(-16, timestamp_duration_us(t1, t2)); 33 | } 34 | 35 | TEST(Timestamp, DurationMax) 36 | { 37 | timestamp_t t1 = 0; 38 | timestamp_t t2 = INT32_MAX; 39 | CHECK_EQUAL(INT32_MAX, timestamp_duration_us(t1, t2)); 40 | t1 = (uint32_t)INT32_MAX + 1; 41 | t2 = UINT32_MAX; 42 | CHECK_EQUAL(INT32_MAX, timestamp_duration_us(t1, t2)); 43 | } 44 | 45 | TEST(Timestamp, DurationMaxNegative) 46 | { 47 | timestamp_t t1 = 0; 48 | timestamp_t t2 = (uint32_t)INT32_MAX + 1; 49 | CHECK_EQUAL(INT32_MIN, timestamp_duration_us(t1, t2)); 50 | t1 = INT32_MAX; 51 | t2 = 0; 52 | CHECK_EQUAL(-INT32_MAX, timestamp_duration_us(t1, t2)); 53 | } 54 | 55 | TEST(Timestamp, DurationFloatSeconds) 56 | { 57 | timestamp_t t1 = 100000; 58 | timestamp_t t2 = 200000; 59 | CHECK_EQUAL(0.1f, timestamp_duration_s(t1, t2)); 60 | } 61 | 62 | TEST(Timestamp, DurationNegativeFloatSeconds) 63 | { 64 | timestamp_t t1 = 200000; 65 | timestamp_t t2 = 100000; 66 | CHECK_EQUAL(-0.1f, timestamp_duration_s(t1, t2)); 67 | } 68 | 69 | TEST_GROUP (LongTimestamp) { 70 | }; 71 | 72 | TEST(LongTimestamp, DurationPositive) 73 | { 74 | ltimestamp_t t1 = 10; 75 | ltimestamp_t t2 = 22; 76 | CHECK(12 == ltimestamp_duration_us(t1, t2)); 77 | } 78 | 79 | TEST(LongTimestamp, DurationNegative) 80 | { 81 | ltimestamp_t t1 = 22; 82 | ltimestamp_t t2 = 10; 83 | CHECK(-12 == ltimestamp_duration_us(t1, t2)); 84 | } 85 | 86 | TEST(LongTimestamp, DurationOverflow) 87 | { 88 | ltimestamp_t t1 = UINT64_MAX - 5; 89 | ltimestamp_t t2 = 10; 90 | CHECK(16 == ltimestamp_duration_us(t1, t2)); 91 | } 92 | 93 | TEST(LongTimestamp, DurationNegativeOverflow) 94 | { 95 | ltimestamp_t t1 = 10; 96 | ltimestamp_t t2 = UINT64_MAX - 5; 97 | CHECK(-16 == ltimestamp_duration_us(t1, t2)); 98 | } 99 | 100 | TEST(LongTimestamp, DurationMax) 101 | { 102 | ltimestamp_t t1 = 0; 103 | ltimestamp_t t2 = INT64_MAX; 104 | CHECK(INT64_MAX == ltimestamp_duration_us(t1, t2)); 105 | t1 = (uint64_t)INT64_MAX + 1; 106 | t2 = UINT64_MAX; 107 | CHECK(INT64_MAX == ltimestamp_duration_us(t1, t2)); 108 | } 109 | 110 | TEST(LongTimestamp, DurationMaxNegative) 111 | { 112 | ltimestamp_t t1 = 0; 113 | ltimestamp_t t2 = (uint64_t)INT64_MAX + 1; 114 | CHECK(INT64_MIN == ltimestamp_duration_us(t1, t2)); 115 | t1 = INT64_MAX; 116 | t2 = 0; 117 | CHECK(-INT64_MAX == ltimestamp_duration_us(t1, t2)); 118 | } 119 | 120 | TEST(LongTimestamp, DurationFloatSeconds) 121 | { 122 | ltimestamp_t t1 = 100000; 123 | ltimestamp_t t2 = 200000; 124 | CHECK_EQUAL(0.1f, ltimestamp_duration_s(t1, t2)); 125 | } 126 | 127 | TEST(LongTimestamp, DurationNegativeFloatSeconds) 128 | { 129 | ltimestamp_t t1 = 200000; 130 | ltimestamp_t t2 = 100000; 131 | CHECK_EQUAL(-0.1f, ltimestamp_duration_s(t1, t2)); 132 | } 133 | -------------------------------------------------------------------------------- /tools/.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *.cover 46 | .hypothesis/ 47 | 48 | # Translations 49 | *.mo 50 | *.pot 51 | 52 | # Django stuff: 53 | *.log 54 | local_settings.py 55 | 56 | # Flask stuff: 57 | instance/ 58 | .webassets-cache 59 | 60 | # Scrapy stuff: 61 | .scrapy 62 | 63 | # Sphinx documentation 64 | docs/_build/ 65 | 66 | # PyBuilder 67 | target/ 68 | 69 | # Jupyter Notebook 70 | .ipynb_checkpoints 71 | 72 | # pyenv 73 | .python-version 74 | 75 | # celery beat schedule file 76 | celerybeat-schedule 77 | 78 | # SageMath parsed files 79 | *.sage.py 80 | 81 | # Environments 82 | .env 83 | .venv 84 | env/ 85 | venv/ 86 | ENV/ 87 | 88 | # Spyder project settings 89 | .spyderproject 90 | .spyproject 91 | 92 | # Rope project settings 93 | .ropeproject 94 | 95 | # mkdocs documentation 96 | /site 97 | 98 | # mypy 99 | .mypy_cache/ 100 | -------------------------------------------------------------------------------- /tools/README.md: -------------------------------------------------------------------------------- 1 | # Tools for the CVRA CAN USB dongle 2 | 3 | This folder contains tools intended to be used with the CAN USB dongle. 4 | For now the following are implemented: 5 | 6 | * `can_dongle_power`: Controls the state of the CAN bus power. 7 | See `--help` for usage. 8 | 9 | ## Installation 10 | 11 | Python 3 is required, the other dependencies will be installed automatically. 12 | You can install the tools by running `pip install .`. 13 | -------------------------------------------------------------------------------- /tools/cvra_can_usb_dongle/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cvra/CAN-USB-dongle-fw/763ef718aa171b62474dc507025ae5d0bdf560bf/tools/cvra_can_usb_dongle/__init__.py -------------------------------------------------------------------------------- /tools/cvra_can_usb_dongle/power.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | Turns on or off the CAN bus power. 4 | """ 5 | 6 | import argparse 7 | import serial 8 | 9 | 10 | 11 | def parse_args(): 12 | parser = argparse.ArgumentParser(description=__doc__) 13 | parser.add_argument("port", help="Serial port to which the dongle is connected.") 14 | parser.add_argument("power", choices=('on', 'off'), help="Bus state to apply") 15 | 16 | return parser.parse_args() 17 | 18 | def main(): 19 | args = parse_args() 20 | 21 | conn = serial.Serial(args.port, 115200) 22 | 23 | if args.power == "on": 24 | msg = "P\r" 25 | else: 26 | msg = "p\r" 27 | 28 | conn.write(msg.encode()) 29 | 30 | data = bytes() 31 | 32 | while not data.endswith(b"\r"): 33 | data += conn.read(1) 34 | 35 | if __name__ == '__main__': 36 | main() 37 | -------------------------------------------------------------------------------- /tools/setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | setup( 4 | name='cvra-can-dongle-tools', 5 | version='1.0.0', 6 | description='Tools for the CVRA CAN USB dongle', 7 | author='Club Vaudois de Robotique Autonome', 8 | author_email='info@cvra.ch', 9 | url='https://github.com/cvra/CAN-USB-dongle-fw', 10 | license='BSD', 11 | packages=['cvra_can_usb_dongle'], 12 | classifiers=[ 13 | 'Development Status :: 5 - Production/Stable', 14 | 'Intended Audience :: Developers', 15 | 'Topic :: Software Development :: Embedded Systems', 16 | 'License :: OSI Approved :: BSD License', 17 | 'Programming Language :: Python :: 3 :: Only', 18 | 'Programming Language :: Python :: 3.4', 19 | 'Programming Language :: Python :: 3.5', 20 | ], 21 | install_requires=[ 22 | 'pyserial', 23 | ], 24 | entry_points={ 25 | 'console_scripts': [ 26 | 'can_dongle_power=cvra_can_usb_dongle.power:main', 27 | ], 28 | }, 29 | ) 30 | 31 | -------------------------------------------------------------------------------- /version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # abort on errors 4 | set -e 5 | set -u 6 | 7 | # All paths are relative to this script 8 | cd $(dirname $0) 9 | 10 | echo "// AUTOMATICALLY GENERATED" > src/version.c.new 11 | echo "#include " >> src/version.c.new 12 | echo "const char * software_version_str = \"$(git rev-parse HEAD)-$(git rev-parse --abbrev-ref HEAD)\";" >> src/version.c.new 13 | echo "const char * hardware_version_str = BOARD_NAME;" >> src/version.c.new 14 | 15 | # If version.c does not exist, overwrite it 16 | if [ ! -e src/version.c ] 17 | then 18 | echo "version.c does not exist, creating it..." 19 | mv src/version.c.new src/version.c 20 | else 21 | # If there is a version.c, check if the file should change before 22 | # overriding it. 23 | # If we don't do this, make will detect a new file and always relink the 24 | # project. 25 | if cmp --quiet src/version.c src/version.c.new 26 | then 27 | echo "No change detected in version.c, skipping..." 28 | rm src/version.c.new 29 | else 30 | echo "version.c changed, overwriting it" 31 | mv src/version.c.new src/version.c 32 | fi 33 | fi 34 | --------------------------------------------------------------------------------