Skip to content

Commit 2412aef

Browse files
authored
Merge pull request #924 from valeros/master
Add initial support for PlatformIO ecosystem
2 parents 3c9aa02 + ab2e8a9 commit 2412aef

File tree

4 files changed

+364
-0
lines changed

4 files changed

+364
-0
lines changed

.travis.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,29 @@ matrix:
3434
else
3535
echo "Coding style check OK";
3636
fi
37+
38+
#
39+
# PlatformIO test
40+
#
41+
- env:
42+
- NAME=PlatformIO
43+
- CMSIS_VERSION=5.5.1
44+
install:
45+
# Install PlatformIO
46+
- pip install -U platformio
47+
# Install the development version of ststm32 platform
48+
- platformio platform install https://github.com/platformio/platform-ststm32.git
49+
# Prepare framework for CI
50+
- python -c "import json; import os; fp=open(os.path.expanduser('~/.platformio/platforms/ststm32/platform.json'), 'r+'); data=json.load(fp); data['packages']['framework-arduinoststm32']['version'] = '*'; fp.seek(0); fp.truncate(); json.dump(data, fp); fp.close()"
51+
- sudo ln -sf $TRAVIS_BUILD_DIR ~/.platformio/packages/framework-arduinoststm32
52+
# Download and unpack CMSIS package
53+
- wget https://github.com/stm32duino/ArduinoModule-CMSIS/releases/download/$CMSIS_VERSION/CMSIS-$CMSIS_VERSION.tar.bz2
54+
- tar -xvjf CMSIS-$CMSIS_VERSION.tar.bz2
55+
before_script:
56+
- cd $TRAVIS_BUILD_DIR/CI/build/
57+
script:
58+
- python platformio-builder.py --board=blackpill_f103c8 --board=remram_v1
59+
3760
#
3861
# Build test
3962
#

CI/build/platformio-builder.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import argparse
2+
import os
3+
import subprocess
4+
import sys
5+
6+
7+
def run_platformio(example_path, boards):
8+
return subprocess.call(
9+
["platformio", "ci", example_path] + ["--board=" + b for b in boards])
10+
11+
12+
def collect_examples(libs_dir):
13+
examples = []
14+
for lib in os.listdir(libs_dir):
15+
lib_dir = os.path.join(libs_dir, lib)
16+
examples_dir = os.path.join(lib_dir, "examples")
17+
if os.path.isdir(examples_dir):
18+
examples.extend(
19+
[os.path.join(examples_dir, ex) for ex in os.listdir(examples_dir)])
20+
return examples
21+
22+
23+
parser = argparse.ArgumentParser(description="Basic PlatformIO runner")
24+
25+
parser.add_argument(
26+
"-b",
27+
"--board",
28+
action="append",
29+
help="board ID used for PlatformIO project"
30+
)
31+
32+
33+
def main():
34+
args = parser.parse_args()
35+
boards = args.board
36+
if boards is None:
37+
boards = ["nucleo_f401re"]
38+
39+
libs_dir = os.path.join(os.environ["TRAVIS_BUILD_DIR"], "libraries")
40+
if any(run_platformio(example, boards) for example in collect_examples(libs_dir)):
41+
sys.exit(1)
42+
43+
44+
if __name__ == "__main__":
45+
main()

package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"name": "framework-arduinoststm32",
3+
"description": "Arduino Wiring-based Framework (STM32 Core)",
4+
"version": "0.0.0",
5+
"url": "https://github.com/stm32duino/Arduino_Core_STM32"
6+
}

tools/platformio-build.py

Lines changed: 290 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,290 @@
1+
# Copyright 2014-present PlatformIO <[email protected]>
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""
16+
Arduino
17+
18+
Arduino Wiring-based Framework allows writing cross-platform software to
19+
control devices attached to a wide range of Arduino boards to create all
20+
kinds of creative coding, interactive objects, spaces or physical experiences.
21+
22+
https://github.com/stm32duino/Arduino_Core_STM32
23+
"""
24+
25+
26+
from os.path import isfile, isdir, join
27+
28+
from SCons.Script import DefaultEnvironment
29+
30+
env = DefaultEnvironment()
31+
platform = env.PioPlatform()
32+
board = env.BoardConfig()
33+
34+
FRAMEWORK_DIR = platform.get_package_dir("framework-arduinoststm32")
35+
CMSIS_DIR = join(platform.get_package_dir(
36+
"framework-arduinoststm32"), "CMSIS", "CMSIS")
37+
assert isdir(FRAMEWORK_DIR)
38+
assert isdir(CMSIS_DIR)
39+
40+
41+
mcu = env.BoardConfig().get("build.mcu", "")
42+
board_name = env.subst("$BOARD")
43+
mcu_type = mcu[:-2]
44+
variant = board.get("build.variant")
45+
series = mcu_type[:7].upper() + "xx"
46+
variants_dir = join(
47+
"$PROJECT_DIR", board.get("build.variants_dir")) if board.get(
48+
"build.variants_dir", "") else join(FRAMEWORK_DIR, "variants")
49+
variant_dir = join(variants_dir, variant)
50+
upload_protocol = env.subst("$UPLOAD_PROTOCOL")
51+
52+
53+
def process_standard_library_configuration(cpp_defines):
54+
if "PIO_FRAMEWORK_ARDUINO_STANDARD_LIB" in cpp_defines:
55+
env['LINKFLAGS'].remove("--specs=nano.specs")
56+
if "PIO_FRAMEWORK_ARDUINO_NANOLIB_FLOAT_PRINTF" in cpp_defines:
57+
env.Append(LINKFLAGS=["-u_printf_float"])
58+
if "PIO_FRAMEWORK_ARDUINO_NANOLIB_FLOAT_SCANF" in cpp_defines:
59+
env.Append(LINKFLAGS=["-u_scanf_float"])
60+
61+
62+
def process_usart_configuration(cpp_defines):
63+
if "PIO_FRAMEWORK_ARDUINO_SERIAL_DISABLED" in cpp_defines:
64+
env['CPPDEFINES'].remove("HAL_UART_MODULE_ENABLED")
65+
66+
elif "PIO_FRAMEWORK_ARDUINO_SERIAL_WITHOUT_GENERIC" in cpp_defines:
67+
env.Append(CPPDEFINES=["HWSERIAL_NONE"])
68+
69+
70+
def process_usb_speed_configuration(cpp_defines):
71+
if "PIO_FRAMEWORK_ARDUINO_USB_HIGHSPEED" in cpp_defines:
72+
env.Append(CPPDEFINES=["USE_USB_HS"])
73+
74+
elif "PIO_FRAMEWORK_ARDUINO_USB_HIGHSPEED_FULLMODE" in cpp_defines:
75+
env.Append(CPPDEFINES=["USE_USB_HS", "USE_USB_HS_IN_FS"])
76+
77+
78+
def process_usb_configuration(cpp_defines):
79+
if "PIO_FRAMEWORK_ARDUINO_ENABLE_CDC" in cpp_defines:
80+
env.Append(CPPDEFINES=["USBD_USE_CDC"])
81+
82+
elif "PIO_FRAMEWORK_ARDUINO_ENABLE_CDC_WITHOUT_SERIAL" in cpp_defines:
83+
env.Append(CPPDEFINES=["USBD_USE_CDC", "DISABLE_GENERIC_SERIALUSB"])
84+
85+
elif "PIO_FRAMEWORK_ARDUINO_ENABLE_HID" in cpp_defines:
86+
env.Append(CPPDEFINES=["USBD_USE_HID_COMPOSITE"])
87+
88+
if any(f in env["CPPDEFINES"] for f in (
89+
"USBD_USE_CDC", "USBD_USE_HID_COMPOSITE")):
90+
env.Append(CPPDEFINES=["HAL_PCD_MODULE_ENABLED"])
91+
92+
93+
def get_arm_math_lib(cpu):
94+
core = board.get("build.cpu")[7:9]
95+
if core == "m4":
96+
return "arm_cortexM4lf_math"
97+
elif core == "m7":
98+
return "arm_cortexM7lfsp_math"
99+
100+
return "arm_cortex%sl_math" % core.upper()
101+
102+
103+
def configure_application_offset(mcu, upload_protocol):
104+
offset = 0
105+
106+
if upload_protocol == "hid":
107+
if mcu.startswith("stm32f1"):
108+
offset = 0x800
109+
elif mcu.startswith("stm32f4"):
110+
offset = 0x4000
111+
112+
env.Append(CPPDEFINES=["BL_HID"])
113+
114+
elif upload_protocol == "dfu":
115+
# STM32F103 series doesn't have embedded DFU over USB
116+
# stm32duino bootloader (v1, v2) is used instead
117+
if mcu.startswith("stm32f103"):
118+
if board.get("upload.boot_version", 2) == 1:
119+
offset = 0x5000
120+
else:
121+
offset = 0x2000
122+
env.Append(CPPDEFINES=["BL_LEGACY_LEAF"])
123+
124+
if offset != 0:
125+
env.Append(
126+
CPPDEFINES=[("VECT_TAB_OFFSET", "%s" % hex(offset))],
127+
)
128+
129+
# LD_FLASH_OFFSET is mandatory even if there is no offset
130+
env.Append(
131+
LINKFLAGS=["-Wl,--defsym=LD_FLASH_OFFSET=%s" % hex(offset)])
132+
133+
134+
if any(mcu in board.get("build.cpu") for mcu in ("cortex-m4", "cortex-m7")):
135+
env.Append(
136+
CCFLAGS=[
137+
"-mfpu=fpv4-sp-d16",
138+
"-mfloat-abi=hard"
139+
],
140+
141+
LINKFLAGS=[
142+
"-mfpu=fpv4-sp-d16",
143+
"-mfloat-abi=hard"
144+
]
145+
)
146+
147+
env.Append(
148+
ASFLAGS=["-x", "assembler-with-cpp"],
149+
150+
CFLAGS=[
151+
"-std=gnu11"
152+
],
153+
154+
CXXFLAGS=[
155+
"-std=gnu++14",
156+
"-fno-threadsafe-statics",
157+
"-fno-rtti",
158+
"-fno-exceptions",
159+
"-fno-use-cxa-atexit"
160+
],
161+
162+
CCFLAGS=[
163+
"-Os", # optimize for size
164+
"-mcpu=%s" % env.BoardConfig().get("build.cpu"),
165+
"-mthumb",
166+
"-ffunction-sections", # place each function in its own section
167+
"-fdata-sections",
168+
"-Wall",
169+
"-nostdlib",
170+
"--param", "max-inline-insns-single=500"
171+
],
172+
173+
CPPDEFINES=[
174+
series,
175+
("ARDUINO", 10808),
176+
"ARDUINO_ARCH_STM32",
177+
"ARDUINO_%s" % board_name.upper(),
178+
("BOARD_NAME", '\\"%s\\"' % board_name.upper()),
179+
"HAL_UART_MODULE_ENABLED"
180+
],
181+
182+
CPPPATH=[
183+
join(FRAMEWORK_DIR, "cores", "arduino", "avr"),
184+
join(FRAMEWORK_DIR, "cores", "arduino", "stm32"),
185+
join(FRAMEWORK_DIR, "cores", "arduino", "stm32", "LL"),
186+
join(FRAMEWORK_DIR, "cores", "arduino", "stm32", "usb"),
187+
join(FRAMEWORK_DIR, "cores", "arduino", "stm32", "usb", "hid"),
188+
join(FRAMEWORK_DIR, "cores", "arduino", "stm32", "usb", "cdc"),
189+
join(FRAMEWORK_DIR, "system", "Drivers",
190+
series + "_HAL_Driver", "Inc"),
191+
join(FRAMEWORK_DIR, "system", "Drivers",
192+
series + "_HAL_Driver", "Src"),
193+
join(FRAMEWORK_DIR, "system", series),
194+
join(FRAMEWORK_DIR, "system", "Middlewares", "ST",
195+
"STM32_USB_Device_Library", "Core", "Inc"),
196+
join(FRAMEWORK_DIR, "system", "Middlewares", "ST",
197+
"STM32_USB_Device_Library", "Core", "Src"),
198+
join(CMSIS_DIR, "Core", "Include"),
199+
join(FRAMEWORK_DIR, "system", "Drivers", "CMSIS",
200+
"Device", "ST", series, "Include"),
201+
join(CMSIS_DIR, "DSP", "Include"),
202+
join(FRAMEWORK_DIR, "system", "Drivers", "CMSIS",
203+
"Device", "ST", series, "Source", "Templates", "gcc"),
204+
join(FRAMEWORK_DIR, "cores", "arduino"),
205+
variant_dir
206+
],
207+
208+
LINKFLAGS=[
209+
"-Os",
210+
"-mthumb",
211+
"-mcpu=%s" % env.BoardConfig().get("build.cpu"),
212+
"--specs=nano.specs",
213+
"-Wl,--gc-sections,--relax",
214+
"-Wl,--check-sections",
215+
"-Wl,--entry=Reset_Handler",
216+
"-Wl,--unresolved-symbols=report-all",
217+
"-Wl,--warn-common",
218+
"-Wl,--defsym=LD_MAX_SIZE=%d" % board.get("upload.maximum_size"),
219+
"-Wl,--defsym=LD_MAX_DATA_SIZE=%d" % board.get(
220+
"upload.maximum_ram_size")
221+
],
222+
223+
LIBS=[
224+
get_arm_math_lib(env.BoardConfig().get("build.cpu")), "c", "m", "gcc", "stdc++"
225+
],
226+
227+
LIBPATH=[
228+
variant_dir,
229+
join(CMSIS_DIR, "DSP", "Lib", "GCC")
230+
]
231+
)
232+
233+
env.ProcessFlags(board.get("build.framework_extra_flags.arduino", ""))
234+
235+
configure_application_offset(mcu, upload_protocol)
236+
237+
#
238+
# Linker requires preprocessing with correct RAM|ROM sizes
239+
#
240+
241+
if not board.get("build.ldscript", ""):
242+
if not isfile(join(env.subst(variant_dir), "ldscript.ld")):
243+
print("Warning! Cannot find linker script for the current target!\n")
244+
env.Replace(LDSCRIPT_PATH=join(variant_dir, "ldscript.ld"))
245+
246+
#
247+
# Process configuration flags
248+
#
249+
250+
cpp_defines = env.Flatten(env.get("CPPDEFINES", []))
251+
252+
process_standard_library_configuration(cpp_defines)
253+
process_usb_configuration(cpp_defines)
254+
process_usb_speed_configuration(cpp_defines)
255+
process_usart_configuration(cpp_defines)
256+
257+
# copy CCFLAGS to ASFLAGS (-x assembler-with-cpp mode)
258+
env.Append(ASFLAGS=env.get("CCFLAGS", [])[:])
259+
260+
env.Append(
261+
LIBSOURCE_DIRS=[
262+
join(FRAMEWORK_DIR, "libraries", "__cores__", "arduino"),
263+
join(FRAMEWORK_DIR, "libraries")
264+
]
265+
)
266+
267+
#
268+
# Target: Build Core Library
269+
#
270+
271+
libs = []
272+
273+
if "build.variant" in env.BoardConfig():
274+
env.Append(
275+
CPPPATH=[variant_dir]
276+
)
277+
env.BuildSources(
278+
join("$BUILD_DIR", "FrameworkArduinoVariant"),
279+
variant_dir
280+
)
281+
282+
env.BuildSources(
283+
join("$BUILD_DIR", "FrameworkArduino"),
284+
join(FRAMEWORK_DIR, "cores", "arduino"))
285+
286+
env.BuildSources(
287+
join("$BUILD_DIR", "SrcWrapper"),
288+
join(FRAMEWORK_DIR, "libraries", "SrcWrapper"))
289+
290+
env.Prepend(LIBS=libs)

0 commit comments

Comments
 (0)