diff --git a/.gitignore b/.gitignore index 2fcebcd..ed39835 100644 --- a/.gitignore +++ b/.gitignore @@ -10,16 +10,11 @@ *~ *.ods *.log - +.DS_Store firmware/p600firmware.bin - firmware/p600firmware.elf - firmware/p600firmware.hex - firmware/p600firmware.lss - firmware/p600firmware.map - firmware/p600firmware.syx -/common/*~ +/build diff --git a/BUILD.md b/BUILD.md new file mode 100644 index 0000000..8be9c1e --- /dev/null +++ b/BUILD.md @@ -0,0 +1,78 @@ +## How to build + +At the time of writing, GCC-AVR 11 seems to be the optimal version to +use as it produces the smallest (working) firmware. + +The general process is as follows: + +* install all required dependencies: gcc-avr, avr-libc, cmake, make and python3. +* compile the code +* use one of the products for flashing + +Compilation in a shell works like this: + +```sh +mkdir -p build && cd build +cmake .. +make +``` + +`p600firmware.bin` and `p600firmware.syx` are the most relevant build +products for flashing via USB or MIDI, respectively. These files are +created by default. Try `make help` for a list of all available build +targets. + +### Using docker or podman + +The most flexible approach is to use a compiler toolchain inside a +dockerized Linux environment as this can easily build and set up on +all operating systems. + +It is also possible to specify a certain compiler version and/or have +multiple versions readily available. + +The Dockerfile supplied with the repository can be used to create a +Docker image based on Alpine Linux and provides gcc-avr, make and python3. + +An overview of the several gcc-avr versions for several Alpine releases can be found [here](https://pkgs.alpinelinux.org/packages?name=gcc-avr&branch=&repo=&arch=&maintainer=). + +```sh +# Build gcc 12 using Alpine Linux edge (default) +docker build -t avr-toolchain:12 . + +# Build gcc 11 using Alpine Linux 3.16 +docker build --build-arg ALPINE_VERSION=3.16 -t avr-toolchain:11 . + +# Build gcc 10 using Alpine Linux 3.15 +docker build --build-arg ALPINE_VERSION=3.15 -t avr-toolchain:10 . + +# Compile project +docker run --rm -v $(pwd):/build avr-toolchain:11 \ + sh -c "mkdir -p build && cd build && cmake .. && make" +``` + +### Building on MacOS + +On MacOS, first set up a [Homebrew](https://brew.sh) environment. + +By adding the +[homebrew-avr](https://github.com/osx-cross/homebrew-avr/) tap from +here, several GCC compiler versions can be installed. + +`avr-gcc@10` and `avr-gcc@11` have been tested successfully on a M1 +Macbook Air and should work on an Intel Macbook as well. + +### Building on Linux + +Depending on the used distribution, it can be hard to find a working +pre-packaged compiler toolchain. + +On Debian for example, there is only GCC-AVR version 5 available by +default. + +Fedora on the other hand offers modern GCC versions in their more +recent [releases](https://src.fedoraproject.org/rpms/avr-gcc). + +### Building on Windows + +Work in progress. diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..b59170f --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,99 @@ +cmake_minimum_required(VERSION 3.11) + +# AVR GCC toolchain (has to be set before project()) +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_CXX_COMPILER avr-g++) +set(CMAKE_C_COMPILER avr-gcc) +set(CMAKE_ASM_COMPILER avr-gcc) + +project(p600fw) +set(PRODUCT_NAME p600firmware) + +# AVR chip configuration +set(F_CPU 16000000UL) +set(MCU at90usb1286) + +# Pass defines to compiler +add_definitions( + -DF_CPU=${F_CPU} +) + +add_compile_options( + -mmcu=${MCU} # MCU + -std=gnu99 # C99 standard + -O2 # optimize + -Wall # enable warnings + -gdwarf-2 + -funsigned-char + -funsigned-bitfields + -fpack-struct + -fshort-enums + -Wstrict-prototypes + -fno-unroll-loops + -fno-inline-functions + -flto=auto + -fuse-linker-plugin +) + +add_link_options( + -mmcu=${MCU} + -flto=auto + -Wl,-Map=p600firmware.map,--cref + -Wl,--relax + -lm + -Wl,--section-start=.updater=0x1e000 + -Wl,--section-start=.nrww_misc=0x1ec00 + -Wl,--section-start=.bootloader=0x1f000 +) + +include_directories( + common + firmware +) + +file(GLOB SRC_FILES + "xnormidi/*.c" + "xnormidi/bytequeue/*.c" + "firmware/*.c" + "common/*.c" +) + +# Generate list files +set(CMAKE_C_COMPILE_OBJECT "${CMAKE_C_COMPILE_OBJECT} -Wa,-adhlns=.lst") + +# Create one target for compiling +add_executable(${PRODUCT_NAME} EXCLUDE_FROM_ALL ${SRC_FILES}) +set_target_properties(${PRODUCT_NAME} PROPERTIES SUFFIX .elf ADDITIONAL_CLEAN_FILES ${PRODUCT_NAME}.map) + +# Call avr-size after building .elf file +add_custom_target(size ALL avr-size ${PRODUCT_NAME}.elf DEPENDS ${PRODUCT_NAME}) + +add_custom_command( + OUTPUT ${PRODUCT_NAME}.hex + COMMAND avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature ${PRODUCT_NAME}.elf ${PRODUCT_NAME}.hex + DEPENDS ${PRODUCT_NAME} +) +add_custom_target(hex DEPENDS ${PRODUCT_NAME}.hex) + +add_custom_command( + OUTPUT ${PRODUCT_NAME}.lss + COMMAND avr-objdump -h -S -z ${PRODUCT_NAME}.elf > ${PRODUCT_NAME}.lss + DEPENDS ${PRODUCT_NAME} +) +add_custom_target(lss DEPENDS ${PRODUCT_NAME}.lss) + +add_custom_command( + OUTPUT ${PRODUCT_NAME}.bin + COMMAND avr-objcopy -O binary -R .eeprom -R .fuse -R .lock -R .signature -R .updater -R .nrww_misc -R .bootloader ${PRODUCT_NAME}.elf ${PRODUCT_NAME}.bin + DEPENDS ${PRODUCT_NAME} +) +add_custom_target(bin DEPENDS ${PRODUCT_NAME}.bin) + +add_custom_command( + OUTPUT ${PRODUCT_NAME}.syx + COMMAND python3 "${CMAKE_SOURCE_DIR}/fw2syx/fw2syx.py" -o ${PRODUCT_NAME}.syx ${PRODUCT_NAME}.bin + DEPENDS bin +) +add_custom_target(syx ALL DEPENDS ${PRODUCT_NAME}.syx) + +add_custom_target(sendsyx p600_send ${PRODUCT_NAME}.syx DEPENDS ${PRODUCT_NAME}.syx) diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..7b04787 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,6 @@ +ARG ALPINE_VERSION=edge +FROM alpine:${ALPINE_VERSION} + +RUN apk --no-cache add avr-libc cmake gcc-avr make python3 + +WORKDIR /build