Skip to content

Commit

Permalink
[porting] Add docs and scripts for porting from xpcc
Browse files Browse the repository at this point in the history
  • Loading branch information
salkinium committed Jun 23, 2018
1 parent 0778699 commit 4ae989e
Show file tree
Hide file tree
Showing 3 changed files with 467 additions and 0 deletions.
98 changes: 98 additions & 0 deletions docs/porting_xpcc_to_modm.md
@@ -0,0 +1,98 @@
# Porting xpcc projects to modm

modm is the direct successor to xpcc and fully replaces it. xpcc is declared deprecated on the 2018q2 release and the repository is archived on the 2018q4 release. We‘ve already manually forward ported all changes to modm and will continue to do so, however, we‘d appreciate it if you contributed to modm directly from now on.

This porting guide is kept up-to-date for the state of xpcc and modm until the 2018q4 release. modm will then take over the quarterly release schedule from xpcc. If you want to port to a newer modm release, we recommend first porting to the modm 2018q4 release as described in this guide, then refactoring your code using the modm Changelog to be compatible with the latest modm release.

modm‘s largest improvement over xpcc is its generic way of generating the HAL by using the explicit code generation capabilities of lbuild. In xpcc this was hacked into the SCons build system, and was very unintuitive to use and extend.
Instead, modm now is a *library generator*, introducing an explicit code generation step *before* compilation. You provide lbuild with a configuration file containing the library options (what modules you want for what target) and lbuild will then create a specific modm library for your project. You can even choose what build system you would like to use (at the time of writing: SCons or CMake) or just use your own, since the generated library is build system agnostic.
Please read the section on [How modm works](https://modm.io/how-modm-works/) for more details on this process.

This is very different from xpcc, where the generated sources where implicitly generated somewhere in the build directory and you were forced to use SCons for building.
In modm we want you to be aware of the generated sources, so you are encouraged to commit the generated modm library and build system into your project VCS.
This will also make it easier to review what has changed when you upgrade modm.

We decided to change the name to modm (Modular Object-oriented Development for
Microcontrollers) to resolve the confusion when talking about the XPCC (Cross Platform Component Communication) protocol (the RPC implementation we use inside our robots) versus the xpcc framework, which was initially build around this protocol, but since then became much more generic.


## Changes

We‘ve created a Python3 script to automate as much of the refactoring as possible.
It will rewrite the source code in the folders you provide as arguments.
If a `project.cfg` file is present, it will translate this to a `project.xml` file,
otherwise it'll output the detected modm modules on the command line.

```sh
python3 /path/to/modm/tools/scripts/xpcc_porting.py src_folder ../other/src/folders
```

However, this script may not have enough information in the sources to port
everything, so please read on to see what you still need to fix manually.

modm continues to support AVR and STM32 targets as well as all three major desktop operating systems. However, support for LPC, Xmega and some custom STM32 boards has been removed.
**Please note that STM32 device identifiers in modm have an additional character denoting the package id!** You must provide this information, the porting script does not have enough information.

modm has been grouped into small modules which allows for a more fine-grained library generation with fewer files that are not needed. This meant adding one `*.lb` file for every module and sometimes a few `*.md` files for documentation.

We are now using a simpler collection of SCons tools maintained by the DLR.
We‘ve integrated it so that the main SCons commands are the same, however, some tools have not been ported or have a different feature set than before.

### API changes

Apart from the code generation changes in lbuild there are also a number of breaking code changes. modm is still very much continuing the C++ concepts laid out in xpcc, however, modm is not a drop-in replacement, so you will have to refactor your projects.

#### Namespaces

In parallel to changing the libraries name, we‘ve also changed the top-level namespace to `modm`, EXCEPT for the XPCC protocol, which remains in namespace `xpcc`.

The target specific namespaces have been renamed from `modm::{at90, attiny, atmega, xmega, stm32}` to simply `modm::platform`. This namespace contains all classes that are specific to the target and should not be used platform-independent code (use the interfaces classes instead).

The remaining sub-namespaces have not been altered.

#### Includes

All modm specific include paths now start with `modm` not `xpcc`.
`#include <xpcc/header.hpp>` becomes `#include <modm/header.hpp>`.

The `<modm/architecture.hpp>` header does NOT include `<modm/platform.hpp>`, so you may have to change that manually if the platform classes are not found.
When using modm-provided BSP header, you need to `#include <modm/board.hpp>` instead, which includes the platform headers too.

#### Preprocessor

All preprocessor definitions were refactored to be prefixed with either `MODM_` or `modm_`.
All double underscores between defines `WORD__WORD` were replaced by single underscores `WORD_WORD`.

#### GPIOs

The entire GPIO implementation has been rewritten from scratch for modm. We‘ve encountered several issues about the xpcc implementation that we could only solve with the much more accurate data of modm-devices and more generic code generation capabilities of lbuild.

The main issue was that the signal connector API `Gpio::connect(Signal);` was not able to map to group signal remaps as used in the Xmega and STM32F1 targets. Furthermore, the signal naming did not reflect the Datasheet naming, and its implemention was dependent on the peripheral driver code.

In modm the connect method is part of the peripheral driver and gets passed a number of pins-signal pairs in independent order: `Uart::connect<GpioD0::Tx, GpioD1::Rx>();`. This allows to check for group remap conflicts at compile time.
In addition, the peripheral driver can configure the pins as needed by the interface.
In this implementation, the peripheral connect method is just a wrapper for convenience, the GPIO implementation does not depend on any peripheral drivers, so it can be used on its own. See [these issues for some details]().

GPIO ports have been rewritten as well to be more efficient, however the code is backwards compatible with the exception of `DataOrder::Reverse` for `GpioPort`, which is now done with a negative index instead: `GpioPort<GpioC7, -8>`. However, this feature was very rarely if ever used. See PR #12 for details.

Classes like `GpioUnused` and `GpioInverted` have been moved into `namespace modm::platform`.

### External code

External code (in `ext/`) is now managed via git submodules, so you need to clone modm recursively! We‘ve taken care to minimize the size of these modules, for some very large repositories (CMSIS, CubeHAL), we‘ve extracted the relevant sources into our own, much smaller repositories.

### Folder structure

A number of folders and files were moved, created or deleted:

- `src/xpcc` -> `src/modm`.
- `src/modm/architecture/platform/drivers` -> `src/modm/platform`.
- `src/modm/architecture/platform/board` -> `src/modm/board`.
- `src/modm/architecture/platform/devices` replaced by the `ext/modm-devices` submodule.
- `src/tools/device_file*` have been moved to the modm-devices project.

All the distributed `test/` folders containing unit tests were moved to `test/modm` with the same relative folder structure.

### Testing

The testing system has been refactored to use the modularized modm. It is now simpler to use than before. Additionally, you can compile modm for all supported targets now. See the [modm guide on testing for details](https://modm.io/guide/testing).
136 changes: 136 additions & 0 deletions tools/scripts/modm_modules.py
@@ -0,0 +1,136 @@
modm_modules = [
(r"modm/architecture.*", r"modm:architecture"),
(r"modm/architecture/interface\.hpp", r"modm:architecture"),
(r"modm/architecture/interface/accessor.*", r"modm:architecture:accessor"),
(r"modm/architecture/interface/adc.*", r"modm:architecture:adc"),
(r"modm/architecture/interface/assert.*", r"modm:architecture:assert"),
(r"modm/architecture/interface/atomic.*", r"modm:architecture:atomic"),
(r"modm/architecture/interface/block_device.*", r"modm:architecture:block.device"),
(r"modm/architecture/interface/can.*", r"modm:architecture:can"),
(r"modm/architecture/interface/clock.*", r"modm:architecture:clock"),
(r"modm/architecture/interface/delay.*", r"modm:architecture:delay"),
(r"modm/architecture/interface/gpio.*", r"modm:architecture:gpio"),
(r"modm/architecture/interface/gpio_expander.*", r"modm:architecture:gpio.expander"),
(r"modm/architecture/interface/i2c\.hpp", r"modm:architecture:i2c"),
(r"modm/architecture/interface/i2c_device.*", r"modm:architecture:i2c.device"),
(r"modm/architecture/interface/i2c_master.*", r"modm:architecture:i2c"),
(r"modm/architecture/interface/i2c_transaction.*", r"modm:architecture:i2c"),
(r"modm/architecture/interface/interrupt.*", r"modm:architecture:interrupt"),
(r"modm/architecture/interface/memory.*", r"modm:architecture:memory"),
(r"modm/architecture/interface/one_wire.*", r"modm:architecture:1-wire"),
(r"modm/architecture/interface/register.*", r"modm:architecture:register"),
(r"modm/architecture/interface/spi\.hpp", r"modm:architecture:spi"),
(r"modm/architecture/interface/spi_device.*", r"modm:architecture:spi.device"),
(r"modm/architecture/interface/spi_master.*", r"modm:architecture:spi"),
(r"modm/architecture/interface/uart.*", r"modm:architecture:uart"),
(r"modm/architecture/interface/unaligned.*", r"modm:architecture:unaligned"),
(r"modm/communication/ros.*", r"modm:communication:ros"),
(r"modm/communication/sab.*", r"modm:communication:sab"),
(r"modm/communication/xpcc.*", r"modm:communication:xpcc"),
(r"modm/container.*", r"modm:container"),
(r"modm/debug.*", r"modm:debug"),
(r"modm/driver/adc/ad7280a\.hpp", r"modm:driver:ad7280a"),
(r"modm/driver/adc/ad7928\.hpp", r"modm:driver:ad7928"),
(r"modm/driver/adc/adc_sampler\.hpp", r"modm:driver:adc_sampler"),
(r"modm/driver/bus/bitbang_memory_interface\.hpp", r"modm:driver:memory_bus"),
(r"modm/driver/bus/tft_memory_bus\.hpp", r"modm:driver:memory_bus"),
(r"modm/driver/can/can_lawicel_formatter\.hpp", r"modm:driver:lawicel"),
(r"modm/driver/can/mcp2515.*", r"modm:driver:mcp2515"),
(r"modm/driver/color/tcs3414\.hpp", r"modm:driver:tcs3414"),
(r"modm/driver/color/tcs3472\.hpp", r"modm:driver:tcs3472"),
(r"modm/driver/display/ea_dog\.hpp", r"modm:driver:ea_dog"),
(r"modm/driver/display/hd44780.*", r"modm:driver:hd44780"),
(r"modm/driver/display/max7219matrix\.hpp", r"modm:driver:max7219"),
(r"modm/driver/display/nokia5110\.hpp", r"modm:driver:nokia5110"),
(r"modm/driver/display/parallel_tft\.hpp", r"modm:driver:parallel_tft_display"),
(r"modm/driver/display/siemens_s65\.hpp", r"modm:driver:siemens_s65"),
(r"modm/driver/display/siemens_s75\.hpp", r"modm:driver:siemens_s75"),
(r"modm/driver/display/ssd1306\.hpp", r"modm:driver:ssd1306"),
(r"modm/driver/display/st7.*", r"modm:driver:ea_dog"),
(r"modm/driver/gpio/mcp23.*", r"modm:driver:mcp23x17"),
(r"modm/driver/gpio/pca8574\.hpp", r"modm:driver:pca8574"),
(r"modm/driver/gpio/pca9535\.hpp", r"modm:driver:pca9535"),
(r"modm/driver/inertial/hmc58.*", r"modm:driver:hmc58x"),
(r"modm/driver/inertial/hmc6343\.hpp", r"modm:driver:hmc6343"),
(r"modm/driver/inertial/itg3200\.hpp", r"modm:driver:itg3200"),
(r"modm/driver/inertial/l3gd20\.hpp", r"modm:driver:l3gd20"),
(r"modm/driver/inertial/lis302dl\.hpp", r"modm:driver:lis302dl"),
(r"modm/driver/inertial/lis3_transport\.hpp", r"modm:driver:lis3.transport"),
(r"modm/driver/inertial/lis3dsh\.hpp", r"modm:driver:lis3dsh"),
(r"modm/driver/inertial/lsm303a\.hpp", r"modm:driver:lsm303a"),
(r"modm/driver/motion/adns9800.*", r"modm:driver:adns9800"),
(r"modm/driver/motor/drv832x_spi\.hpp", r"modm:driver:drv832x_spi"),
(r"modm/driver/position/vl53l0\.hpp", r"modm:driver:vl53l0"),
(r"modm/driver/position/vl6180\.hpp", r"modm:driver:vl6180"),
(r"modm/driver/pressure/amsys5915\.hpp", r"modm:driver:amsys5915"),
(r"modm/driver/pressure/bme280.*", r"modm:driver:bme280"),
(r"modm/driver/pressure/bmp085.*", r"modm:driver:bmp085"),
(r"modm/driver/pressure/hclax\.hpp", r"modm:driver:hclax"),
(r"modm/driver/pwm/max6966\.hpp", r"modm:driver:max6966"),
(r"modm/driver/pwm/pca9685\.hpp", r"modm:driver:pca9685"),
(r"modm/driver/pwm/ws2812b\.hpp", r"modm:driver:ws2812"),
(r"modm/driver/radio/nrf24.*", r"modm:driver:nrf24"),
(r"modm/driver/rtc/ds1302\.hpp", r"modm:driver:ds1302"),
(r"modm/driver/storage/block_device_heap\.hpp", r"modm:driver:block.device:heap"),
(r"modm/driver/storage/block_device_mirror\.hpp", r"modm:driver:block.device:mirror"),
(r"modm/driver/storage/block_device_spiflash\.hpp", r"modm:driver:block.device:spi.flash"),
(r"modm/driver/storage/fat\.hpp", r"modm:driver:fat"),
(r"modm/driver/storage/i2c_eeprom\.hpp", r"modm:driver:i2c.eeprom"),
(r"modm/driver/temperature/ds1631\.hpp", r"modm:driver:ds1631"),
(r"modm/driver/temperature/ds18b20\.hpp", r"modm:driver:ds18b20"),
(r"modm/driver/temperature/lm75\.hpp", r"modm:driver:lm75"),
(r"modm/driver/temperature/ltc2984\.hpp", r"modm:driver:ltc2984"),
(r"modm/driver/temperature/tmp102\.hpp", r"modm:driver:tmp102"),
(r"modm/driver/temperature/tmp175\.hpp", r"modm:driver:tmp175"),
(r"modm/driver/touch/ads7843\.hpp", r"modm:driver:ads7843"),
(r"modm/driver/touch/ft6x06\.hpp", r"modm:driver:ft6x06"),
(r"modm/driver/usb/ft245\.hpp", r"modm:driver:ft245"),
(r"modm/io.*", r"modm:io"),
(r"modm/math/filter.*", r"modm:math:filter"),
(r"modm/math/geometry.*", r"modm:math:geometry"),
(r"modm/math/interpolation.*", r"modm:math:interpolation"),
(r"modm/math/lu_decomposition\.hpp", r"modm:math:matrix"),
(r"modm/math/matrix\.hpp", r"modm:math:matrix"),
(r"modm/math/saturated/saturated\.hpp", r"modm:math:saturated"),
(r"modm/math/tolerance\.hpp", r"modm:math"),
(r"modm/math/utils.*", r"modm:math:utils"),

(r"modm/processing\.hpp", r"modm:processing"),
(r"modm/processing/protothread.*", r"modm:processing:protothread"),
(r"modm/processing/resumable.*", r"modm:processing:resumable"),
(r"modm/processing/rtos.*", r"modm:processing:rtos"),
(r"modm/processing/scheduler/scheduler\.hpp", r"modm:processing:scheduler"),
(r"modm/processing/task\.hpp", r"modm:processing"),
(r"modm/processing/timer.*", r"modm:processing:timer"),
(r"modm/ui/animation.*", r"modm:ui:animation"),
(r"modm/ui/button.*", r"modm:ui:button"),
(r"modm/ui/color\.hpp", r"modm:ui:color"),
(r"modm/ui/display.*", r"modm:ui:display"),
(r"modm/ui/gui.*", r"modm:ui:gui"),
(r"modm/ui/led.*", r"modm:ui:led"),
(r"modm/ui/menu.*", r"modm:ui:menu"),
(r"modm/ui/time/time\.hpp", r"modm:ui:time"),
(r"modm/utils.*", r"modm:utils"),

# All the platform modules
(r"modm/platform\.hpp", r"modm:platform:core"),
# As a last resort check the class names to get the platform modules
(r"BitBangOneWireMaster", r"modm:platform:1-wire.bitbang"),
(r"(Adc(\d))", r"modm:platform:adc:\2"),
(r"(AdcInterrupt(\d))", r"modm:platform:adc:\2"),
(r"(Can(\d))", r"modm:platform:can:\2"),
(r"ClockControl", r"modm:platform:clock"),
(r"SystemClock", r"modm:platform:clock"),
(r"(Dma(\d))", r"modm:platform:dma:\2"),
(r"Gpio\w*?[A-Z]\d{1,2}", r"modm:platform:gpio"),
(r"BitBangI2cMaster", r"modm:platform:i2c.bitbang"),
(r"(I2cMaster(\d))", r"modm:platform:i2c:\2"),
(r"modm/platform/id/id\.hpp", r"modm:platform:id"),
(r"RandomNumberGenerator", r"modm:platform:random"),
(r"BitBangSpiMaster", r"modm:platform:spi.bitbang"),
(r"(SpiMaster(\d))", r"modm:platform:spi:\2"),
(r"(UartSpiMaster(\d))", r"modm:platform:uart.spi:\2"),
(r"(Timer(\d{1,2}))", r"modm:platform:timer:\2"),
(r"(Us?art(\d))", r"modm:platform:uart:\2"),
]

0 comments on commit 4ae989e

Please sign in to comment.