├── .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 | [](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 |
--------------------------------------------------------------------------------