diff --git a/cores/arduino/board.h b/cores/arduino/board.h index e759d7d474..b517d19fa1 100644 --- a/cores/arduino/board.h +++ b/cores/arduino/board.h @@ -10,6 +10,7 @@ #include "clock.h" #include "core_callback.h" #include "digital_io.h" +#include "dwt.h" #include "hw_config.h" #include "low_power.h" #include "rtc.h" diff --git a/cores/arduino/stm32/clock.c b/cores/arduino/stm32/clock.c index 7dac1da133..e2867b8680 100644 --- a/cores/arduino/stm32/clock.c +++ b/cores/arduino/stm32/clock.c @@ -48,7 +48,7 @@ extern "C" { * @param None * @retval None */ -uint32_t GetCurrentMicro(void) +uint32_t getCurrentMicros(void) { /* Ensure COUNTFLAG is reset by reading SysTick control and status register */ LL_SYSTICK_IsActiveCounterFlag(); @@ -66,7 +66,7 @@ uint32_t GetCurrentMicro(void) * @param None * @retval None */ -uint32_t GetCurrentMilli(void) +uint32_t getCurrentMillis(void) { return HAL_GetTick(); } @@ -78,7 +78,7 @@ void noOsSystickHandler() void osSystickHandler() __attribute__((weak, alias("noOsSystickHandler"))); /** - * @brief Function called when t he tick interruption falls + * @brief Function called when the tick interruption falls * @param None * @retval None */ diff --git a/cores/arduino/stm32/clock.h b/cores/arduino/stm32/clock.h index f2655a8212..8841640261 100644 --- a/cores/arduino/stm32/clock.h +++ b/cores/arduino/stm32/clock.h @@ -58,8 +58,8 @@ typedef enum { /* Exported constants --------------------------------------------------------*/ /* Exported macro ------------------------------------------------------------*/ /* Exported functions ------------------------------------------------------- */ -uint32_t GetCurrentMilli(void); -uint32_t GetCurrentMicro(void); +uint32_t getCurrentMillis(void); +uint32_t getCurrentMicros(void); void enableClock(sourceClock_t source); #ifdef __cplusplus diff --git a/cores/arduino/stm32/dwt.c b/cores/arduino/stm32/dwt.c new file mode 100644 index 0000000000..30618d98fb --- /dev/null +++ b/cores/arduino/stm32/dwt.c @@ -0,0 +1,89 @@ +/** + ****************************************************************************** + * @file dwt.c + * @author Frederic Pillon + * @brief Provide Data Watchpoint and Trace services + ****************************************************************************** + * @attention + * + * Copyright (c) 2019, STMicroelectronics + * All rights reserved. + * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +#include "dwt.h" + +#ifdef DWT_BASE +#ifdef __cplusplus +extern "C" { +#endif + + +uint32_t dwt_init(void) +{ + + /* Enable use of DWT */ + if (!(CoreDebug->DEMCR & CoreDebug_DEMCR_TRCENA_Msk)) { + CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; + } + + /* Unlock */ + dwt_access(true); + + /* Reset the clock cycle counter value */ + DWT->CYCCNT = 0; + + /* Enable clock cycle counter */ + DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; + + /* 3 NO OPERATION instructions */ + asm volatile(" nop \n\t" + " nop \n\t" + " nop \n\t"); + + /* Check if clock cycle counter has started */ + return (DWT->CYCCNT) ? 0 : 1; +} + +void dwt_access(bool ena) +{ +#if (__CORTEX_M == 0x07U) + /* + * Define DWT LSR mask which is (currentuly) not defined by the CMSIS. + * Same as ITM LSR one. + */ +#if !defined DWT_LSR_Present_Msk +#define DWT_LSR_Present_Msk ITM_LSR_Present_Msk +#endif +#if !defined DWT_LSR_Access_Msk +#define DWT_LSR_Access_Msk ITM_LSR_Access_Msk +#endif + uint32_t lsr = DWT->LSR; + + if ((lsr & DWT_LSR_Present_Msk) != 0) { + if (ena) { + if ((lsr & DWT_LSR_Access_Msk) != 0) { //locked + DWT->LAR = 0xC5ACCE55; + } + } else { + if ((lsr & DWT_LSR_Access_Msk) == 0) { //unlocked + DWT->LAR = 0; + } + } + } +#else /* __CORTEX_M */ + UNUSED(ena); +#endif /* __CORTEX_M */ +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/cores/arduino/stm32/dwt.h b/cores/arduino/stm32/dwt.h new file mode 100644 index 0000000000..f519f6e278 --- /dev/null +++ b/cores/arduino/stm32/dwt.h @@ -0,0 +1,61 @@ +/** + ****************************************************************************** + * @file dwt.h + * @author Frederic Pillon + * @brief Header for dwt.c module + ****************************************************************************** + * @attention + * + * Copyright (c) 2019, STMicroelectronics + * All rights reserved. + * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef _DWT_H_ +#define _DWT_H_ + +#include "stm32_def.h" +#include + +#ifdef DWT_BASE + +#ifdef __cplusplus +extern "C" { +#endif + +uint32_t dwt_init(void); +void dwt_access(bool ena); + +static inline uint32_t dwt_max_sec(void) +{ + return (UINT32_MAX / SystemCoreClock); +}; + +static inline uint32_t dwt_max_msec(void) +{ + return (UINT32_MAX / (SystemCoreClock / 1000)); +}; + +static inline uint32_t dwt_max_usec(void) +{ + return (UINT32_MAX / (SystemCoreClock / 1000000)); +}; + +static inline uint32_t dwt_getCycles(void) +{ + return (DWT->CYCCNT); +}; + +#ifdef __cplusplus +} +#endif + +#endif /* DWT_BASE */ +#endif /* _DWT_H_ */ diff --git a/cores/arduino/stm32/hw_config.c b/cores/arduino/stm32/hw_config.c index e865f788a3..e5a8281d2e 100644 --- a/cores/arduino/stm32/hw_config.c +++ b/cores/arduino/stm32/hw_config.c @@ -38,6 +38,7 @@ #include "stm32_def.h" #include "hw_config.h" #include "usbd_if.h" +#include "dwt.h" #ifdef __cplusplus extern "C" { @@ -50,15 +51,21 @@ extern "C" { */ void hw_config_init(void) { - //Initialize the HAL + /* Init DWT if present */ +#ifdef DWT_BASE + dwt_init(); +#endif + + /* Initialize the HAL */ HAL_Init(); - // Configure the system clock + /* Configure the system clock */ SystemClock_Config(); #if defined (USBCON) && defined(USBD_USE_CDC) USBD_CDC_init(); #endif + } #ifdef __cplusplus } diff --git a/cores/arduino/wiring_time.c b/cores/arduino/wiring_time.c index b0237ad53a..c28d556c4a 100644 --- a/cores/arduino/wiring_time.c +++ b/cores/arduino/wiring_time.c @@ -24,25 +24,24 @@ extern "C" { uint32_t millis(void) { - // todo: ensure no interrupts - return GetCurrentMilli() ; + // ToDo: ensure no interrupts + return getCurrentMillis(); } // Interrupt-compatible version of micros uint32_t micros(void) { - return GetCurrentMicro(); + return getCurrentMicros(); } void delay(uint32_t ms) { - if (ms == 0) { - return; + if (ms != 0) { + uint32_t start = getCurrentMillis(); + do { + yield(); + } while (getCurrentMillis() - start < ms); } - uint32_t start = GetCurrentMilli(); - do { - yield(); - } while (GetCurrentMilli() - start < ms); } #ifdef __cplusplus diff --git a/cores/arduino/wiring_time.h b/cores/arduino/wiring_time.h index 7af8b0ee49..1fa68eb656 100644 --- a/cores/arduino/wiring_time.h +++ b/cores/arduino/wiring_time.h @@ -21,6 +21,7 @@ #define _WIRING_TIME_H_ #include "clock.h" +#include "dwt.h" #ifdef __cplusplus extern "C" { @@ -50,21 +51,27 @@ extern uint32_t micros(void) ; * \brief Pauses the program for the amount of time (in miliseconds) specified as parameter. * (There are 1000 milliseconds in a second.) * - * \param dwMs the number of milliseconds to pause (uint32_t) + * \param ms the number of milliseconds to pause (uint32_t) */ -extern void delay(uint32_t dwMs) ; +extern void delay(uint32_t ms) ; /** * \brief Pauses the program for the amount of time (in microseconds) specified as parameter. * - * \param dwUs the number of microseconds to pause (uint32_t) + * \param us the number of microseconds to pause (uint32_t) */ static inline void delayMicroseconds(uint32_t) __attribute__((always_inline, unused)); -static inline void delayMicroseconds(uint32_t usec) +static inline void delayMicroseconds(uint32_t us) { - uint32_t start = GetCurrentMicro(); +#if defined(DWT_BASE) && !defined(DWT_DELAY_DISABLED) + int32_t start = dwt_getCycles(); + int32_t cycles = us * (SystemCoreClock / 1000000); - while ((start + usec) > GetCurrentMicro()); + while ((int32_t)dwt_getCycles() - start < cycles); +#else + uint32_t start = getCurrentMicros(); + while (getCurrentMicros() - start < us); +#endif } #ifdef __cplusplus