├── .gitignore ├── CMakeLists.txt ├── CONTRIBUTING.md ├── LICENSE.md ├── License.txt ├── Readme.md ├── STM32FLASH.ld ├── cmake.py ├── converter.py ├── ewpproject.py └── uvprojxproject.py /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # CMake minimum version 2 | cmake_minimum_required (VERSION {{ cmake.version }}) 3 | 4 | # Project Infomation 5 | project( {{ cmake.project }} ) 6 | enable_language(ASM) 7 | enable_language(C) 8 | 9 | # Reset output path 10 | set (EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin) 11 | set (LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib) 12 | 13 | # STDLIB 14 | set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS) 15 | 16 | # Set include path 17 | {% for inc in cmake.incs %} 18 | include_directories ({{ inc }}) 19 | {% endfor %} 20 | 21 | # The need build source path and build all files 22 | {% for src in cmake.files %} 23 | set ({{ src.var }} {{ src.path }}) 24 | {% endfor %} 25 | 26 | {% for as in cmake.ass %} 27 | set_source_files_properties({{ as.path }} PROPERTIES COMPILE_FLAGS "-x assembler-with-cpp") 28 | {% endfor %} 29 | 30 | set(CROSS_TARGET_TRIPLET "arm-none-eabi-") 31 | 32 | # CC AR LD AS 33 | set(CMAKE_C_COMPILER "${CROSS_TARGET_TRIPLET}gcc") 34 | {%if cmake.cxx == 'true' %} 35 | set(CMAKE_CXX_COMPILER "${CROSS_TARGET_TRIPLET}g++") 36 | {% endif %} 37 | set(CMAKE_ASM_COMPILER "${CROSS_TARGET_TRIPLET}gcc") 38 | 39 | # CFLAGS 40 | set (CMAKE_C_FLAGS "{{ cmake.c_flags }}" CACHE INTERNAL "c compiler flags") 41 | set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} {% for define in cmake.defines %} -D {{ define }} {% endfor %}") 42 | 43 | # CXXFLAGS 44 | set (CMAKE_CXX_FLAGS "{{ cmake.cxx_flags }}" CACHE INTERNAL "cxx compiler flags") 45 | 46 | # ASMFLAGS 47 | set (CMAKE_ASM_FLAGS "{{ cmake.asm_flags }}" CACHE INTERNAL "asm compiler flags") 48 | 49 | # LDFLAGS 50 | set (CMAKE_EXE_LINKER_FLAGS "{{ cmake.linker_flags }}" CACHE INTERNAL "executable linker flags") 51 | set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -T ${CMAKE_SOURCE_DIR}/{{ cmake.linker_script }} -L {{ cmake.linker_path }}") 52 | 53 | {% for lib in cmake.libs %} 54 | # Load the the extern library 55 | set ({{ lib.name }} ${CMAKE_SOURCE_DIR}/{{ lib.path }}/{{ lib.name }}.a) 56 | #add_library ({{ lib.name }} STATIC IMPORTED) 57 | #set_property ({{ lib.name }} PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/{{ lib.path }}/{{ lib.name }}.a) 58 | {% endfor %} 59 | 60 | # Generate the target 61 | add_executable (${CMAKE_PROJECT_NAME}.elf {% for src in cmake.files %} {{ '${' }}{{ src.var }}{{ '}' }} {% endfor %}) 62 | 63 | # Link the library to the target 64 | target_link_libraries (${CMAKE_PROJECT_NAME}.elf {% for lib in cmake.libs %} {{ lib.name }} {% endfor %}) 65 | 66 | # Generate the binary file 67 | add_custom_target (${CMAKE_PROJECT_NAME}.bin ALL arm-none-eabi-objcopy -Obinary "${EXECUTABLE_OUTPUT_PATH}/${CMAKE_PROJECT_NAME}.elf" "${EXECUTABLE_OUTPUT_PATH}/${CMAKE_PROJECT_NAME}.bin" DEPENDS ${EXECUTABLE_OUTPUT_PATH}/${CMAKE_PROJECT_NAME}.elf) 68 | 69 | # Generate the hex file 70 | add_custom_target (${CMAKE_PROJECT_NAME}.hex ALL arm-none-eabi-objcopy -Oihex "${EXECUTABLE_OUTPUT_PATH}/${CMAKE_PROJECT_NAME}.elf" "${EXECUTABLE_OUTPUT_PATH}/${CMAKE_PROJECT_NAME}.hex" DEPENDS ${EXECUTABLE_OUTPUT_PATH}/${CMAKE_PROJECT_NAME}.elf) 71 | 72 | # Echo the size Infomation 73 | add_custom_target (size ALL arm-none-eabi-size "${EXECUTABLE_OUTPUT_PATH}/${CMAKE_PROJECT_NAME}.elf" DEPENDS ${EXECUTABLE_OUTPUT_PATH}/${CMAKE_PROJECT_NAME}.elf) 74 | 75 | # Make flash to the board by st-link 76 | add_custom_target (flash COMMAND st-flash write ${EXECUTABLE_OUTPUT_PATH}/${CMAKE_PROJECT_NAME}.bin 0x8000000) 77 | 78 | # Make clean-all 79 | add_custom_target (clean-all COMMAND rm -rf ${CMAKE_BINARY_DIR}/*) 80 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | When contributing to this repository, please first discuss the change you wish to make via issue, 4 | email, or any other method with the owners of this repository before making a change. 5 | 6 | Please note we have a code of conduct, please follow it in all your interactions with the project. 7 | 8 | ## Pull Request Process 9 | 10 | 1. Ensure any install or build dependencies are removed before the end of the layer when doing a 11 | build. 12 | 2. Update the README.md with details of changes to the interface, this includes new environment 13 | variables, exposed ports, useful file locations and container parameters. 14 | 3. Increase the version numbers in any examples files and the README.md to the new version that this 15 | Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/). 16 | 4. You may merge the Pull Request in once you have the sign-off of two other developers, or if you 17 | do not have permission to do that, you may request the second reviewer to merge it for you. 18 | 19 | ## Code of Conduct 20 | 21 | ### Our Pledge 22 | 23 | In the interest of fostering an open and welcoming environment, we as 24 | contributors and maintainers pledge to making participation in our project and 25 | our community a harassment-free experience for everyone, regardless of age, body 26 | size, disability, ethnicity, gender identity and expression, level of experience, 27 | nationality, personal appearance, race, religion, or sexual identity and 28 | orientation. 29 | 30 | ### Our Standards 31 | 32 | Examples of behavior that contributes to creating a positive environment 33 | include: 34 | 35 | * Using welcoming and inclusive language 36 | * Being respectful of differing viewpoints and experiences 37 | * Gracefully accepting constructive criticism 38 | * Focusing on what is best for the community 39 | * Showing empathy towards other community members 40 | 41 | Examples of unacceptable behavior by participants include: 42 | 43 | * The use of sexualized language or imagery and unwelcome sexual attention or 44 | advances 45 | * Trolling, insulting/derogatory comments, and personal or political attacks 46 | * Public or private harassment 47 | * Publishing others' private information, such as a physical or electronic 48 | address, without explicit permission 49 | * Other conduct which could reasonably be considered inappropriate in a 50 | professional setting 51 | 52 | ### Our Responsibilities 53 | 54 | Project maintainers are responsible for clarifying the standards of acceptable 55 | behavior and are expected to take appropriate and fair corrective action in 56 | response to any instances of unacceptable behavior. 57 | 58 | Project maintainers have the right and responsibility to remove, edit, or 59 | reject comments, commits, code, wiki edits, issues, and other contributions 60 | that are not aligned to this Code of Conduct, or to ban temporarily or 61 | permanently any contributor for other behaviors that they deem inappropriate, 62 | threatening, offensive, or harmful. 63 | 64 | ### Scope 65 | 66 | This Code of Conduct applies both within project spaces and in public spaces 67 | when an individual is representing the project or its community. Examples of 68 | representing a project or community include using an official project e-mail 69 | address, posting via an official social media account, or acting as an appointed 70 | representative at an online or offline event. Representation of a project may be 71 | further defined and clarified by project maintainers. 72 | 73 | ### Enforcement 74 | 75 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 76 | reported by contacting the project team at [INSERT EMAIL ADDRESS]. All 77 | complaints will be reviewed and investigated and will result in a response that 78 | is deemed necessary and appropriate to the circumstances. The project team is 79 | obligated to maintain confidentiality with regard to the reporter of an incident. 80 | Further details of specific enforcement policies may be posted separately. 81 | 82 | Project maintainers who do not follow or enforce the Code of Conduct in good 83 | faith may face temporary or permanent repercussions as determined by other 84 | members of the project's leadership. 85 | 86 | ### Attribution 87 | 88 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 89 | available at [http://contributor-covenant.org/version/1/4][version] 90 | 91 | [homepage]: http://contributor-covenant.org 92 | [version]: http://contributor-covenant.org/version/1/4/ 93 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright 2020 Petr Hodina 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 | -------------------------------------------------------------------------------- /License.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017 Petr Hodina 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # Project converter for Embedded Projects 2 | 3 | A lot of Embedded Projects use proprietary IDEs and build processes. This make any CI/CD painful. Therefore these simple python scripts allow conversion of existing projects into CMake and corresponding linker file for GCC toolchain. Currently supported are *IAR's ewp* and *ARM's KEIL uvprojx* project formats. 4 | 5 | ## Module description 6 | 7 | - [cmake.py](cmake.py) - Cmake and linker file generation 8 | - [converter.py](converter.py) - Argument parsing 9 | - [ewpproject.py](ewpproject) - Parser for IAR's ewp file format 10 | - [uvprojx.py](uvprojx.py) - Parser for ARM's KEIL uvprojx file format 11 | 12 | ## Prerequisites 13 | 14 | Install `python3` on your system run: 15 | ```shell 16 | pip install Jinja2 17 | ``` 18 | 19 | ## Usage 20 | 21 | Run in output dir. 22 | 23 | Convert project from IAR: 24 | ``` 25 | python converter.py ewp 26 | ``` 27 | Convert project from ARM's KEIL: 28 | ``` 29 | python converter.py uvprojx 30 | ``` 31 | 32 | ## Contributing 33 | 34 | Please read [CONTRIBUTING.md](CONTRIBUTING.md) for details on our code of conduct, and the process for submitting pull requests to us. 35 | 36 | ## Versioning 37 | 38 | We use [SemVer](semver.org) for versioning. 39 | 40 | ## Authors 41 | 42 | - Petr Hodina - *Initial work* 43 | 44 | ## License 45 | 46 | The project is licensed under the [Apache License v2.0](https://www.apache.org/licenses/LICENSE-2.0) - see the [LICENSE.md](LICENSE.md) file for details. 47 | 48 | ## TODO 49 | - [ ] Package as python module and publish it 50 | - [ ] Seperate templates into submodule 51 | - [ ] Support generation of Makefile 52 | - [ ] Support additional compilers 53 | - [ ] Test on MAC OSX 54 | - [ ] Arg to specify build directory 55 | - [ ] Add Tests 56 | -------------------------------------------------------------------------------- /STM32FLASH.ld: -------------------------------------------------------------------------------- 1 | /* 2 | ***************************************************************************** 3 | ** 4 | 5 | ** File : LinkerScript.ld 6 | ** 7 | ** Abstract : Linker script for STM32F030R8Tx Device with 8 | ** 64KByte FLASH, 8KByte RAM 9 | ** 10 | ** Set heap size, stack size and stack location according 11 | ** to application requirements. 12 | ** 13 | ** Set memory bank area and size if external memory is used. 14 | ** 15 | ** Target : STMicroelectronics STM32 16 | ** 17 | ** 18 | ** Distribution: The file is distributed as is, without any warranty 19 | ** of any kind. 20 | ** 21 | ***************************************************************************** 22 | ** @attention 23 | ** 24 | **

© COPYRIGHT(c) 2014 Ac6

25 | ** 26 | ** Redistribution and use in source and binary forms, with or without modification, 27 | ** are permitted provided that the following conditions are met: 28 | ** 1. Redistributions of source code must retain the above copyright notice, 29 | ** this list of conditions and the following disclaimer. 30 | ** 2. Redistributions in binary form must reproduce the above copyright notice, 31 | ** this list of conditions and the following disclaimer in the documentation 32 | ** and/or other materials provided with the distribution. 33 | ** 3. Neither the name of Ac6 nor the names of its contributors 34 | ** may be used to endorse or promote products derived from this software 35 | ** without specific prior written permission. 36 | ** 37 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 38 | ** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 39 | ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 40 | ** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 41 | ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 42 | ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 43 | ** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 44 | ** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 45 | ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 46 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 47 | ** 48 | ***************************************************************************** 49 | */ 50 | 51 | /* Entry Point */ 52 | ENTRY(Reset_Handler) 53 | 54 | /* Highest address of the user mode stack */ 55 | _estack = 0x20002000; /* end of RAM */ 56 | /* Generate a link error if heap and stack don't fit into RAM */ 57 | _Min_Heap_Size = 0x200; /* required amount of heap */ 58 | _Min_Stack_Size = 0x400; /* required amount of stack */ 59 | 60 | /* Specify the memory areas */ 61 | MEMORY 62 | { 63 | FLASH (rx) : ORIGIN = 0x8000000, LENGTH = {{ flash }}K 64 | RAM (xrw) : ORIGIN = 0x20000000, LENGTH = {{ ram }}K 65 | } 66 | 67 | /* Define output sections */ 68 | SECTIONS 69 | { 70 | /* The startup code goes first into FLASH */ 71 | .isr_vector : 72 | { 73 | . = ALIGN(4); 74 | KEEP(*(.isr_vector)) /* Startup code */ 75 | . = ALIGN(4); 76 | } >FLASH 77 | 78 | /* The program code and other data goes into FLASH */ 79 | .text : 80 | { 81 | . = ALIGN(4); 82 | *(.text) /* .text sections (code) */ 83 | *(.text*) /* .text* sections (code) */ 84 | *(.glue_7) /* glue arm to thumb code */ 85 | *(.glue_7t) /* glue thumb to arm code */ 86 | *(.eh_frame) 87 | 88 | KEEP (*(.init)) 89 | KEEP (*(.fini)) 90 | 91 | . = ALIGN(4); 92 | _etext = .; /* define a global symbols at end of code */ 93 | } >FLASH 94 | 95 | /* Constant data goes into FLASH */ 96 | .rodata : 97 | { 98 | . = ALIGN(4); 99 | *(.rodata) /* .rodata sections (constants, strings, etc.) */ 100 | *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ 101 | . = ALIGN(4); 102 | } >FLASH 103 | 104 | .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH 105 | .ARM : { 106 | __exidx_start = .; 107 | *(.ARM.exidx*) 108 | __exidx_end = .; 109 | } >FLASH 110 | 111 | .preinit_array : 112 | { 113 | PROVIDE_HIDDEN (__preinit_array_start = .); 114 | KEEP (*(.preinit_array*)) 115 | PROVIDE_HIDDEN (__preinit_array_end = .); 116 | } >FLASH 117 | .init_array : 118 | { 119 | PROVIDE_HIDDEN (__init_array_start = .); 120 | KEEP (*(SORT(.init_array.*))) 121 | KEEP (*(.init_array*)) 122 | PROVIDE_HIDDEN (__init_array_end = .); 123 | } >FLASH 124 | .fini_array : 125 | { 126 | PROVIDE_HIDDEN (__fini_array_start = .); 127 | KEEP (*(SORT(.fini_array.*))) 128 | KEEP (*(.fini_array*)) 129 | PROVIDE_HIDDEN (__fini_array_end = .); 130 | } >FLASH 131 | 132 | /* used by the startup to initialize data */ 133 | _sidata = LOADADDR(.data); 134 | 135 | /* Initialized data sections goes into RAM, load LMA copy after code */ 136 | .data : 137 | { 138 | . = ALIGN(4); 139 | _sdata = .; /* create a global symbol at data start */ 140 | *(.data) /* .data sections */ 141 | *(.data*) /* .data* sections */ 142 | 143 | . = ALIGN(4); 144 | _edata = .; /* define a global symbol at data end */ 145 | } >RAM AT> FLASH 146 | 147 | 148 | /* Uninitialized data section */ 149 | . = ALIGN(4); 150 | .bss : 151 | { 152 | /* This is used by the startup in order to initialize the .bss secion */ 153 | _sbss = .; /* define a global symbol at bss start */ 154 | __bss_start__ = _sbss; 155 | *(.bss) 156 | *(.bss*) 157 | *(COMMON) 158 | 159 | . = ALIGN(4); 160 | _ebss = .; /* define a global symbol at bss end */ 161 | __bss_end__ = _ebss; 162 | } >RAM 163 | 164 | /* User_heap_stack section, used to check that there is enough RAM left */ 165 | ._user_heap_stack : 166 | { 167 | . = ALIGN(8); 168 | PROVIDE ( end = . ); 169 | PROVIDE ( _end = . ); 170 | . = . + _Min_Heap_Size; 171 | . = . + _Min_Stack_Size; 172 | . = ALIGN(8); 173 | } >RAM 174 | 175 | 176 | 177 | /* Remove information from the standard libraries */ 178 | /DISCARD/ : 179 | { 180 | libc.a ( * ) 181 | libm.a ( * ) 182 | libgcc.a ( * ) 183 | } 184 | 185 | .ARM.attributes 0 : { *(.ARM.attributes) } 186 | } 187 | 188 | 189 | -------------------------------------------------------------------------------- /cmake.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ CMake generation module 4 | @file 5 | """ 6 | 7 | import os 8 | import platform 9 | import datetime 10 | from jinja2 import Environment, FileSystemLoader 11 | 12 | class CMake (object): 13 | 14 | def __init__(self, project, path): 15 | 16 | self.path = path 17 | self.project = project 18 | self.context = {} 19 | 20 | def populateCMake (self): 21 | """ Generate CMakeList.txt file for building the project 22 | """ 23 | 24 | # For debug run cmake -DCMAKE_BUILD_TYPE=Debug or Release 25 | cmake = {} 26 | #fpu = '-mfpu=fpv5-sp-d16 -mfloat-abi=softfp' 27 | fpu = '' 28 | 29 | core = '' 30 | 31 | if 'STM32F0' in self.project['chip']: 32 | core = '-mcpu=cortex-m0' 33 | elif 'STM32F1' in self.project['chip']: 34 | core = '-mcpu=cortex-m3' 35 | elif 'STM32F2' in self.project['chip']: 36 | core = '-mcpu=cortex-m3' 37 | elif 'STM32F3' in self.project['chip']: 38 | core = '-mcpu=cortex-m4' 39 | elif 'STM32F4' in self.project['chip']: 40 | core = '-mcpu=cortex-m4' 41 | elif 'STM32F7' in self.project['chip']: 42 | core = '-mcpu=cortex-m7' 43 | elif 'STM32L0' in self.project['chip']: 44 | core = '-mcpu=cortex-m0plus' 45 | elif 'STM32L1' in self.project['chip']: 46 | core = '-mcpu=cortex-m3' 47 | elif 'STM32L4' in self.project['chip']: 48 | core = '-mcpu=cortex-m4' 49 | 50 | cmake['version'] = '3.1' 51 | cmake['project'] = self.project['name'] 52 | cmake['incs'] = [] 53 | for inc in self.project['incs']: 54 | cmake['incs'].append(inc) 55 | cmake['srcs'] = [] 56 | 57 | i=0 58 | 59 | cmake['files']=[] 60 | cmake['ass']=[] 61 | 62 | for file in self.project['srcs']: 63 | if file.endswith('.c') or file.endswith('.h') or file.endswith('.cpp'): 64 | cmake['files'].append({'path': file,'var':'SRC_FILE' + str(i)}) 65 | i = i+1 66 | 67 | for file in self.project['files']: 68 | print ('Assembly added ' + file) 69 | cmake['ass'].append({'path': file}) 70 | cmake['files'].append({'path': file,'var':'SRC_FILE' + str(i)}) 71 | i = i+1 72 | 73 | cmake['cxx'] = 'false' 74 | 75 | cmake['c_flags'] = '-g -Wextra -Wshadow -Wimplicit-function-declaration -Wredundant-decls -Wmissing-prototypes -Wstrict-prototypes -fno-common -ffunction-sections -fdata-sections -MD -Wall -Wundef -mthumb ' + core + ' ' + fpu 76 | 77 | cmake['cxx_flags'] = '-Wextra -Wshadow -Wredundant-decls -Weffc++ -fno-common -ffunction-sections -fdata-sections -MD -Wall -Wundef -mthumb ' + core + ' ' + fpu 78 | 79 | cmake['asm_flags'] = '-g -mthumb ' + core + ' ' + fpu #+ ' -x assembler-with-cpp' 80 | cmake['linker_flags'] = '-g -Wl,--gc-sections -Wl,-Map=' + cmake['project'] + '.map -mthumb ' + core + ' ' + fpu 81 | cmake['linker_script'] = 'STM32FLASH.ld' 82 | cmake['linker_path'] = '' 83 | 84 | self.linkerScript('STM32FLASH.ld',os.path.join(self.path,'STM32FLASH.ld')) 85 | 86 | cmake['oocd_target'] = 'stm32f3x' 87 | cmake['defines'] = [] 88 | for define in self.project['defs']: 89 | cmake['defines'].append(define) 90 | 91 | cmake['libs'] = [] 92 | 93 | self.context['cmake'] = cmake 94 | 95 | abspath = os.path.abspath(os.path.join(self.path,'CMakeLists.txt')) 96 | self.generateFile('CMakeLists.txt', abspath) 97 | 98 | print ('Created file CMakeLists.txt [{}]'.format(abspath)) 99 | 100 | # def generateFile (self, pathSrc, pathDst='', author='Pegasus', version='v1.0.0', licence='licence.txt', template_dir='../PegasusTemplates'): 101 | def generateFile (self, pathSrc, pathDst='', author='Pegasus', version='v1.0.0', licence='licence.txt', template_dir='.'): 102 | 103 | if (pathDst == ''): 104 | pathDst = pathSrc 105 | 106 | self.context['file'] = os.path.basename(str(pathSrc)) 107 | self.context['author'] = author 108 | self.context['date'] = datetime.date.today().strftime('%d, %b %Y') 109 | self.context['version'] = version 110 | self.context['licence'] = licence 111 | 112 | env = Environment(loader=FileSystemLoader(template_dir),trim_blocks=True,lstrip_blocks=True) 113 | template = env.get_template(str(pathSrc)) 114 | 115 | generated_code = template.render(self.context) 116 | 117 | if platform.system() == 'Windows': 118 | 119 | with open(pathDst, 'w') as f: 120 | f.write(generated_code) 121 | 122 | elif platform.system() == 'Linux': 123 | 124 | with open(pathDst, 'w') as f: 125 | f.write(generated_code) 126 | else: 127 | # Different OS than Windows or Linux 128 | pass 129 | 130 | def linkerScript(self,pathSrc, pathDst='',template_dir='.'): 131 | # def linkerScript(self,pathSrc, pathDst='',template_dir='.../PegasusTemplates'): 132 | 133 | if (pathDst == ''): 134 | pathDst = pathSrc 135 | 136 | self.context['file'] = os.path.basename(str(pathSrc)) 137 | self.context['flash'] = '64' 138 | self.context['ram'] = '8' 139 | 140 | env = Environment(loader=FileSystemLoader(template_dir),trim_blocks=True,lstrip_blocks=True) 141 | template = env.get_template(str(pathSrc)) 142 | 143 | generated_code = template.render(self.context) 144 | 145 | if platform.system() == 'Windows': 146 | 147 | with open(pathDst, 'w') as f: 148 | f.write(generated_code) 149 | 150 | elif platform.system() == 'Linux': 151 | 152 | with open(pathDst, 'w') as f: 153 | f.write(generated_code) 154 | else: 155 | # Different OS than Windows or Linux 156 | pass 157 | 158 | 159 | -------------------------------------------------------------------------------- /converter.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ Entry point for project conversion 4 | @file 5 | """ 6 | 7 | import os 8 | import argparse 9 | import cmake 10 | import ewpproject 11 | import uvprojxproject 12 | 13 | def find_file(path, fileext): 14 | """ Find file with extension in path 15 | @param path Root path of the project 16 | @param fileext File extension to find 17 | @return File name 18 | """ 19 | filename = '' 20 | for root, dirs, files in os.walk(path): 21 | for file in files: 22 | if file.endswith(fileext): 23 | filename = os.path.join(root, file) 24 | return filename 25 | 26 | if __name__ == '__main__': 27 | """ Parses params and calls the right conversion""" 28 | 29 | parser = argparse.ArgumentParser() 30 | parser.add_argument("format", choices=("ewp", "uvprojx")) 31 | parser.add_argument("path", type=str, help="Root directory of project") 32 | #"--ewp", help="Search for *.EWP file in project structure", action='store_true') 33 | #parser.add_argument("--uvprojx", help="Search for *.UPROJX file in project structure", action='store_true') 34 | args = parser.parse_args() 35 | 36 | if os.path.isdir(args.path): 37 | if args.format == 'ewp': 38 | print('Looking for *.ewp file in ' + args.path) 39 | filename = find_file(args.path, '.ewp') 40 | if len(filename): 41 | print('Found project file: ' + filename) 42 | project = ewpproject.EWPProject(args.path, filename) 43 | project.parseProject() 44 | project.displaySummary() 45 | cmakefile = cmake.CMake(project.getProject(), args.path) 46 | cmakefile.populateCMake() 47 | else: 48 | print('No project *.ewp file found') 49 | elif args.format == 'uvprojx': 50 | print('Looking for *.uvprojx file in ' + args.path) 51 | filename = find_file(args.path, '.uvprojx') 52 | if len(filename): 53 | print('Found project file: ' + filename) 54 | project = uvprojxproject.UVPROJXProject(args.path, filename) 55 | project.parseProject() 56 | project.displaySummary() 57 | 58 | cmakefile = cmake.CMake(project.getProject(), args.path) 59 | cmakefile.populateCMake() 60 | else: 61 | print('No project *.uvprojx file found') 62 | else: 63 | print ('No format specified') 64 | else: 65 | print('Not a valid file path') 66 | -------------------------------------------------------------------------------- /ewpproject.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ Module for converting EWP project format file 4 | @file 5 | """ 6 | 7 | import os 8 | from lxml import objectify 9 | 10 | 11 | class EWPProject(object): 12 | """ Class for converting EWP project format file 13 | """ 14 | 15 | def __init__(self, path, xmlFile): 16 | self.project = {} 17 | self.path = path 18 | self.xmlFile = xmlFile 19 | xmltree = objectify.parse(xmlFile) 20 | self.root = xmltree.getroot() 21 | 22 | def parseProject(self): 23 | """ Parses EWP project file for project settings 24 | """ 25 | self.project['name'] = self.root.configuration.name 26 | self.project['chip'] = '' 27 | 28 | #TODO: parse into tree structure 29 | self.project['srcs'] = [] 30 | self.searchGroups(self.root, self.project['srcs']) 31 | 32 | self.project['defs'] = [] 33 | self.project['incs'] = [] 34 | 35 | for element in self.root.configuration.getchildren(): 36 | if element.tag == 'settings': 37 | for e in element.data.getchildren(): 38 | if e.tag == 'option': 39 | if e.name.text == 'OGChipSelectEditMenu': 40 | self.project['chip'] = str(e.state) 41 | elif e.name.text == 'CCDefines': 42 | for d in e.getchildren(): 43 | if d.tag == 'state' and d.text != None: 44 | self.project['defs'].append(d.text) 45 | elif e.name.text == 'CCIncludePath2': 46 | for d in e.getchildren(): 47 | if d.tag == 'state' and d.text != None: 48 | self.project['incs'].append(d.text) 49 | 50 | for i in range(0, len(self.project['incs'])): 51 | s = str(self.project['incs'][i]) 52 | if os.path.sep not in s: 53 | if os.path.sep == '\\': 54 | s = s.replace('/', '\\') 55 | elif os.path.sep == '/': 56 | s = s.replace('\\', '/') 57 | 58 | self.project['incs'][i] = s.replace('$PROJ_DIR$'+os.path.sep+'..', self.path) 59 | 60 | self.project['files'] = [] 61 | i = 0 62 | 63 | if os.path.exists(self.path + '/Drivers/CMSIS/Device/ST/STM32F3xx/Source/Templates/gcc'): 64 | for entry in os.listdir(self.path + '/Drivers/CMSIS/Device/ST/STM32F3xx/Source/Templates/gcc'): 65 | if entry.endswith('.S') or entry.endswith('.s'): 66 | self.project['files'].append(self.path + '/Drivers/CMSIS/Device/ST/STM32F3xx/Source/Templates/gcc/'+entry) 67 | 68 | def displaySummary(self): 69 | """ Display summary of parsed project settings 70 | """ 71 | print('Project Name:' + self.project['name']) 72 | print('Project chip:' + self.project['chip']) 73 | print('Project includes: ' + ' '.join(self.project['incs'])) 74 | print('Project defines: ' + ' '.join(self.project['defs'])) 75 | print('Project srcs: ' + ' '.join(self.project['srcs'])) 76 | 77 | def searchGroups(self, xml, sources): 78 | """ Display summary of parsed project settings 79 | @param xml XML file with project settings configuration 80 | @param sources List containing source files 81 | """ 82 | for element in xml.getchildren(): 83 | if element.tag == 'group': 84 | self.searchGroups(element, sources) 85 | elif element.tag == 'file': 86 | if not str(element.name).endswith('.s'): 87 | s = str(element.name) 88 | if os.path.sep not in s: 89 | if os.path.sep == '\\': 90 | s = s.replace('/', '\\') 91 | elif os.path.sep == '/': 92 | s = s.replace('\\', '/') 93 | 94 | sources.append(s.replace('$PROJ_DIR$'+os.path.sep+'..', self.path)) 95 | 96 | def getProject(self): 97 | """ Return parsed project settings stored as dictionary 98 | @return Dictionary containing project settings 99 | """ 100 | return self.project 101 | -------------------------------------------------------------------------------- /uvprojxproject.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ Module for converting UVPROJX project format file 4 | @file 5 | """ 6 | 7 | import os 8 | from lxml import objectify 9 | 10 | class UVPROJXProject(object): 11 | """ Class for converting UVPROJX project format file 12 | """ 13 | 14 | def __init__(self, path, xmlFile): 15 | self.path = path 16 | self.project = {} 17 | self.xmlFile = xmlFile 18 | xmltree = objectify.parse(xmlFile) 19 | self.root = xmltree.getroot() 20 | 21 | def parseProject(self): 22 | """ Parses EWP project file for project settings 23 | """ 24 | self.project['name'] = self.root.Targets.Target.TargetName 25 | self.project['chip'] = str(self.root.Targets.Target.TargetOption.TargetCommonOption.Device) 26 | self.project['incs'] = self.root.Targets.Target.TargetOption.TargetArmAds.Cads.VariousControls.IncludePath.text.split(';') 27 | self.project['mems'] = self.root.Targets.Target.TargetOption.TargetCommonOption.Cpu 28 | self.project['defs'] = self.root.Targets.Target.TargetOption.TargetArmAds.Cads.VariousControls.Define.text.split(',') 29 | self.project['srcs'] = [] 30 | 31 | for element in self.root.Targets.Target.Groups.getchildren(): 32 | print('GroupName: ' + element.GroupName.text) 33 | if hasattr(element, 'Files'): 34 | for file in element.Files.getchildren(): 35 | if not str(file.FilePath.text).endswith('.s'): 36 | s = str(file.FilePath.text) 37 | if os.path.sep not in s: 38 | if os.path.sep == '\\': 39 | s = s.replace('/', '\\') 40 | elif os.path.sep == '/': 41 | s = s.replace('\\', '/') 42 | self.project['srcs'].append(s.replace('..', self.path, 1)) 43 | 44 | for i in range(0, len(self.project['incs'])): 45 | s = str(self.project['incs'][i]) 46 | if os.path.sep not in s: 47 | if os.path.sep == '\\': 48 | s = s.replace('/', '\\') 49 | elif os.path.sep == '/': 50 | s = s.replace('\\', '/') 51 | 52 | self.project['incs'][i] = s.replace('..', self.path, 1) 53 | 54 | self.project['files'] = [] 55 | i = 0 56 | 57 | if os.path.exists(self.path + '/Drivers/CMSIS/Device/ST/STM32F3xx/Source/Templates/gcc'): 58 | for entry in os.listdir(self.path + '/Drivers/CMSIS/Device/ST/STM32F3xx/Source/Templates/gcc'): 59 | if entry.endswith('.S') or entry.endswith('.s'): 60 | self.project['files'].append(self.path + '/Drivers/CMSIS/Device/ST/STM32F3xx/Source/Templates/gcc/'+ entry) 61 | 62 | def displaySummary(self): 63 | """ Display summary of parsed project settings 64 | """ 65 | print('Project Name:' + self.project['name']) 66 | print('Project chip:' + self.project['chip']) 67 | print('Project includes: ' + ' '.join(self.project['incs'])) 68 | print('Project defines: ' + ' '.join(self.project['defs'])) 69 | print('Project srcs: ' + ' '.join(self.project['srcs'])) 70 | print('Project: ' + self.project['mems']) 71 | 72 | def getProject(self): 73 | """ Return parsed project settings stored as dictionary 74 | @return Dictionary containing project settings 75 | """ 76 | return self.project 77 | --------------------------------------------------------------------------------