Library 54- General library for STM32F4xx devices
For 54th lib I decided to make it’s name to be “General”. With this name I mean that in this library, a lot of different stuff, maybe unrelated between, but very useful things will be implemented.
It allows you to make software reset, get reset source, disable or enable global interrupts (NVIC) and more.
It will be updated frequently but for now it’s just a start to use it in your projects.
Library
Features
- Support for software reset with callback
- Get reset source, what resets your MCU
- Disable or enable global NVIC interrupts
- Get different clock speeds in your system
- Operate with DWT counter inside Cortex-M4 CPU
- Precise delay using DWT timer
- Check if number is odd or even or if it is power of 2
- Round float numbers
- Convert float number to integer and decimal parts
Dependencies
- CMSIS
- STM32F4xx
- STM32F4xx RCC
- TM
- defines.h
- attributes.h
- defines.h
Functions and enumerations
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 |
/** * @defgroup TM_GENERAL_Typedefs * @brief Library Typedefs * @{ */ /** * @brief Clock speed enumeration */ typedef enum { TM_GENERAL_Clock_HSI, /*!< High speed internal clock */ TM_GENERAL_Clock_HSE, /*!< High speed external clock */ TM_GENERAL_Clock_SYSCLK, /*!< System core clock */ TM_GENERAL_Clock_PCLK1, /*!< PCLK1 (APB1) peripheral clock */ TM_GENERAL_Clock_PCLK2, /*!< PCLK2 (APB2) peripheral clock */ TM_GENERAL_Clock_HCLK /*!< HCLK (AHB1) high speed clock */ } TM_GENERAL_Clock_t; /** * @brief All possible reset sources */ typedef enum { TM_GENERAL_ResetSource_None = 0x00, /*!< No reset source detected. Flags are already cleared */ TM_GENERAL_ResetSource_LowPower = 0x01, /*!< Low-power management reset occurs */ TM_GENERAL_ResetSource_WWDG = 0x02, /*!< Window watchdog reset occurs */ TM_GENERAL_ResetSource_IWDG = 0x03, /*!< Independent watchdog reset occurs */ TM_GENERAL_ResetSource_Software = 0x04, /*!< Software reset occurs */ TM_GENERAL_ResetSource_POR = 0x05, /*!< POR/PDR reset occurs */ TM_GENERAL_ResetSource_PIN = 0x06, /*!< NRST pin is set to low by hardware reset, hardware reset */ TM_GENERAL_ResetSource_BOR = 0x07, /*!< BOR reset occurs */ } TM_GENERAL_ResetSource_t; /** * @brief Float number operation structure */ typedef struct { int32_t Integer; /*!< Integer part of float number */ uint32_t Decimal; /*!< Decimal part of float number */ } TM_GENERAL_Float_t; /** * @} */ /** * @defgroup TM_GENERAL_Functions * @brief Library Functions * @{ */ /** * @brief Performs a system reset * @note Before system will be reset, @ref TM_GENERAL_SoftwareResetCallback() will be called, * where you can do important stuff if necessary * @param None * @retval None */ void TM_GENERAL_SystemReset(void); /** * @brief Gets reset source why system was reset * @param reset_flags: After read, clear reset flags * - 0: Flags will stay untouched * - > 0: All reset flags will reset * @retval Member of @ref TM_GENERAL_ResetSource_t containing reset source */ TM_GENERAL_ResetSource_t TM_GENERAL_GetResetSource(uint8_t reset_flags); /** * @brief Disables all interrupts in system * @param None * @retval None */ void TM_GENERAL_DisableInterrupts(void); /** * @brief Enables interrupts in system. * @note This function has nesting support. This means that if you call @ref TM_GENERAL_DisableInterrupts() 4 times, * then you have to call this function also 4 times to enable interrupts. * @param None * @retval Interrupt enabled status: * - 0: Interrupts were not enabled * - > 0: Interrupts were enabled */ uint8_t TM_GENERAL_EnableInterrupts(void); /** * @brief Checks if code execution is inside active IRQ * @param None * @retval IRQ Execution status: * - 0: Code execution is not inside IRQ, thread mode * - > 0: Code execution is inside IRQ, IRQ mode * @note Defines as macro for faster execution */ #define TM_GENERAL_IsIRQMode() (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) /** * @brief Gets specific clock speed value from STM32F4xx device * @param clock: Clock type you want to know speed for. This parameter can be a value of @ref TM_GENERAL_Clock_t enumeration * @retval Clock speed in units of hertz */ uint32_t TM_GENERAL_GetClockSpeed(TM_GENERAL_Clock_t clock); /** * @brief Gets system clock speed in units of MHz * @param None * @retval None * @note Defined as macro for faster execution */ #define TM_GENERAL_GetSystemClockMHz() ((uint16_t)(SystemCoreClock * (float)0.000001)) /** * @brief Enables DWT counter in Cortex-M4 core * @param None * @retval DWT Status: * - 0: DWT has not started, hardware/software reset is required * - > 0: DWT has started and is ready to use * @note It may happen, that DWT counter won't start after reprogramming device. * This happened to me when I use onboard ST-Link on Discovery or Nucleo boards. * When I used external debugger (J-Link or ULINK2) it worked always without problems. * If your DWT doesn't start, you should perform software/hardware reset by yourself. */ uint8_t TM_GENERAL_DWTCounterEnable(void); /** * @brief Disables DWT counter in Cortex-M4 core * @param None * @retval None * @note Defined as macro for faster execution */ #define TM_GENERAL_DWTCounterDisable() (DWT->CTRL &= ~0x00000001) /** * @brief Gets current DWT counter value * @param None * @retval DWT counter value * @note Defined as macro for faster execution */ #define TM_GENERAL_DWTCounterGetValue() (DWT->CYCCNT) /** * @brief Sets DWT counter value * @param x: Value to be set to DWT counter * @retval None * @note Defined as macro for faster execution */ #define TM_GENERAL_DWTCounterSetValue(x) (DWT->CYCCNT = (x)) /** * @brief Delays for amount of microseconds using DWT counter * @param micros: Number of micro seconds for delay * @retval None * @note DWT Counter HAVE to be initialized first using @ref TM_GENERAL_EnableDWTCounter() */ static __INLINE void TM_GENERAL_DWTCounterDelayus(uint32_t micros) { uint32_t c = TM_GENERAL_DWTCounterGetValue(); /* Calculate clock cycles */ micros *= (SystemCoreClock / 1000000); micros -= 12; /* Wait till done */ while ((TM_GENERAL_DWTCounterGetValue() - c) < micros) { /* Do nothing */ } } /** * @brief Delays for amount of milliseconds using DWT counter * @param millis: Number of micro seconds for delay * @retval None * @note DWT Counter HAVE to be initialized first using @ref TM_GENERAL_EnableDWTCounter() */ static __INLINE void TM_GENERAL_DWTCounterDelayms(uint32_t millis) { uint32_t c = TM_GENERAL_DWTCounterGetValue(); /* Calculate clock cycles */ millis *= (SystemCoreClock / 1000); millis -= 12; /* Wait till done */ while ((TM_GENERAL_DWTCounterGetValue() - c) < millis) { /* Do nothing */ } } /** * @brief Checks if number is power of 2 * @note It can be used to determine if number has more than just one bit set * If only one bit is set, function will return > 0 because this is power of 2. * @param number: Number to check if it is power of 2 * @retval Is power of 2 status: * - 0: Number if not power of 2 * - > 0: Number is power of 2 * @note Defined as macro for faster execution */ #define TM_GENERAL_IsNumberPowerOfTwo(number) (number && !(number & (number - 1))) /** * @brief Checks if number is odd or even * @param number: Number to check if it is odd or even * @retval Is number even status: * - 0: Number is odd * - > 0: Number is even * @note Defined as macro for faster execution */ #define TM_GENERAL_IsNumberEven(number) ((number & 1) == 0) /** * @brief Converts float coded number into integer and decimal part * @param *Float_Struct: Pointer to empty @ref TM_GENERAL_Float_t to store result into * @param Number: Float number to convert * @param decimals: Number of decimal places for conversion, maximum 9 decimal places * @retval None * @note Example: You have number 15.002 in float format. * - You want to split this to integer and decimal part with 6 decimal places. * - Call @ref TM_GENERAL_ConvertFloat(&Float_Struct, 15.002, 6); * - Result will be: Integer: 15; Decimal: 2000 (0.002 * 10^6) */ void TM_GENERAL_ConvertFloat(TM_GENERAL_Float_t* Float_Struct, float Number, uint8_t decimals); /** * @brief Round float number to nearest number with custom number of decimal places * @param Number: Float number to round * @param decimals: Number of decimal places to round, maximum 9 decimal places * @retval Rounded float number */ float TM_GENERAL_RoundFloat(float Number, uint8_t decimals); /** * @brief Calculates next power of 2 from given number * @param number: Input number to be calculated * @param Number with next power of 2 * Example: * - Input number: 450 * - Next power of 2 is: 512 = 2^9 */ uint32_t TM_GENERAL_NextPowerOf2(uint32_t number); /** * @brief Software reset callback. * Function is called before software reset occurs. * @param None * @retval None * @note With __weak parameter to prevent link errors if not defined by user */ __weak void TM_GENERAL_SoftwareResetCallback(void); /** * @} */ |
Example
- Example shows how to get reset source and how to get frequencies inside your system.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
/** * Keil project example for GENERAL library * * Before you start, select your target, on the right of the "Load" button * * @author Tilen Majerle * @email tilen@majerle.eu * @website http://stm32f4-discovery.net * @ide Keil uVision 5 * @conf PLL parameters are set in "Options for Target" -> "C/C++" -> "Defines" * @packs STM32F4xx Keil packs version 2.4.0 or greater required * @stdperiph STM32F4xx Standard peripheral drivers version 1.5.0 or greater required */ /* Include core modules */ #include "stm32f4xx.h" /* Include my libraries here */ #include "defines.h" #include "tm_stm32f4_delay.h" #include "tm_stm32f4_disco.h" #include "tm_stm32f4_general.h" #include "tm_stm32f4_usart.h" #include "stdio.h" int main(void) { /* Initialize system */ SystemInit(); /* Initialize delay */ TM_DELAY_Init(); /* Initialize leds on board */ TM_DISCO_LedInit(); /* Init button */ TM_DISCO_ButtonInit(); /* Init USART6, TX: PC6, 115200 baud */ TM_USART_Init(USART6, TM_USART_PinsPack_1, 115200); /* Get system reset source and clear flags after read */ printf("System reset source: %d\n", (uint8_t)TM_GENERAL_GetResetSource(1)); /* Get system reset source and clear flags after read */ /* You should see number which corresponds to "None", because we cleared flags in statement above */ printf("System reset source: %d\n", (uint8_t)TM_GENERAL_GetResetSource(1)); /* Get system core and PCLK1 (Peripheral Clock 1, APB1) clocks */ printf("System core clock: %u Hz; PCLK1 clock: %u Hz\n", TM_GENERAL_GetClockSpeed(TM_GENERAL_Clock_SYSCLK), TM_GENERAL_GetClockSpeed(TM_GENERAL_Clock_PCLK1) ); while (1) { /* If button pressed */ if (TM_DISCO_ButtonOnPressed()) { /* Send to USER */ printf("Software reset will happen in a moment\n"); /* Wait a little */ Delayms(500); /* Perform system software reset */ TM_GENERAL_SystemReset(); } } } /* Called from printf */ int fputc(int ch, FILE* f) { /* Send over USART */ TM_USART_Putc(USART6, ch); /* Return character */ return ch; } |
Project is available on my Github, download library below.
Recent comments