Merge pull request #60 from valeros/develop

Add STM32 platform with CMSIS, SPL and OpenCM3 frameworks
This commit is contained in:
Ivan Kravets
2015-02-03 14:49:53 +02:00
24 changed files with 1020 additions and 14 deletions

View File

@ -0,0 +1,24 @@
#
# Project Configuration File
#
# A detailed documentation with the EXAMPLES is located here:
# http://docs.platformio.org/en/latest/projectconf.html
#
# A sign `#` at the beginning of the line indicates a comment
# Comment lines are ignored.
# Simple and base environment
# [env:mybaseenv]
# platform = %INSTALLED_PLATFORM_NAME_HERE%
# framework =
# board =
#
# Automatic targets - enable auto-uploading
# targets = upload
[env:stm32]
platform = stm32
framework = cmsis
board = stm32ldiscovery

View File

@ -0,0 +1,27 @@
#include "stm32l1xx.h"
void ms_delay(int ms)
{
while (ms-- > 0) {
volatile int x=500;
while (x-- > 0)
__asm("nop");
}
}
//Alternates blue and green LEDs quickly
int main(void)
{
RCC->AHBENR |= RCC_AHBENR_GPIOBEN; // enable the clock to GPIOB
GPIOB->MODER |= (1 << 12); // set pin 6 to be general purpose output
GPIOB->MODER |= (1 << 14); // set pin 7 to be general purpose output
GPIOB->ODR |= (1 << 7); // Set the pin 7 high
for (;;) {
ms_delay(100);
GPIOB->ODR ^= (1 << 6); // Toggle the pin
GPIOB->ODR ^= (1 << 7); // Toggle the pin
}
}

View File

@ -0,0 +1,23 @@
#
# Project Configuration File
#
# A detailed documentation with the EXAMPLES is located here:
# http://docs.platformio.org/en/latest/projectconf.html
#
# A sign `#` at the beginning of the line indicates a comment
# Comment lines are ignored.
# Simple and base environment
# [env:mybaseenv]
# platform = %INSTALLED_PLATFORM_NAME_HERE%
# framework =
# board =
#
# Automatic targets - enable auto-uploading
# targets = upload
[env:stm32]
platform = stm32
board = stm32ldiscovery
framework = opencm3

View File

@ -0,0 +1,70 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
* Copyright (C) 2011 Stephen Caudle <scaudle@doceme.com>
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/gpio.h>
static void gpio_setup(void)
{
/* Enable GPIOB clock. */
/* Manually: */
//RCC_AHBENR |= RCC_AHBENR_GPIOBEN;
/* Using API functions: */
rcc_periph_clock_enable(RCC_GPIOB);
/* Set GPIO6 (in GPIO port B) to 'output push-pull'. */
/* Using API functions: */
gpio_mode_setup(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO6);
}
int main(void)
{
int i;
gpio_setup();
/* Blink the LED (PB6) on the board. */
while (1) {
/* Manually: */
// GPIOB_BSRR = GPIO6; /* LED off */
// for (i = 0; i < 1000000; i++) /* Wait a bit. */
// __asm__("nop");
// GPIOB_BRR = GPIO6; /* LED on */
// for (i = 0; i < 1000000; i++) /* Wait a bit. */
// __asm__("nop");
/* Using API functions gpio_set()/gpio_clear(): */
// gpio_set(GPIOB, GPIO6); /* LED off */
// for (i = 0; i < 1000000; i++) /* Wait a bit. */
// __asm__("nop");
// gpio_clear(GPIOB, GPIO6); /* LED on */
// for (i = 0; i < 1000000; i++) /* Wait a bit. */
// __asm__("nop");
/* Using API function gpio_toggle(): */
gpio_toggle(GPIOB, GPIO6); /* LED on/off */
for (i = 0; i < 1000000; i++) { /* Wait a bit. */
__asm__("nop");
}
}
return 0;
}

View File

@ -0,0 +1,24 @@
#
# Project Configuration File
#
# A detailed documentation with the EXAMPLES is located here:
# http://docs.platformio.org/en/latest/projectconf.html
#
# A sign `#` at the beginning of the line indicates a comment
# Comment lines are ignored.
# Simple and base environment
# [env:mybaseenv]
# platform = %INSTALLED_PLATFORM_NAME_HERE%
# framework =
# board =
#
# Automatic targets - enable auto-uploading
# targets = upload
[env:stm32]
platform = stm32
framework = cmsis,spl
board = stm32ldiscovery

View File

@ -0,0 +1,49 @@
#include <stm32l1xx_gpio.h>
#include <stm32l1xx_rcc.h>
#include <misc.h>
/* timing is not guaranteed :) */
void simple_delay(uint32_t us)
{
/* simple delay loop */
while (us--) {
asm volatile ("nop");
}
}
/* system entry point */
int main(void)
{
/* gpio init struct */
GPIO_InitTypeDef gpio;
/* reset rcc */
RCC_DeInit();
/* enable clock to GPIOB */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
/* use pin 7 */
gpio.GPIO_Pin = GPIO_Pin_7;
/* mode: output */
gpio.GPIO_Mode = GPIO_Mode_OUT;
/* output type: push-pull */
gpio.GPIO_OType = GPIO_OType_PP;
/* apply configuration */
GPIO_Init(GPIOB, &gpio);
/* main program loop */
for (;;) {
/* set led on */
GPIO_SetBits(GPIOB, GPIO_Pin_7);
/* delay */
simple_delay(100000);
/* clear led */
GPIO_ResetBits(GPIOB, GPIO_Pin_7);
/* delay */
simple_delay(100000);
}
/* never reached */
return 0;
}

View File

@ -0,0 +1,23 @@
#
# Project Configuration File
#
# A detailed documentation with the EXAMPLES is located here:
# http://docs.platformio.org/en/latest/projectconf.html
#
# A sign `#` at the beginning of the line indicates a comment
# Comment lines are ignored.
# Simple and base environment
# [env:mybaseenv]
# platform = %INSTALLED_PLATFORM_NAME_HERE%
# framework =
# board =
#
# Automatic targets - enable auto-uploading
# targets = upload
[env:launchpad_tm4c1230c3pm]
platform = titiva
framework = energia
board = lptm4c1230c3pm

View File

@ -0,0 +1,19 @@
/**
* Copyright (C) Ivan Kravets <me@ikravets.com>
* See LICENSE for details.
*/
#include "Energia.h"
void setup()
{
pinMode(GREEN_LED, OUTPUT); // set pin as output
}
void loop()
{
digitalWrite(GREEN_LED, HIGH); // set the LED on
delay(1000); // wait for a second
digitalWrite(GREEN_LED, LOW); // set the LED off
delay(1000); // wait for a second
}

View File

Before

Width:  |  Height:  |  Size: 2.0 MiB

After

Width:  |  Height:  |  Size: 2.0 MiB

View File

@ -21,4 +21,3 @@
platform = titiva
framework = energia
board = lplm4f120h5qr
targets = upload

View File

@ -0,0 +1,23 @@
#
# Project Configuration File
#
# A detailed documentation with the EXAMPLES is located here:
# http://docs.platformio.org/en/latest/projectconf.html
#
# A sign `#` at the beginning of the line indicates a comment
# Comment lines are ignored.
# Simple and base environment
# [env:mybaseenv]
# platform = %INSTALLED_PLATFORM_NAME_HERE%
# framework =
# board =
#
# Automatic targets - enable auto-uploading
# targets = upload
[env:launchpad_lm4f120]
platform = titiva
framework = opencm3
board = lplm4f120h5qr

View File

@ -0,0 +1,206 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2011 Gareth McMullin <gareth@blacksphere.co.nz>
* Copyright (C) 2012-2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* \addtogroup Examples
*
* Flashes the Red, Green and Blue diodes on the board, in order.
*
* RED controlled by PF1
* Green controlled by PF3
* Blue controlled by PF2
*/
#include <libopencm3/cm3/nvic.h>
#include <libopencm3/lm4f/systemcontrol.h>
#include <libopencm3/lm4f/rcc.h>
#include <libopencm3/lm4f/gpio.h>
#include <libopencm3/lm4f/nvic.h>
#include <stdbool.h>
#include <stdio.h>
/* This is how the RGB LED is connected on the stellaris launchpad */
#define RGB_PORT GPIOF
enum {
LED_R = GPIO1,
LED_G = GPIO3,
LED_B = GPIO2,
};
/* This is how the user switches are connected to GPIOF */
enum {
USR_SW1 = GPIO4,
USR_SW2 = GPIO0,
};
/* The divisors we loop through when the user presses SW2 */
enum {
PLL_DIV_80MHZ = 5,
PLL_DIV_57MHZ = 7,
PLL_DIV_40MHZ = 10,
PLL_DIV_20MHZ = 20,
PLL_DIV_16MHZ = 25,
};
static const uint8_t plldiv[] = {
PLL_DIV_80MHZ,
PLL_DIV_57MHZ,
PLL_DIV_40MHZ,
PLL_DIV_20MHZ,
PLL_DIV_16MHZ,
0
};
/* The PLL divisor we are currently on */
static size_t ipll = 0;
/* Are we bypassing the PLL, or not? */
static bool bypass = false;
/*
* Clock setup:
* Take the main crystal oscillator at 16MHz, run it through the PLL, and divide
* the 400MHz PLL clock to get a system clock of 80MHz.
*/
static void clock_setup(void)
{
rcc_sysclk_config(OSCSRC_MOSC, XTAL_16M, PLL_DIV_80MHZ);
}
/*
* GPIO setup:
* Enable the pins driving the RGB LED as outputs.
*/
static void gpio_setup(void)
{
/*
* Configure GPIOF
* This port is used to control the RGB LED
*/
periph_clock_enable(RCC_GPIOF);
const uint32_t outpins = (LED_R | LED_G | LED_B);
gpio_mode_setup(RGB_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, outpins);
gpio_set_output_config(RGB_PORT, GPIO_OTYPE_PP, GPIO_DRIVE_2MA, outpins);
/*
* Now take care of our buttons
*/
const uint32_t btnpins = USR_SW1 | USR_SW2;
/*
* PF0 is a locked by default. We need to unlock it before we can
* re-purpose it as a GPIO pin.
*/
gpio_unlock_commit(GPIOF, USR_SW2);
/* Configure pins as inputs, with pull-up. */
gpio_mode_setup(GPIOF, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, btnpins);
}
/*
* IRQ setup:
* Trigger an interrupt whenever a button is depressed.
*/
static void irq_setup(void)
{
const uint32_t btnpins = USR_SW1 | USR_SW2;
/* Trigger interrupt on rising-edge (when button is depressed) */
gpio_configure_trigger(GPIOF, GPIO_TRIG_EDGE_RISE, btnpins);
/* Finally, Enable interrupt */
gpio_enable_interrupts(GPIOF, btnpins);
/* Enable the interrupt in the NVIC as well */
nvic_enable_irq(NVIC_GPIOF_IRQ);
}
#define FLASH_DELAY 800000
static void delay(void)
{
int i;
for (i = 0; i < FLASH_DELAY; i++) /* Wait a bit. */
__asm__("nop");
}
int main(void)
{
gpio_enable_ahb_aperture();
clock_setup();
gpio_setup();
irq_setup();
/* Blink each color of the RGB LED in order. */
while (1) {
/*
* Flash the Red diode
*/
gpio_set(RGB_PORT, LED_R);
delay(); /* Wait a bit. */
gpio_clear(RGB_PORT, LED_R);
delay(); /* Wait a bit. */
/*
* Flash the Green diode
*/
gpio_set(RGB_PORT, LED_G);
delay(); /* Wait a bit. */
gpio_clear(RGB_PORT, LED_G);
delay(); /* Wait a bit. */
/*
* Flash the Blue diode
*/
gpio_set(RGB_PORT, LED_B);
delay(); /* Wait a bit. */
gpio_clear(RGB_PORT, LED_B);
delay(); /* Wait a bit. */
}
return 0;
}
void gpiof_isr(void)
{
if (gpio_is_interrupt_source(GPIOF, USR_SW1)) {
/* SW1 was just depressed */
bypass = !bypass;
if (bypass) {
rcc_pll_bypass_enable();
/*
* The divisor is still applied to the raw clock.
* Disable the divisor, or we'll divide the raw clock.
*/
SYSCTL_RCC &= ~SYSCTL_RCC_USESYSDIV;
}
else
{
rcc_change_pll_divisor(plldiv[ipll]);
}
/* Clear interrupt source */
gpio_clear_interrupt_flag(GPIOF, USR_SW1);
}
if (gpio_is_interrupt_source(GPIOF, USR_SW2)) {
/* SW2 was just depressed */
if (!bypass) {
if (plldiv[++ipll] == 0)
ipll = 0;
rcc_change_pll_divisor(plldiv[ipll]);
}
/* Clear interrupt source */
gpio_clear_interrupt_flag(GPIOF, USR_SW2);
}
}

View File

@ -0,0 +1,50 @@
{
"stm32f4discovery": {
"build": {
"core": "stm32",
"f_cpu": "168000000L",
"ldscript": "stm32f405x6.ld",
"mcu": "cortex-m4",
"variant": "stm32f4",
"extra_flags": "-DSTM32F40_41xxx"
},
"name": "STM32F4Discovery (168 MHz) with digital accelerometer, digital microphone, audio DAC",
"platform": "stm32",
"upload": {
"maximum_ram_size": 131071,
"maximum_size": 1048575
}
},
"stm32ldiscovery": {
"build": {
"core": "stm32",
"f_cpu": "32000000L",
"ldscript": "stm32l15xx6.ld",
"mcu": "cortex-m3",
"variant": "stm32l1",
"extra_flags": "-DSTM32L1XX_MD"
},
"name": "STM32LDiscovery (32 MHz) ultra low-power development kit",
"platform": "stm32",
"upload": {
"maximum_ram_size": 16384,
"maximum_size": 131072
}
},
"stm32f3discovery": {
"build": {
"core": "stm32",
"f_cpu": "72000000L",
"ldscript": "stm32f30xx.ld",
"mcu": "cortex-m4",
"variant": "stm32f3",
"extra_flags": "-DSTM32F303xC"
},
"name": "STM32F3Discovery (72 MHz) with accelerometer, gyroscope and e-compass",
"platform": "stm32",
"upload": {
"maximum_ram_size": 262144,
"maximum_size": 131072
}
}
}

View File

@ -7,7 +7,7 @@ except ImportError:
import sys
for _path in sys.path:
if "platformio" in _path:
sys.path.insert(0, _path[:_path.rfind("platformio")-1])
sys.path.insert(0, _path[:_path.rfind("platformio") - 1])
break
from platformio import util
@ -84,6 +84,15 @@ if "BOARD" in env:
env.Replace(UPLOAD_PROTOCOL="${BOARD_OPTIONS['upload']['protocol']}")
if "UPLOAD_SPEED" not in env:
env.Replace(UPLOAD_SPEED="${BOARD_OPTIONS['upload']['speed']}")
# specific linker script
if "ldscript" in env.get("BOARD_OPTIONS", {}).get("build", {}):
env.Replace(
LINKFLAGS=["-T", join(
"$PIOHOME_DIR", "packages", "ldscripts",
"${BOARD_OPTIONS['build']['ldscript']}")]
)
if "extra_flags" in env.get("BOARD_OPTIONS", {}).get("build", {}):
env.MergeFlags(env.subst("${BOARD_OPTIONS['build']['extra_flags']}"))
if "IGNORE_LIBS" in env:
env['IGNORE_LIBS'] = [l.strip() for l in env['IGNORE_LIBS'].split(",")]

View File

@ -0,0 +1,42 @@
# Copyright (C) Ivan Kravets <me@ikravets.com>
# See LICENSE for details.
"""
Build script for CMSIS Framework.
"""
from os.path import join
from SCons.Script import Import, Return
env = None
Import("env")
env.VariantDir(
join("$BUILD_DIR", "FrameworkCMSIS"),
join("$PIOPACKAGES_DIR", "framework-cmsis",
"cores", "${BOARD_OPTIONS['build']['core']}")
)
env.Append(
CPPPATH=[
join("$BUILD_DIR", "FrameworkCMSIS"),
join("$BUILD_DIR", "FrameworkCMSISVariant")
]
)
envsafe = env.Clone()
#
# Target: Build Core Library
#
libs = []
libs.append(envsafe.BuildLibrary(
join("$BUILD_DIR", "FrameworkCMSISVariant"),
join("$PIOPACKAGES_DIR", "framework-cmsis", "variants",
"${BOARD_OPTIONS['build']['variant']}")
))
Return("env libs")

View File

@ -33,16 +33,11 @@ env.Append(
]
)
# specific linker script for TIVA devices
if "ldscript" in env.subst("${BOARD_OPTIONS['build']}"):
if env.get("BOARD_OPTIONS", {}).get("build", {}).get("core") == "lm4f":
env.Append(
LINKFLAGS=["-T", join(
"$PLATFORMFW_DIR", "cores",
"${BOARD_OPTIONS['build']['core']}",
"${BOARD_OPTIONS['build']['ldscript']}")]
LINKFLAGS=["-Wl,--entry=ResetISR"]
)
#
# Target: Build Core Library
#

View File

@ -0,0 +1,172 @@
# Copyright (C) Ivan Kravets <me@ikravets.com>
# See LICENSE for details.
"""
Build script for OpenCM3 Framework.
"""
import re
from os import listdir, sep, walk
from os.path import isfile, join, normpath
from SCons.Script import Import, Return
from platformio.util import exec_command
env = None
Import("env")
BOARD_BUILDOPTS = env.get("BOARD_OPTIONS", {}).get("build", {})
def find_ldscript(src_dir):
ldscript = None
matches = []
for item in listdir(src_dir):
_path = join(src_dir, item)
if not isfile(_path) or not item.endswith(".ld"):
continue
matches.append(_path)
if len(matches) == 1:
ldscript = matches[0]
elif isfile(join(src_dir, BOARD_BUILDOPTS['ldscript'])):
ldscript = join(src_dir, BOARD_BUILDOPTS['ldscript'])
assert isfile(ldscript)
return ldscript
def generate_nvic_files():
fw_dir = join(env.get("PIOHOME_DIR"), "packages", "framework-opencm3")
for root, _, files in walk(join(fw_dir, "include", "libopencm3")):
if "irq.json" not in files or isfile(join(root, "nvic.h")):
continue
exec_command(
["python", join("scripts", "irq2nvic_h"),
join("." + root.replace(fw_dir, ""),
"irq.json").replace("\\", "/")],
cwd=fw_dir
)
def parse_makefile_data(makefile):
data = {"includes": [], "objs": [], "vpath": ["./"]}
with open(makefile) as f:
content = f.read()
# fetch "includes"
re_include = re.compile(r"^include\s+([^\r\n]+)", re.M)
for match in re_include.finditer(content):
data['includes'].append(match.group(1))
# fetch "vpath"s
re_vpath = re.compile(r"^VPATH\s+\+?=\s+([^\r\n]+)", re.M)
for match in re_vpath.finditer(content):
data['vpath'] += match.group(1).split(":")
# fetch obj files
objs_match = re.search(
r"^OBJS\s+\+?=\s+([^\.]+\.o\s*(?:\s+\\s+)?)+", content, re.M)
assert objs_match
data['objs'] = re.sub(
r"(OBJS|[\+=\\\s]+)", "\n", objs_match.group(0)).split()
return data
def get_source_files(src_dir):
mkdata = parse_makefile_data(join(src_dir, "Makefile"))
for include in mkdata['includes']:
_mkdata = parse_makefile_data(normpath(join(src_dir, include)))
for key, value in _mkdata.iteritems():
for v in value:
if v not in mkdata[key]:
mkdata[key].append(v)
sources = []
lib_root = env.subst(
join(env.get("PIOHOME_DIR"), "packages", "framework-opencm3"))
for obj_file in mkdata['objs']:
src_file = obj_file[:-1] + "c"
for search_path in mkdata['vpath']:
src_path = normpath(join(src_dir, search_path, src_file))
if isfile(src_path):
sources.append(join("$BUILD_DIR", "FrameworkOpenCM3",
src_path.replace(lib_root + sep, "")))
break
return sources
def merge_ld_scripts(main_ld_file):
def _include_callback(match):
included_ld_file = match.group(1)
# search included ld file in lib directories
for root, _, files in walk(join(
env.get("PIOHOME_DIR"), "packages",
"framework-opencm3", "lib")):
if included_ld_file not in files:
continue
with open(join(root, included_ld_file)) as fp:
return fp.read()
return match.group(0)
content = ""
with open(main_ld_file) as f:
content = f.read()
incre = re.compile(r"^INCLUDE\s+\"?([^\.]+\.ld)\"?", re.M)
with open(main_ld_file, "w") as f:
f.write(incre.sub(_include_callback, content))
#
# Processing ...
#
if BOARD_BUILDOPTS.get("core") == "lm4f":
env.Append(
CPPDEFINES=["LM4F"]
)
env.VariantDir(
join("$BUILD_DIR", "FrameworkOpenCM3Variant"),
join("$PIOPACKAGES_DIR", "framework-opencm3", "include")
)
env.Append(
CPPPATH=[
join("$BUILD_DIR", "FrameworkOpenCM3"),
join("$BUILD_DIR", "FrameworkOpenCM3Variant")
]
)
root_dir = join(env.get("PIOHOME_DIR"), "packages", "framework-opencm3", "lib",
BOARD_BUILDOPTS.get("core"))
if BOARD_BUILDOPTS.get("core") == "stm32":
root_dir = join(root_dir, BOARD_BUILDOPTS.get("variant")[-2:])
ldscript_path = find_ldscript(root_dir)
merge_ld_scripts(ldscript_path)
generate_nvic_files()
# override ldscript by opencm3
assert env['LINKFLAGS'][0] == "-T"
env['LINKFLAGS'][1] = ldscript_path
libs = []
env.VariantDir(
join("$BUILD_DIR", "FrameworkOpenCM3"),
join(env.get("PIOHOME_DIR"), "packages", "framework-opencm3")
)
libs.append(env.Library(
join("$BUILD_DIR", "FrameworkOpenCM3"),
get_source_files(root_dir)
))
Return("env libs")

View File

@ -0,0 +1,64 @@
# Copyright (C) Ivan Kravets <me@ikravets.com>
# See LICENSE for details.
"""
Build script for SPL Framework
"""
from os.path import join
from SCons.Script import Import, Return
env = None
Import("env")
env.VariantDir(
join("$BUILD_DIR", "FrameworkSPLInc"),
join("$PIOPACKAGES_DIR", "framework-spl",
"${BOARD_OPTIONS['build']['core']}",
"variants", "${BOARD_OPTIONS['build']['variant']}", "inc")
)
env.Append(
CPPPATH=[
join("$BUILD_DIR", "FrameworkSPLInc"),
join("$BUILD_DIR", "FrameworkSPL")
]
)
envsafe = env.Clone()
envsafe.Append(
CPPPATH=[
join("$BUILD_DIR", "src")
],
CPPDEFINES=[
"USE_STDPERIPH_DRIVER"
]
)
#
# Target: Build SPL Library
#
extra_flags = env.get("BOARD_OPTIONS", {}).get("build", {}).get("extra_flags")
ignore_files = []
if "STM32F40_41xxx" in extra_flags:
ignore_files += ["stm32f4xx_fmc.c"]
elif "STM32F303xC" in extra_flags:
ignore_files += ["stm32f30x_hrtim.c"]
elif "STM32L1XX_MD" in extra_flags:
ignore_files += ["stm32l1xx_flash_ramfunc.c"] # removed warning
libs = []
libs.append(envsafe.BuildLibrary(
join("$BUILD_DIR", "FrameworkSPL"),
join("$PIOPACKAGES_DIR", "framework-spl",
"${BOARD_OPTIONS['build']['core']}", "variants",
"${BOARD_OPTIONS['build']['variant']}", "src"),
ignore_files
))
Return("env libs")

View File

@ -0,0 +1,141 @@
# Copyright (C) Ivan Kravets <me@ikravets.com>
# See LICENSE for details.
"""
Builder for STMicroelectronics
STM32 Series ARM microcontrollers.
"""
from os.path import join
from SCons.Script import (COMMAND_LINE_TARGETS, AlwaysBuild, Builder, Default,
DefaultEnvironment)
env = DefaultEnvironment()
env.Replace(
AR="arm-none-eabi-ar",
AS="arm-none-eabi-gcc",
CC="arm-none-eabi-gcc",
CXX="arm-none-eabi-g++",
OBJCOPY="arm-none-eabi-objcopy",
RANLIB="arm-none-eabi-ranlib",
ARFLAGS=["rcs"],
ASFLAGS=[
"-c",
"-g", # include debugging info (so errors include line numbers)
"-x", "assembler-with-cpp",
"-Wall",
"-mthumb",
"-mcpu=${BOARD_OPTIONS['build']['mcu']}"
],
CCFLAGS=[
"-g", # include debugging info (so errors include line numbers)
"-Os", # optimize for size
"-ffunction-sections", # place each function in its own section
"-fdata-sections",
"-Wall",
"-mthumb",
"-mcpu=${BOARD_OPTIONS['build']['mcu']}",
"-MMD" # output dependancy info
],
CXXFLAGS=[
"-fno-rtti",
"-fno-exceptions"
],
UPLOADER=join("$PIOPACKAGES_DIR", "tool-stlink", "st-flash"),
UPLOADERFLAGS=[
"write", # write in flash
"$SOURCES", # firmware path to flash
"0x08000000" # flash start adress
],
UPLOADCMD="$UPLOADER $UPLOADERFLAGS"
)
env.Append(
CPPDEFINES=[
"F_CPU=$BOARD_F_CPU",
"${BOARD_OPTIONS['build']['variant'].upper()}"
]
)
env.Append(
LINKFLAGS=[
"-Os",
"-nostartfiles",
"-nostdlib",
"-Wl,--gc-sections",
"-mthumb",
"-mcpu=${BOARD_OPTIONS['build']['mcu']}"
]
)
if env.get("BOARD_OPTIONS", {}).get("build", {}).get("mcu")[-2:] == "m4":
env.Append(
ASFLAGS=[
"-mfloat-abi=hard",
"-mfpu=fpv4-sp-d16",
"-fsingle-precision-constant"
],
CCFLAGS=[
"-mfloat-abi=hard",
"-mfpu=fpv4-sp-d16",
"-fsingle-precision-constant"
],
LINKFLAGS=[
"-mfloat-abi=hard",
"-mfpu=fpv4-sp-d16",
"-fsingle-precision-constant"
]
)
env.Append(
BUILDERS=dict(
ElfToBin=Builder(
action=" ".join([
"$OBJCOPY",
"-O",
"binary",
"$SOURCES",
"$TARGET"]),
suffix=".bin"
)
)
)
CORELIBS = env.ProcessGeneral()
#
# Target: Build executable and linkable firmware
#
target_elf = env.BuildFirmware(CORELIBS + ["c", "gcc", "m", "nosys"])
#
# Target: Build the .bin file
#
if "uploadlazy" in COMMAND_LINE_TARGETS:
target_bin = join("$BUILD_DIR", "firmware.bin")
else:
target_bin = env.ElfToBin(join("$BUILD_DIR", "firmware"), target_elf)
#
# Target: Upload by default .bin file
#
upload = env.Alias(["upload", "uploadlazy"], target_bin, ("$UPLOADCMD"))
AlwaysBuild(upload)
#
# Target: Define targets
#
Default(target_bin)

View File

@ -59,21 +59,22 @@ env.Replace(
"F_CPU=$BOARD_F_CPU"
],
UPLOADER=join("$PIOPACKAGES_DIR", "tool-lm4flash", "lm4flash"),
UPLOADCMD="$UPLOADER $SOURCES"
)
env.Append(
LINKFLAGS=[
"-Os",
"-nostartfiles",
"-nostdlib",
"-Wl,--gc-sections",
"-Wl,--entry=ResetISR",
"-mthumb",
"-mcpu=cortex-m4",
"-mfloat-abi=hard",
"-mfpu=fpv4-sp-d16",
"-fsingle-precision-constant"
],
UPLOADER=join("$PIOPACKAGES_DIR", "tool-lm4flash", "lm4flash"),
UPLOADCMD="$UPLOADER $SOURCES"
]
)
env.Append(

View File

@ -0,0 +1,40 @@
# Copyright (C) Ivan Kravets <me@ikravets.com>
# See LICENSE for details.
from platformio.platforms.base import BasePlatform
class Stm32Platform(BasePlatform):
"""
An embedded platform for STMicroelectronics ARM microcontrollers
"""
PACKAGES = {
"toolchain-gccarmnoneeabi": {
"alias": "toolchain",
"default": True
},
"ldscripts": {
"default": True
},
"tool-stlink": {
"alias": "uploader",
"default": True
},
"framework-cmsis": {
"default": True
},
"framework-spl": {
"default": True
},
"framework-opencm3": {
"default": True
}
}

View File

@ -5,6 +5,7 @@ from platformio.platforms.base import BasePlatform
class TitivaPlatform(BasePlatform):
"""
An embedded platform for TI TIVA C ARM microcontrollers
(with Energia Framework)
@ -17,6 +18,10 @@ class TitivaPlatform(BasePlatform):
"default": True
},
"ldscripts": {
"default": True
},
"tool-lm4flash": {
"alias": "uploader",
"default": True