Skip to content

Commit

Permalink
Merge pull request #1 from ussserrr/dev
Browse files Browse the repository at this point in the history
v0.8 release
  • Loading branch information
ussserrr authored Sep 21, 2019
2 parents 0d2968a + 9db8e04 commit 39384d4
Show file tree
Hide file tree
Showing 17 changed files with 503 additions and 478 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ ENV/

# editors
.vscode
.idea

# macOS-specific
.DS_Store
20 changes: 20 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,23 @@ stm32pio changelog:
- Changed: util.py functions now raising the exceptions instead of forcing the exit
- Changed: test '.ioc' file is updated to the latest STM32CubeMX version (5.1.0 at the moment)
- Changed: documentation improvements

ver. 0.8 (09.19):
- New: setup.py can now install executable script to run 'stm32pio' from any location
- New: stm32pio logo/schematic
- New: add PyCharm to .gitignore
- New: add clear TODOs for the next release (some sort of a roadmap)
- New: single __version__ reference
- New: add some new tests (test_build_should_raise, test_file_not_found)
- Fixed: options '--start-editor' and '--with-build' can now be used both for 'new' and 'generate' commands
- Fixed: import scheme is now as it should be
- Changed: migrate from 'os.path' to 'pathlib' as much as possible for paths management (as a more high-level module)
- Changed: 'start editor' feature is now starting an arbitrary editor (in the same way as you do it from the terminal)
- Changed: take outside 'platformio' command (to 'settings')
- Changed: screenshots were actualized for recent CubeMX versions
- Changed: logging output in standard (non-verbose) mode is simpler
- Changed: move tests in new location
- Changed: revised and improved tests
- Changed: tests are now run by 'python -m unittest' and cannot be run as standalone
- Changed: actualized .ioc file and clean-up the code according to the latest STM32CubeMX version (5.3.0 at the moment)
- Changed: revised and improved util module
2 changes: 1 addition & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ include MANIFEST.in
include CHANGELOG
include TODO.md
include .gitignore
include stm32pio-test/stm32pio-test.ioc
recursive-include stm32pio/tests *
include screenshots/*.png
73 changes: 44 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
# stm32pio
Small cross-platform Python app that can create and update [PlatformIO](https://platformio.org) projects from [STM32CubeMX](http://www.st.com/en/development-tools/stm32cubemx.html) `.ioc` files.
Small cross-platform Python app that can create and update [PlatformIO](https://platformio.org) projects from [STM32CubeMX](https://www.st.com/en/development-tools/stm32cubemx.html) `.ioc` files.

![Logo](/screenshots/logo.png)


## Features
- Start the new project in a single directory using only `.ioc` file
- Update existing project after adding/changing hardware options from CubeMX
- Start the new project in a single directory using only an `.ioc` file
- Update existing project after changing hardware options from CubeMX
- Clean-up the project (WARNING: it deletes ALL content of 'path' except the `.ioc` file!)
- *[optional]* Automatically run your favorite editor in the end
- *[optional]* Make an initial build of the project


## Restrictions
- The tool doesn't check for different parameters compatibility, e.g. CPU frequency, memory sizes and so on. It simply ease your workflow with these 2 programs (PlatformIO and STM32CubeMX) a little bit.
- CubeMX middlewares doesn't support yet because it's hard to be prepared for every possible configuration. You need to manually adjust them to build appropriately. For example, FreeRTOS can be added via PlatformIO' `lib` feature or be directly compiled in its own directory using `lib_extra_dirs` option:
- The tool doesn't check for different parameters compatibility, e.g. CPU frequency, memory sizes and so on. It simply eases your workflow with these 2 programs (PlatformIO and STM32CubeMX) a little bit.
- CubeMX middlewares don't support yet because it's hard to be prepared for every possible configuration. You need to manually adjust them to build appropriately. For example, FreeRTOS can be added via PlatformIO' `lib` feature or be directly compiled in its own directory using `lib_extra_dirs` option:
```ini
lib_extra_dirs = Middlewares/Third_Party/FreeRTOS
```
Expand All @@ -30,55 +32,68 @@ Small cross-platform Python app that can create and update [PlatformIO](https://


## Usage
Basically, you need to follow such pattern:
Basically, you need to follow such a pattern:
1. Create CubeMX project, set-up hardware configuration
2. Run stm32pio that automatically invoke CubeMX to generate the code, create PlatformIO project, patch an '.ini' file and so on
3. Work on the project in your editor, compile/upload/debug it
4. Edit the configuration in CubeMX when necessary, then run stm32pio to regenerate the code.

Refer to Example section on more detailed steps.

stm32pio will create an accessory file 'cubemx-script' in your project directory that contains commands passed to CubeMX. You can safely delete it (it will be created again on the next run) or edit corresponding to your goals.
stm32pio will create an accessory file `cubemx-script`'` in your project directory that contains commands passed to CubeMX. You can safely delete it (it will be created again on the next run) or edit corresponding to your goals.
Check `settings.py` to make sure that all user-specific parameters are valid. Run
```bash
```shell script
$ python3 stm32pio.py --help
```
to see help.
## Installation
Starting from v0.8 it is possible to install the utility to be able to run stm32pio from anywhere. Use
```shell script
stm32pio-repo/ $ pip3 install .
```
command to launch the setup process. To uninstall run
```shell script
$ pip3 uninstall stm32pio
```
## Example
1. Run CubeMX, choose MCU/board, do all necessary stuff
2. Open `Project -> Settings` menu, specify Project Name, choose Other Toolchains (GPDSC). In Code Generator tab check "Copy only the necessary library files" and "Generate periphery initialization as a pair of '.c/.h' files per peripheral" options
2. Select `Project Manager -> Project` tab, specify "Project Name", choose "Other Toolchains (GPDSC)". In `Code Generator` tab check "Copy only the necessary library files" and "Generate periphery initialization as a pair of '.c/.h' files per peripheral" options
![Code Generator tab](/screenshots/tab_CodeGenerator.png)
3. Back in the first tab (Project) copy the "Toolchain Folder Location" string. Click OK, close CubeMX
3. Back in the first tab (Project) copy the "Toolchain Folder Location" string (you maybe not be able to copy it in modern CubeMX versions so use terminal or file manager to do this). Save the project, close CubeMX
![Project tab](/screenshots/tab_Project.png)
4. Use copied string as a `-d` argument for stm32pio. So it is assumed that the name of the project folder matches the name of `.ioc` file. (`-d` argument can be omitted if your current working directory is already a project directory)
4. Use a copied string as a `-d` argument for stm32pio. So it is assumed that the name of the project folder matches the name of `.ioc` file. (`-d` argument can be omitted if your current working directory is already a project directory)
5. Run `platformio boards` (`pio boards`) or go to [boards](https://docs.platformio.org/en/latest/boards) to list all supported devices. Pick one and use its ID as a `-b` argument (for example, `nucleo_f031k6`)
6. All done. You can now run
```bash
$ python3 stm32pio.py new -d /path/to/cubemx/project -b nucleo_f031k6 --start-editor=vscode --with-build
```
to complete generation, start the Visual Studio Code editor with opened folder and compile the project (as example, not required). Make sure you have all tools in PATH (`java` (or set in `settings.py`), editor, Python)

6. All done! You can now run
```shell script
$ python3 stm32pio.py new -d path/to/cubemx/project/ -b nucleo_f031k6 --start-editor=vscode --with-build
```
to complete generation, start the Visual Studio Code editor with opened folder and compile the project (as an example, not required). Make sure you have all tools in PATH (`java` (or set its path in `settings.py`), `python`, editor). You can use shorter form if you are already located in the project directory (also using shebang alias):
```shell script
path/to/cubemx/project/ $ stm32pio.py new -b nucleo_f031k6
```
7. If you will be in need to update hardware configuration in the future, make all necessary stuff in CubeMX and run `generate` command in a similar way:
```bash
$ python3 stm32pio.py generate -d /path/to/cubemx/project
```
8. To clean-up the folder and keep only `.ioc` file run `clean` command
```shell script
$ python3 stm32pio.py generate -d /path/to/cubemx/project
```
8. To clean-up the folder and keep only the `.ioc` file run `clean` command
## Testing
Since ver. 0.45 there are some unit-tests in file `tests.py` (based on the unittest module). Run
```bash
$ python3 tests.py -v
Since ver. 0.45 there are some unit-tests in file `stm32pio/tests/test.py` (based on the unittest module). Run
```shell script
stm32pio-repo/ $ python3 -m unittest discover -v
```
to test the app. It uses STM32F0 framework to generate and build a code from the `./stm32pio-test/stm32pio-test.ioc` file.


## Notes
- CI is hard to implement for all target OSes during the requirement to have all tools (PlatformIO, Java, CubeMX, etc.) installed during the test. For example, ST doesn't even provide a direct link to CubeMX for downloading
or
```shell script
stm32pio-repo/ $ python3 -m stm32pio.tests.test -v
```
to test the app. It uses STM32F0 framework to generate and build a code from the `stm32pio/tests/stm32pio-test-project/stm32pio-test-project.ioc` file. It's fine to fail an editor test as you not necessarily should have all the editors on your machine. CI is hard to implement for all target OSes during the requirement to have all tools (PlatformIO, Java, CubeMX, etc.) installed during the test. For example, ST doesn't even provide a direct link to CubeMX for downloading
5 changes: 4 additions & 1 deletion TODO.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# TODOs

- [ ] Middleware support (FreeRTOS, etc.)
- [ ] Add more checks, for example when updating the project (`generate` command), check for boards matching and so on...
- [ ] Do we need some sort of GUI? For example, drop the folder into small window (with checkboxes corresponding with CLI options) and get the output
- [ ] remade as Class (constructor init(project_path))
- [ ] test CLI (i.e. run stm32pio as subprocess)
- [ ] upload to PyPI
Binary file added screenshots/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified screenshots/tab_CodeGenerator.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified screenshots/tab_Project.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 10 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import setuptools

with open("README.md", "r") as fh:
from stm32pio.stm32pio import __version__

with open("README.md", 'r') as fh:
long_description = fh.read()

setuptools.setup(
name="stm32pio",
version="0.74",
version=__version__,
author="ussserrr",
author_email="[email protected]",
description="Small cross-platform Python app that can create and update PlatformIO projects from STM32CubeMX .ioc "
Expand All @@ -19,5 +21,10 @@
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
],
include_package_data=True
include_package_data=True,
entry_points={
'console_scripts': [
'stm32pio = stm32pio.stm32pio:main'
]
}
)
2 changes: 0 additions & 2 deletions stm32pio/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +0,0 @@
name = "stm32pio"
__version__ = "0.74"
27 changes: 13 additions & 14 deletions stm32pio/settings.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,24 @@
import logging
import pathlib
import platform
import pathlib


my_os = platform.system()
home_dir = str(pathlib.Path.home())

logger = logging.getLogger('')


# (default is OK) How do you start Java from command line? (edit if Java not in PATH)
java_cmd = 'java'

# (default is OK) How do you start PlatformIO from command line? (edit if not in PATH, check
# https://docs.platformio.org/en/latest/installation.html#install-shell-commands)
platformio_cmd = 'platformio'

# (default is OK) We trying to guess STM32CubeMX location. You can just avoid this and hard-code it.
# Note that STM32CubeMX will be called as 'java -jar CUBEMX'
# Note that STM32CubeMX will be invoked as 'java -jar CUBEMX'
# macOS default: 'Applications' folder
if my_os == 'Darwin':
cubemx_path = "/Applications/STMicroelectronics/STM32CubeMX.app/Contents/Resources/STM32CubeMX"
# Linux (Ubuntu) default:
elif my_os == 'Linux':
cubemx_path = "/usr/local/STMicroelectronics/STM32Cube/STM32CubeMX/STM32CubeMX"
cubemx_path = pathlib.Path.home().joinpath("STM32CubeMX/STM32CubeMX")
# Windows default:
elif my_os == 'Windows':
cubemx_path = "C:/Program Files/STMicroelectronics/STM32Cube/STM32CubeMX/STM32CubeMX.exe"
Expand All @@ -28,11 +27,11 @@
cubemx_script_filename = 'cubemx-script'

# (default is OK) see CubeMX user manual PDF to see other useful options
cubemx_script_text = "config load {cubemx_ioc_full_filename}\n" \
"generate code {project_path}\n" \
"exit\n"
cubemx_script_content = "config load {cubemx_ioc_full_filename}\n" \
"generate code {project_path}\n" \
"exit\n"

# (default is OK)
platformio_ini_patch_text = "\n[platformio]\n" \
"include_dir = Inc\n" \
"src_dir = Src\n"
platformio_ini_patch_content = "\n[platformio]\n" \
"include_dir = Inc\n" \
"src_dir = Src\n"
81 changes: 40 additions & 41 deletions stm32pio/stm32pio.py
Original file line number Diff line number Diff line change
@@ -1,57 +1,54 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

__version__ = "0.8"

if __name__ == '__main__':

import argparse
import logging
import sys
import os
import argparse
import logging
import sys
import pathlib

import __init__

def main():
parser = argparse.ArgumentParser(description="Automation of creating and updating STM32CubeMX-PlatformIO projects. "
"Requirements: Python 3.6+, STM32CubeMX, Java, PlatformIO CLI. Edit "
"settings.py to set project path to the STM32CubeMX (if default "
"doesn't work)")
# global arguments (there is also automatically added '-h, --help' option)
parser.add_argument('--version', action='version', version=f"%(prog)s v{__init__.__version__}")
parser.add_argument('-v', '--verbose', help="enable verbose output (default: INFO)",
action='count', required=False)
"settings.py to set path to the STM32CubeMX (if default doesn't work)")
# Global arguments (there is also an automatically added '-h, --help' option)
parser.add_argument('--version', action='version', version=f"%(prog)s v{__version__}")
parser.add_argument('-v', '--verbose', help="enable verbose output (default: INFO)", action='count', required=False)

subparsers = parser.add_subparsers(dest='subcommand', title='subcommands',
description="valid subcommands", help="modes of operation")

parser_new = subparsers.add_parser('new',
help="generate CubeMX code, create PlatformIO project [and start the editor]")
parser_new.add_argument('-d', '--directory', dest='project_path',
help="path to the project (current directory, if not given)", default=os.getcwd())
parser_new.add_argument('-b', '--board', dest='board', help="PlatformIO name of the board", required=True)
parser_new.add_argument('--start-editor', dest='editor', help="use specified editor to open PlatformIO project",
choices=['atom', 'vscode', 'sublime'], required=False)
parser_new.add_argument('--with-build', action='store_true', help="initiate a build after project generation",
required=False)

parser_generate = subparsers.add_parser('generate', help="generate CubeMX code")
parser_generate.add_argument('-d', '--directory', dest='project_path',
help="path to the project (current directory, if not given)", default=os.getcwd())

parser_clean = subparsers.add_parser('clean', help="clean-up the project (WARNING: it deletes ALL content of "
"'path' except the .ioc file)")
parser_clean.add_argument('-d', '--directory', dest='project_path',
help="path to the project (current directory, if not given)", default=os.getcwd())

# Common subparsers options
for p in [parser_new, parser_generate, parser_clean]:
p.add_argument('-d', '--directory', dest='project_path', help="path to the project (current directory, if not "
"given)", default=pathlib.Path.cwd())
for p in [parser_new, parser_generate]:
p.add_argument('--start-editor', dest='editor', help="use specified editor to open PlatformIO project (e.g. "
"subl, code, atom)", required=False)
p.add_argument('--with-build', action='store_true', help="build a project after generation", required=False)

parser_new.add_argument('-b', '--board', dest='board', help="PlatformIO name of the board", required=True)

args = parser.parse_args()


# Logger instance goes through the whole program.
# Currently only 2 levels of verbosity through the '-v' option are counted
logging.basicConfig(format="%(levelname)-8s %(funcName)-16s %(message)s")
logger = logging.getLogger('')
# Currently only 2 levels of verbosity through the '-v' option are counted (INFO and DEBUG)
logger = logging.getLogger()
if args.verbose:
logging.basicConfig(format="%(levelname)-8s %(funcName)-16s %(message)s")
logger.setLevel(logging.DEBUG)
logger.debug("debug logging enabled")
else:
logging.basicConfig(format="%(levelname)-8s %(message)s")
logger.setLevel(logging.INFO)


Expand All @@ -62,27 +59,29 @@

# Main routine
else:
import util
import stm32pio.util

try:
if args.subcommand == 'new':
util.generate_code(args.project_path)
util.pio_init(args.project_path, args.board)
util.patch_platformio_ini(args.project_path)
if args.subcommand == 'new' or args.subcommand == 'generate':
stm32pio.util.generate_code(args.project_path)
if args.subcommand == 'new':
stm32pio.util.pio_init(args.project_path, args.board)
stm32pio.util.patch_platformio_ini(args.project_path)

if args.editor:
util.start_editor(args.project_path, args.editor)
if args.with_build:
util.pio_build(args.project_path)

elif args.subcommand == 'generate':
util.generate_code(args.project_path)
stm32pio.util.pio_build(args.project_path)
if args.editor:
stm32pio.util.start_editor(args.project_path, args.editor)

elif args.subcommand == 'clean':
util.clean(args.project_path)
stm32pio.util.clean(args.project_path)

except Exception as e:
print(e.__repr__())


logger.info("exiting...")


if __name__ == '__main__':
main()
Loading

0 comments on commit 39384d4

Please sign in to comment.