{"id":4443,"date":"2026-05-09T08:11:28","date_gmt":"2026-05-09T08:11:28","guid":{"rendered":"https:\/\/blog.embeddedexpert.io\/?p=4443"},"modified":"2026-05-09T08:12:16","modified_gmt":"2026-05-09T08:12:16","slug":"getting-started-with-stm32-low-layer-ll-develop-time-base","status":"publish","type":"post","link":"https:\/\/blog.embeddedexpert.io\/?p=4443","title":{"rendered":"Getting Started with STM32 Low Layer (LL): Develop Time Base"},"content":{"rendered":"\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"559\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/Gemini_Generated_Image_y2zzhuy2zzhuy2zz-1024x559.png\" alt=\"\" class=\"wp-image-4444\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/Gemini_Generated_Image_y2zzhuy2zzhuy2zz-1024x559.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/Gemini_Generated_Image_y2zzhuy2zzhuy2zz-300x164.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/Gemini_Generated_Image_y2zzhuy2zzhuy2zz-768x419.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/Gemini_Generated_Image_y2zzhuy2zzhuy2zz-1150x627.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/Gemini_Generated_Image_y2zzhuy2zzhuy2zz-750x409.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/Gemini_Generated_Image_y2zzhuy2zzhuy2zz-400x218.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/Gemini_Generated_Image_y2zzhuy2zzhuy2zz-250x136.png 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/Gemini_Generated_Image_y2zzhuy2zzhuy2zz.png 1408w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>By offloading time management to the&nbsp;<strong>SysTick timer interrupt<\/strong>, you can replace blocking delays with a non-blocking, interrupt-driven time base that keeps your CPU free for other tasks. This guide demonstrates how to configure the 24-bit SysTick counter using Low Layer (LL) functions to increment a global millisecond counter for precise application timing.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>In this guide, we shall cover the following:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Introduction.<\/li>\n\n\n\n<li>STM32CubeMX setup.<\/li>\n\n\n\n<li>Importing project to STM32CubeIDE.<\/li>\n\n\n\n<li>Firmware Development.<\/li>\n\n\n\n<li>Results.<\/li>\n<\/ul>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1. Introduction:<\/h2>\n\n\n\n<h5 class=\"wp-block-heading\">The Power of Deterministic Timing: Understanding the SysTick Timer<\/h5>\n\n\n\n<p>In the realm of real-time embedded systems, time is the most critical resource. While initial projects often rely on &#8220;blocking&#8221; delays\u2014where the processor sits in a useless loop wasting millions of clock cycles\u2014professional firmware requires a non-blocking&nbsp;<strong>time base<\/strong>. This is where the&nbsp;<strong>SysTick (System Tick) timer<\/strong>&nbsp;becomes indispensable. Integrated directly into the ARM Cortex-M4 core of your STM32F411, the SysTick is a 24-bit down-counter specifically designed to provide a consistent heartbeat for the processor, independent of complex peripheral timers.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Why an Interrupt-Driven Time Base Matters<\/h5>\n\n\n\n<p>Using Low Layer (LL) drivers to configure the SysTick interrupt allows you to shift from a &#8220;synchronous&#8221; mindset to an &#8220;asynchronous&#8221; one. Instead of the CPU being held hostage by a&nbsp;<code>delay()<\/code>&nbsp;function, the SysTick timer triggers an&nbsp;<strong>Interrupt Service Routine (ISR)<\/strong>&nbsp;at regular intervals (typically every 1 millisecond). This heartbeat allows you to:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Multi-task efficiently:<\/strong>&nbsp;You can check for button presses, update displays, and run state machines based on a global&nbsp;<code>uwTick<\/code>&nbsp;variable while the main loop continues to execute other logic.<\/li>\n\n\n\n<li><strong>Achieve Precise Periodicity:<\/strong>&nbsp;Unlike software loops, which vary in speed based on compiler optimizations or CPU frequency, the SysTick interrupt is tied directly to the hardware clock, ensuring that &#8220;1 millisecond&#8221; remains exactly that.<\/li>\n\n\n\n<li><strong>Reduce Power Consumption:<\/strong>&nbsp;A dedicated time base allows the processor to enter low-power modes between tasks, waking up only when the timer indicates it is time to perform an action.<\/li>\n<\/ul>\n\n\n\n<h5 class=\"wp-block-heading\">LL Drivers vs. Middleware Timing<\/h5>\n\n\n\n<p>While many developers use the standard&nbsp;<code>HAL_Delay()<\/code>, implementing your own time base using&nbsp;<strong>LL drivers<\/strong>&nbsp;provides a deeper understanding of the exception-handling mechanism of the Cortex-M4. By manually initializing the tick frequency with&nbsp;<code>LL_Init1msTick<\/code>&nbsp;and defining the&nbsp;<code>SysTick_Handler<\/code>, you eliminate the overhead of the HAL state machine. This lean approach is essential for high-performance applications where you need to minimize the &#8220;latency&#8221; between a timer event and the execution of your code.<\/p>\n\n\n\n<p>In this guide, we will transform your STM32F411 from a device that &#8220;waits&#8221; into a device that &#8220;schedules,&#8221; creating a robust foundation for everything from debouncing buttons to complex sensor sampling.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2. STM32CubeMX setup:<\/h2>\n\n\n\n<p>Open STM32CubeMX as start a new project as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"662\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-04-37-1024x662.jpg\" alt=\"\" class=\"wp-image-3990\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-04-37-1024x662.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-04-37-300x194.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-04-37-768x497.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-04-37-1536x993.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-04-37-2048x1324.jpg 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-04-37-1150x744.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-04-37-750x485.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-04-37-400x259.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-04-37-250x162.jpg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Search for your STM32 MCU, select the MCU and click on Start New Project as follows:<\/p>\n\n\n\n<p>This guide shall use STM32F767Zi Nucleo-144 board<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"723\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-02_09-54-43-1024x723.png\" alt=\"\" class=\"wp-image-4421\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-02_09-54-43-1024x723.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-02_09-54-43-300x212.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-02_09-54-43-768x542.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-02_09-54-43-1536x1084.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-02_09-54-43-2048x1445.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-02_09-54-43-1150x812.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-02_09-54-43-750x529.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-02_09-54-43-400x282.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-02_09-54-43-250x176.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Since STM32F7 is an ARM Cortex M7, it requires to setup the cache, we shall go with the default setup since we don\u2019t care about it right now.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"239\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-02_09-55-54-1024x239.png\" alt=\"\" class=\"wp-image-4422\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-02_09-55-54-1024x239.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-02_09-55-54-300x70.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-02_09-55-54-768x179.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-02_09-55-54-1150x268.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-02_09-55-54-750x175.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-02_09-55-54-400x93.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-02_09-55-54-250x58.png 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-02_09-55-54.png 1346w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Next, we don&#8217;t need to do anything extra. From Project Manager tab, Advanced Settings, set both, RCC and Cortex M7 to LL as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"662\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-09_10-25-28-1024x662.png\" alt=\"\" class=\"wp-image-4445\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-09_10-25-28-1024x662.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-09_10-25-28-300x194.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-09_10-25-28-768x497.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-09_10-25-28-1536x993.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-09_10-25-28-2048x1324.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-09_10-25-28-1150x744.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-09_10-25-28-750x485.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-09_10-25-28-400x259.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-09_10-25-28-250x162.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Next, from Project, set toolchain\/IDE to STM32CubeIDE, give the project a name and click generate code as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"662\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-09_10-25-50-1024x662.png\" alt=\"\" class=\"wp-image-4446\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-09_10-25-50-1024x662.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-09_10-25-50-300x194.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-09_10-25-50-768x497.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-09_10-25-50-1536x993.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-09_10-25-50-2048x1324.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-09_10-25-50-1150x744.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-09_10-25-50-750x485.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-09_10-25-50-400x259.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-09_10-25-50-250x162.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Thats all for STM32CubeMX setup.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">3. Importing Project to STM32CubeMX:<\/h2>\n\n\n\n<p>Open STM32CubeIDE, select your workspace and click on Launch.<\/p>\n\n\n\n<p>From the IDE, click File and select STM32 Project Create\/Import as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"873\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_16-57-21-1024x873.jpg\" alt=\"\" class=\"wp-image-3997\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_16-57-21-1024x873.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_16-57-21-300x256.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_16-57-21-768x655.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_16-57-21-1150x981.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_16-57-21-750x640.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_16-57-21-400x341.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_16-57-21-250x213.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_16-57-21.jpg 1524w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Next, from Import STM32 Project, select STM32CubeMX\/STM32CubeIDE Project and click on Next as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"769\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_17-00-37-1024x769.jpg\" alt=\"\" class=\"wp-image-3998\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_17-00-37-1024x769.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_17-00-37-300x225.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_17-00-37-768x577.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_17-00-37-1150x863.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_17-00-37-750x563.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_17-00-37-400x300.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_17-00-37-250x188.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_17-00-37.jpg 1172w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Next, select the folder that contains the .ioc file and click on Finish as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"652\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/2026-04-11_11-31-41-1024x652.jpg\" alt=\"\" class=\"wp-image-4360\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/2026-04-11_11-31-41-1024x652.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/2026-04-11_11-31-41-300x191.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/2026-04-11_11-31-41-768x489.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/2026-04-11_11-31-41-1536x977.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/2026-04-11_11-31-41-1150x732.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/2026-04-11_11-31-41-750x477.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/2026-04-11_11-31-41-400x255.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/2026-04-11_11-31-41-250x159.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/2026-04-11_11-31-41.jpg 1760w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Note: Project name is for reference only.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">4. Firmware Development:<\/h2>\n\n\n\n<p>From project explorer, open stm32f7xx_it.c fro src folder.<\/p>\n\n\n\n<p>In the source file, in user code begin PV, declare the following variable:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">volatile uint32_t ticks=0;<\/pre><\/div>\n\n\n\n<p>This will hold the current ticks generated each 1ms from SysTick interrupt.<\/p>\n\n\n\n<p>Within same source, in user code begin 0, declare the following two functions:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">uint32_t getCurrentTicks(void)\n{\n\tuint32_t temp_ticks=ticks;\n\treturn temp_ticks;\n}\n\nstatic void TickInc(void)\n{\n\tticks++;\n}<\/pre><\/div>\n\n\n\n<p>These two functions serve as the software interface for your custom time base, acting as the bridge between the hardware interrupt and your application logic.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\"><code>getCurrentTicks<\/code><\/h5>\n\n\n\n<p>This is a&nbsp;<strong>getter function<\/strong>&nbsp;used to safely retrieve the current system time.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Purpose:<\/strong>&nbsp;It returns the total number of milliseconds elapsed since the processor started (or since the counter last rolled over).<\/li>\n\n\n\n<li><strong>Safe Access:<\/strong>&nbsp;By assigning&nbsp;<code>ticks<\/code>&nbsp;to a local&nbsp;<code>temp_ticks<\/code>&nbsp;variable before returning, it provides a consistent snapshot of the time for the caller, ensuring that even if an interrupt occurs during the return process, the logic remains predictable.<\/li>\n<\/ul>\n\n\n\n<h5 class=\"wp-block-heading\"><code>TickInc<\/code><\/h5>\n\n\n\n<p>This is the&nbsp;<strong>incrementer function<\/strong>, typically called from within the&nbsp;<code>SysTick_Handler<\/code>&nbsp;interrupt service routine.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Purpose:<\/strong>&nbsp;It performs the actual &#8220;work&#8221; of the time base by incrementing the global&nbsp;<code>ticks<\/code>&nbsp;variable by 1.<\/li>\n\n\n\n<li><strong>Static Scope:<\/strong>&nbsp;Marked as&nbsp;<code>static<\/code>, this function is private to the file where it is defined, preventing other parts of the code from accidentally modifying the system clock and ensuring that only the intended hardware trigger can advance time.<\/li>\n<\/ul>\n\n\n\n<p><\/p>\n\n\n\n<p>Next, in <strong>void<\/strong> <strong>SysTick_Handler<\/strong>(<strong>void<\/strong>) in USER CODE BEGIN SysTick_IRQn 0, call TickInc function as follows:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">void SysTick_Handler(void)\n{\n  \/* USER CODE BEGIN SysTick_IRQn 0 *\/\n\tTickInc();\n  \/* USER CODE END SysTick_IRQn 0 *\/\n\n  \/* USER CODE BEGIN SysTick_IRQn 1 *\/\n\n  \/* USER CODE END SysTick_IRQn 1 *\/\n}<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>Next, in stm32f7xx_it.h header file, in USER CODE BEGIN EFP, include <code>getCurrentTicks<\/code> function as follows:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">uint32_t getCurrentTicks(void);<\/pre><\/div>\n\n\n\n<p>Finally, in main.c file, we start by including stm32f7xx_it.h as follows:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">#include &quot;stm32f7xx_it.h&quot;<\/pre><\/div>\n\n\n\n<p>In user code begin PV, declare the following variable:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">uint32_t currentTicks=0;<\/pre><\/div>\n\n\n\n<p>Next, in main function, in USER CODE BEGIN SysInit, enable SysTick interrupt as follows:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">SysTick-&gt;CTRL|=SysTick_CTRL_TICKINT_Msk;<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>Next, in user code begin 3 in while 1 loop:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">currentTicks=getCurrentTicks();<\/pre><\/div>\n\n\n\n<p>Get the current ticks and store it in CurrentTicks variable.<\/p>\n\n\n\n<p>Thats all for the firmware.<\/p>\n\n\n\n<p>Thats all for the firmware.<\/p>\n\n\n\n<p>Save, build the project and run it as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"34\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/image-1-1024x34.png\" alt=\"\" class=\"wp-image-4349\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/image-1-1024x34.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/image-1-300x10.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/image-1-768x26.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/image-1-1536x51.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/image-1-1150x38.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/image-1-750x25.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/image-1-400x13.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/image-1-250x8.png 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/image-1.png 1986w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">5. Results:<\/h2>\n\n\n\n<p>Open a debugging session, add  currentTicks to Live Expressions and run the project.<\/p>\n\n\n\n<p>You should get the following:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"676\" height=\"1024\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/Screen-Recording-2026-05-09-at-10.32.32-676x1024.gif\" alt=\"\" class=\"wp-image-4447\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/Screen-Recording-2026-05-09-at-10.32.32-676x1024.gif 676w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/Screen-Recording-2026-05-09-at-10.32.32-198x300.gif 198w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/Screen-Recording-2026-05-09-at-10.32.32-768x1164.gif 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/Screen-Recording-2026-05-09-at-10.32.32-1013x1536.gif 1013w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/Screen-Recording-2026-05-09-at-10.32.32-750x1137.gif 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/Screen-Recording-2026-05-09-at-10.32.32-400x606.gif 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/Screen-Recording-2026-05-09-at-10.32.32-250x379.gif 250w\" sizes=\"(max-width: 676px) 100vw, 676px\" \/><\/figure>\n\n\n\n<p>Thats all for this guide.<\/p>\n\n\n\n<p>Happy coding \ud83d\ude09<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>By offloading time management to the&nbsp;SysTick timer interrupt, you can replace blocking delays with a non-blocking, interrupt-driven time base that keeps your CPU free for other tasks. This guide demonstrates how to configure the 24-bit SysTick counter using Low Layer (LL) functions to increment a global millisecond counter for precise application timing. In this guide, [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2,11,12],"tags":[],"class_list":["post-4443","post","type-post","status-publish","format-standard","hentry","category-embedded-systems","category-peripheral-drivers","category-stm32"],"_links":{"self":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/4443"}],"collection":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=4443"}],"version-history":[{"count":2,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/4443\/revisions"}],"predecessor-version":[{"id":4449,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/4443\/revisions\/4449"}],"wp:attachment":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=4443"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=4443"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=4443"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}