From 8faed4f3d54afef9366f11b83dae505951768173 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5ns=20Nilsson?= Date: Thu, 9 Jan 2020 13:13:43 +0100 Subject: [PATCH] TFLu: Add stm32f4 and build target Add new TARGET=stm32f4 that is working with Renode. Add new target that will just build the test binaries. Add new CI script for this as well. The purpose of this is CMSIS-NN regression. --- tensorflow/lite/micro/stm32f4/debug_log.cc | 25 +++++ .../lite/micro/tools/ci_build/test_all.sh | 3 + .../lite/micro/tools/ci_build/test_stm32f4.sh | 40 +++++++ tensorflow/lite/micro/tools/make/Makefile | 7 +- .../micro/tools/make/helper_functions.inc | 1 + .../tools/make/targets/stm32f4/stm32f4.lds | 102 ++++++++++++++++++ .../tools/make/targets/stm32f4_makefile.inc | 86 +++++++++++++++ 7 files changed, 263 insertions(+), 1 deletion(-) create mode 100644 tensorflow/lite/micro/stm32f4/debug_log.cc create mode 100755 tensorflow/lite/micro/tools/ci_build/test_stm32f4.sh create mode 100644 tensorflow/lite/micro/tools/make/targets/stm32f4/stm32f4.lds create mode 100644 tensorflow/lite/micro/tools/make/targets/stm32f4_makefile.inc diff --git a/tensorflow/lite/micro/stm32f4/debug_log.cc b/tensorflow/lite/micro/stm32f4/debug_log.cc new file mode 100644 index 00000000000..311005fd1ca --- /dev/null +++ b/tensorflow/lite/micro/stm32f4/debug_log.cc @@ -0,0 +1,25 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/micro/debug_log.h" + +extern "C" void DebugLog(const char* s) { + asm("mov r0, #0x04\n" // SYS_WRITE0 + "mov r1, %[str]\n" + "bkpt #0xAB\n" + : + : [ str ] "r"(s) + : "r0", "r1"); +} diff --git a/tensorflow/lite/micro/tools/ci_build/test_all.sh b/tensorflow/lite/micro/tools/ci_build/test_all.sh index 28358610e96..873cb8b2506 100755 --- a/tensorflow/lite/micro/tools/ci_build/test_all.sh +++ b/tensorflow/lite/micro/tools/ci_build/test_all.sh @@ -49,4 +49,7 @@ tensorflow/lite/micro/tools/ci_build/test_sparkfun.sh echo "Running x86 tests at `date`" tensorflow/lite/micro/tools/ci_build/test_x86.sh +echo "Running stm32f4 tests at `date`" +tensorflow/lite/micro/tools/ci_build/test_stm32f4.sh + echo "Finished all micro tests at `date`" diff --git a/tensorflow/lite/micro/tools/ci_build/test_stm32f4.sh b/tensorflow/lite/micro/tools/ci_build/test_stm32f4.sh new file mode 100755 index 00000000000..14e229c092f --- /dev/null +++ b/tensorflow/lite/micro/tools/ci_build/test_stm32f4.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash +# Copyright 2020 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +# +# Tests the microcontroller code for stm32f4 + +set -e + +TARGET=stm32f4 +TAGS=cmsis-nn +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +ROOT_DIR=${SCRIPT_DIR}/../../../../.. +cd ${ROOT_DIR} +pwd + +source tensorflow/lite/micro/tools/ci_build/helper_functions.sh + +readable_run make -f tensorflow/lite/micro/tools/make/Makefile clean + +# TODO(b/143715361): downloading first to allow for parallel builds. +readable_run make -f tensorflow/lite/micro/tools/make/Makefile TAGS=${TAGS} TARGET=${TARGET} third_party_downloads + +# Build test binaries first +readable_run make -j8 -f tensorflow/lite/micro/tools/make/Makefile TAGS=${TAGS} TARGET=${TARGET} build + +# Parallell builds doesn't work very well with this +readable_run make -f tensorflow/lite/micro/tools/make/Makefile TAGS=${TAGS} TARGET=${TARGET} test + diff --git a/tensorflow/lite/micro/tools/make/Makefile b/tensorflow/lite/micro/tools/make/Makefile index 224ee879cb5..7fb32175622 100644 --- a/tensorflow/lite/micro/tools/make/Makefile +++ b/tensorflow/lite/micro/tools/make/Makefile @@ -81,6 +81,8 @@ CC_PREFIX := # runtime that can be linked in to other programs. MICROLITE_LIB_NAME := libtensorflow-microlite.a +MICRO_LITE_EXAMPLE_TESTS := $(wildcard tensorflow/lite/micro/examples/*/Makefile.inc) + MICROLITE_TEST_SRCS := \ $(wildcard tensorflow/lite/micro/*test.cc) \ $(wildcard tensorflow/lite/micro/kernels/*test.cc) \ @@ -240,7 +242,7 @@ CC := $(CC_PREFIX)${TARGET_TOOLCHAIN_PREFIX}${CC_TOOL} AR := $(CC_PREFIX)${TARGET_TOOLCHAIN_PREFIX}${AR_TOOL} # Load the examples. -include $(wildcard tensorflow/lite/micro/examples/*/Makefile.inc) +include $(MICRO_LITE_EXAMPLE_TESTS) # Create rules for downloading third-party dependencies. THIRD_PARTY_TARGETS := @@ -308,6 +310,9 @@ $(eval $(call microlite_test,kernel_$(notdir $(basename $(TEST_TARGET))),$(TEST_ test: $(MICROLITE_TEST_TARGETS) +# Just build the test targets +build: $(MICROLITE_BUILD_TARGETS) + generate_projects: $(ALL_PROJECT_TARGETS) generate_non_kernel_projects: $(filter-out generate_kernel%,$(ALL_PROJECT_TARGETS)) diff --git a/tensorflow/lite/micro/tools/make/helper_functions.inc b/tensorflow/lite/micro/tools/make/helper_functions.inc index 5a162675f85..ca357c55f5c 100644 --- a/tensorflow/lite/micro/tools/make/helper_functions.inc +++ b/tensorflow/lite/micro/tools/make/helper_functions.inc @@ -371,6 +371,7 @@ test_$(1): $$($(1)_BINARY) $$(TEST_SCRIPT) $$($(1)_BINARY) '~~~ALL TESTS PASSED~~~' ifneq (,$(findstring _test,$(1))) MICROLITE_TEST_TARGETS += test_$(1) + MICROLITE_BUILD_TARGETS += $$($(1)_BINARY) endif $(eval $(call generate_microlite_projects,$(1),$(call specialize,$(2)),$(3))) endef diff --git a/tensorflow/lite/micro/tools/make/targets/stm32f4/stm32f4.lds b/tensorflow/lite/micro/tools/make/targets/stm32f4/stm32f4.lds new file mode 100644 index 00000000000..6ecde0000b2 --- /dev/null +++ b/tensorflow/lite/micro/tools/make/targets/stm32f4/stm32f4.lds @@ -0,0 +1,102 @@ +/* Copyright 2020 Google Inc. All Rights Reserved. + +Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +/* Copied and modified from: tensorflow/lite/micro/tools/make/targets/bluepill/bluepill.lds + +*/ + +/* + * 0x00000000 - 0x07ffffff - aliased to flash or sys memory depending on BOOT jumpers. + * 0x08000000 - 0x0801ffff - Flash. + * 0x1ffff000 - 0x1ffff7ff - Boot firmware in system memory. + * 0x1ffff800 - 0x1fffffff - Option bytes. + * 0x20000000 - 0x20004fff - SRAM. + * 0x40000000 - 0x40023400 - Peripherals + */ + +/* Define main entry point */ +ENTRY(_main) + +/* 20K of RAM and 128K of FLASH */ +MEMORY { +RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K +FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 256K +} + +/* Compute where the stack ends rather than hard coding it */ +_ld_stack_end_addr = ORIGIN(RAM) + LENGTH(RAM); +_ld_min_stack_size = 0x200; + +SECTIONS { + +/* interrupt vector goes to top of flash */ + +.interrupt_vector : { + . = ALIGN(4); + KEEP(*(.interrupt_vector)) + . = ALIGN(4); +} >FLASH + +/* read only .text and .rodata go to flash */ + +.text : { + . = ALIGN(4); + KEEP(*(.text.interrupt_handler)) + *(.text*) +} >FLASH + +.rodata : { + . = ALIGN(4); + *(.rodata*) + . = ALIGN(4); +} >FLASH + +/* read mwrite data needs to be stored in flash but copied to ram */ +.data : { + . = ALIGN(4); + _ld_data_load_dest_start = .; /* export where to load from */ + *(.data*) + . = ALIGN(4); + _ld_data_load_dest_stop = .; /* export where to load from */ +} >RAM AT> FLASH +_ld_data_load_source = LOADADDR(.data); + +/* unitialized data section needs zero initialization */ +.bss : +{ + . = ALIGN(4); + _ld_bss_data_start = .; + *(.bss*) + . = ALIGN(4); + _ld_bss_data_stop = .; +} >RAM + +._user_heap_stack : +{ + . = ALIGN(8); + . += _ld_min_stack_size; + PROVIDE(end = .); + . = ALIGN(8); +} >RAM + +/DISCARD/ : +{ + libc.a (*) + libm.a (*) + libgcc.a (*) +} + +} /* SECTIONS */ diff --git a/tensorflow/lite/micro/tools/make/targets/stm32f4_makefile.inc b/tensorflow/lite/micro/tools/make/targets/stm32f4_makefile.inc new file mode 100644 index 00000000000..b99e11e0328 --- /dev/null +++ b/tensorflow/lite/micro/tools/make/targets/stm32f4_makefile.inc @@ -0,0 +1,86 @@ +# Settings for stm32f4 based platforms +ifeq ($(TARGET), stm32f4) + export PATH := $(MAKEFILE_DIR)/downloads/gcc_embedded/bin/:$(PATH) + TARGET_ARCH := cortex-m4 + TARGET_TOOLCHAIN_PREFIX := arm-none-eabi- + + $(eval $(call add_third_party_download,$(GCC_EMBEDDED_URL),$(GCC_EMBEDDED_MD5),gcc_embedded,)) + $(eval $(call add_third_party_download,$(CMSIS_URL),$(CMSIS_MD5),cmsis,)) + $(eval $(call add_third_party_download,$(STM32_BARE_LIB_URL),$(STM32_BARE_LIB_MD5),stm32_bare_lib,)) + + PLATFORM_FLAGS = \ + -DGEMMLOWP_ALLOW_SLOW_SCALAR_FALLBACK \ + -DTF_LITE_STATIC_MEMORY \ + -DTF_LITE_MCU_DEBUG_LOG \ + -fno-rtti \ + -fmessage-length=0 \ + -fno-exceptions \ + -fno-unwind-tables \ + -fno-builtin \ + -ffunction-sections \ + -fdata-sections \ + -funsigned-char \ + -MMD \ + -mcpu=cortex-m4 \ + -mthumb \ + -std=gnu++11 \ + -Wvla \ + -Wall \ + -Wextra \ + -Wno-unused-parameter \ + -Wno-missing-field-initializers \ + -Wno-write-strings \ + -Wno-sign-compare \ + -fno-delete-null-pointer-checks \ + -fomit-frame-pointer \ + -fpermissive \ + -g \ + -Os + CXXFLAGS += $(PLATFORM_FLAGS) + CCFLAGS += $(PLATFORM_FLAGS) + LDFLAGS += \ + --specs=nosys.specs \ + -T $(MAKEFILE_DIR)/targets/stm32f4/stm32f4.lds \ + -Wl,-Map=$(MAKEFILE_DIR)/gen/$(TARGET).map,--cref \ + -Wl,--gc-sections + BUILD_TYPE := micro + MICROLITE_LIBS := \ + -lm + INCLUDES += \ + -isystem$(MAKEFILE_DIR)/downloads/cmsis/CMSIS/Core/Include/ \ + -I$(MAKEFILE_DIR)/downloads/stm32_bare_lib/include + MICROLITE_CC_SRCS += \ + $(wildcard $(MAKEFILE_DIR)/downloads/stm32_bare_lib/source/*.c) \ + $(wildcard $(MAKEFILE_DIR)/downloads/stm32_bare_lib/source/*.cc) + EXCLUDED_SRCS := \ + $(MAKEFILE_DIR)/downloads/stm32_bare_lib/source/debug_log.c + MICROLITE_CC_SRCS := $(filter-out $(EXCLUDED_SRCS), $(MICROLITE_CC_SRCS)) + # Stm32f4 is reusing the bluepill renode scripts for now + TEST_SCRIPT := tensorflow/lite/micro/testing/test_bluepill_binary.sh + # TODO, non working tests.. the micro_speech example and conv_test.cc/depthwise_conv_test.cc partly works + EXCLUDED_TESTS := \ + tensorflow/lite/micro/micro_interpreter_test.cc \ + tensorflow/lite/micro/micro_allocator_test.cc \ + tensorflow/lite/micro/memory_helpers_test.cc \ + tensorflow/lite/micro/kernels/depthwise_conv_test.cc \ + tensorflow/lite/micro/kernels/conv_test.cc \ + tensorflow/lite/micro/simple_tensor_allocator_test.cc + MICROLITE_TEST_SRCS := $(filter-out $(EXCLUDED_TESTS), $(MICROLITE_TEST_SRCS)) + EXCLUDED_EXAMPLE_TESTS := \ + tensorflow/lite/micro/examples/magic_wand/Makefile.inc \ + tensorflow/lite/micro/examples/person_detection/Makefile.inc \ + tensorflow/lite/micro/examples/person_detection_experimental/Makefile.inc \ + tensorflow/lite/micro/examples/mobilenet_v2/Makefile.inc \ + tensorflow/lite/micro/examples/micro_speech/Makefile.inc \ + tensorflow/lite/micro/examples/ds_cnn_l/Makefile.inc + MICRO_LITE_EXAMPLE_TESTS := $(filter-out $(EXCLUDED_EXAMPLE_TESTS), $(MICRO_LITE_EXAMPLE_TESTS)) + +# These are microcontroller-specific rules for converting the ELF output +# of the linker into a binary image that can be loaded directly. +OBJCOPY := $(TARGET_TOOLCHAIN_PREFIX)objcopy + +$(BINDIR)/%.bin: $(BINDIR)/% + @mkdir -p $(dir $@) + $(OBJCOPY) $< $@ -O binary + +endif