From 31442f0adc4d46e0afbc710fe5811100b0d7a681 Mon Sep 17 00:00:00 2001 From: Balazs Racz Date: Sun, 10 Apr 2022 23:17:44 +0200 Subject: [PATCH 1/2] Adds shared code for STM32 implementation of the crash blinker. --- src/freertos_drivers/st/Stm32Blinker.hxx | 161 +++++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 src/freertos_drivers/st/Stm32Blinker.hxx diff --git a/src/freertos_drivers/st/Stm32Blinker.hxx b/src/freertos_drivers/st/Stm32Blinker.hxx new file mode 100644 index 000000000..fd2bc4680 --- /dev/null +++ b/src/freertos_drivers/st/Stm32Blinker.hxx @@ -0,0 +1,161 @@ +/** \copyright + * Copyright (c) 2022, Balazs Racz + * 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. + * + * 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 THE COPYRIGHT HOLDER OR 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. + * + * \file Stm32Blinker.hxx + * Implements the crash blinker using an STM32 timer. + * + * @author Balazs Racz + * @date 10 April 2022 + */ + +#ifndef _FREERTOS_DRIVERS_ST_STM32BLINKER_HXX_ +#define _FREERTOS_DRIVERS_ST_STM32BLINKER_HXX_ + +/* How to use: + +Add the following code to the hardware.hxx +``` + #define BLINKER_INTERRUPT_HANDLER timer14_interrupt_handler + + struct BlinkerHw + { + static constexpr uint32_t TIMER_BASE = TIM14_BASE; + static constexpr auto TIMER_IRQn = TIM14_IRQn; + static void clock_enable() + { + __HAL_RCC_TIM14_CLK_ENABLE(); + } + }; +``` + +then +``` +#include "freertos_drivers/st/Stm32Blinker.hxx" +``` + +in HwInit.cxx after hardware.hxx was included. Call setup_blinker() in +hw_preinit. +*/ + +#ifndef BLINKER_INTERRUPT_HANDLER +#error must include hardware.hxx before Stm32Blinker.hxx +#endif + +/// @return constexpr timer instance typecast to the correct struct pointer. +static inline TIM_TypeDef *get_blinker_timer() +{ + return (TIM_TypeDef *)BlinkerHw::TIMER_BASE; +} + +extern "C" { + +/// Call this function in hw_preinit to set up the blinker timer. +void setup_blinker() +{ + BlinkerHw::clock_enable(); + /* Initializes the blinker timer. */ + TIM_HandleTypeDef TimHandle; + memset(&TimHandle, 0, sizeof(TimHandle)); + TimHandle.Instance = get_blinker_timer(); + TimHandle.Init.Period = configCPU_CLOCK_HZ / 10000 / 5; + TimHandle.Init.Prescaler = 10000; + TimHandle.Init.ClockDivision = 0; + TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP; + TimHandle.Init.RepetitionCounter = 0; + if (HAL_TIM_Base_Init(&TimHandle) != HAL_OK) + { + /* Initialization Error */ + HASSERT(0); + } + if (HAL_TIM_Base_Start_IT(&TimHandle) != HAL_OK) + { + /* Starting Error */ + HASSERT(0); + } + NVIC_SetPriority(BlinkerHw::TIMER_IRQn, 0); + NVIC_EnableIRQ(BlinkerHw::TIMER_IRQn); +} + +/// Stores the canonical pattern for the blinker. +uint32_t blinker_pattern = 0; +/// Stores what is left of the pattern during the current period. +static uint32_t rest_pattern = 0; + +extern void hw_set_to_safe(void); + +void resetblink(uint32_t pattern) +{ + blinker_pattern = pattern; + rest_pattern = pattern ? 1 : 0; + BLINKER_RAW_Pin::set(pattern ? true : false); + /* todo: make a timer event trigger immediately */ +} + +void setblink(uint32_t pattern) +{ + resetblink(pattern); +} + +void BLINKER_INTERRUPT_HANDLER(void) +{ + // + // Clear the timer interrupt. + // + get_blinker_timer()->SR = ~TIM_IT_UPDATE; + + // Set output LED. + BLINKER_RAW_Pin::set(rest_pattern & 1); + + // Shift and maybe reset pattern. + rest_pattern >>= 1; + if (!rest_pattern) + { + rest_pattern = blinker_pattern; + } +} + +void wait_with_blinker(void) +{ + if (get_blinker_timer()->SR & TIM_IT_UPDATE) + { + BLINKER_INTERRUPT_HANDLER(); + } +} + +void diewith(uint32_t pattern) +{ + asm("cpsid i\n"); + hw_set_to_safe(); + resetblink(pattern); + while (1) + { + wait_with_blinker(); + } +} + +} // extern "C" + +#endif // _FREERTOS_DRIVERS_ST_STM32BLINKER_HXX_ From 66feca8b6fe81b1614f47bcbb672d540856f00d2 Mon Sep 17 00:00:00 2001 From: Balazs Racz Date: Sun, 10 Apr 2022 23:19:04 +0200 Subject: [PATCH 2/2] Makes microdelay use C linkage. Fixes up the clang-format rules to not indent after extern "C". --- .clang-format | 20 ++++++++++++++++++++ src/os/sleep.h | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/.clang-format b/.clang-format index 01a63dcba..7e1039a3a 100644 --- a/.clang-format +++ b/.clang-format @@ -43,5 +43,25 @@ SpacesInCStyleCastParentheses: false SpaceAfterControlStatementKeyword: true SpaceBeforeAssignmentOperators: true ContinuationIndentWidth: 4 + +# This big block of settings works around indentation after an extern "C" +BraceWrapping: + AfterClass: true + AfterControlStatement: true + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: true + AfterStruct: true + AfterUnion: true + AfterExternBlock: false + BeforeCatch: true + BeforeElse: true + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: false + SplitEmptyNamespace: false +BreakBeforeBraces: Custom +IndentExternBlock: false ... diff --git a/src/os/sleep.h b/src/os/sleep.h index 42d796f90..a61280f16 100644 --- a/src/os/sleep.h +++ b/src/os/sleep.h @@ -48,6 +48,6 @@ static void microsleep(uint32_t microseconds) __attribute__((weakref("usleep"))) /// Executes a busy loop for a given amount of time. It is recommended to use /// this only for small number of microseconds (e.g. <100 usec). /// @param microseconds how long to delay. -extern void microdelay(uint32_t microseconds); +extern "C" void microdelay(uint32_t microseconds); #endif // _OS_SLEEP_H_