Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
itzandroidtab authored Oct 2, 2023
0 parents commit 6f9147f
Show file tree
Hide file tree
Showing 13 changed files with 970 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"image": "mcr.microsoft.com/devcontainers/universal:2",
"features": {
},
"postCreateCommand": "chmod +x ./.devcontainer/postcreate.sh && ./.devcontainer/postcreate.sh"
}
27 changes: 27 additions & 0 deletions .devcontainer/postcreate.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
mkdir -p ../arm-none-eabi/
cd ../arm-none-eabi/

if [ ! -f ./arm-gnu-toolchain-12.3.rel1-x86_64-arm-none-eabi.tar.xz ]
then
echo "Downloading arm-none-eabi-gcc"
wget https://developer.arm.com/-/media/Files/downloads/gnu/12.3.rel1/binrel/arm-gnu-toolchain-12.3.rel1-x86_64-arm-none-eabi.tar.xz
fi

echo "Unpacking arm-none-eabi-gcc"
tar xf arm-gnu-toolchain-12.3.rel1-x86_64-arm-none-eabi.tar.xz

sudo rm -f /usr/bin/arm-none-eabi-gcc || true
sudo rm -f /usr/bin/arm-none-eabi-g++ || true
sudo rm -f /usr/bin/arm-none-eabi-gdb || true
sudo rm -f /usr/bin/arm-none-eabi-size || true
sudo rm -f /usr/bin/arm-none-eabi-objcopy || true
sudo rm -f /usr/bin/arm-none-eabi-objdump || true

echo "Linking arm-none-eabi"

sudo ln -s `pwd`/arm-gnu-toolchain-12.3.rel1-x86_64-arm-none-eabi/bin/arm-none-eabi-gcc /usr/bin/arm-none-eabi-gcc
sudo ln -s `pwd`/arm-gnu-toolchain-12.3.rel1-x86_64-arm-none-eabi/bin/arm-none-eabi-g++ /usr/bin/arm-none-eabi-g++
sudo ln -s `pwd`/arm-gnu-toolchain-12.3.rel1-x86_64-arm-none-eabi/bin/arm-none-eabi-gdb /usr/bin/arm-none-eabi-gdb
sudo ln -s `pwd`/arm-gnu-toolchain-12.3.rel1-x86_64-arm-none-eabi/bin/arm-none-eabi-size /usr/bin/arm-none-eabi-size
sudo ln -s `pwd`/arm-gnu-toolchain-12.3.rel1-x86_64-arm-none-eabi/bin/arm-none-eabi-objcopy /usr/bin/arm-none-eabi-objcopy
sudo ln -s `pwd`/arm-gnu-toolchain-12.3.rel1-x86_64-arm-none-eabi/bin/arm-none-eabi-objdump /usr/bin/arm-none-eabi-objdump
38 changes: 38 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: flash loader template

on:
push:
branches: [ master ]
pull_request:
branches: [ master ]

env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: Release

jobs:
build:
# The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac.
# You can convert this to a matrix build if you need cross-platform coverage.
# See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- name: arm-none-eabi-gcc install
uses: carlosperate/[email protected]
with:
release: '12.2.Rel1'

- name: arm-none-eabi-gcc version
run: arm-none-eabi-gcc --version

- name: Configure CMake
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
run: CC=arm-none-eabi-gcc CXX=arm-none-eabi-g++ cmake -B ${{github.workspace}}/build

- name: Build
# Build your program with the given configuration
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.vscode/
build/
97 changes: 97 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# set minimum version of CMake.
cmake_minimum_required(VERSION 3.13)

# The Generic system name is used for embedded targets (targets without OS) in
# CMake
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR ARM)

# Supress Error when trying to test the compiler
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
set(BUILD_SHARED_LIBS OFF)

# set project name and version
project(flash_loader VERSION 0.0.1)

# enable assembly
enable_language(ASM)

set(SOURCES
${CMAKE_SOURCE_DIR}/entry/entry.c
${CMAKE_SOURCE_DIR}/entry/cortex-vector.cpp
${CMAKE_SOURCE_DIR}/flash/main.cpp
${CMAKE_SOURCE_DIR}/flash/flash_device.cpp
)

set(HEADERS
${CMAKE_SOURCE_DIR}/entry/entry.hpp
)

# add our executable
add_executable(flash_loader
${SOURCES} ${HEADERS}
)

# enable C++20 support for the library
target_compile_features(flash_loader PUBLIC cxx_std_20)

# set the output filename
set_target_properties(flash_loader PROPERTIES OUTPUT_NAME "flash_loader" SUFFIX ".elf")

# compiler optimisations
target_compile_options(flash_loader PRIVATE "-g")
target_compile_options(flash_loader PRIVATE "-Os")

# set the cpu options for the compiler
target_compile_options(flash_loader PRIVATE "-march=armv7e-m")
target_compile_options(flash_loader PRIVATE "-mcpu=cortex-m4")
target_compile_options(flash_loader PRIVATE "-mthumb")

# other compiler settings
target_compile_options(flash_loader PRIVATE "-Wno-attributes")
target_compile_options(flash_loader PRIVATE "-fno-non-call-exceptions")
target_compile_options(flash_loader PRIVATE "-fno-common")
target_compile_options(flash_loader PRIVATE "-ffunction-sections")
target_compile_options(flash_loader PRIVATE "-fdata-sections")
target_compile_options(flash_loader PRIVATE "-fno-exceptions")
target_compile_options(flash_loader PRIVATE "-Wno-maybe-uninitialized")
target_compile_options(flash_loader PRIVATE "-Wno-unused-local-typedefs")
target_compile_options(flash_loader PRIVATE "-Wno-unused-but-set-variable")
target_compile_options(flash_loader PRIVATE "-Wno-unused-function")
target_compile_options(flash_loader PRIVATE "-fomit-frame-pointer")
target_compile_options(flash_loader PRIVATE "-Wall")
target_compile_options(flash_loader PRIVATE "-Werror")

# set the c++ only options
target_compile_options(flash_loader PUBLIC $<$<COMPILE_LANGUAGE:CXX>:-fno-threadsafe-statics>)
target_compile_options(flash_loader PUBLIC $<$<COMPILE_LANGUAGE:CXX>:-fno-rtti>)
target_compile_options(flash_loader PUBLIC $<$<COMPILE_LANGUAGE:CXX>:-fconcepts>)
target_compile_options(flash_loader PUBLIC $<$<COMPILE_LANGUAGE:CXX>:-fno-use-cxa-get-exception-ptr>)
target_compile_options(flash_loader PUBLIC $<$<COMPILE_LANGUAGE:CXX>:-fno-use-cxa-atexit>)
target_compile_options(flash_loader PUBLIC $<$<COMPILE_LANGUAGE:CXX>:-Wno-volatile>)

# set the cpu options for the linker
target_link_options(flash_loader PRIVATE "-march=armv7e-m")
target_link_options(flash_loader PRIVATE "-mcpu=cortex-m4")
target_link_options(flash_loader PRIVATE "-mthumb")

# other linker options
target_link_options(flash_loader PUBLIC "-ffunction-sections")
target_link_options(flash_loader PUBLIC "-fdata-sections")
target_link_options(flash_loader PUBLIC "-nostdlib")
target_link_options(flash_loader PUBLIC "-nodefaultlibs")
target_link_options(flash_loader PUBLIC "-nostartfiles")
target_link_options(flash_loader PUBLIC "-Wl,--gc-sections")
target_link_options(flash_loader PUBLIC "-Wl,-fatal-warnings")
target_link_options(flash_loader PUBLIC "-Wl,-cref,-Map=flash_loader.map")
target_link_options(flash_loader PUBLIC "-Wl,--print-memory-usage")
target_link_options(flash_loader PUBLIC "-Wl,--no-warn-rwx-segments")

# link to the linkerscript of the target cpu
target_link_options(flash_loader PUBLIC "-T${CMAKE_SOURCE_DIR}/linkerscript.ld")

# Custom commands for processing the build binary and show some statistics and debug info
add_custom_command(TARGET flash_loader DEPENDS ${CMAKE_BINARY_DIR}/flash_loader.elf POST_BUILD COMMAND arm-none-eabi-objcopy ARGS -O binary -R .bss -R .stack flash_loader.elf flash_loader.bin)
add_custom_command(TARGET flash_loader DEPENDS ${CMAKE_BINARY_DIR}/flash_loader.elf POST_BUILD COMMAND arm-none-eabi-objdump ARGS -C -S flash_loader.elf > flash_loader.lss)
add_custom_command(TARGET flash_loader DEPENDS ${CMAKE_BINARY_DIR}/flash_loader.elf POST_BUILD COMMAND arm-none-eabi-objdump ARGS -C -sj PrgCode -sj DevDscr -sj .bss -sj .data -sj .rodata -S flash_loader.elf > flash_loader.memory)
add_custom_command(TARGET flash_loader DEPENDS ${CMAKE_BINARY_DIR}/flash_loader.elf POST_BUILD COMMAND arm-none-eabi-size ARGS -A flash_loader.elf -x)
5 changes: 5 additions & 0 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Flash loader template
Flash loader template without the need for a Keil/Segger DSK license. Uses Cmake and arm-none-eabi. Uses parts of [klib](https://github.com/itzandroidtab/klib/)

## Targets of this project
Compatible with Segger J-link (Rip Open flash loader (OFL))
24 changes: 24 additions & 0 deletions entry/cortex-vector.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// include the header with the global reset handler and the default handler
#include "entry.hpp"

// array with the initial vector table. Interrupt handlers should all point
// to the default handler as the irq class should be used to register the
// the handlers for interrupts.
void (*const volatile __vectors[])(void) __attribute__ ((section(".vectors"))) = {
(void (*)(void)) &__stack_end,
__reset_handler, // The reset handler
__default_handler, // The NMI handler
__default_handler, // The hard fault handler
__default_handler, // The MPU fault handler
__default_handler, // The bus fault handler
__default_handler, // The usage fault handler
0, // Reserved
0, // Reserved
0, // Reserved
0, // Reserved
__default_handler, // SVCall handler
__default_handler, // Debug monitor handler
0, // Reserved
__default_handler, // The PendSV handler
__default_handler // The SysTick handler
};
83 changes: 83 additions & 0 deletions entry/entry.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#include <stdbool.h>
#include <stdint.h>

// type for constructors
typedef void (*entry_constructor)(void);

// declaration to the main function
int main();

/**
* @brief Reset handler when the target starts running. This function
* initilizes the bss and data segements
*
* @details declares all linker variables as extern. Then we refer to the
* value using the &operator as the variables is at a valid data address.
*
* Functions that need to be called before main are run should have the
* attribute "__constructor__". When marked the function will be added to
* the ".init_array" segment and called before main is called.
*
*/
void __attribute__((__noreturn__, __naked__)) __reset_handler() {
// initialize the stack pointer. As we are running from ram
// the stack pointer is not setup yet. Move it to the stack
// end segment to prevent a hardfault
extern uint32_t __stack_end;
asm volatile ("mov sp, %0" : : "r" (&__stack_end) : );

extern uint8_t __bss_start;
extern uint8_t __bss_end;

// set the bss section to 0x00
for (uint32_t i = 0; i < (&__bss_end - &__bss_start); i++) {
((volatile uint8_t*)(&__bss_start))[i] = 0x00;
}

extern const entry_constructor __preinit_array_start;
extern const entry_constructor __preinit_array_end;

// excecute all the preinit constructors
for (uint32_t i = 0; i < (&__preinit_array_end - &__preinit_array_start); i++) {
// call the preinit calls
(&__preinit_array_start)[i]();
}

extern const entry_constructor __init_array_start;
extern const entry_constructor __init_array_end;

// excecute all the global constructors
for (uint32_t i = 0; i < (&__init_array_end - &__init_array_start); i++) {
// call every constructor we have
(&__init_array_start)[i]();
}

// run main
(void)main();

extern const entry_constructor __fini_array_start;
extern const entry_constructor __fini_array_end;

// run all the destructors. Should never be called but if it happens
// it should work
for (uint32_t i = 0; i < (&__fini_array_end - &__fini_array_start); i++) {
// call every destructor we have
(&__fini_array_start)[i]();
}

// we should never be here. If this happens loop to make
// sure we never exit the reset handler
while (true) {};
}

/**
* @brief Default handler that locks the cpu.
*
*/
void __default_handler() {
// do nothing and wait
while (true) {}
}

// called when a vft entry is not yet filled in
void __cxa_pure_virtual() {}
41 changes: 41 additions & 0 deletions entry/entry.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#ifndef KLIB_ENTRY_HPP
#define KLIB_ENTRY_HPP

#include <stdint.h>

// extern c for c linkage in c++. No ifdef cplusplus as targets
// should be implemented using c++
extern "C" {
// pointer to the end of the stack. Definition is done in the
// linkerscript. Only the address of the variable should be used. The
// address points to the correct location of the variable
extern const uint32_t __stack_end;

// pointer to the start of the heap. Definition is done in the
// linkerscript. Only the address of the variable should be used. The
// address points to the correct location of the variable
extern const uint32_t __heap_start;

// pointer to the end of the heap. Definition is done in the
// linkerscript. Only the address of the variable should be used. The
// address points to the correct location of the variable
extern const uint32_t __heap_end;

/**
* @brief Generic reset handler that initializes the .bss and .data
* segments. It calls all the constructors and runs main. When code
* before main needs to be executed the "__constructor__" attribute
* can be added to the function.
*
*/
void __reset_handler();

/**
* @brief Default handler. Should be used to initialize the default
* arm vector table.
*
*/
void __default_handler();
}

#endif
Loading

0 comments on commit 6f9147f

Please sign in to comment.