reflow-oven-control-sw/stm-firmware/systick.c

128 lines
3.0 KiB
C

/* Reflow Oven Controller
*
* Copyright (C) 2020 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of the Reflow Oven Controller Project.
*
* The reflow oven controller is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* The Reflow Oven Control Firmware is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the reflow oven controller project.
* If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file systick.c
*/
#include <reflow-controller/systick.h>
#include <helper-macros/helper-macros.h>
#include <stm32/stm32f4xx.h>
#include <cmsis/core_cm4.h>
volatile uint32_t IN_SECTION(.ccm.bss) wait_tick_ms = 0UL;
volatile uint64_t IN_SECTION(.ccm.bss) global_tick_ms = 0ULL;
volatile uint32_t IN_SECTION(.ccm.bss) lcd_tick_100us = 0UL;
void systick_setup(void)
{
/* Setup Systick for 100us tick @ 168 MHz Clock Speed */
SysTick_Config(SYSTICK_RELOAD);
}
void systick_wait_ms(uint32_t ms)
{
wait_tick_ms = 0UL;
while (wait_tick_ms < ms)
;
}
uint64_t systick_get_global_tick(void)
{
uint64_t temp;
__disable_irq();
temp = global_tick_ms;
__enable_irq();
return temp;
}
void systick_get_uptime_from_tick(uint32_t *days, uint32_t *hours, uint32_t *minutes, uint32_t *seconds)
{
uint64_t tick_secs;
uint32_t secs;
uint32_t mins;
uint32_t hs;
uint32_t ds;
tick_secs = systick_get_global_tick() / 1000;
secs = tick_secs % 60;
tick_secs /= 60;
mins = tick_secs % 60;
tick_secs /= 60;
hs = tick_secs % 60;
tick_secs /= 24;
ds = tick_secs;
if (days)
*days = ds;
if (hours)
*hours = hs;
if (minutes)
*minutes = mins;
if (seconds)
*seconds = secs;
}
bool __attribute__((optimize("O3"))) systick_ticks_have_passed(uint64_t start_timestamp, uint64_t ticks)
{
uint64_t end_timestamp = start_timestamp + ticks;
uint64_t current_timestamp = systick_get_global_tick();
/* wrap around expected */
if (end_timestamp < start_timestamp) {
/* Wrap around occured */
if (current_timestamp < start_timestamp) {
if (current_timestamp >= end_timestamp)
return true;
}
} else {
if (current_timestamp >= end_timestamp)
return true;
}
return false;
}
/**
* @brief Interrupt Handler for SysTick
*
* This handler is called every 100 us.
* It is important to keep this function simple as it is called that often and may prevent program flow.
*
* @warning For calling cyclic functions use separate timers/flags and don't spoil this function
*/
void __attribute__((optimize("O3"))) SysTick_Handler(void)
{
static uint32_t IN_SECTION(.ccm.bss) pre_tick = 0UL;
pre_tick++;
if (pre_tick == 10) {
pre_tick = 0;
/* Increase tick counters */
wait_tick_ms++;
global_tick_ms++;
}
lcd_tick_100us++;
}