-
Notifications
You must be signed in to change notification settings - Fork 19
Development
For the intrepid maker, hacker, programmer,... here is some information on how this firmware is being developed.
The Local Build System
Automated Builds, Travis-CI
- minimal changes to the original Marlin source code
- preserve Marlin functionality and behaviors
- explicitly document and control the build process
- create an "optimal" port for Monoprice MP Mini Delta
- command-line build, automated build process
- use make and a single Makefile to explicitly document and control the build process
- no changes to the original Marlin source, create a separate directory to hold modified Marlin source files
- no changes to the CPU SDK (STM32Cube), create a separate directory to hold SDK changes and customizations
- to limit changes to Marlin source files, use an "always_include.h" header file to help "re-map" Marlin's "AVR-ness" to the "STM32F0" processor family
- to limit changes to Marlin source files, use empty header files to satisfy included Arduino library header files
- place and run the tool-chain via changeroot or docker virtual machine (VM)
- use GitHub / Travis-CI for source control, automated builds and deployment
Overall, things went more or less according to plan. I was hoping to change fewer Marlin source files, but
some of the Marlin source files needed small (benign) changes to effect the port, and I found a few bugs
in Marlin which I hadn't anticipated (which led to even more changes). I grossly underestimated the
number of alterations to Marlin_main.cpp
-- thinking initially that I'd need only to change a few setup
and initialization things. The file does preserve the original Marlin code, but in hindsight, Marlin_main.cpp
probably should have become Marlin_main_stm32.cpp
and treated like a port-specific rewrite of the original
file (similar to MarlinSerial_stm32.cpp
, etc.).
(excerpt from HAL_stm32.h)
/* NOTE: include this file before all others (e.g. gcc -include HAL_stm32.h)
* to select the cpu device (CMSIS, STM32F070xB) and to configure the HAL
* driver appropriately. ALSO, this file provides several work-arounds to
* "preempt" the inclusion of a few of the original Marlin include files
* that would otherwise cause problems when compiling for the STM32F070xB.
* An included file that is NOT part of Marlin (e.g.'include <avr/eeprom.h>')
* is created as an empty file and placed in the "included files search path"
* to satisfy the reference to the file. Using these techniques, then, our
* port requires only minimal changes to the original Marlin source files.
*
* Highlights of the required changes (*file compatible with the original):
* boards.h - added MALYAN_M300 board definition*
* pins.h - include MALYAN_M300 pins description*
* pins_MALYAN_M300.h - created, the MALYAN_M300 pins description
* Configuration.h - Marlin configuration for MALYAN_M300
* Configuration_adv.h - Marlin configuration for MALYAN_M300
* delay.h - minor (benign) change for MALYAN_M300*
* cardreader.h - minor (benign) change for MALYAN_M300*
* stepper.h - minor (benign) change for MALYAN_M300*
* stepper.cpp - minor (benign) change for MALYAN_M300*
* temperature.h - minor (benign) change for MALYAN_M300*
* temperature.cpp - minor (benign) change for MALYAN_M300*
* Marlin_main.cpp - add inverted KILL pin for MALYAN_M300*
* HAL_stm32.h - replacement for HAL.h
* HAL_stm32.c - HAL "glue" to support the STM32F070xB
* MarlinSerial_stm32.cpp - replacement for MarlinSerial.cpp
* Sd2Card_stm32.cpp - replacement for Sd2Card.cpp
* configuration_store_stm32.cpp - replacement for configuration_store.cpp
* watchdog_stm32.cpp - replacement for watchdog.cpp
* malyanlcd_stm32.cpp - replacement for malyanlcd.cpp
*/
(excerpt from HAL_stm32.h)
// The 60-watt power supply of the Monoprice Mini Delta doesn't provide
// sufficient power to heat the nozzle and the build plate at the same
// time. We slightly modify the temperature isr (see temperature.cpp)
// to ensure that only one heater is active at a time. Our VERY simple
// implementation, though, limits "full-on" for the heat bed to 99.2%,
// and always gives priority to hotend -- hopefully not a problem.
#define ONLY_ONE_HEATER_AT_A_TIME 1
#if MAKE_05ALIMIT
#undef ONLY_ONE_HEATER_AT_A_TIME
#define ONLY_ONE_HEATER_AT_A_TIME 1
#endif
#if MAKE_10ALIMIT
#undef ONLY_ONE_HEATER_AT_A_TIME
#define ONLY_ONE_HEATER_AT_A_TIME 0
#endif
// Configure IO as Marlin directs (as opposed to configuring all of the
// IO at the program's start) -- nice idea, but requires a workaround to
// use hardware pwm (FAN_USES_HARDWARE_PWM). (see the GPIO_20 hack below)
#define CONFIGURE_IO_INDIVIDUALLY 0
// Configure the fan output to use hardware pwm
#define FAN_USES_HARDWARE_PWM 1
// The single fan of the Monoprice Mini Delta is normally configured as
// an auto-cooling extruder fan. Set CONFIGURE_FAN_AS_PART_COOLING to 1
// to use M106/M107 to control the fan (NOT RECOMMENDED).
#define CONFIGURE_FAN_AS_PART_COOLING 0
// The stock firmware of the Monoprice Mini Delta places the "front" of
// the build plate away from the LCD display. Set ROTATE_TOWER_AXES to 1
// to redefine the stepper motor axes and thus rotate the tower axes.
// Specifically, X<=Y, Y<=Z, and Z<=X (where A<=B means A becomes B)
#define ROTATE_TOWER_AXES 1
// Invert the direction of a stepper motor by setting the corresponding
// bit(X,Y,Z,E) in STEPPER_DIRECTION_XYZE. It seems that Monoprice does
// not configure the stepper motors consistently, so it may be necessary
// adjust this value. Use the M503 report from the stock firmware to
// determine an appropriate value.
// e.g. if the stock firmware M503 reports:
// (M562 XYZE) XYZABCD---+... use 0b0001 (0x1)
// (M562 XYZE) XYZABCD+++-... use 0b1110 (0xe)
// (M562 XYZE) XYZABCD----... use 0b0000 (0x0)
// (M562 XYZE) XYZABCD++++... use 0b1111 (0xf)
//
// NOTE! IMPORTANT! Be careful here, if we rotate the tower axes
// (#define ROTATE_TOWER_AXES 1), then the output from the stock
// M503 (M562) command must be adjusted (mapped) accordingly.
// e.g. if the stock firmware M503 reports:
// (M562 XYZE) XYZABCD+---... use 0b0100 (0x4)
// (M562 XYZE) XYZABCD-+--... use 0b0010 (0x2)
// (M562 XYZE) XYZABCD--+-... use 0b1000 (0x8)
//
#ifndef INVERT_STEPPER_DIRECTION_XYZE
#define INVERT_STEPPER_DIRECTION_XYZE 0b0001
#endif
// Custom codes, M988 and M989, open and close an output log file
// in the current working directory. Use a DOS 8.3 name for the
// file. "#define OVERLY_SIMPLISTIC_OUTPUT_LOGGING_HACK 1" to
// enable this feature.
// e.g.
// M988 logfile.txt ; start writing output to "logfile.txt"
// M503 ; report settings
// M989 ; stop writing (close) the log file
//
#define OVERLY_SIMPLISTIC_OUTPUT_LOGGING_HACK 1
The build system is linux based, specifically Debian "buster" with the following additional packages installed:
(ARM bare metal compiler, libraries, and tools)
$ apt-get install build-essential gcc-arm-none-eabi binutils-arm-none-eabi
$ apt-get install libnewlib-arm-none-eabi libnewlib-dev libstdc++\-arm-none-eabi-newlib
$ apt-get install gdb-multiarch openocd telnet emacs-nox
(basic git -- for GitHub, ssh, ...)
$ apt-get install git quilt patchutils openssh-client ca-certificates gnupg wget curl
(optional, but I find useful)
$ apt-get install sudo rename xsltproc picocom zip unzip p7zip-full p7zip-rar
The "Makefile" documents the entire build process. The default target (make) and the "all" target (make all) are good places to start. The "Makefile" also defines the release number (e.g. RELEASE = 00).
Generate two (2) "firmware.bin" files -- one for use with a 60watt power adapter (05Alimit) and one for use with a 120watt power adapter (10Alimit).
$ make all
Generate a single "firmware.bin" file with the prevailing configuration of the original Marlin4MPDM source (currently matches the 10Alimit configuration).
$ make
The automated build site, Travis-CI, compiles the firmware automatically whenever a change is pushed to the mpmd_marlin_1.1.x repository. A tagged commit, when the tag matches the pattern of a version number, triggers the (Travis-CI) process to build and deploy a release.
I like the way the automated build process has come together. We select Ubuntu linux for Travis-CI's basic
build processes, but the arm cross compilation tools (arm gcc tool chain) reside in a minimal (Debian) docker
container. Travis-CI launches the docker container attached to the source directory and runs a single "make"
command to build the firmware. After which, IF the build is tagged with a version number, Travis-CI executes
its deploy stage. Travis-CI runs "make" one more time (in Ubuntu) to generate the zip file of the SD card contents before returning the build artifacts (.bin files, zipped SD card contents, etc.) to GitHub. The whole thing is
neatly described in two short files: .travis_dockerfile
to create the docker container and .travis.yml
to
direct the Travis-CI automation. The Travis-CI automation particulars are completely separate from the details
of building the firmware (captured in the Makefile). Very nice indeed.