/* * Copyright (C) 2023 Daniele Lacamera * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ /* * This 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. * * frosted 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 frosted. If not, see . * * Author: Daniele Lacamera * * */ #include #include "system.h" #include #include extern int AudioPulse; #define TIM2_BASE (0x40000000) #define TIM2_CR1 (*(volatile uint32_t *)(TIM2_BASE + 0x00)) #define TIM2_DIER (*(volatile uint32_t *)(TIM2_BASE + 0x0c)) #define TIM2_CNT (*(volatile uint32_t *)(TIM2_BASE + 0x24)) #define TIM2_PSC (*(volatile uint32_t *)(TIM2_BASE + 0x28)) #define TIM2_ARR (*(volatile uint32_t *)(TIM2_BASE + 0x2c)) #define TIM_DIER_UIE (1 << 0) #define TIM_CR1_CLOCK_ENABLE (1 << 0) #define TIM_CR1_UPD_RS (1 << 2) #define TIM_CR1_EV_DISABLE (1 << 1) #define TIM2_SR (*(volatile uint32_t *)(TIM2_BASE + 0x10)) #define TIM_SR_UIF (1 << 0) int timer_start(uint32_t clock, uint32_t prescaler, uint32_t interval_us) { uint32_t val = 0; uint32_t psc = 1; uint32_t err = 0; uint32_t reg = 0; clock = ((clock * prescaler) / 2000000) * interval_us; while (psc < 65535) { val = clock / psc; err = clock % psc; if ((val < 65535) && (err == 0)) { val--; break; } val = 0; psc++; } if (val == 0) return -1; nvic_irq_enable(NVIC_TIM2_IRQN); nvic_set_priority(NVIC_TIM2_IRQN, 3); APB1_CLOCK_RST |= TIM2_APB1_CLOCK_ER_VAL; DMB(); APB1_CLOCK_RST &= ~TIM2_APB1_CLOCK_ER_VAL; APB1_CLOCK_ER |= TIM2_APB1_CLOCK_ER_VAL; TIM2_CR1 = 0; DMB(); TIM2_PSC = psc; TIM2_ARR = val; TIM2_CNT = val - 1; reg = TIM2_CR1; reg &= ~TIM_CR1_EV_DISABLE; reg |= TIM_CR1_CLOCK_ENABLE; TIM2_CR1 = reg; TIM2_DIER |= TIM_DIER_UIE; DMB(); return 0; } void timer_stop(void) { APB1_CLOCK_RST |= TIM2_APB1_CLOCK_ER_VAL; DMB(); APB1_CLOCK_RST &= ~TIM2_APB1_CLOCK_ER_VAL; TIM2_CR1 |= TIM_CR1_EV_DISABLE; APB1_CLOCK_ER &= ~TIM2_APB1_CLOCK_ER_VAL; } void isr_tim2(void) { TIM2_SR &= ~TIM_SR_UIF; // AudioPulse++; }