From 8afc8dfdc3baa2458dfecd28386cfc6045cda740 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Mon, 9 Feb 2015 13:50:37 +0100 Subject: [PATCH] cpu/kinetis_common: add common startup.c cpu/kinetis_common/wdog.c: move wdog disable code to initial wdog driver cpu/kinetis_common/wdog.c: add COP WDOG cpu/kinetis_common/include/wdog.h: add configuration example cpu/kinetis_common: add fault handlers cpu/kinetis_common: add .ramcode and ISR vector relocation to startup.c --- cpu/kinetis_common/Makefile.include | 6 + cpu/kinetis_common/fault_handlers.c | 60 +++++++++ cpu/kinetis_common/include/fault_handlers.h | 85 +++++++++++++ cpu/kinetis_common/include/wdog.h | 57 +++++++++ cpu/kinetis_common/startup.c | 129 ++++++++++++++++++++ cpu/kinetis_common/wdog.c | 75 ++++++++++++ 6 files changed, 412 insertions(+) create mode 100644 cpu/kinetis_common/fault_handlers.c create mode 100644 cpu/kinetis_common/include/fault_handlers.h create mode 100644 cpu/kinetis_common/include/wdog.h create mode 100644 cpu/kinetis_common/startup.c create mode 100644 cpu/kinetis_common/wdog.c diff --git a/cpu/kinetis_common/Makefile.include b/cpu/kinetis_common/Makefile.include index c366fe5091..e52ffc5428 100644 --- a/cpu/kinetis_common/Makefile.include +++ b/cpu/kinetis_common/Makefile.include @@ -3,3 +3,9 @@ export INCLUDES += -I$(RIOTCPU)/kinetis_common/include # Add search path for linker scripts export LINKFLAGS += -L$(RIOTCPU)/kinetis_common/ldscripts + +# add the CPU specific startup code for the linker +export UNDEF += $(BINDIR)kinetis_common/startup.o + +# add the CPU specific fault handlers for the linker +export UNDEF += $(BINDIR)kinetis_common/fault_handlers.o diff --git a/cpu/kinetis_common/fault_handlers.c b/cpu/kinetis_common/fault_handlers.c new file mode 100644 index 0000000000..9b98d54d96 --- /dev/null +++ b/cpu/kinetis_common/fault_handlers.c @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2014 Freie Universität Berlin + * Copyright (C) 2015 PHYTEC Messtechnik GmbH + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License v2.1. See the file LICENSE in the top level directory for more + * details. + */ + +/** + * @ingroup cpu_kinetis_common_fhandlers + * @{ + * + * @file + * @brief Fault Handlers for Freescale Kinetis MCUs + * + * @author Hauke Petersen + * @author Johann Fischer + * + * @} + */ + +#include +#include "crash.h" +#include "fault_handlers.h" + +void isr_nmi(void) +{ + core_panic(PANIC_NMI_HANDLER, "NMI HANDLER"); +} + +void isr_hard_fault(void) +{ + core_panic(PANIC_HARD_FAULT, "HARD FAULT"); +} + +void isr_mem_manage(void) +{ + core_panic(PANIC_MEM_MANAGE, "MEM MANAGE HANDLER"); +} + +void isr_bus_fault(void) +{ + core_panic(PANIC_BUS_FAULT, "BUS FAULT"); +} + +void isr_usage_fault(void) +{ + core_panic(PANIC_USAGE_FAULT, "ISR USAGE FAULT"); +} + +void isr_debug_mon(void) +{ + core_panic(PANIC_DEBUG_MON, "DEBUG MON HANDLER"); +} + +void isr_unhandled(void) +{ + core_panic(PANIC_UNHANDLED_ISR, "UNHANDLED ISR"); +} diff --git a/cpu/kinetis_common/include/fault_handlers.h b/cpu/kinetis_common/include/fault_handlers.h new file mode 100644 index 0000000000..778cba8f55 --- /dev/null +++ b/cpu/kinetis_common/include/fault_handlers.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2014 Freie Universität Berlin + * Copyright (C) 2015 PHYTEC Messtechnik GmbH + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License v2.1. See the file LICENSE in the top level directory for more + * details. + */ + +/** + * @defgroup cpu_kinetis_common_fhandlers Kinetis Fault Handlers + * @ingroup cpu_kinetis_common + * @brief Fault Handlers for Freescale Kinetis MCUs. + * + * @{ + + * @file + * @brief Interface definition for the Kinetis Fault Handlers. + * + * @author Hauke Petersen + * @author Johann Fischer + */ + +#ifndef FAULT_HANDLERS_H +#define FAULT_HANDLERS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Non Maskable Interrupt + */ +void isr_nmi(void); + +/** + * @brief HardFault + */ +void isr_hard_fault(void); + +/** + * @brief MemManage + */ +void isr_mem_manage(void); + +/** + * @brief BusFault + */ +void isr_bus_fault(void); + +/** + * @brief UsageFault + */ +void isr_usage_fault(void); + +/** + * @brief Debug Interrupt + */ +void isr_debug_mon(void); + +/** + * @brief Default handler, called in case no interrupt handler was defined. + */ +void isr_unhandled(void); + +/** + * @brief Definition of different panic modes + */ +typedef enum { + PANIC_NMI_HANDLER, /**< non maskable interrupt */ + PANIC_HARD_FAULT, /**< hard fault */ + PANIC_MEM_MANAGE, /**< memory controller interrupt */ + PANIC_BUS_FAULT, /**< bus fault */ + PANIC_USAGE_FAULT, /**< undefined instruction or unaligned access */ + PANIC_DEBUG_MON, /**< debug interrupt */ + PANIC_UNHANDLED_ISR, /**< unhandled interrupt */ +} panic_t; + + +#ifdef __cplusplus +} +#endif + +#endif /* FAULT_HANDLERS_H */ +/** @} */ diff --git a/cpu/kinetis_common/include/wdog.h b/cpu/kinetis_common/include/wdog.h new file mode 100644 index 0000000000..2efc3e7ae0 --- /dev/null +++ b/cpu/kinetis_common/include/wdog.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2015 PHYTEC Messtechnik GmbH + * Copyright (C) 2015 Eistec AB + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License v2.1. See the file LICENSE in the top level directory for more + * details. + */ + +/** + * @defgroup cpu_kinetis_common_wdog Kinetis WDOG + * @ingroup cpu_kinetis_common + * @brief Driver for Freescale WDOG device. + * There are different implementations of the Watchdog devices. + * Currently, it is only possible to turn the Watchdog off. + * It supports two types: an advanced Watchdog, mostly found + * on Kinetis MCUs with Cortex-M4 inside and a simpler + * COP Watchdog. + * + * ### WDOG Configuration Example (for periph_conf.h) ### + * The driver attempts to determine the type of the WDOG. + * Also you can force the use of advanced WDOG: + * + * #define KINETIS_WDOG_ADVANCED 1 + * + * Or the use of COP WDOG: + * + * #define KINETIS_WDOG_ADVANCED 0 + * + * @{ + + * @file + * @brief Interface definition for the Kinetis WDOG driver. + * + * @author Johann Fischer + * @author Joakim Gebart + */ + +#ifndef WDOG_H +#define WDOG_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * @brief Disable hardware watchdog. + */ +void wdog_disable(void); + +#ifdef __cplusplus +} +#endif + +#endif /* WDOG_H */ +/** @} */ diff --git a/cpu/kinetis_common/startup.c b/cpu/kinetis_common/startup.c new file mode 100644 index 0000000000..31c4591563 --- /dev/null +++ b/cpu/kinetis_common/startup.c @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2014 Freie Universität Berlin + * Copyright (C) 2015 PHYTEC Messtechnik GmbH + * Copyright (C) 2015 Eistec AB + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License v2.1. See the file LICENSE in the top level directory for more + * details. + */ + +/** + * @ingroup cpu_kinetis_common + * @{ + * + * @file + * @brief Startup code for Freescale Kinetis MCUs + * + * @author Hauke Petersen + * @author Johann Fischer + * @author Joakim Gebart + * + * @} + */ + +#include +#include "cpu-conf.h" +#include "wdog.h" + +/** + * @name Memory markers as defined in the linker script + * @{ + */ +extern uint32_t _sfixed[]; +extern uint32_t _efixed[]; +extern uint32_t _etext[]; +extern uint32_t _srelocate[]; +extern uint32_t _erelocate[]; +extern uint32_t _szero[]; +extern uint32_t _ezero[]; +extern uint32_t _sstack[]; +extern uint32_t _ramcode_start[]; +extern uint32_t _ramcode_end[]; +extern uint32_t _ramcode_load[]; +extern uint32_t _vector_ram_start[]; +extern uint32_t _vector_ram_end[]; +extern uint32_t _vector_rom[]; +/** @} */ + +/** + * @brief functions for initializing the board, std-lib and kernel + */ +extern void board_init(void); +extern void kernel_init(void); +extern void __libc_init_array(void); + +/** + * @brief This function is the entry point after a system reset + * + * After a system reset, the following steps are necessary and carried out: + * 0. disable the Watchdog Timer + * 1. load data section from flash to ram + * 2. overwrite uninitialized data section (BSS) with zeros + * 3. initialize the newlib + * 4. initialize the board (sync clock, setup std-IO) + * 5. initialize and start RIOTs kernel + */ +void reset_handler(void) +{ + uint32_t *dst; + uint32_t *src = _etext; + + /* disable the WDOG */ + wdog_disable(); + + /* load .data section from flash to ram */ + for (dst = _srelocate; dst < _erelocate;) { + *(dst++) = *(src++); + } + + /* default .bss section to zero */ + for (dst = _szero; dst < _ezero;) { + *(dst++) = 0; + } + + /* copy .ramcode from flash to RAM */ + src = _ramcode_load; + for (dst = _ramcode_start; dst < _ramcode_end;) { + *(dst++) = *(src++); + } + + /* + * Copy ISR vector from flash to RAM. + * + * To use this CPU feature, define RAMVECT_SIZE=0x400 when building and write + * the new vector table address in RAM to SCB->VTOR. + */ + src = _vector_rom; + for (dst = _vector_ram_start; dst < _vector_ram_end;) { + *(dst++) = *(src++); + } + + /* initialize the board and startup the kernel */ + board_init(); + /* initialize std-c library (this should be done after board_init) */ + __libc_init_array(); + /* startup the kernel */ + kernel_init(); +} + +/* fcfield table */ +__attribute__((weak, section(".fcfield"))) +const uint8_t flash_configuration_field[] = { + 0xff, /* backdoor comparison key 3., offset: 0x0 */ + 0xff, /* backdoor comparison key 2., offset: 0x1 */ + 0xff, /* backdoor comparison key 1., offset: 0x2 */ + 0xff, /* backdoor comparison key 0., offset: 0x3 */ + 0xff, /* backdoor comparison key 7., offset: 0x4 */ + 0xff, /* backdoor comparison key 6., offset: 0x5 */ + 0xff, /* backdoor comparison key 5., offset: 0x6 */ + 0xff, /* backdoor comparison key 4., offset: 0x7 */ + 0xff, /* non-volatile p-flash protection 1 - low register, offset: 0x8 */ + 0xff, /* non-volatile p-flash protection 1 - high register, offset: 0x9 */ + 0xff, /* non-volatile p-flash protection 0 - low register, offset: 0xa */ + 0xff, /* non-volatile p-flash protection 0 - high register, offset: 0xb */ + 0xfe, /* non-volatile flash security register, offset: 0xc */ + 0xff, /* non-volatile flash option register, offset: 0xd */ + 0xff, /* non-volatile eeram protection register, offset: 0xe */ + 0xff, /* non-volatile d-flash protection register, offset: 0xf */ +}; diff --git a/cpu/kinetis_common/wdog.c b/cpu/kinetis_common/wdog.c new file mode 100644 index 0000000000..fefa22b64f --- /dev/null +++ b/cpu/kinetis_common/wdog.c @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2015 PHYTEC Messtechnik GmbH + * Copyright (C) 2015 Eistec AB + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License v2.1. See the file LICENSE in the top level directory for more + * details. + */ + +/** + * @ingroup cpu_kinetis_common_wdog + * + * @{ + * + * @file + * @brief Low-level WDOG driver implementation + * + * @author Johann Fischer + * @author Joakim Gebart + * + * @} + */ + +#include +#include "wdog.h" +#include "cpu-conf.h" +#include "periph_conf.h" + +#ifndef KINETIS_WDOG_ADVANCED +/** + * Attempts to determine the type of the WDOG, + * using the WDOG_STCTRLH_CLKSRC_MASK field. + */ +#ifdef WDOG_STCTRLH_CLKSRC_MASK +#define KINETIS_WDOG_ADVANCED 1 +#endif +#endif + +/** + * @brief Disable hardware watchdog. + * + * For advanced WDOG (mostly Kinetis MCUs with Cortex-M4 inside): + * The following unlock sequence must be completed within 256 bus cycles or + * the watchdog will reset the system. The watchdog is enabled by default at + * power on. + * + * The sequence is: + * 1. Write 0xC520 to the unlock register + * 2. Write 0xD928 to the unlock register + * + * Watchdog is now unlocked to allow us to change its settings + * + * 3. Clear the WDOGEN bit of the WDOG_STCTRLH register to completely disable + * the watchdog. + * + * It is now possible to single step through the code without the watchdog + * resetting the system. + * + * TODO: Only disable watchdog on debug builds. + */ +void wdog_disable(void) +{ +#if KINETIS_WDOG_ADVANCED + /* unlock and disable the WDOG */ + WDOG->UNLOCK = (uint16_t)0xc520; + WDOG->UNLOCK = (uint16_t)0xd928; + WDOG->STCTRLH = (uint16_t)(WDOG_STCTRLH_WAITEN_MASK + | WDOG_STCTRLH_STOPEN_MASK + | WDOG_STCTRLH_ALLOWUPDATE_MASK + | WDOG_STCTRLH_CLKSRC_MASK); +#else + /* disable the COP WDOG */ + SIM->COPC = (uint32_t)0x00u; +#endif +}