-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 534f1a2
Showing
3 changed files
with
284 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
name: klib bootloader | ||
|
||
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 | ||
|
||
strategy: | ||
matrix: | ||
cpu: [ lpc1756 ] | ||
|
||
steps: | ||
- uses: actions/checkout@v3 | ||
|
||
- name: arm-none-eabi-gcc install | ||
uses: carlosperate/arm-none-eabi-gcc-action@v1.6.0 | ||
with: | ||
release: '12.2.Rel1' | ||
|
||
- name: arm-none-eabi-gcc version | ||
run: arm-none-eabi-gcc --version | ||
|
||
- name: getting arm headers | ||
uses: actions/checkout@v3 | ||
with: | ||
repository: ARM-software/CMSIS_5 | ||
ref: 'develop' | ||
fetch-depth: '1' | ||
path: './CMSIS' | ||
|
||
- name: moving arm headers | ||
run: | | ||
cp ${{github.workspace}}/CMSIS/CMSIS/Core/Include/* ${{github.workspace}}/targets/arm/ | ||
- name: generating header | ||
run: | | ||
mkdir -p ${{github.workspace}}/targets/${{matrix.cpu}}/docs | ||
wget -q -O ${{github.workspace}}/targets/${{matrix.cpu}}/docs/${{matrix.cpu}}.svd https://raw.githubusercontent.com/itzandroidtab/klib-svd/master/${{matrix.cpu}}.svd | ||
wget -q -O ${{github.workspace}}/svdconv.tbz2 https://github.com/Open-CMSIS-Pack/devtools/releases/download/tools%2Fsvdconv%2F3.3.44/svdconv-3.3.44-linux64-amd64.tbz2 | ||
tar -xf ${{github.workspace}}/svdconv.tbz2 | ||
chmod +x ${{github.workspace}}/svdconv | ||
${{github.workspace}}/svdconv ${{github.workspace}}/targets/${{matrix.cpu}}/docs/${{matrix.cpu}}.svd --generate=header -o ${{github.workspace}}/targets/${{matrix.cpu}}/ > /dev/null || true | ||
sed -i '/#include "system_/d' ${{github.workspace}}/targets/${{matrix.cpu}}/${{matrix.cpu}}.h | ||
- name: Create main | ||
# create a main file that includes all the header files for the current target | ||
run: | | ||
find ${{github.workspace}}/klib/ -type f -name "*.hpp" -exec echo "#include \"{}\"" >> ${{github.workspace}}/project/main.cpp \; | ||
find ${{github.workspace}}/targets/${{matrix.cpu}} -type f -name "*.hpp" -exec echo "#include \"{}\"" >> ${{github.workspace}}/project/main.cpp \; | ||
echo "int main() {return 0;}" >> ${{github.workspace}}/project/main.cpp | ||
echo "Contents of main:" | ||
cat ${{github.workspace}}/project/main.cpp | ||
- 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 -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DTARGET_CPU=${{matrix.cpu}} | ||
|
||
- name: Build | ||
# Build your program with the given configuration | ||
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} | ||
|
||
- name: Uploading artifact | ||
uses: actions/upload-artifact@v3 | ||
# upload the elf file as a artifact | ||
with: | ||
name: ${{matrix.cpu}} | ||
path: | | ||
${{github.workspace}}/build/project/klib.elf | ||
${{github.workspace}}/build/project/klib.map | ||
${{github.workspace}}/build/project/klib.lss | ||
${{github.workspace}}/build/project/klib.memory | ||
${{github.workspace}}/build/project/klib.hex | ||
${{github.workspace}}/build/project/klib.bin |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
# set the sources | ||
set(SOURCES | ||
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp | ||
) | ||
|
||
set(HEADERS) | ||
|
||
# add our executable | ||
add_executable(klib_project | ||
${SOURCES} ${HEADERS} | ||
) | ||
|
||
# set the output filename | ||
set_target_properties(klib_project PROPERTIES OUTPUT_NAME "klib" SUFFIX ".elf") | ||
|
||
# set the interrupt implementation | ||
target_compile_definitions(klib PUBLIC "KLIB_IRQ=irq_ram") | ||
# target_compile_definitions(klib PUBLIC "KLIB_IRQ=irq_hooked") | ||
# target_compile_definitions(klib PUBLIC "KLIB_IRQ=irq_flash") | ||
|
||
# set the default cout/cin | ||
# target_compile_definitions(klib PUBLIC "KLIB_DEFAULT_COUT=rtt") | ||
# target_compile_definitions(klib PUBLIC "KLIB_DEFAULT_CIN=rtt") | ||
|
||
# override the rtt buffer size (not required and not used when no segger rtt is used) | ||
target_compile_definitions(klib PUBLIC "BUFFER_SIZE_UP=256") | ||
target_compile_definitions(klib PUBLIC "BUFFER_SIZE_DOWN=16") | ||
|
||
# link the klib_project to klib and the cpu target | ||
target_link_libraries(klib_project PUBLIC klib) | ||
target_link_libraries(klib_project PUBLIC target_cpu) | ||
|
||
# Libraries to link for all targets | ||
target_link_libraries(klib_project PUBLIC m) | ||
|
||
# link to the linkerscript of the target cpu | ||
target_link_options(klib_project PUBLIC "-T${TARGET_LINKERSCRIPT}") | ||
set_target_properties(klib_project PROPERTIES LINK_DEPENDS ${TARGET_LINKERSCRIPT}) | ||
|
||
# add the project directory to the include directories | ||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}) | ||
|
||
# Custom commands for processing the build binary and show some statistics and debug info | ||
add_custom_command(TARGET klib_project DEPENDS ${CMAKE_BINARY_DIR}/klib.elf POST_BUILD COMMAND arm-none-eabi-objcopy ARGS -O binary -R .bss -R .stack klib.elf klib.bin) | ||
add_custom_command(TARGET klib_project DEPENDS ${CMAKE_BINARY_DIR}/klib.elf POST_BUILD COMMAND arm-none-eabi-objcopy ARGS -O ihex -R .bss -R .stack klib.elf klib.hex) | ||
add_custom_command(TARGET klib_project DEPENDS ${CMAKE_BINARY_DIR}/klib.elf POST_BUILD COMMAND arm-none-eabi-objdump ARGS -C -S klib.elf > klib.lss) | ||
add_custom_command(TARGET klib_project DEPENDS ${CMAKE_BINARY_DIR}/klib.elf POST_BUILD COMMAND arm-none-eabi-objdump ARGS -C -sj .bss -sj .data -sj .rodata -sj .vectors -S klib.elf > klib.memory) | ||
add_custom_command(TARGET klib_project DEPENDS ${CMAKE_BINARY_DIR}/klib.elf POST_BUILD COMMAND arm-none-eabi-size ARGS -A klib.elf -x) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
#include <klib/klib.hpp> | ||
#include <klib/usb/device/dfu.hpp> | ||
|
||
#include <io/usb.hpp> | ||
#include <io/system.hpp> | ||
#include <io/pins.hpp> | ||
#include <io/flash.hpp> | ||
|
||
namespace target = klib::target; | ||
|
||
// location of the user vector table | ||
constexpr static uint32_t app_vector_address = 0x2000; | ||
|
||
// transfer buffer size. Same value is used as the write amount | ||
constexpr static uint32_t transfer_size = 256; | ||
|
||
/** | ||
* @brief Helper class to write to flash memory | ||
* | ||
*/ | ||
class dfu { | ||
public: | ||
/** | ||
* @brief Write memory to flash | ||
* | ||
* @param offset | ||
* @param data | ||
* @param length | ||
* @return true | ||
* @return false | ||
*/ | ||
static bool write(uint32_t offset, uint8_t* data, uint32_t length) { | ||
// get the address we are trying to write | ||
const uint32_t address = app_vector_address + offset; | ||
|
||
// check if we are at the start of the sector | ||
const bool start_sector = ( | ||
target::io::flash::address_to_sector(address) == | ||
target::io::flash::address_to_sector(address + (0x1000 - 1)) | ||
); | ||
|
||
// check if we should erase the currect sector by | ||
// checking if it is blank (only do it when we are | ||
// at the start of the sector) | ||
if (start_sector && !target::io::flash::is_blank(address)) { | ||
// flash is not blank. Erase it | ||
target::io::flash::erase(target::io::flash::erase_mode::sector, address); | ||
} | ||
|
||
// write the data to the flash (always write the full dfu buffer size) | ||
return target::io::flash::write(address, data, transfer_size); | ||
} | ||
|
||
/** | ||
* @brief Get the write timeout | ||
* | ||
* @return uint32_t | ||
*/ | ||
static uint32_t get_write_timeout() { | ||
return 1; | ||
} | ||
|
||
/** | ||
* @brief Callback that gets called when the CPU should | ||
* be reset | ||
* | ||
*/ | ||
static void reset() { | ||
// do a system reset | ||
NVIC_SystemReset(); | ||
} | ||
}; | ||
|
||
// using for the usb driver | ||
using usb_bulk = target::io::usb<target::io::periph::lqfp_80::usb0, klib::usb::device::dfu<dfu, transfer_size>>; | ||
|
||
/** | ||
* @brief Helper function that moves the vector table and | ||
* starts the user application | ||
* | ||
* @warning this function resets the stack pointer to the | ||
* address in the vector table of the user code. This | ||
* function should not use the stack after this is done | ||
* | ||
*/ | ||
static __attribute__((__noreturn__, __naked__)) void start_application() { | ||
// helper using for moving the vector table | ||
using irq = klib::irq_flash<16>; | ||
|
||
// move the vector table to the vector table | ||
// of the user | ||
irq::init(reinterpret_cast<irq::interrupt_callback*>(app_vector_address)); | ||
|
||
// load the stack pointer of the application | ||
asm volatile ("MSR msp, %0" : : "r" (*reinterpret_cast<uint32_t*>(app_vector_address)) : ); | ||
|
||
// call the user application | ||
(*reinterpret_cast<void(**)()>((app_vector_address + 0x4)))(); | ||
|
||
while (true) {} | ||
} | ||
|
||
int main() { | ||
// get the bootloader pin | ||
using bootloader_pin = target::io::pin_in<target::pins::package::lqfp_80::p40>; | ||
|
||
// init it as a pin in | ||
bootloader_pin::init(); | ||
|
||
// check if we should run the user application | ||
if (!bootloader_pin::get() && !target::io::flash::is_blank(app_vector_address)) { | ||
// boot the application | ||
start_application(); | ||
|
||
// we will never get here as "start_application" | ||
// has the noreturn attribute. We are also | ||
// overriding the stack. This prevents the user | ||
// application from returning to this place as | ||
// the stack is probably pointing somewhere | ||
// else by then | ||
} | ||
|
||
// setup the flash wait state to 4 + 1 CPU clocks | ||
target::io::system::flash::setup<4>(); | ||
|
||
// using for setting up the main clock | ||
using clock = target::io::system::clock; | ||
|
||
// setup the clock to 96Mhz from the 12mhz oscillator | ||
// to speed up the dfu flash programming | ||
// (((15 + 1) * 2 * 12Mhz) / (0 + 1) = 384Mhz) / (3 + 1) = 96Mhz | ||
clock::set_main<clock::source::main, 96'000'000, 15, 0, 3>(); | ||
|
||
// setup the vector table for the usb interrupts | ||
target::irq::init(); | ||
|
||
// bootloader mode. configure the usb pll | ||
target::io::system::clock::set_usb<12'000'000>(); | ||
|
||
// init the usb hardware | ||
usb_bulk::init<true, true, false>(); | ||
|
||
// wait until we are reset in the dfu handler | ||
while (true) { | ||
// do nothing | ||
} | ||
} |