diff --git a/cpu/atmega_common/Kconfig b/cpu/atmega_common/Kconfig index 5311f0db60..c49d8fe1b8 100644 --- a/cpu/atmega_common/Kconfig +++ b/cpu/atmega_common/Kconfig @@ -9,6 +9,7 @@ config CPU_COMMON_ATMEGA select CPU_CORE_AVR select HAS_ATMEGA_PCINT0 select HAS_CPP + select HAS_DBGPIN select HAS_PERIPH_CPUID select HAS_PERIPH_EEPROM select HAS_PERIPH_GPIO diff --git a/cpu/atmega_common/Makefile.features b/cpu/atmega_common/Makefile.features index a90abb1aa5..8287eba643 100644 --- a/cpu/atmega_common/Makefile.features +++ b/cpu/atmega_common/Makefile.features @@ -4,6 +4,7 @@ include $(RIOTCPU)/avr8_common/Makefile.features # Only add Additional features FEATURES_PROVIDED += atmega_pcint0 +FEATURES_PROVIDED += dbgpin FEATURES_PROVIDED += periph_cpuid FEATURES_PROVIDED += periph_eeprom FEATURES_PROVIDED += periph_gpio periph_gpio_irq diff --git a/cpu/avr8_common/startup.c b/cpu/avr8_common/startup.c index da9f6263d1..26b5c5f6b6 100644 --- a/cpu/avr8_common/startup.c +++ b/cpu/avr8_common/startup.c @@ -30,6 +30,9 @@ #ifdef MODULE_PUF_SRAM #include "puf_sram.h" #endif +#ifdef MODULE_DBGPIN +#include "dbgpin.h" +#endif /** * @brief functions for initializing the board, std-lib and kernel @@ -73,6 +76,11 @@ __attribute__((used)) void reset_handler(void) #ifdef MODULE_PUF_SRAM puf_sram_init((uint8_t *)RAMEND-SEED_RAM_LEN, SEED_RAM_LEN); #endif + +#ifdef MODULE_DBGPIN + dbgpin_init(); +#endif + /* initialize the board and startup the kernel */ board_init(); /* startup the kernel */ diff --git a/cpu/cortexm_common/Kconfig b/cpu/cortexm_common/Kconfig index 51267c16a9..0f921bb37a 100644 --- a/cpu/cortexm_common/Kconfig +++ b/cpu/cortexm_common/Kconfig @@ -48,6 +48,7 @@ config CPU_CORE_CORTEX_M select HAS_SSP select HAS_CORTEXM_SVC select HAS_NEWLIB + select HAS_DBGPIN ## Common CPU symbols config CPU_CORE diff --git a/cpu/cortexm_common/Makefile.features b/cpu/cortexm_common/Makefile.features index 869d8988e7..5c1e56f60f 100644 --- a/cpu/cortexm_common/Makefile.features +++ b/cpu/cortexm_common/Makefile.features @@ -4,6 +4,7 @@ FEATURES_PROVIDED += cortexm_svc FEATURES_PROVIDED += cpp FEATURES_PROVIDED += cpu_check_address FEATURES_PROVIDED += cpu_core_cortexm +FEATURES_PROVIDED += dbgpin FEATURES_PROVIDED += libstdcpp FEATURES_PROVIDED += newlib FEATURES_PROVIDED += periph_pm diff --git a/cpu/cortexm_common/vectors_cortexm.c b/cpu/cortexm_common/vectors_cortexm.c index f0e2c0816c..c158c12242 100644 --- a/cpu/cortexm_common/vectors_cortexm.c +++ b/cpu/cortexm_common/vectors_cortexm.c @@ -37,6 +37,9 @@ #ifdef MODULE_PUF_SRAM #include "puf_sram.h" #endif +#ifdef MODULE_DBGPIN +#include "dbgpin.h" +#endif #ifndef SRAM_BASE #define SRAM_BASE 0 @@ -172,6 +175,10 @@ void reset_handler_default(void) post_startup(); +#ifdef MODULE_DBGPIN + dbgpin_init(); +#endif + /* initialize the board (which also initiates CPU initialization) */ board_init(); diff --git a/cpu/kinetis/include/cpu_conf.h b/cpu/kinetis/include/cpu_conf.h index ac3ac66fae..ec8282b3e5 100644 --- a/cpu/kinetis/include/cpu_conf.h +++ b/cpu/kinetis/include/cpu_conf.h @@ -19,6 +19,19 @@ #ifndef CPU_CONF_H #define CPU_CONF_H +/* This is needed to homogenize the symbolic IRQ names across different versions + * of the vendor headers. These must be defined before any vendor headers are + * included */ +#define FTFA_IRQn FTF_IRQn +#define FTFA_Collision_IRQn Read_Collision_IRQn +#define FTFE_IRQn FTF_IRQn +#define FTFE_Collision_IRQn Read_Collision_IRQn +#define FTFL_IRQn FTF_IRQn +#define FTFL_Collision_IRQn Read_Collision_IRQn +#define PMC_IRQn LVD_LVW_IRQn +#define Watchdog_IRQn WDOG_EWM_IRQn +#define LVD_LVW_DCDC_IRQn LVD_LVW_IRQn + /* Dispatch to a separate file per family */ #if defined(KINETIS_SERIES_K) #include "cpu_conf_kinetis_k.h" diff --git a/cpu/kinetis/vectors.c b/cpu/kinetis/vectors.c index 12a3775b71..4ca2d86d57 100644 --- a/cpu/kinetis/vectors.c +++ b/cpu/kinetis/vectors.c @@ -26,20 +26,6 @@ * @name Interrupt vector definition * @{ */ - -/* This is needed to homogenize the symbolic IRQ names across different versions - * of the vendor headers. These must be defined before any vendor headers are - * included */ -#define FTFA_IRQn FTF_IRQn -#define FTFA_Collision_IRQn Read_Collision_IRQn -#define FTFE_IRQn FTF_IRQn -#define FTFE_Collision_IRQn Read_Collision_IRQn -#define FTFL_IRQn FTF_IRQn -#define FTFL_Collision_IRQn Read_Collision_IRQn -#define PMC_IRQn LVD_LVW_IRQn -#define Watchdog_IRQn WDOG_EWM_IRQn -#define LVD_LVW_DCDC_IRQn LVD_LVW_IRQn - #include "vectors_kinetis.h" /* CPU specific interrupt vector table */ diff --git a/cpu/msp430_common/Kconfig b/cpu/msp430_common/Kconfig index 0b0e21d8cb..d5cdcd9b28 100644 --- a/cpu/msp430_common/Kconfig +++ b/cpu/msp430_common/Kconfig @@ -10,6 +10,7 @@ config CPU_ARCH_MSP430 bool select HAS_ARCH_16BIT select HAS_ARCH_MSP430 + select HAS_DBGPIN select HAS_PERIPH_FLASHPAGE select HAS_PERIPH_FLASHPAGE_PAGEWISE select HAS_NEWLIB diff --git a/cpu/msp430_common/Makefile.features b/cpu/msp430_common/Makefile.features index a987418df6..f6dafead7c 100644 --- a/cpu/msp430_common/Makefile.features +++ b/cpu/msp430_common/Makefile.features @@ -3,6 +3,7 @@ CPU_CORE = msp430 FEATURES_PROVIDED += arch_16bit FEATURES_PROVIDED += arch_msp430 +FEATURES_PROVIDED += dbgpin FEATURES_PROVIDED += newlib FEATURES_PROVIDED += periph_flashpage FEATURES_PROVIDED += periph_flashpage_pagewise diff --git a/cpu/msp430_common/startup.c b/cpu/msp430_common/startup.c index 8c68c0f8dc..7db0c8bdcc 100644 --- a/cpu/msp430_common/startup.c +++ b/cpu/msp430_common/startup.c @@ -27,6 +27,9 @@ #include "stdio_base.h" #include "irq.h" #include "log.h" +#ifdef MODULE_DBGPIN +#include "dbgpin.h" +#endif extern void board_init(void); @@ -34,6 +37,10 @@ __attribute__((constructor)) static void startup(void) { board_init(); +#ifdef MODULE_DBGPIN + dbgpin_init(); +#endif + #ifdef MODULE_NEWLIB void _init(void); _init(); diff --git a/kconfigs/Kconfig.features b/kconfigs/Kconfig.features index f60b8bb940..99c394b361 100644 --- a/kconfigs/Kconfig.features +++ b/kconfigs/Kconfig.features @@ -52,6 +52,12 @@ config HAS_CPU_CHECK_ADDRESS help Indicates that address validity check is supported. +config HAS_DBGPIN + bool + help + Indicates that a platform provides the neccessary initialization hooks + for the dbgpin module. + config HAS_EMULATOR_RENODE bool help diff --git a/makefiles/pseudomodules.inc.mk b/makefiles/pseudomodules.inc.mk index e6c4f6ba1f..a4acda742a 100644 --- a/makefiles/pseudomodules.inc.mk +++ b/makefiles/pseudomodules.inc.mk @@ -20,6 +20,7 @@ PSEUDOMODULES += cortexm_fpu PSEUDOMODULES += cortexm_svc PSEUDOMODULES += cpu_check_address PSEUDOMODULES += crypto_% # crypto_aes or crypto_3des +PSEUDOMODULES += dbgpin PSEUDOMODULES += devfs_% PSEUDOMODULES += dhcpv6_% PSEUDOMODULES += ecc_% diff --git a/sys/Makefile.dep b/sys/Makefile.dep index 019d117ef1..22c395fba7 100644 --- a/sys/Makefile.dep +++ b/sys/Makefile.dep @@ -1126,4 +1126,9 @@ ifneq (,$(filter ecc_%,$(USEMODULE))) USEMODULE += ecc endif +ifneq (,$(filter dbgpin,$(USEMODULE))) + FEATURES_REQUIRED += periph_gpio + FEATURES_REQUIRED += dbgpin +endif + include $(RIOTBASE)/sys/test_utils/Makefile.dep diff --git a/sys/include/dbgpin.h b/sys/include/dbgpin.h new file mode 100644 index 0000000000..c5e11ddb98 --- /dev/null +++ b/sys/include/dbgpin.h @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2020 Freie Universität Berlin + * + * 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 sys_dbgpin Direct pin control for debugging/profiling + * @ingroup sys + * + * @warning This module does not verify the given pin number, so make sure + * the pin numbers you use are actually configured! + * + * @{ + * @file + * @brief GPIO wrapper for debugging/profiling purposes + * + * @author Hauke Petersen + */ + +#ifndef DBGPIN_H +#define DBGPIN_H + +#include "kernel_defines.h" +#include "periph/gpio.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +#ifndef DBGPIN_PINS +#error Please specify the pins to use with the dbgpin module (DBGPIN_PINS) +#endif + +/** + * @brief Set the given debug pin to HIGH + * + * @param[in] pin pin to set, pin number is offset to the list of defined + * debug pins in DBGPIN_PINS + */ +static inline void dbgpin_set(unsigned pin) +{ + static const gpio_t dbgpin_pins[] = { DBGPIN_PINS }; + gpio_set(dbgpin_pins[pin]); +} + +/** + * @brief Set the given debug pin to LOW + * + * @param[in] pin pin to set, pin number is offset to the list of defined + * debug pins in DBGPIN_PINS + */ +static inline void dbgpin_clear(unsigned pin) +{ + static const gpio_t dbgpin_pins[] = { DBGPIN_PINS }; + gpio_clear(dbgpin_pins[pin]); +} + +/** + * @brief Toggle the given debug pin + * + * @param[in] pin pin to set, pin number is offset to the list of defined + * debug pins in DBGPIN_PINS + */ +static inline void dbgpin_toggle(unsigned pin) +{ + static const gpio_t dbgpin_pins[] = { DBGPIN_PINS }; + gpio_toggle(dbgpin_pins[pin]); +} + +/** + * @brief Output a pulse on the given debug pin (toggles the pin twice) + * + * @param[in] pin pin to set, pin number is offset to the list of defined + * debug pins in DBGPIN_PINS + */ +static inline void dbgpin_pulse(unsigned pin) +{ + dbgpin_toggle(pin); + dbgpin_toggle(pin); +} + +/** + * @brief Output a specified number of pulses on the given debug pin + * + * @param[in] pin pin to set, pin number is offset to the list of defined + * debug pins in DBGPIN_PINS + * @param[in] num number of pulses to output + */ +static inline void dbgpin_signal(unsigned pin, unsigned num) +{ + for (unsigned i = 0; i < num; i++) { + dbgpin_pulse(pin); + } +} + +/** + * @brief Get the number of configured debug pins + * + * @return number of configured debug pins + */ +static inline size_t dbgpin_count(void) +{ + static const gpio_t dbgpin_pins[] = { DBGPIN_PINS }; + return ARRAY_SIZE(dbgpin_pins); +} + + +/** + * @brief Initialize the configured input pins + */ +static inline void dbgpin_init(void) +{ + static const gpio_t dbgpin_pins[] = { DBGPIN_PINS }; + for (unsigned i = 0; i < ARRAY_SIZE(dbgpin_pins); i++) { + gpio_init(dbgpin_pins[i], GPIO_OUT); + gpio_clear(dbgpin_pins[i]); + } +} + +#ifdef __cplusplus +} +#endif + +#endif /* DBGPIN_H */ +/** @} **/ diff --git a/tests/dbgpin/Makefile b/tests/dbgpin/Makefile new file mode 100644 index 0000000000..9a02af2ac2 --- /dev/null +++ b/tests/dbgpin/Makefile @@ -0,0 +1,9 @@ +include ../Makefile.tests_common + +USEMODULE += dbgpin +USEMODULE += xtimer + +DBGPIN_PINS ?= GPIO_PIN(0,0) +CFLAGS += -DDBGPIN_PINS="$(DBGPIN_PINS)" + +include $(RIOTBASE)/Makefile.include diff --git a/tests/dbgpin/main.c b/tests/dbgpin/main.c new file mode 100644 index 0000000000..589c9e860f --- /dev/null +++ b/tests/dbgpin/main.c @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2020 Freie Universität Berlin + * + * 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 tests + * @{ + * + * @file + * @brief Test for the dbgpin module + * + * @author Hauke Petersen + * + * @} + */ + +#include + +#include "dbgpin.h" +#include "xtimer.h" + +#define TICK_MS 5U + +int main(void) +{ + printf("Found %i configured debug pin(s)\n", dbgpin_count()); + + for (unsigned p = 0; p < dbgpin_count(); p++) { + printf("Testing pin %u\n", p); + dbgpin_set(p); + xtimer_msleep(TICK_MS); + dbgpin_clear(p); + xtimer_msleep(TICK_MS); + dbgpin_toggle(p); + xtimer_msleep(2 * TICK_MS); + dbgpin_toggle(p); + xtimer_msleep(TICK_MS); + dbgpin_pulse(p); + xtimer_msleep(TICK_MS); + for (unsigned i = 2; i <= 5; i++) { + dbgpin_signal(p, i); + xtimer_msleep(TICK_MS); + } + } + + puts("Test successful."); + + return 0; +} diff --git a/tests/dbgpin/tests/01-run.py b/tests/dbgpin/tests/01-run.py new file mode 100755 index 0000000000..1b1cac95f3 --- /dev/null +++ b/tests/dbgpin/tests/01-run.py @@ -0,0 +1,12 @@ +#!/usr/bin/env python3 + +import sys +from testrunner import run + + +def testfunc(child): + child.expect_exact('Test successful.') + + +if __name__ == "__main__": + sys.exit(run(testfunc))