diff --git a/CMakeLists.txt b/CMakeLists.txt index 1013cf0d..f627ae63 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,8 +4,6 @@ # ASM is crucial enable_language(ASM-ATT) -# Subproject may use tests -enable_testing() # Obvious requirement cmake_minimum_required(VERSION 3.4) @@ -138,4 +136,4 @@ add_subdirectory(lib) add_subdirectory(dev) add_subdirectory(kernel) add_dependencies(all_cppcheck ${PROJECT_NAME}) -add_dependencies(${PROJECT_NAME} thecore_validate) \ No newline at end of file +add_dependencies(${PROJECT_NAME} thecore_validate) diff --git a/arch/arm_cm/CMakeLists.txt b/arch/arm_cm/CMakeLists.txt index 758c589c..a6f386d6 100644 --- a/arch/arm_cm/CMakeLists.txt +++ b/arch/arm_cm/CMakeLists.txt @@ -3,13 +3,19 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. # ARM Cortex-M architecture -add_library(arch STATIC startup_arm_cm.S arch.cpp) +if(TARGET_MCU_ARCH MATCHES "^arm_cm0") + # Slightely different architecture used there + add_library(arch STATIC startup_arm_cm0.S arch.cpp) +else() + add_library(arch STATIC startup_arm_cm.S arch.cpp) +endif() # By default CMake do not pass compile definitions to ASM files. # Probably due to the fact that it depends on assembler used and some of the # assemblers may not support preprocessing. # This command forces use of gcc instead of as. It allows to pass compile definitions set_source_files_properties(startup_arm_cm.S PROPERTIES LANGUAGE C) +set_source_files_properties(startup_arm_cm0.S PROPERTIES LANGUAGE C) # ASM code requires some symbols present in outer libraries target_link_libraries(arch PRIVATE sys) @@ -54,6 +60,21 @@ if(NOT TARGET_PLATFORM_IS_NOT_CMSIS_COMPLIANT) target_sources(arch PUBLIC ${CMAKE_CURRENT_LIST_DIR}/execution.cpp) endif() +# Custom stack size +if(TARGET_STACK_SIZE) + target_compile_definitions(arch PRIVATE -D__STACK_SIZE=${TARGET_STACK_SIZE}) +endif() + +# Custom heap size +if(TARGET_HEAP_SIZE) + target_compile_definitions(arch PRIVATE -D__HEAP_SIZE=${TARGET_HEAP_SIZE}) +endif() + +# Kinetis-specific definitions +if(TARGET_KINETIS_FLASH_PROTECT_SECTION) + target_compile_definitions(arch PRIVATE -DTARGET_KINETIS_FLASH_PROTECT_SECTION=1) +endif() + # Apply memory layout configure_file(gcc_arm_cm.ld ${CMAKE_CURRENT_BINARY_DIR}/gcc_arm_cm.ld) diff --git a/arch/arm_cm/arch.cpp b/arch/arm_cm/arch.cpp index f6891cc0..076b1ece 100644 --- a/arch/arm_cm/arch.cpp +++ b/arch/arm_cm/arch.cpp @@ -8,9 +8,11 @@ extern "C" void __attribute__((naked)) arch_delay(uint32_t loop_count) { (void)loop_count; #if defined ( __GNUC__ ) - __asm(" subs r0, #1\n" - " bne arch_delay\n" - " bx lr"); + __asm(" .syntax unified\n" + " subs r0, #1\n" + " bne arch_delay\n" + " bx lr\n" + " .syntax divided\n"); #else #error Not yet implemented for your compiler #endif diff --git a/arch/arm_cm/export/arch/defs.S b/arch/arm_cm/export/arch/defs.S new file mode 100644 index 00000000..9d33b708 --- /dev/null +++ b/arch/arm_cm/export/arch/defs.S @@ -0,0 +1,12 @@ +#ifndef ARCH_ASM_DEFS_H_ +#define ARCH_ASM_DEFS_H_ + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + +#endif /* ARCH_ASM_DEFS_H_ */ diff --git a/arch/arm_cm/export/arch/execution.hpp b/arch/arm_cm/export/arch/execution.hpp index 412ad566..6fed3afe 100644 --- a/arch/arm_cm/export/arch/execution.hpp +++ b/arch/arm_cm/export/arch/execution.hpp @@ -18,6 +18,8 @@ #include #elif defined arm_cm3 #include +#elif defined arm_cm0plus +#include #endif #include diff --git a/arch/arm_cm/gcc_arm_cm.ld b/arch/arm_cm/gcc_arm_cm.ld index 3f2f4692..9472ec82 100644 --- a/arch/arm_cm/gcc_arm_cm.ld +++ b/arch/arm_cm/gcc_arm_cm.ld @@ -121,6 +121,8 @@ SECTIONS } > FLASH */ + . = ALIGN(4); + __etext = .; .data : AT (__etext) @@ -129,7 +131,6 @@ SECTIONS *(vtable) *(.data*) - . = ALIGN(4); /* preinit data */ PROVIDE_HIDDEN (__preinit_array_start = .); KEEP(*(.preinit_array)) diff --git a/arch/arm_cm/startup_arm_cm.S b/arch/arm_cm/startup_arm_cm.S index c604fdb5..ed74cd0c 100644 --- a/arch/arm_cm/startup_arm_cm.S +++ b/arch/arm_cm/startup_arm_cm.S @@ -51,6 +51,8 @@ __StackLimit: __StackTop: .size __StackTop, . - __StackTop + .include "arch/defs.S" + .section .heap .align 3 #ifdef __HEAP_SIZE @@ -238,14 +240,6 @@ Default_Handler: b . .size Default_Handler, . - Default_Handler -/* Macro to define default handlers. Default handler - * will be weak symbol and just dead loops. They can be - * overwritten by other handlers */ - .macro def_irq_handler handler_name - .weak \handler_name - .set \handler_name, Default_Handler - .endm - def_irq_handler NMI_Handler def_irq_handler HardFault_Handler def_irq_handler MemManage_Handler diff --git a/arch/arm_cm/startup_arm_cm0.S b/arch/arm_cm/startup_arm_cm0.S new file mode 100644 index 00000000..a7821395 --- /dev/null +++ b/arch/arm_cm/startup_arm_cm0.S @@ -0,0 +1,297 @@ +/* File: startup_ARMCM0.S + * Purpose: startup file for Cortex-M0 devices. Should use with + * GCC for ARM Embedded Processors + * Version: V2.01 + * Date: 12 June 2014 + * + */ +/* Copyright (c) 2011 - 2014 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + + .syntax unified + .arch armv6-m + + .section .stack + .align 3 +#ifdef __STACK_SIZE + .equ Stack_Size, __STACK_SIZE +#else + .equ Stack_Size, 0x00000400 +#endif + .globl __StackTop + .globl __StackLimit +__StackLimit: + .space Stack_Size + .size __StackLimit, . - __StackLimit +__StackTop: + .size __StackTop, . - __StackTop + + .include "arch/defs.S" + + .section .heap + .align 3 +#ifdef __HEAP_SIZE + .equ Heap_Size, __HEAP_SIZE +#else + .equ Heap_Size, 0x00000C00 +#endif + .globl __HeapBase + .globl __HeapLimit +__HeapBase: + .if Heap_Size + .space Heap_Size + .endif + .size __HeapBase, . - __HeapBase +__HeapLimit: + .size __HeapLimit, . - __HeapLimit + + .section .vectors + .align 2 + .globl __Vectors +__Vectors: + .long __StackTop /* Top of Stack */ + .long Reset_Handler /* Reset Handler */ + .long NMI_Handler /* NMI Handler */ + .long HardFault_Handler /* Hard Fault Handler */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long SVC_Handler /* SVCall Handler */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long PendSV_Handler /* PendSV Handler */ + .long SysTick_Handler /* SysTick Handler */ + + /* External interrupts, provided by the platform */ +#include "platform/irq.S" + + .size __Vectors, . - __Vectors + + /* Flash protect - only for Freescale Kinetis */ +#ifdef TARGET_KINETIS_FLASH_PROTECT_SECTION + .equ BackDoorK0, 0xFF + .equ BackDoorK1, 0xFF + .equ BackDoorK2, 0xFF + .equ BackDoorK3, 0xFF + .equ BackDoorK4, 0xFF + .equ BackDoorK5, 0xFF + .equ BackDoorK6, 0xFF + .equ BackDoorK7, 0xFF + + .equ EEPROT, 0xFF + + .equ FPROT, 0xFF + + .equ FSEC, 0xFE + + .equ FOPT, 0xFE + + .org 0x400 + .byte BackDoorK0 + .byte BackDoorK1 + .byte BackDoorK2 + .byte BackDoorK3 + .byte BackDoorK4 + .byte BackDoorK5 + .byte BackDoorK6 + .byte BackDoorK7 + .byte 0xFF /* Reserved */ + .byte 0xFF /* Reserved */ + .byte 0xFF /* Reserved */ + .byte 0xFF /* Reserved */ + .byte EEPROT + .byte FPROT + .byte FSEC + .byte FOPT +#endif + + .text + .thumb + .thumb_func + .align 1 + .globl Reset_Handler + .type Reset_Handler, %function +Reset_Handler: +/* Firstly it copies data from read only memory to RAM. There are two schemes + * to copy. One can copy more than one sections. Another can only copy + * one section. The former scheme needs more instructions and read-only + * data to implement than the latter. + * Macro __STARTUP_COPY_MULTIPLE is used to choose between two schemes. */ + +#ifdef __STARTUP_COPY_MULTIPLE +/* Multiple sections scheme. + * + * Between symbol address __copy_table_start__ and __copy_table_end__, + * there are array of triplets, each of which specify: + * offset 0: LMA of start of a section to copy from + * offset 4: VMA of start of a section to copy to + * offset 8: size of the section to copy. Must be multiply of 4 + * + * All addresses must be aligned to 4 bytes boundary. + */ + ldr r4, =__copy_table_start__ + ldr r5, =__copy_table_end__ + +.L_loop0: + cmp r4, r5 + bge .L_loop0_done + ldr r1, [r4] + ldr r2, [r4, #4] + ldr r3, [r4, #8] + +.L_loop0_0: + subs r3, #4 + blt .L_loop0_0_done + ldr r0, [r1, r3] + str r0, [r2, r3] + b .L_loop0_0 + +.L_loop0_0_done: + adds r4, #12 + b .L_loop0 + +.L_loop0_done: +#else +/* Single section scheme. + * + * The ranges of copy from/to are specified by following symbols + * __etext: LMA of start of the section to copy from. Usually end of text + * __data_start__: VMA of start of the section to copy to + * __data_end__: VMA of end of the section to copy to + * + * All addresses must be aligned to 4 bytes boundary. + */ + ldr r1, =__etext + ldr r2, =__data_start__ + ldr r3, =__data_end__ + + subs r3, r2 + ble .L_loop1_done + +.L_loop1: + subs r3, #4 + ldr r0, [r1,r3] + str r0, [r2,r3] + bgt .L_loop1 + +.L_loop1_done: +#endif /*__STARTUP_COPY_MULTIPLE */ + +/* This part of work usually is done in C library startup code. Otherwise, + * define this macro to enable it in this startup. + * + * There are two schemes too. One can clear multiple BSS sections. Another + * can only clear one section. The former is more size expensive than the + * latter. + * + * Define macro __STARTUP_CLEAR_BSS_MULTIPLE to choose the former. + * Otherwise efine macro __STARTUP_CLEAR_BSS to choose the later. + */ +#ifdef __STARTUP_CLEAR_BSS_MULTIPLE +/* Multiple sections scheme. + * + * Between symbol address __copy_table_start__ and __copy_table_end__, + * there are array of tuples specifying: + * offset 0: Start of a BSS section + * offset 4: Size of this BSS section. Must be multiply of 4 + */ + ldr r3, =__zero_table_start__ + ldr r4, =__zero_table_end__ + +.L_loop2: + cmp r3, r4 + bge .L_loop2_done + ldr r1, [r3] + ldr r2, [r3, #4] + movs r0, 0 + +.L_loop2_0: + subs r2, #4 + blt .L_loop2_0_done + str r0, [r1, r2] + b .L_loop2_0 +.L_loop2_0_done: + + adds r3, #8 + b .L_loop2 +.L_loop2_done: +#elif defined (__STARTUP_CLEAR_BSS) +/* Single BSS section scheme. + * + * The BSS section is specified by following symbols + * __bss_start__: start of the BSS section. + * __bss_end__: end of the BSS section. + * + * Both addresses must be aligned to 4 bytes boundary. + */ + ldr r1, =__bss_start__ + ldr r2, =__bss_end__ + + movs r0, 0 + + subs r2, r1 + ble .L_loop3_done + +.L_loop3: + subs r2, #4 + str r0, [r1, r2] + bgt .L_loop3 +.L_loop3_done: +#endif /* __STARTUP_CLEAR_BSS_MULTIPLE || __STARTUP_CLEAR_BSS */ + +#ifndef __NO_SYSTEM_INIT + bl SystemInit +#endif + +#ifndef __START +#define __START _start +#endif + bl __START + + .pool + .size Reset_Handler, . - Reset_Handler + + .align 1 + .thumb_func + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + b . + .size Default_Handler, . - Default_Handler + + def_irq_handler NMI_Handler + def_irq_handler HardFault_Handler + def_irq_handler SVC_Handler + def_irq_handler PendSV_Handler + def_irq_handler SysTick_Handler + + .end diff --git a/build_api.cmake b/build_api.cmake index b4e9a95d..739ffb2d 100644 --- a/build_api.cmake +++ b/build_api.cmake @@ -48,7 +48,7 @@ endfunction(msg_trace) # Add test only if not cross-compiling if(CMAKE_HOST_SYSTEM_NAME STREQUAL CMAKE_SYSTEM_NAME) find_package(CppUTest) - if(NOT ${CPPUTEST_FOUND}) + if(NOT CPPUTEST_FOUND) msg_warn("CppUTest library not present. Tests are disabled.") endif() endif() @@ -63,6 +63,10 @@ endif() # [INC_DIRS list_of_include_directories...] # [COMPILE_OPTIONS list_of_compiler_options...]) function(add_unit_host_test) + if(NOT BUILD_TESTING) + return() + endif() + set(CC_WARN_FLAGS -Wall -Wextra -Wpedantic -Werror) set(CXX_WARN_FLAGS ${CC_WARN_FLAGS}) @@ -281,6 +285,8 @@ function(theCore_get_thirdparty_cmd NAME GIT_REMOTE GIT_COMMIT) endif() msg_trace("Requested thirdparty: ${NAME} from: ${GIT_REMOTE} commit: ${GIT_COMMIT}") + msg_trace("Thirdparty git: ${THECORE_THIRDPARTY_DIR}/${NAME}") + msg_trace("Thirdparty worktree: ${THECORE_BUILD_THIRDPARTY_DIR}/${NAME}") if(NOT THECORE_THIRDPARTY_DIR) msg_fatal("THECORE_THIRDPARTY_DIR must be specified in order to persist thirdparty packages") diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 4f76ad16..8b839ff9 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -17,6 +17,7 @@ set(THECORE_BUILD_THIRDPARTY_DIR "${CMAKE_CURRENT_BINARY_DIR}/thirdparty_worktre # Convinient alias set(ARM_CM4_GNU_TOOLCHAIN ${CMAKE_CURRENT_LIST_DIR}/../toolchains/arm-cm4-gnu.cmake) +set(ARM_CM0_PLUS_GNU_TOOLCHAIN ${CMAKE_CURRENT_LIST_DIR}/../toolchains/arm-cm0-plus-gnu.cmake) ################################################################################ # Hello World host example. @@ -104,8 +105,20 @@ ExternalProject_Add(tm4c_fatfs SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/tm4c_fatfs CMAKE_ARGS -DTHECORE_BUILD_THIRDPARTY_DIR=${THECORE_BUILD_THIRDPARTY_DIR} - -DEXAMPLE_TARGET=tivac -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_TOOLCHAIN_FILE=${ARM_CM4_GNU_TOOLCHAIN} BUILD_ALWAYS 1 # Allows to rebuild external project if its files changes INSTALL_COMMAND echo "Install isn't required, skipping...") + +################################################################################ +# KE02 example +################################################################################ + +ExternalProject_Add(ke02_hello + SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/ke02_hello + CMAKE_ARGS + -DTHECORE_BUILD_THIRDPARTY_DIR=${THECORE_BUILD_THIRDPARTY_DIR} + -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + -DCMAKE_TOOLCHAIN_FILE=${ARM_CM0_PLUS_GNU_TOOLCHAIN} + BUILD_ALWAYS 1 # Allows to rebuild external project if its files changes + INSTALL_COMMAND echo "Install isn't required, skipping...") diff --git a/examples/ke02_hello/CMakeLists.txt b/examples/ke02_hello/CMakeLists.txt new file mode 100644 index 00000000..9a4e5334 --- /dev/null +++ b/examples/ke02_hello/CMakeLists.txt @@ -0,0 +1,29 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +cmake_minimum_required(VERSION 3.2) + +# Objvious. +project(ke02_hello) + +# theCore framework directory. +set(CORE_DIR ../../) + +# Required. +include(${CORE_DIR}/build_api.cmake) + +# Our demo sources. +add_executable(ke02_hello main.cpp) + +# Some dependencies +target_link_libraries(ke02_hello the_core) + +# Configuration parameters +theCore_set_target_config(${CMAKE_CURRENT_LIST_DIR}/target.json) + +# Include theCore into the build process +add_subdirectory(${CORE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/core) + +# Produce complete binary, suitable for flashing to the target +strip_executable(ke02_hello) diff --git a/examples/ke02_hello/README.md b/examples/ke02_hello/README.md new file mode 100644 index 00000000..2844e090 --- /dev/null +++ b/examples/ke02_hello/README.md @@ -0,0 +1 @@ +# theCore _KE02 hello_ example diff --git a/examples/ke02_hello/main.cpp b/examples/ke02_hello/main.cpp new file mode 100644 index 00000000..b24755fb --- /dev/null +++ b/examples/ke02_hello/main.cpp @@ -0,0 +1,36 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include +#include +#include + +extern "C" +void board_init() +{ + +} + +int main() +{ + ecl::cout << "Hello, Host World!" << ecl::endl << ecl::endl; + + ecl::cout << "Starting delay test..." << ecl::endl << ecl::endl; + + ecl::cout << "[--] Waiting for 2 seconds" << ecl::endl; + ecl::spin_wait(2000); + ecl::cout << "[--] Done waiting 2 seconds" << ecl::endl << ecl::endl; + + ecl::cout << "[----] Waiting for 4 seconds" << ecl::endl; + ecl::spin_wait(4000); + ecl::cout << "[----] Done waiting 4 seconds" << ecl::endl << ecl::endl; + + ecl::cout << "[--------] Waiting for 8 seconds" << ecl::endl; + ecl::spin_wait(8000); + ecl::cout << "[--------] Done waiting 8 seconds" << ecl::endl << ecl::endl; + + ecl_assert_msg(1 == 0, "This is an assert demonstration. Application will abort."); + + return 0; +} diff --git a/examples/ke02_hello/target.json b/examples/ke02_hello/target.json new file mode 100644 index 00000000..18c2f196 --- /dev/null +++ b/examples/ke02_hello/target.json @@ -0,0 +1,14 @@ +{ + "platform": { + "name": "ke02", + "device": "KE02Z2", + "console": "UART1", + + "uart": [ + { + "id": "UART1", + "comment": "UART-over-USB console output" + } + ] + } +} diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index e2843a9e..6386e109 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -25,6 +25,7 @@ add_subdirectory(stm32-spl) add_subdirectory(ti-tivaware) add_subdirectory(unity) add_subdirectory(particle_firmware) +add_subdirectory(kexx_drv) # Some platforms may not feel well with definitions in FAT headers # TODO: fix it. diff --git a/lib/debug/CMakeLists.txt b/lib/debug/CMakeLists.txt index e1732fd5..5c5e431d 100644 --- a/lib/debug/CMakeLists.txt +++ b/lib/debug/CMakeLists.txt @@ -4,4 +4,4 @@ add_library(dbg STATIC ${CMAKE_CURRENT_LIST_DIR}/assert.cpp) target_include_directories(dbg PUBLIC export types) -target_link_libraries(dbg PUBLIC ${PLATFORM_NAME}) +target_link_libraries(dbg PUBLIC platform_common utils ${PLATFORM_NAME}) diff --git a/lib/kexx_drv/CMakeLists.txt b/lib/kexx_drv/CMakeLists.txt new file mode 100644 index 00000000..d23e100c --- /dev/null +++ b/lib/kexx_drv/CMakeLists.txt @@ -0,0 +1,52 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +if(CONFIG_PLATFORM STREQUAL "ke02") + theCore_get_thirdparty(kexx_drv https://github.com/forGGe/kexx_driverlib 93eaf3f5d) +else() + return() +endif() + +set(KEXX_DRV_DIR ${THECORE_BUILD_THIRDPARTY_DIR}/kexx_drv) +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-error") + +add_library(kexx_drv STATIC + ${KEXX_DRV_DIR}/src/drivers/uart/uart.c + ${KEXX_DRV_DIR}/src/drivers/gpio/gpio.c + ${KEXX_DRV_DIR}/src/drivers/ics/ics.c + ${KEXX_DRV_DIR}/src/drivers/sim/sim.c + ${KEXX_DRV_DIR}/src/drivers/pit/pit.c + ${KEXX_DRV_DIR}/src/drivers/nvm/flash.c + ${KEXX_DRV_DIR}/src/drivers/ftm/ftm.c + ${KEXX_DRV_DIR}/src/drivers/wdog/wdog.c + ${KEXX_DRV_DIR}/src/drivers/adc/adc.c + ${KEXX_DRV_DIR}/src/drivers/kbi/kbi.c + ${KEXX_DRV_DIR}/src/cpu/sysinit.c + ${KEXX_DRV_DIR}/src/common/assert.c + # All I/O functions are intentionally avoided, + # due to hard-coded output device. Instead, theCore provides its + # own I/O implementation. + # ${KEXX_DRV_DIR}/src/common/io.c + ${KEXX_DRV_DIR}/src/common/printf.c + ${KEXX_DRV_DIR}/src/common/alloc.c) + +target_include_directories(kexx_drv SYSTEM PUBLIC + ${KEXX_DRV_DIR}/src/drivers/uart/ + ${KEXX_DRV_DIR}/src/drivers/gpio/ + ${KEXX_DRV_DIR}/src/drivers/wdog/ + ${KEXX_DRV_DIR}/src/drivers/sim/ + ${KEXX_DRV_DIR}/src/drivers/ics/ + ${KEXX_DRV_DIR}/src/drivers/pit/ + ${KEXX_DRV_DIR}/src/drivers/nvm/ + ${KEXX_DRV_DIR}/src/drivers/ftm/ + ${KEXX_DRV_DIR}/src/drivers/adc/ + ${KEXX_DRV_DIR}/src/drivers/kbi/ + ${KEXX_DRV_DIR}/src/platforms/ + ${KEXX_DRV_DIR}/src/common/ + ${KEXX_DRV_DIR}/src/cpu/headers + ${KEXX_DRV_DIR}/src/cpu/) + +# TODO: move it to the header, rather than compile difinitions +target_compile_definitions(kexx_drv PUBLIC -DFRDM_KE02 -DCPU_KE02) +target_link_libraries(kexx_drv PUBLIC cmsis) diff --git a/lib/newlib/stubs.cpp b/lib/newlib/stubs.cpp index 63a799f3..a104c6f3 100644 --- a/lib/newlib/stubs.cpp +++ b/lib/newlib/stubs.cpp @@ -8,6 +8,7 @@ //! Examples include forking or using memory allocations. #include +#include #include #include @@ -33,6 +34,20 @@ int _close(int file) return -1; } +int _isatty(int file) +{ + switch (file) + { + case STDOUT_FILENO: + case STDERR_FILENO: + case STDIN_FILENO: + return 1; + default: + errno = EBADF; + return 0; + } +} + extern "C" char *__env[1]; @@ -113,11 +128,22 @@ int _read(int file, void *ptr, size_t len) return -1; } +extern uint8_t __HeapBase; +extern uint8_t __HeapLimit; +static uint8_t *heap_current = &__HeapBase; +static uint8_t *heap_end = &__HeapLimit; + extern "C" void *_sbrk(ptrdiff_t incr) { - (void)incr; - ecl::abort(); // Dynamic allocation is not allowed by default. + if (heap_current + incr > heap_end) { + ecl::abort(); // TODO: better handling + errno = ENOMEM; + return nullptr; + } + + heap_current += incr; + return heap_current; } extern "C" @@ -155,9 +181,14 @@ int _wait(int *status) extern "C" int _write(int file, const void *ptr, size_t sz) { - (void)file; - (void)ptr; - (void)sz; - errno = EBADF; - return -1; + if (file != STDOUT_FILENO || file != STDERR_FILENO) { + errno = EBADF; + return -1; + } + + for (size_t i = 0; i < sz; ++i) { + ecl::bypass_putc(static_cast(ptr)[i]); + } + + return 0; } diff --git a/platform/common/CMakeLists.txt b/platform/common/CMakeLists.txt index 297ef6c4..0e6f736e 100644 --- a/platform/common/CMakeLists.txt +++ b/platform/common/CMakeLists.txt @@ -5,7 +5,7 @@ if(PLATFORM_NAME STREQUAL host) add_library(platform_common INTERFACE) target_include_directories(platform_common INTERFACE export) - target_link_libraries(platform_common INTERFACE dbg utils) + target_link_libraries(platform_common INTERFACE utils) else() # IRQ management must be enabled only if cross-compiling for embedded boards @@ -13,8 +13,7 @@ else() target_include_directories(platform_common PUBLIC export) - target_link_libraries(platform_common PUBLIC ${PLATFORM_NAME} types) - target_link_libraries(platform_common PRIVATE dbg utils) + target_link_libraries(platform_common PUBLIC ${PLATFORM_NAME} dbg types utils) target_compile_definitions(platform_common PRIVATE -DIRQ_COUNT=${TARGET_MCU_IRQ_COUNT}) endif() diff --git a/platform/common/export/common/console.hpp b/platform/common/export/common/console.hpp index 8c2a3eb1..fff07be8 100644 --- a/platform/common/export/common/console.hpp +++ b/platform/common/export/common/console.hpp @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ //! \file -//! \brief Common bypas console implementation. +//! \brief Common bypass console implementation. #ifndef PLATFORM_COMMON_CONSOLE_HPP_ #define PLATFORM_COMMON_CONSOLE_HPP_ diff --git a/platform/ke02/CMakeLists.txt b/platform/ke02/CMakeLists.txt new file mode 100644 index 00000000..5381da72 --- /dev/null +++ b/platform/ke02/CMakeLists.txt @@ -0,0 +1,76 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +file(MAKE_DIRECTORY ${CORE_GEN_DIR}/export/aux) + +add_library(ke02 platform.cpp) + +include(mcu_cfg.cmake) + +target_link_libraries(ke02 PUBLIC arch cmsis kexx_drv platform_common dbg utils containers) + +target_include_directories(ke02 PUBLIC export) + +# Validate incoming JSON +theCore_create_json_validator_runner( + NAME ke02_validate + JSON ${THECORE_TARGET_CONFIG_FILE} + SCHEMA ${CMAKE_CURRENT_LIST_DIR}/schemas/ke02.schema.json + SUBOBJECT "platform" + WORKDIR ${CMAKE_CURRENT_LIST_DIR}/schemas +) + +#------------------------------------------------------------------------------- + +# Convenient function to generate ke02 platform files. +function(generate_source IN_NAME OUT_NAME) + # Place header in separate directory + if(OUT_NAME MATCHES "\.hpp$") + set(OUT_DIR ${CORE_GEN_DIR}/export/aux) + else() + set(OUT_DIR ${CORE_GEN_DIR}) + endif() + + set(OUT_PATH "${OUT_DIR}/${OUT_NAME}") + set(IN_PATH "${CMAKE_CURRENT_LIST_DIR}/templates/${IN_NAME}") + list(APPEND GENERATED_FILES ${OUT_PATH}) + set(GENERATED_FILES ${GENERATED_FILES} PARENT_SCOPE) + + theCore_create_cog_runner( + IN ${IN_PATH} + OUT ${OUT_PATH} + DEPENDS ${THECORE_TARGET_CONFIG_FILE} ${IN_PATH} + ARGS "-DJSON_CFG=${THECORE_TARGET_CONFIG_FILE}") +endfunction() + +#------------------------------------------------------------------------------- + +# Generate platform definitions. +generate_source(defines.in.hpp platform_defines.hpp) + +# Generate UART definitions. +generate_source(uart_cfg.in.hpp uart_cfg.hpp) + +#------------------------------------------------------------------------------- + +# Enable console driver. + +msg_trace("KE02: Checking console configuration") +if(DEFINED thecore_cfg.platform.console) + msg_info("Console driver will be used") + # Bypass console must be enabled automatically. + set(THECORE_CONFIG_USE_CONSOLE 1 CACHE FORCE "Console enable flag") + target_sources(ke02 PUBLIC ${CMAKE_CURRENT_LIST_DIR}/console.cpp) +endif() + +if(NOT CONFIG_OS) + target_compile_definitions(ke02 PUBLIC -DTHECORE_NO_OS=1) +endif() + +#------------------------------------------------------------------------------- + +# Tie all generated code together. +add_custom_target(platform_generated DEPENDS ke02_validate ${GENERATED_FILES}) +add_dependencies(ke02 platform_generated) +target_include_directories(ke02 PUBLIC ${CORE_GEN_DIR}/export/) diff --git a/platform/ke02/console.cpp b/platform/ke02/console.cpp new file mode 100644 index 00000000..756b45e6 --- /dev/null +++ b/platform/ke02/console.cpp @@ -0,0 +1,46 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include // Test if we need this or not. +#include + +#include "platform/console.hpp" + +namespace ecl +{ +//! \addtogroup platform Platform defintions and drivers +//! @{ + +//! \addtogroup ke02 Freescale FRDM-KE02Z platform +//! @{ + +//! \defgroup ke02_console Console +//! @{ + +//! \file +//! \brief KE02 bypass console implementation. + +void bypass_console_init() +{ + UART_ConfigType sConfig; + + sConfig.u32SysClkHz = BUS_CLK_HZ; + sConfig.u32Baudrate = UART_PRINT_BITRATE; // 115200 + + UART_Init(platform_console::pick_sysctl(), &sConfig); +} + +void bypass_putc(char c) +{ + UART_PutChar(platform_console::pick_sysctl(), c); +} + +//! @} + +//! @} + +//! @} +} // namespace ecl diff --git a/platform/ke02/export/aux/generated.hpp b/platform/ke02/export/aux/generated.hpp new file mode 100644 index 00000000..044e65ae --- /dev/null +++ b/platform/ke02/export/aux/generated.hpp @@ -0,0 +1,30 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//! \addtogroup platform Platform defintions and drivers +//! @{ + +//! \addtogroup ke02 Freescale Kinetis KE02 platform +//! @{ + +//! \defgroup ke02_other Other modules +//! @{ + +//! \file +//! \brief Enlists all generated headers by tm4c platform. Further used +//! by theCore or the user. +#ifndef KE02_PLATFORM_GENERATED_HPP_ +#define KE02_PLATFORM_GENERATED_HPP_ + +#include "aux/platform_defines.hpp" +#include "aux/uart_cfg.hpp" + +#endif // KE02_PLATFORM_GENERATED_HPP_ + +//! @} + +//! @} + +//! @} + diff --git a/platform/ke02/export/aux/uart.hpp b/platform/ke02/export/aux/uart.hpp new file mode 100644 index 00000000..18d34e00 --- /dev/null +++ b/platform/ke02/export/aux/uart.hpp @@ -0,0 +1,347 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//! \file +//! \brief UART implementation for Freescale Kinetis KE02 MCU +//! \ingroup ke02_uart + +#ifndef PLATFORM_KE02_UART_HPP_ +#define PLATFORM_KE02_UART_HPP_ + +#include + +#include +#include +#include + +// Platform vendor lib. +#include // Test if we need this or not. +#include + +namespace ecl +{ + +//! \addtogroup platform Platform defintions and drivers +//! @{ + +//! \addtogroup ke02 Freescale Kinetis KE02 platform +//! @{ + +//! \defgroup ke02_uart UART driver +//! @{ + +//! Represents distinct UART peripheral devices (channels) +enum class uart_channel +{ + ch0 = UART0_BASE, + ch1 = UART1_BASE, + ch2 = UART2_BASE, +}; + +//! UART driver. +//! \tparam ch Peripheral channel to use with this driver +template +class uart +{ + //! Bypass console routines, partially reuse UART driver code. + friend void bypass_console_init(); + friend void bypass_putc(char c); +public: + + //! \brief Lazy initialization. + //! \return Status of operation. + static err init(); + + //! \brief Sets rx buffer with given size. + //! \param[in,out] rx Buffer to write data to. Optional. + //! \param[in] size Size + static void set_rx(uint8_t *rx, size_t size); + + //! \brief Sets rx buffer made-up from sequence of similar bytes. + //! \param[in] size Size of sequence + //! \param[in] fill_byte Byte to fill a sequence. Optional. + static void set_tx(size_t size, uint8_t fill_byte = 0xff); + + //! \brief Sets tx buffer with given size. + //! \param[in] tx Buffer to transmit. Optional. + //! \param[in] size Buffer size. + static void set_tx(const uint8_t *tx, size_t size); + + //! \brief Sets event handler. + //! Handler will be used by the bus, until reset_handler() will be called. + //! \param[in] handler Handler itself. + static void set_handler(const bus_handler &handler); + + //! \brief Reset xfer buffers. + //! Buffers that were set by \sa set_tx() and \sa set_rx() + //! will be no longer used after this call. + static void reset_buffers(); + + //! \brief Resets previously set handler. + static void reset_handler(); + + //! \brief Executes xfer, using buffers previously set. + //! When it will be done, handler will be invoked. + //! \return Status of operation. + static err do_xfer(); + + //! \brief Cancels xfer. + //! After this call no xfer will occur. + //! \return Status of operation. + static err cancel_xfer(); + + uart(const uart&) = delete; + uart &operator=(uart&) = delete; + +private: + //! Gets SYSCTL associated with given UART. + static constexpr auto pick_sysctl(); + + //! Gets UART bus context. + static constexpr auto &get_ctx(); + + //! Stub handler, called in case if no one listens for bus events. + static void stub_handler(bus_channel, bus_event, size_t) + { + ecl_assert_msg(false, "UART event wasn't handled"); + } + + //! Private context of the UART bus driver. + struct ctx + { + //! Constructs default context. + ctx() + :h{stub_handler}, + tx{nullptr}, + tx_sz{0}, + tx_idx{0}, + rx{nullptr}, + rx_sz{0}, + rx_idx{0}, + status{0} + { } + + // Ctx is not CopyConstructible. + ctx(const ctx&) = delete; + ctx &operator=(ctx&) = delete; + + //! Bit set in status field if bus is initialized. + static constexpr uint8_t inited = 0x1; + //! Bit set in status field if bus is in fill mode. + static constexpr uint8_t fill = 0x2; + //! Bit set in status field if bus is finished with TX. + static constexpr uint8_t tx_done = 0x4; + //! Bit set in status field if bus is finished with RX. + static constexpr uint8_t rx_done = 0x8; + + bus_handler h; //! Event handler. + union + { + const uint8_t *buf; //! TX buffer. + uint8_t fill_byte; //! Fill byte. + } tx; + + size_t tx_sz; //! TX buffer size. + //! TX buffer current index. + //! In fill mode it counts bytes written. + size_t tx_idx; + uint8_t *rx; //! RX buffer. + size_t rx_sz; //! RX buffer size. + size_t rx_idx; //! RX buffer current index. + uint8_t status; //! Bus status. + }; + + //! Private context storage. + //! \details Default-initialized during static objects zero-initialization. + //! Afterwards, init() is responsible of calling non-trival ctor of ctx. + static safe_storage m_ctx_storage; +}; + +template +safe_storage::ctx> uart::m_ctx_storage; + +//------------------------------------------------------------------------------ +// Private members + +template +constexpr auto uart::pick_sysctl() +{ + switch (ch) { + case uart_channel::ch0: + return UART0; + case uart_channel::ch1: + return UART1; + case uart_channel::ch2: + return UART2; + } +} + +template +constexpr auto &uart::get_ctx() +{ + return m_ctx_storage.get(); +} + +//------------------------------------------------------------------------------ + +template +err uart::init() +{ + // POD-type fields of ctx will be initialized to 0, so it is valid to access + // flags there. + auto &bus_ctx = get_ctx(); + + ecl_assert(!bus_ctx.status); + + constexpr auto periph_sysctl = pick_sysctl(); + + m_ctx_storage.init(); + + UART_ConfigType sConfig; + + sConfig.u32SysClkHz = BUS_CLK_HZ; + sConfig.u32Baudrate = UART_PRINT_BITRATE; // 115200 + + UART_Init(periph_sysctl, &sConfig); + + bus_ctx.status |= (ctx::inited | ctx::rx_done | ctx::tx_done); + return err::ok; +} + +template +void uart::set_rx(uint8_t *rx, size_t size) +{ + auto &bus_ctx = get_ctx(); + + ecl_assert((bus_ctx.status & (ctx::inited | ctx::rx_done)) + == (ctx::inited | ctx::rx_done)); + + bus_ctx.rx = rx; + bus_ctx.rx_sz = size; + bus_ctx.rx_idx = 0; +} + +template +void uart::set_tx(const uint8_t *tx, size_t size) +{ + auto &bus_ctx = get_ctx(); + + ecl_assert((bus_ctx.status & (ctx::inited | ctx::tx_done)) + == (ctx::inited | ctx::tx_done)); + + bus_ctx.tx.buf = tx; + bus_ctx.tx_sz = size; + bus_ctx.tx_idx = 0; + + bus_ctx.status &= ~ctx::fill; +} + +template +void uart::set_tx(size_t size, uint8_t fill_byte) +{ + auto &bus_ctx = get_ctx(); + + ecl_assert((bus_ctx.status & (ctx::inited | ctx::tx_done)) + == (ctx::inited | ctx::tx_done)); + + bus_ctx.tx.fill_byte = fill_byte; + bus_ctx.tx_sz = size; + + bus_ctx.status |= ctx::fill; +} + +template +void uart::set_handler(const bus_handler &handler) +{ + auto &bus_ctx = get_ctx(); + + ecl_assert((bus_ctx.status & (ctx::inited | ctx::tx_done | ctx::rx_done)) + == (ctx::inited | ctx::tx_done | ctx::rx_done)); + + bus_ctx.h = handler; +} + +template +void uart::reset_buffers() +{ + auto &bus_ctx = get_ctx(); + + ecl_assert((bus_ctx.status & (ctx::inited | ctx::tx_done | ctx::rx_done)) + == (ctx::inited | ctx::tx_done | ctx::rx_done)); + + // If buffers are not set then fill mode must be disabled to avoid + // ambiguity. + bus_ctx.status &= ~ctx::fill; + bus_ctx.tx.buf = nullptr; + bus_ctx.rx = nullptr; +} + +template +void uart::reset_handler() +{ + auto &bus_ctx = get_ctx(); + + ecl_assert((bus_ctx.status & (ctx::inited | ctx::tx_done | ctx::rx_done)) + == (ctx::inited | ctx::tx_done | ctx::rx_done)); + + bus_ctx.h = stub_handler; +} + +template +err uart::do_xfer() +{ + auto &bus_ctx = get_ctx(); + + ecl_assert((bus_ctx.status & (ctx::inited | ctx::tx_done | ctx::rx_done)) + == (ctx::inited | ctx::tx_done | ctx::rx_done)); + + // At least one of direction should be enabled + ecl_assert(bus_ctx.tx.buf || bus_ctx.rx); + + if ((bus_ctx.status & ctx::fill) || bus_ctx.tx.buf) { + UART_Type * ut = pick_sysctl(); + + if (bus_ctx.status & ctx::fill) { + for(size_t i = 0; i < bus_ctx.tx_sz; i++) { + UART_PutChar(ut, bus_ctx.tx.fill_byte); + } + } else { + while(bus_ctx.tx_idx < bus_ctx.tx_sz) { + UART_PutChar(ut, bus_ctx.tx.buf[bus_ctx.tx_idx]); + bus_ctx.tx_idx++; + } + } + + bus_ctx.status |= ctx::tx_done; + } + + if (bus_ctx.rx) { + // TODO: Implement RX mechanism. + bus_ctx.status |= ctx::rx_done; + } + + bus_ctx.h(bus_channel::meta, bus_event::tc, 0); + + return err::ok; +} + +template +err uart::cancel_xfer() +{ + auto &bus_ctx = get_ctx(); + + bus_ctx.status |= (ctx::tx_done & ctx::rx_done); + + return err::ok; +} + +//! @} + +//! @} + +//! @} + +} // namespace ecl + +#endif // PLATFORM_KE02_UART_HPP_ diff --git a/platform/ke02/export/platform/cm_device.hpp b/platform/ke02/export/platform/cm_device.hpp new file mode 100644 index 00000000..e071d303 --- /dev/null +++ b/platform/ke02/export/platform/cm_device.hpp @@ -0,0 +1,30 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//! \file +//! \brief Proxy header, required by architecture module due to CMSIS-compliancy. +//! \ingroup ke02_other + +#ifndef THE_CORE_CM_DEVICE_HPP_ +#define THE_CORE_CM_DEVICE_HPP_ + +//! \addtogroup platform Platform defintions and drivers +//! @{ + +//! \addtogroup ke02 KE02 platform +//! @{ + +//! \addtogroup ke02_other Other modules +//! @{ + +#include +#include + +//! @} + +//! @} + +//! @} + +#endif // THE_CORE_CM_DEVICE_HPP_ diff --git a/platform/ke02/export/platform/console.hpp b/platform/ke02/export/platform/console.hpp new file mode 100644 index 00000000..a50c2314 --- /dev/null +++ b/platform/ke02/export/platform/console.hpp @@ -0,0 +1,55 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//! \file +//! \brief KE02 bypass console driver +//! \ingroup ke02_console +#ifndef KE02_PLATFORM_CONSOLE_HPP_ +#define KE02_PLATFORM_CONSOLE_HPP_ + +// All console definitions are generated in the USART config header +#include + +#include // Test if we need this or not. +#include + +namespace ecl +{ + +//! \addtogroup platform Platform defintions and drivers +//! @{ + +//! \addtogroup ke02 Freescale FRDM-KE02Z platform +//! @{ + +//! \defgroup ke02_console Console +//! @{ + + +#if !THECORE_CONFIG_USE_CONSOLE + +//! Does nothing if console is disabled. +static inline void bypass_putc(char c) +{ + (void) c; +} + +#else // THECORE_CONFIG_USE_CONSOLE + +//! Bypasses console drivers and puts data directly to the UART. +//! \details Required to print debug of the failed asserts including one that +//! executed during ISR. +void bypass_putc(char c); + +#endif // THECORE_CONFIG_USE_CONSOLE + +//! @} + +//! @} + +//! @} + +} // namespace ecl + +#endif // KE02_PLATFORM_CONSOLE_HPP_ diff --git a/platform/ke02/export/platform/execution.hpp b/platform/ke02/export/platform/execution.hpp new file mode 100644 index 00000000..41377e3c --- /dev/null +++ b/platform/ke02/export/platform/execution.hpp @@ -0,0 +1,46 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//! \file +//! \brief KE02 execution control header. +//! \ingroup ke02_execution + +#ifndef KE02_PLATFORM_EXECUTION_H_ +#define KE02_PLATFORM_EXECUTION_H_ + +#include +#include + +namespace ecl +{ + +//! \addtogroup platform Platform defintions and drivers +//! @{ + +//! \addtogroup ke02 KE02 platform +//! @{ + +//! \defgroup ke02_execution Execution control module +//! @{ + +//! \brief Performs a dummy busy wait for specified amount of milliseconds. +//! \param ms number of milliseconds to wait. +//! +//! This function is useful for a short delays. +//! +//! \return None. +static inline void spin_wait(uint32_t ms) +{ + ecl::arch_spin_wait(ms); +} + +//! @} + +//! @} + +//! @} + +} //namespace ecl + +#endif // KE02_PLATFORM_EXECUTION_H_ diff --git a/platform/ke02/export/platform/irq.S b/platform/ke02/export/platform/irq.S new file mode 100644 index 00000000..1f6c95a2 --- /dev/null +++ b/platform/ke02/export/platform/irq.S @@ -0,0 +1,75 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef DEVICE_IRQ_DEFS_H_ +#define DEVICE_IRQ_DEFS_H_ + + // External Interrupts + .long Reserved16_IRQHandler // Reserved interrupt 16 + .long Reserved17_IRQHandler // Reserved interrupt 17 + .long Reserved18_IRQHandler // Reserved interrupt 18 + .long Reserved19_IRQHandler // Reserved interrupt 19 + .long Reserved20_IRQHandler // Reserved interrupt 20 + .long FTMRH_IRQHandler // FTMRH command complete/read collision interrupt + .long LVD_LVW_IRQHandler // Low Voltage Detect, Low Voltage Warning + .long IRQ_IRQHandler // External interrupt + .long I2C0_IRQHandler // I2C0 interrupt + .long Reserved25_IRQHandler // Reserved interrupt 25 + .long SPI0_IRQHandler // SPI0 interrupt + .long SPI1_IRQHandler // SPI1 interrupt + .long UART0_IRQHandler // UART0 status/error interrupt + .long UART1_IRQHandler // UART1 status/error interrupt + .long UART2_IRQHandler // UART2 status/error interrupt + .long ADC0_IRQHandler // ADC0 interrupt + .long ACMP0_IRQHandler // ACMP0 interrupt + .long FTM0_IRQHandler // FTM0 Single interrupt vector for all sources + .long FTM1_IRQHandler // FTM1 Single interrupt vector for all sources + .long FTM2_IRQHandler // FTM2 Single interrupt vector for all sources + .long RTC_IRQHandler // RTC overflow + .long ACMP1_IRQHandler // ACMP1 interrupt + .long PIT_CH0_IRQHandler // PIT CH0 overflow + .long PIT_CH1_IRQHandler // PIT CH1 overflow + .long KBI0_IRQHandler // Keyboard interrupt 0 + .long KBI1_IRQHandler // Keyboard interrupt 1 + .long Reserved42_IRQHandler // Reserved interrupt 42 + .long ICS_IRQHandler // MCG interrupt + .long Watchdog_IRQHandler // WDOG Interrupt + .long Reserved45_IRQHandler // Reserved interrupt 45 + .long Reserved46_IRQHandler // Reserved interrupt 46 + .long Reserved47_IRQHandler // Reserved interrupt 47 + + def_irq_handler Reserved16_IRQHandler + def_irq_handler Reserved17_IRQHandler + def_irq_handler Reserved18_IRQHandler + def_irq_handler Reserved19_IRQHandler + def_irq_handler Reserved20_IRQHandler + def_irq_handler FTMRH_IRQHandler + def_irq_handler LVD_LVW_IRQHandler + def_irq_handler IRQ_IRQHandler + def_irq_handler I2C0_IRQHandler + def_irq_handler Reserved25_IRQHandler + def_irq_handler SPI0_IRQHandler + def_irq_handler SPI1_IRQHandler + def_irq_handler UART0_IRQHandler + def_irq_handler UART1_IRQHandler + def_irq_handler UART2_IRQHandler + def_irq_handler ADC0_IRQHandler + def_irq_handler ACMP0_IRQHandler + def_irq_handler FTM0_IRQHandler + def_irq_handler FTM1_IRQHandler + def_irq_handler FTM2_IRQHandler + def_irq_handler RTC_IRQHandler + def_irq_handler ACMP1_IRQHandler + def_irq_handler PIT_CH0_IRQHandler + def_irq_handler PIT_CH1_IRQHandler + def_irq_handler KBI0_IRQHandler + def_irq_handler KBI1_IRQHandler + def_irq_handler Reserved42_IRQHandler + def_irq_handler ICS_IRQHandler + def_irq_handler Watchdog_IRQHandler + def_irq_handler Reserved45_IRQHandler + def_irq_handler Reserved46_IRQHandler + def_irq_handler Reserved47_IRQHandler + +#endif /* DEVICE_IRQ_DEFS_H_ */ diff --git a/platform/ke02/export/platform/irq.hpp b/platform/ke02/export/platform/irq.hpp new file mode 100644 index 00000000..7e77766f --- /dev/null +++ b/platform/ke02/export/platform/irq.hpp @@ -0,0 +1,71 @@ +#ifndef KE02_PLATFORM_IRQ_HPP_ +#define KE02_PLATFORM_IRQ_HPP_ + + +// Temporary measure, while we are throwing away redundant IRQ manager +#define THECORE_NO_IRQ_MANAGER 1 + +namespace ecl +{ + +using irq_num = int; + +namespace irq +{ + +//! Masks or disables the given IRQ. +//! \param[in] irqn Valid IRQ number. +//! +static inline void mask(irq_num irqn) +{ + (void)irqn; +} + +//! Unmasks or enables the given IRQ. +//! \param[in] irqn Valid IRQ number. +//! +static inline void unmask(irq_num irqn) +{ + (void)irqn; +} + +//! Gets current IRQ number. +//! \warn Results are unspecified if called not within IRQ context. +//! \return Current IRQ number +static inline irq_num get_current_irqn() +{ + return 0; +} + +//! Checks if a processor is in handler mode of execution at this time. +//! \retval true Processor is in handler mode. I.e. servicing IRQ or exception. +//! \retval false Processor is in thread mode. +static inline bool in_isr() +{ + return false; +} + +//! Disables interrupts globally. +static inline void disable() +{ +} + +//! Enables interrupts globally. +static inline void enable() +{ +} + +//! Clears pending interrupt of the given IRQ. +//! \param[in] irqn Valid IRQ number. +//! +static inline void clear(irq_num irqn) +{ + (void)irqn; +} + +} // namespace irq + +} // namespace ecl + + +#endif // diff --git a/platform/ke02/linker/gnu/gnu.cmake b/platform/ke02/linker/gnu/gnu.cmake new file mode 100644 index 00000000..6569e587 --- /dev/null +++ b/platform/ke02/linker/gnu/gnu.cmake @@ -0,0 +1,5 @@ +set(CMAKE_C_LINK_FLAGS + "-fuse-linker-plugin -march=armv6s-m -mcpu=cortex-m0plus -nostartfiles \ + -specs=nano.specs -mthumb -Wl,--gc-sections" + CACHE STRING "Linker C flags") +set(CMAKE_CXX_LINK_FLAGS ${CMAKE_C_LINK_FLAGS} CACHE STRING "Linker C++ flags") diff --git a/platform/ke02/mcu_cfg.cmake b/platform/ke02/mcu_cfg.cmake new file mode 100644 index 00000000..3afa9501 --- /dev/null +++ b/platform/ke02/mcu_cfg.cmake @@ -0,0 +1,22 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +set(TARGET_USE_NVIC_IRQ_NAMES 1 CACHE STRING "Platform uses NVIC IRQ names") +set(TARGET_MCU_ARCH "arm_cm0plus" CACHE STRING "MCU architecture") + +# Special protect section must be included in ASM +set(TARGET_KINETIS_FLASH_PROTECT_SECTION 1 CACHE STRING "Flash protect for Kinetis") + +# Memory layout +# TODO: differentiate layout with respect to full device specification +# TODO: #107 - allow user to override these values +set(TARGET_MCU_ROM_START 0x00000000 CACHE STRING "Flash region start") +set(TARGET_MCU_ROM_SIZE 0xffff CACHE STRING "Flash region size") # 64k of ROM +set(TARGET_MCU_RAM_START 0x20000000 CACHE STRING "RAM region start") +set(TARGET_MCU_RAM_SIZE 0xc00 CACHE STRING "RAM region size") # 3072 bytes of RAM + +# TODO: Provide two-segment memory values. (see RM) + +set(TARGET_STACK_SIZE 0x100 CACHE STRING "Stack size") +set(TARGET_HEAP_SIZE 0x200 CACHE STRING "Heap size") diff --git a/platform/ke02/platform.cpp b/platform/ke02/platform.cpp new file mode 100644 index 00000000..ebe9c8ea --- /dev/null +++ b/platform/ke02/platform.cpp @@ -0,0 +1,104 @@ +extern "C" { +#include +} + +#include + +#include "common.h" +#include "sysinit.h" +#include "sim.h" +#include "ics.h" +#include "uart.h" +#include "wdog.h" +#include "platform/console.hpp" + +uint32_t SystemCoreClock = 20000000UL; + +extern "C" +uint8_t __atomic_exchange_1(volatile void *dest, uint8_t val, int model) +{ + (void)model; + + __disable_irq(); + + uint8_t *u8_dest = (uint8_t*)dest; + uint8_t old_val = *u8_dest; + *u8_dest = val; + + __enable_irq(); + + return old_val; +} + +#ifdef THECORE_CONFIG_USE_CONSOLE + +namespace ecl +{ + extern void bypass_console_init(); +} // namespace ecl + +#endif // THECORE_CONFIG_USE_CONSOLE + +extern "C" +void platform_init() {} + +extern "C" +void out_char(char c) +{ + ecl::bypass_putc(c); +} + +extern "C" +void SystemInit() +{ + SIM_ConfigType sSIMConfig; + ICS_ConfigType sICSConfig; + + ICS_Trim(0x57); /*!< Trim IRC to 39.0625KHz and FLL output = 40MHz */ + + /* + * Enable SWD pin, RESET pin + * + * NOTE: please make sure other register bits are also write-once and + * need add other bit mask here if needed. + */ +#if defined(SPI0_PINREMAP) + sSIMConfig.u32PinSel |= SIM_PINSEL_SPI0PS_MASK; +#endif + +#if defined(OUTPUT_BUSCLK) + sSIMConfig.sBits.bEnableCLKOUT = 1; /* Output bus clock if enabled */ +#endif + +#if defined(DISABLE_NMI) + sSIMConfig.sBits.bDisableNMI = 1; +#endif + +#if !defined(CPU_KE04) + /* Make sure clocks to peripheral modules are enabled */ + sSIMConfig.u32SCGC |= (SIM_SCGC_SWD_MASK | + SIM_SCGC_FLASH_MASK | + SIM_SCGC_UART0_MASK | + SIM_SCGC_UART1_MASK | + SIM_SCGC_UART2_MASK); +#else + sSIMConfig.u32SCGC |= (SIM_SCGC_SWD_MASK | SIM_SCGC_FLASH_MASK | SIM_SCGC_UART0_MASK); +#endif + + SIM_Init(&sSIMConfig); /* Initialize SIM */ + + sICSConfig.u8ClkMode = ICS_CLK_MODE_FEI; + sICSConfig.bLPEnable = 0; + sICSConfig.oscConfig.bEnable = 0; /* Disable OSC */ + + ICS_Init(&sICSConfig); /* Initialise ICS */ + + /* Disable the watchdog timer */ + WDOG_DisableWDOGEnableUpdate(); + + ecl::bypass_console_init(); + + void print_sys_log(void); + + print_sys_log(); +} diff --git a/platform/ke02/schemas/ke02.schema.json b/platform/ke02/schemas/ke02.schema.json new file mode 100644 index 00000000..71ac32db --- /dev/null +++ b/platform/ke02/schemas/ke02.schema.json @@ -0,0 +1,13 @@ +{ + "$schema": "http://json-schema.org/schema#", + + "properties": { + "name": { "type": "string", "pattern": "^ke02$" }, + "device": { "enum": [ "KE02Z2" ] }, + "console": { "type": "string", "pattern": "^UART\\d$" }, + + "uart": { "$ref": "file:uart.schema.json" } + }, + + "required": [ "name", "device" ] +} diff --git a/platform/ke02/schemas/uart.schema.json b/platform/ke02/schemas/uart.schema.json new file mode 100644 index 00000000..9f93b51c --- /dev/null +++ b/platform/ke02/schemas/uart.schema.json @@ -0,0 +1,16 @@ +{ + "$schema": "http://json-schema.org/schema#", + "type": "array", + + "items": { + "type": "object", + + "properties": { + "id": { "type": "string", "pattern": "^UART\\d$" }, + "alias": { "type": "string" }, + "comment": { "type": "string" } + }, + + "required": [ "id" ] + } +} diff --git a/platform/ke02/templates/defines.in.hpp b/platform/ke02/templates/defines.in.hpp new file mode 100644 index 00000000..94ef0e8a --- /dev/null +++ b/platform/ke02/templates/defines.in.hpp @@ -0,0 +1,31 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//! \file +//! \brief KE02 platform definitions template + +#ifndef KE02_PLATFORM_DEFINES_ +#define KE02_PLATFORM_DEFINES_ + +/*[[[cog +import cog +import json + +f = open(JSON_CFG) +cfg = json.load(f) +cfg = cfg['platform'] + +]]]*/ +//[[[end]]] + +// Console configuration ------------------------------------------------------- +/*[[[cog + +if 'console' in cfg: + cog.outl('#define THECORE_CONFIG_USE_CONSOLE 1') + +]]]*/ +//[[[end]]] + +#endif // KE02_PLATFORM_DEFINES_ diff --git a/platform/ke02/templates/uart_cfg.in.hpp b/platform/ke02/templates/uart_cfg.in.hpp new file mode 100644 index 00000000..720cf379 --- /dev/null +++ b/platform/ke02/templates/uart_cfg.in.hpp @@ -0,0 +1,63 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//! \file +//! \brief KE02 UART definitions template + +#ifndef KE02_UART_DEFINES_ +#define KE02_UART_DEFINES_ + +#include "aux/platform_defines.hpp" +#include "aux/uart.hpp" + + +/*[[[cog +import cog +import json + +cfg = json.load(open(JSON_CFG)) +cfg = cfg['platform'] + +# UART device alias, used internally by bypass console driver +template_console_dev = '''static constexpr uart_channel UART{CHANNEL_INDEX}_channel = uart_channel::ch{CHANNEL_INDEX}; +using UART{CHANNEL_INDEX}_driver = uart; +using platform_console = UART{CHANNEL_INDEX}_driver;''' + +# Gets string representation of UART theCore enum. +def get_uart_enum(uart_cfg): + return int(uart_cfg['id'][-1]) + +]]]*/ +//[[[end]]] + +namespace ecl +{ + +// UART configuration --------------------------------------------------------- + +/*[[[cog + +uart_cfgs = {} + +if 'uart' in cfg: + uart_cfgs = cfg['uart'] + +for uart_cfg in uart_cfgs: + # Place comment line if needed + if 'comment' in uart_cfg: + # Avoid using begin and end comment section tokens + cog.outl(('\n%s* ' + uart_cfg['comment'] + ' *%s') % ('/', '/')) + + cog.outl(template_console_dev.format(CHANNEL_INDEX = get_uart_enum(uart_cfg))) + + if 'alias' in uart_cfg: + cog.outl('using {ALIAS_NAME} = UART{CHANNEL_INDEX}_driver;'.format(ALIAS_NAME = uart_cfg['alias'], + CHANNEL_INDEX = get_uart_enum(uart_cfg))) +]]]*/ +//[[[end]]] + + +} // namespace ecl + +#endif // KE02_UART_DEFINES_ diff --git a/platform/platform_stub/CMakeLists.txt b/platform/platform_stub/CMakeLists.txt new file mode 100644 index 00000000..58c8ffd8 --- /dev/null +++ b/platform/platform_stub/CMakeLists.txt @@ -0,0 +1,9 @@ +add_library(ke02 platform.cpp) + +include(mcu_cfg.cmake) + +set(TARGET_USE_NVIC_IRQ_NAMES 1 CACHE STRING "Platform uses NVIC IRQ names") +set(TARGET_MCU_ARCH "arm_cm0plus" CACHE STRING "MCU architecture") + +target_include_directories(ke02 PUBLIC export) +target_link_libraries(ke02 PUBLIC arch) diff --git a/platform/platform_stub/export/device_irq.S b/platform/platform_stub/export/device_irq.S new file mode 100644 index 00000000..ee3c34e6 --- /dev/null +++ b/platform/platform_stub/export/device_irq.S @@ -0,0 +1,71 @@ +#ifndef DEVICE_IRQ_DEFS_H_ +#define DEVICE_IRQ_DEFS_H_ + + // External Interrupts + .long Reserved16_IRQHandler // Reserved interrupt 16 + .long Reserved17_IRQHandler // Reserved interrupt 17 + .long Reserved18_IRQHandler // Reserved interrupt 18 + .long Reserved19_IRQHandler // Reserved interrupt 19 + .long Reserved20_IRQHandler // Reserved interrupt 20 + .long FTMRH_IRQHandler // FTMRH command complete/read collision interrupt + .long LVD_LVW_IRQHandler // Low Voltage Detect, Low Voltage Warning + .long IRQ_IRQHandler // External interrupt + .long I2C0_IRQHandler // I2C0 interrupt + .long Reserved25_IRQHandler // Reserved interrupt 25 + .long SPI0_IRQHandler // SPI0 interrupt + .long SPI1_IRQHandler // SPI1 interrupt + .long UART0_IRQHandler // UART0 status/error interrupt + .long UART1_IRQHandler // UART1 status/error interrupt + .long UART2_IRQHandler // UART2 status/error interrupt + .long ADC0_IRQHandler // ADC0 interrupt + .long ACMP0_IRQHandler // ACMP0 interrupt + .long FTM0_IRQHandler // FTM0 Single interrupt vector for all sources + .long FTM1_IRQHandler // FTM1 Single interrupt vector for all sources + .long FTM2_IRQHandler // FTM2 Single interrupt vector for all sources + .long RTC_IRQHandler // RTC overflow + .long ACMP1_IRQHandler // ACMP1 interrupt + .long PIT_CH0_IRQHandler // PIT CH0 overflow + .long PIT_CH1_IRQHandler // PIT CH1 overflow + .long KBI0_IRQHandler // Keyboard interrupt 0 + .long KBI1_IRQHandler // Keyboard interrupt 1 + .long Reserved42_IRQHandler // Reserved interrupt 42 + .long ICS_IRQHandler // MCG interrupt + .long Watchdog_IRQHandler // WDOG Interrupt + .long Reserved45_IRQHandler // Reserved interrupt 45 + .long Reserved46_IRQHandler // Reserved interrupt 46 + .long Reserved47_IRQHandler // Reserved interrupt 47 + + def_irq_handler Reserved16_IRQHandler + def_irq_handler Reserved17_IRQHandler + def_irq_handler Reserved18_IRQHandler + def_irq_handler Reserved19_IRQHandler + def_irq_handler Reserved20_IRQHandler + def_irq_handler FTMRH_IRQHandler + def_irq_handler LVD_LVW_IRQHandler + def_irq_handler IRQ_IRQHandler + def_irq_handler I2C0_IRQHandler + def_irq_handler Reserved25_IRQHandler + def_irq_handler SPI0_IRQHandler + def_irq_handler SPI1_IRQHandler + def_irq_handler UART0_IRQHandler + def_irq_handler UART1_IRQHandler + def_irq_handler UART2_IRQHandler + def_irq_handler ADC0_IRQHandler + def_irq_handler ACMP0_IRQHandler + def_irq_handler FTM0_IRQHandler + def_irq_handler FTM1_IRQHandler + def_irq_handler FTM2_IRQHandler + def_irq_handler RTC_IRQHandler + def_irq_handler ACMP1_IRQHandler + def_irq_handler PIT_CH0_IRQHandler + def_irq_handler PIT_CH1_IRQHandler + def_irq_handler KBI0_IRQHandler + def_irq_handler KBI1_IRQHandler + def_irq_handler Reserved42_IRQHandler + def_irq_handler ICS_IRQHandler + def_irq_handler Watchdog_IRQHandler + def_irq_handler Reserved45_IRQHandler + def_irq_handler Reserved46_IRQHandler + def_irq_handler Reserved47_IRQHandler + +#endif /* DEVICE_IRQ_DEFS_H_ */ diff --git a/platform/platform_stub/export/platform/console.hpp b/platform/platform_stub/export/platform/console.hpp new file mode 100644 index 00000000..8f635ec7 --- /dev/null +++ b/platform/platform_stub/export/platform/console.hpp @@ -0,0 +1,16 @@ +#ifndef KE02_PLATFORM_CONSOLE_HPP_ +#define KE02_PLATFORM_CONSOLE_HPP_ + +namespace ecl +{ + +//! Bypasses console drivers and puts data directly to the UART +static inline void bypass_putc(char c) +{ + (void)c; +} + +} // namespace ecl + + +#endif // KE02_PLATFORM_CONSOLE_HPP_ diff --git a/platform/platform_stub/export/platform/execution.h b/platform/platform_stub/export/platform/execution.h new file mode 100644 index 00000000..90ecaf99 --- /dev/null +++ b/platform/platform_stub/export/platform/execution.h @@ -0,0 +1,26 @@ +#ifndef KE02_PLATFORM_EXECUTION_H_ +#define KE02_PLATFORM_EXECUTION_H_ + +#include + +__attribute__((noreturn)) +void ecl_abort() +{ + for(;;); +} + +static inline uint32_t get_clk_spd() +{ + // TODO + return 100000; +} + +static inline uint32_t get_clk() +{ + return 100000; +} + + + + +#endif // KE02_PLATFORM_EXECUTION_H_ diff --git a/platform/platform_stub/export/platform/irq.hpp b/platform/platform_stub/export/platform/irq.hpp new file mode 100644 index 00000000..f4c1c2bc --- /dev/null +++ b/platform/platform_stub/export/platform/irq.hpp @@ -0,0 +1,68 @@ +#ifndef KE02_PLATFORM_IRQ_HPP_ +#define KE02_PLATFORM_IRQ_HPP_ + + +namespace ecl +{ + +using irq_num = int; + +namespace irq +{ + +//! Masks or disables the given IRQ. +//! \param[in] irqn Valid IRQ number. +//! +static inline void mask(irq_num irqn) +{ + (void)irqn; +} + +//! Unmasks or enables the given IRQ. +//! \param[in] irqn Valid IRQ number. +//! +static inline void unmask(irq_num irqn) +{ + (void)irqn; +} + +//! Gets current IRQ number. +//! \warn Results are unspecified if called not within IRQ context. +//! \return Current IRQ number +static inline irq_num get_current_irqn() +{ + return 0; +} + +//! Checks if a processor is in handler mode of execution at this time. +//! \retval true Processor is in handler mode. I.e. servicing IRQ or exception. +//! \retval false Processor is in thread mode. +static inline bool in_isr() +{ + return false; +} + +//! Disables interrupts globally. +static inline void disable() +{ +} + +//! Enables interrupts globally. +static inline void enable() +{ +} + +//! Clears pending interrupt of the given IRQ. +//! \param[in] irqn Valid IRQ number. +//! +static inline void clear(irq_num irqn) +{ + (void)irqn; +} + +} // namespace irq + +} // namespace ecl + + +#endif // diff --git a/platform/platform_stub/linker/gnu/gnu.cmake b/platform/platform_stub/linker/gnu/gnu.cmake new file mode 100644 index 00000000..fd66ef67 --- /dev/null +++ b/platform/platform_stub/linker/gnu/gnu.cmake @@ -0,0 +1,4 @@ +set(CMAKE_C_LINK_FLAGS + "-fuse-linker-plugin -mcpu=cortex-m0plus -nostartfiles -mthumb -Wl,--gc-sections" + CACHE STRING "Linker C flags") +set(CMAKE_CXX_LINK_FLAGS ${CMAKE_C_LINK_FLAGS} CACHE STRING "Linker C++ flags") diff --git a/platform/platform_stub/mcu_cfg.cmake b/platform/platform_stub/mcu_cfg.cmake new file mode 100644 index 00000000..0b426d21 --- /dev/null +++ b/platform/platform_stub/mcu_cfg.cmake @@ -0,0 +1,12 @@ +# Memory layout +# TODO: differentiate layout with respect to full device specification +# TODO: #107 - allow user to override these values +set(TARGET_MCU_ROM_START 0x00000000 CACHE STRING "Flash region start") +set(TARGET_MCU_ROM_SIZE 0xffff CACHE STRING "Flash region size") # 64k of ROM +set(TARGET_MCU_RAM_START 0x20000000 CACHE STRING "RAM region start") +set(TARGET_MCU_RAM_SIZE 0xc00 CACHE STRING "RAM region size") # 3072 bytes of RAM + +# TODO: Provide two-segment memory values. (see RM) + +set(TARGET_STACK_SIZE 0x800 CACHE STRING "Stack size") +set(TARGET_HEAP_SIZE 0x3ff CACHE STRING "Heap size") diff --git a/platform/platform_stub/platform.cpp b/platform/platform_stub/platform.cpp new file mode 100644 index 00000000..a8160d5f --- /dev/null +++ b/platform/platform_stub/platform.cpp @@ -0,0 +1,11 @@ +extern "C" +void platform_init() +{ + +} + +extern "C" +void SystemInit() +{ + +} diff --git a/platform/tm4c/export/platform/irq.S b/platform/tm4c/export/platform/irq.S index 9c0f6498..8af34095 100644 --- a/platform/tm4c/export/platform/irq.S +++ b/platform/tm4c/export/platform/irq.S @@ -2,6 +2,9 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef DEVICE_IRQ_DEFS_H_ +#define DEVICE_IRQ_DEFS_H_ + .long GPIOA_Handler /* 16 GPIO Port A */ .long GPIOB_Handler /* 17 GPIO Port B */ .long GPIOC_Handler /* 18 GPIO Port C */ @@ -141,3 +144,5 @@ .long PWM1_2_Handler /* 152 PWM1 Generator 2 */ .long PWM1_3_Handler /* 153 PWM1 Generator 3 */ .long PWM1_FAULT_Handler /* 154 PWM1 Fault */ + +#endif /* DEVICE_IRQ_DEFS_H_ */ diff --git a/platform/tm4c/mcu_cfg.cmake b/platform/tm4c/mcu_cfg.cmake index 9ecd9c9e..a589fcfc 100644 --- a/platform/tm4c/mcu_cfg.cmake +++ b/platform/tm4c/mcu_cfg.cmake @@ -30,4 +30,4 @@ if(thecore_cfg.platform.device STREQUAL "TM4C123GH6PM") return() endif() -msg_fatal("Device: ${CONFIG_PLATFORM_DEVICE} is not supported") +message(FATAL_ERROR "${CONFIG_PLATFORM_DEVICE} is not supported") diff --git a/scripts/ke02_jlink.gdbinit b/scripts/ke02_jlink.gdbinit new file mode 100644 index 00000000..34993304 --- /dev/null +++ b/scripts/ke02_jlink.gdbinit @@ -0,0 +1,31 @@ +#************************************************* +# +# Connect to J-Link and debug application in flash on Cortex-M3 +# +#************************************************* + + +# Connect to the J-Link gdb server +target remote localhost:2331 +monitor speed 1000 +monitor endian little + +monitor flash device = MKE02Z64xxx2 +monitor flash breakpoints = 1 +monitor flash download = 1 + + +def target_reset + monitor reset 6 + + # Initializing PC and stack pointer + monitor reg r13 = (0x00000000) + monitor reg pc = (0x00000004) +end + +def target_load + monitor halt + + load + target_reset +end \ No newline at end of file diff --git a/sys/sys.cpp b/sys/sys.cpp index 3aa14f5d..7f7589c5 100644 --- a/sys/sys.cpp +++ b/sys/sys.cpp @@ -92,9 +92,9 @@ extern "C" void core_main() board_init(); #ifdef CONFIG_USE_BYPASS_CONSOLE - // Dirty hack to make sure pin configuration is established before - // bypass console will be used. - // It should be fixed by configuring console GPIO directly in the platform, + // Dirty hack to make sure pin configuration is established before + // bypass console will be used. + // It should be fixed by configuring console GPIO directly in the platform, // not in the user's `board_init()` routine. See issue #151. ecl::wait_for(50); #endif // CONFIG_USE_BYPASS_CONSOLE diff --git a/toolchains/arm-cm0-plus-gnu.cmake b/toolchains/arm-cm0-plus-gnu.cmake new file mode 100644 index 00000000..92d6ff8d --- /dev/null +++ b/toolchains/arm-cm0-plus-gnu.cmake @@ -0,0 +1,92 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# this one is important +set(CMAKE_SYSTEM_NAME Generic) +# this one not so much +set(CMAKE_SYSTEM_VERSION 1) + +# GCC is used as a linker in order to use LTO properly +set(CMAKE_C_LINKER arm-none-eabi-gcc) +set(CMAKE_CXX_LINKER arm-none-eabi-g++) + +# specify the cross compiler +set(CMAKE_C_COMPILER arm-none-eabi-gcc) +set(CMAKE_CXX_COMPILER arm-none-eabi-g++) + +# Way to avoid specifying linking flags in the toolchain. +# See https://cmake.org/pipermail/cmake-developers/2016-February/027888.html +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) + +# where is the target environment +set(CMAKE_FIND_ROOT_PATH /usr/arm-none-eabi) + +# search for programs in the build host directories +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +# for libraries and headers in the target directories +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + +################################################################################ +# Flags and definitions used with GNU complilation suite + +# Essential stuff for using 3rd-party libs +set(CMAKE_INCLUDE_SYSTEM_FLAG_C "-isystem ") +set(CMAKE_INCLUDE_SYSTEM_FLAG_CXX "-isystem ") + +# avoid using any additional flags when linking with shared libraries +set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") + +# common flags for current platform +set(CC_PLATFORM_FLAGS "-specs=nano.specs -ffreestanding -mcpu=cortex-m0plus -mthumb -march=armv6s-m \ + -fdata-sections -ffunction-sections -fno-common") + +# -fno-use-cxa-atexit helps resolve issue with DSO handle undefined reference +# why???? +set(CXX_PLATFORM_FLAGS "-fno-use-cxa-atexit -fno-exceptions -fno-rtti ${CC_PLATFORM_FLAGS}") + +# TODO: move std and gdwarf flags out of toolchain into the core listfile itself +set(C_CXX_EXTRA_FLAGS "-gdwarf-2") +set(CC_EXTRA_FLAGS "-std=c99 ${C_CXX_EXTRA_FLAGS}") +set(CXX_EXTRA_FLAGS "-std=c++14 ${C_CXX_EXTRA_FLAGS}") + +# Set general flags for C\C++ compiler and linker +set(CC_WARN_FLAGS "-Wall -Wextra -Wpedantic -Werror") +set(CXX_WARN_FLAGS "${CC_WARN_FLAGS} -Weffc++") + +# Supported modes are normal, release, debug and minimum size +# Normal mode +set(CMAKE_C_FLAGS + "${CMAKE_C_FLAGS} ${CC_PLATFORM_FLAGS} ${CC_WARN_FLAGS} ${CC_EXTRA_FLAGS}" + CACHE STRING "C flags") +set(CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} ${CXX_PLATFORM_FLAGS} ${CXX_WARN_FLAGS} ${CXX_EXTRA_FLAGS}" + CACHE STRING "C++ flags") + +# Release flags, optimization is on, +set(CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG " + CACHE STRING "Release C flags") +set(CMAKE_CXX_FLAGS_RELEASE ${CMAKE_C_FLAGS_RELEASE} + CACHE STRING "Release C++ flags") + +# Minimum size release flags, LTO and minimum size +set(CMAKE_C_FLAGS_MINSIZEREL "-Os -DNDEBUG " + CACHE STRING "Minsize C flags") +set(CMAKE_CXX_FLAGS_MINSIZEREL ${CMAKE_C_FLAGS_MINSIZEREL} + CACHE STRING "Minsize C++ flags") + +# Debug mode, no LTO and maximum debug info +set(CMAKE_C_FLAGS_DEBUG "-Og -g3 " + CACHE STRING "Debug C flags") +set(CMAKE_CXX_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG} + CACHE STRING "Debug C++ flags") + +set(CMAKE_OBJCOPY arm-none-eabi-objcopy CACHE STRING "Objcopy executable") + +set(CMAKE_ASM-ATT_COMPILE_OBJECT + " -mthumb -march=armv6s-m -mcpu=cortex-m0plus -o ") +set(CMAKE_C_LINK_EXECUTABLE + "${CMAKE_C_LINKER} -o ") +set(CMAKE_CXX_LINK_EXECUTABLE + "${CMAKE_CXX_LINKER} -o ")