2018-10-03 03:26:07 -05:00
|
|
|
/**
|
|
|
|
* Marlin 3D Printer Firmware
|
|
|
|
*
|
2020-02-03 08:00:57 -06:00
|
|
|
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
2018-10-03 03:26:07 -05:00
|
|
|
* Copyright (c) 2016 Bob Cousins bobcousins42@googlemail.com
|
|
|
|
* Copyright (c) 2015-2016 Nico Tonnhofer wurstnase.reprap@gmail.com
|
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU 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 General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*
|
|
|
|
*/
|
2019-07-10 03:41:50 -05:00
|
|
|
#if defined(ARDUINO_ARCH_STM32) && !defined(STM32GENERIC)
|
2018-10-03 03:26:07 -05:00
|
|
|
|
|
|
|
#include "HAL.h"
|
|
|
|
|
2019-09-02 19:49:58 -05:00
|
|
|
#include "timers.h"
|
2018-10-03 03:26:07 -05:00
|
|
|
|
2019-07-09 22:30:06 -05:00
|
|
|
// ------------------------
|
2018-10-03 03:26:07 -05:00
|
|
|
// Local defines
|
2019-07-09 22:30:06 -05:00
|
|
|
// ------------------------
|
2018-10-03 03:26:07 -05:00
|
|
|
|
|
|
|
#define NUM_HARDWARE_TIMERS 2
|
|
|
|
|
2019-11-12 19:23:02 -06:00
|
|
|
#define __TIMER_DEV(X) TIM##X
|
|
|
|
#define _TIMER_DEV(X) __TIMER_DEV(X)
|
|
|
|
#define STEP_TIMER_DEV _TIMER_DEV(STEP_TIMER)
|
|
|
|
#define TEMP_TIMER_DEV _TIMER_DEV(TEMP_TIMER)
|
|
|
|
|
2019-07-09 22:30:06 -05:00
|
|
|
// ------------------------
|
2018-10-03 03:26:07 -05:00
|
|
|
// Private Variables
|
2019-07-09 22:30:06 -05:00
|
|
|
// ------------------------
|
2018-10-03 03:26:07 -05:00
|
|
|
|
2019-11-12 19:23:02 -06:00
|
|
|
HardwareTimer *timer_instance[NUM_HARDWARE_TIMERS] = { NULL };
|
|
|
|
bool timer_enabled[NUM_HARDWARE_TIMERS] = { false };
|
2018-10-03 03:26:07 -05:00
|
|
|
|
2019-07-09 22:30:06 -05:00
|
|
|
// ------------------------
|
2018-10-03 03:26:07 -05:00
|
|
|
// Public functions
|
2019-07-09 22:30:06 -05:00
|
|
|
// ------------------------
|
2018-10-03 03:26:07 -05:00
|
|
|
|
2019-11-12 19:23:02 -06:00
|
|
|
// frequency is in Hertz
|
2018-10-03 03:26:07 -05:00
|
|
|
void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
|
2019-11-12 19:23:02 -06:00
|
|
|
if (!HAL_timer_initialized(timer_num)) {
|
2018-10-03 03:26:07 -05:00
|
|
|
switch (timer_num) {
|
2019-11-12 19:23:02 -06:00
|
|
|
case STEP_TIMER_NUM: // STEPPER TIMER - use a 32bit timer if possible
|
|
|
|
timer_instance[timer_num] = new HardwareTimer(STEP_TIMER_DEV);
|
|
|
|
/* Set the prescaler to the final desired value.
|
|
|
|
* This will change the effective ISR callback frequency but when
|
|
|
|
* HAL_timer_start(timer_num=0) is called in the core for the first time
|
|
|
|
* the real frequency isn't important as long as, after boot, the ISR
|
|
|
|
* gets called with the correct prescaler and count register. So here
|
|
|
|
* we set the prescaler to the correct, final value and ignore the frequency
|
|
|
|
* asked. We will call back the ISR in 1 second to start at full speed.
|
|
|
|
*
|
|
|
|
* The proper fix, however, would be a correct initialization OR a
|
|
|
|
* HAL_timer_change(const uint8_t timer_num, const uint32_t frequency)
|
|
|
|
* which changes the prescaler when an IRQ frequency change is needed
|
|
|
|
* (for example when steppers are turned on)
|
|
|
|
*/
|
|
|
|
timer_instance[timer_num]->setPrescaleFactor(STEPPER_TIMER_PRESCALE); //the -1 is done internally
|
|
|
|
timer_instance[timer_num]->setOverflow(_MIN(hal_timer_t(HAL_TIMER_TYPE_MAX), (HAL_TIMER_RATE) / (STEPPER_TIMER_PRESCALE) /* /frequency */), TICK_FORMAT);
|
|
|
|
break;
|
|
|
|
case TEMP_TIMER_NUM: // TEMP TIMER - any available 16bit timer
|
|
|
|
timer_instance[timer_num] = new HardwareTimer(TEMP_TIMER_DEV);
|
|
|
|
// The prescale factor is computed automatically for HERTZ_FORMAT
|
|
|
|
timer_instance[timer_num]->setOverflow(frequency, HERTZ_FORMAT);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
HAL_timer_enable_interrupt(timer_num);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Initializes (and unfortunately starts) the timer.
|
|
|
|
* This is needed to set correct IRQ priority at the moment but causes
|
|
|
|
* no harm since every call to HAL_timer_start() is actually followed by
|
|
|
|
* a call to HAL_timer_enable_interrupt() which means that there isn't
|
|
|
|
* a case in which you want the timer to run without a callback.
|
|
|
|
*/
|
|
|
|
timer_instance[timer_num]->resume(); // First call to resume() MUST follow the attachInterrupt()
|
|
|
|
|
|
|
|
// This is fixed in Arduino_Core_STM32 1.8.
|
|
|
|
// These calls can be removed and replaced with
|
|
|
|
// timer_instance[timer_num]->setInterruptPriority
|
2019-11-12 22:16:54 -06:00
|
|
|
switch (timer_num) {
|
2018-10-03 03:26:07 -05:00
|
|
|
case STEP_TIMER_NUM:
|
2018-10-16 06:42:41 -05:00
|
|
|
HAL_NVIC_SetPriority(STEP_TIMER_IRQ_NAME, STEP_TIMER_IRQ_PRIO, 0);
|
2018-10-03 03:26:07 -05:00
|
|
|
break;
|
|
|
|
case TEMP_TIMER_NUM:
|
2018-10-16 06:42:41 -05:00
|
|
|
HAL_NVIC_SetPriority(TEMP_TIMER_IRQ_NAME, TEMP_TIMER_IRQ_PRIO, 0);
|
2018-10-03 03:26:07 -05:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void HAL_timer_enable_interrupt(const uint8_t timer_num) {
|
2019-11-12 19:23:02 -06:00
|
|
|
if (HAL_timer_initialized(timer_num) && !timer_enabled[timer_num]) {
|
|
|
|
timer_enabled[timer_num] = true;
|
|
|
|
switch (timer_num) {
|
|
|
|
case STEP_TIMER_NUM:
|
|
|
|
timer_instance[timer_num]->attachInterrupt(Step_Handler);
|
|
|
|
break;
|
|
|
|
case TEMP_TIMER_NUM:
|
|
|
|
timer_instance[timer_num]->attachInterrupt(Temp_Handler);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2018-10-03 03:26:07 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void HAL_timer_disable_interrupt(const uint8_t timer_num) {
|
2019-11-12 19:23:02 -06:00
|
|
|
if (HAL_timer_interrupt_enabled(timer_num)) {
|
|
|
|
timer_instance[timer_num]->detachInterrupt();
|
|
|
|
timer_enabled[timer_num] = false;
|
|
|
|
}
|
2018-10-03 03:26:07 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
bool HAL_timer_interrupt_enabled(const uint8_t timer_num) {
|
2019-11-12 19:23:02 -06:00
|
|
|
return HAL_timer_initialized(timer_num) && timer_enabled[timer_num];
|
|
|
|
}
|
|
|
|
|
|
|
|
// Only for use within the HAL
|
|
|
|
TIM_TypeDef * HAL_timer_device(const uint8_t timer_num) {
|
|
|
|
switch (timer_num) {
|
|
|
|
case STEP_TIMER_NUM: return STEP_TIMER_DEV;
|
|
|
|
case TEMP_TIMER_NUM: return TEMP_TIMER_DEV;
|
|
|
|
}
|
|
|
|
return nullptr;
|
2018-10-03 03:26:07 -05:00
|
|
|
}
|
|
|
|
|
2019-06-28 23:04:33 -05:00
|
|
|
#endif // ARDUINO_ARCH_STM32 && !STM32GENERIC
|