mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2024-11-24 08:36:14 +01:00
Merge 13bb1175f3
into 33b2820095
This commit is contained in:
commit
bde3d23d27
|
@ -3,6 +3,7 @@
|
||||||
* © 2021 Mike S
|
* © 2021 Mike S
|
||||||
* © 2021-2023 Harald Barth
|
* © 2021-2023 Harald Barth
|
||||||
* © 2021 Fred Decker
|
* © 2021 Fred Decker
|
||||||
|
* © 2023 Travis Farmer
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This file is part of CommandStation-EX
|
* This file is part of CommandStation-EX
|
||||||
|
@ -90,6 +91,8 @@ private:
|
||||||
static const int DCC_SIGNAL_TIME=58; // this is the 58uS DCC 1-bit waveform half-cycle
|
static const int DCC_SIGNAL_TIME=58; // this is the 58uS DCC 1-bit waveform half-cycle
|
||||||
#if defined(ARDUINO_ARCH_STM32) // TODO: PMA temporary hack - assumes 100Mhz F_CPU as STM32 can change frequency
|
#if defined(ARDUINO_ARCH_STM32) // TODO: PMA temporary hack - assumes 100Mhz F_CPU as STM32 can change frequency
|
||||||
static const long CLOCK_CYCLES=(100000000L / 1000000 * DCC_SIGNAL_TIME) >>1;
|
static const long CLOCK_CYCLES=(100000000L / 1000000 * DCC_SIGNAL_TIME) >>1;
|
||||||
|
#elif defined(ARDUINO_GIGA)
|
||||||
|
static const long CLOCK_CYCLES=(480000000L / 1000000 * DCC_SIGNAL_TIME) >>1;
|
||||||
#else
|
#else
|
||||||
static const long CLOCK_CYCLES=(F_CPU / 1000000 * DCC_SIGNAL_TIME) >>1;
|
static const long CLOCK_CYCLES=(F_CPU / 1000000 * DCC_SIGNAL_TIME) >>1;
|
||||||
#endif
|
#endif
|
||||||
|
|
206
DCCTimerGiga.cpp
Normal file
206
DCCTimerGiga.cpp
Normal file
|
@ -0,0 +1,206 @@
|
||||||
|
/*
|
||||||
|
* © 2023 Travis Farmer
|
||||||
|
* © 2023 Neil McKechnie
|
||||||
|
* © 2022-2023 Paul M. Antoine
|
||||||
|
* © 2021 Mike S
|
||||||
|
* © 2021, 2023 Harald Barth
|
||||||
|
* © 2021 Fred Decker
|
||||||
|
* © 2021 Chris Harlow
|
||||||
|
* © 2021 David Cutting
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of Asbelos DCC API
|
||||||
|
*
|
||||||
|
* This 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.
|
||||||
|
*
|
||||||
|
* It 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 CommandStation. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// ATTENTION: this file only compiles on a STM32 based boards
|
||||||
|
// Please refer to DCCTimer.h for general comments about how this class works
|
||||||
|
// This is to avoid repetition and duplication.
|
||||||
|
#if defined(ARDUINO_GIGA)
|
||||||
|
|
||||||
|
#include "DCCTimer.h"
|
||||||
|
#include "DIAG.h"
|
||||||
|
#include "GigaHardwareTimer.h"
|
||||||
|
#include <Arduino_AdvancedAnalog.h>
|
||||||
|
//#include "config.h"
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Experimental code for High Accuracy (HA) DCC Signal mode
|
||||||
|
// Warning - use of TIM2 and TIM3 can affect the use of analogWrite() function on certain pins,
|
||||||
|
// which is used by the DC motor types.
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
INTERRUPT_CALLBACK interruptHandler=0;
|
||||||
|
|
||||||
|
//HardwareTimer* timer = NULL;
|
||||||
|
//HardwareTimer* timerAux = NULL;
|
||||||
|
HardwareTimer timer(TIM2);
|
||||||
|
HardwareTimer timerAux(TIM3);
|
||||||
|
|
||||||
|
static bool tim2ModeHA = false;
|
||||||
|
static bool tim3ModeHA = false;
|
||||||
|
|
||||||
|
void DCCTimer_Handler() __attribute__((interrupt));
|
||||||
|
|
||||||
|
void DCCTimer_Handler() {
|
||||||
|
interruptHandler();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DCCTimer::begin(INTERRUPT_CALLBACK callback) {
|
||||||
|
interruptHandler=callback;
|
||||||
|
noInterrupts();
|
||||||
|
|
||||||
|
// adc_set_sample_rate(ADC_SAMPLETIME_480CYCLES);
|
||||||
|
timer.pause();
|
||||||
|
timerAux.pause();
|
||||||
|
timer.setPrescaleFactor(1);
|
||||||
|
timer.setOverflow(DCC_SIGNAL_TIME, MICROSEC_FORMAT);
|
||||||
|
timer.attachInterrupt(DCCTimer_Handler);
|
||||||
|
timer.refresh();
|
||||||
|
timerAux.setPrescaleFactor(1);
|
||||||
|
timerAux.setOverflow(DCC_SIGNAL_TIME, MICROSEC_FORMAT);
|
||||||
|
timerAux.refresh();
|
||||||
|
|
||||||
|
timer.resume();
|
||||||
|
timerAux.resume();
|
||||||
|
|
||||||
|
interrupts();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DCCTimer::isPWMPin(byte pin) {
|
||||||
|
switch (pin) {
|
||||||
|
case 12:
|
||||||
|
return true;
|
||||||
|
case 13:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DCCTimer::setPWM(byte pin, bool high) {
|
||||||
|
switch (pin) {
|
||||||
|
case 12:
|
||||||
|
if (!tim3ModeHA) {
|
||||||
|
timerAux.setMode(1, TIMER_OUTPUT_COMPARE_INACTIVE, 12);
|
||||||
|
tim3ModeHA = true;
|
||||||
|
}
|
||||||
|
if (high)
|
||||||
|
TIM2->CCMR1 = (TIM2->CCMR1 & ~TIM_CCMR1_OC1M_Msk) | TIM_CCMR1_OC1M_0;
|
||||||
|
else
|
||||||
|
TIM2->CCMR1 = (TIM2->CCMR1 & ~TIM_CCMR1_OC1M_Msk) | TIM_CCMR1_OC1M_1;
|
||||||
|
break;
|
||||||
|
case 13:
|
||||||
|
if (!tim2ModeHA) {
|
||||||
|
timer.setMode(1, TIMER_OUTPUT_COMPARE_INACTIVE, 13);
|
||||||
|
tim2ModeHA = true;
|
||||||
|
}
|
||||||
|
if (high)
|
||||||
|
TIM3->CCMR1 = (TIM3->CCMR1 & ~TIM_CCMR1_OC1M_Msk) | TIM_CCMR1_OC1M_0;
|
||||||
|
else
|
||||||
|
TIM3->CCMR1 = (TIM3->CCMR1 & ~TIM_CCMR1_OC1M_Msk) | TIM_CCMR1_OC1M_1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DCCTimer::clearPWM() {
|
||||||
|
timer.setMode(1, TIMER_OUTPUT_COMPARE_INACTIVE, NC);
|
||||||
|
tim2ModeHA = false;
|
||||||
|
timerAux.setMode(1, TIMER_OUTPUT_COMPARE_INACTIVE, NC);
|
||||||
|
tim3ModeHA = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DCCTimer::getSimulatedMacAddress(byte mac[6]) {
|
||||||
|
volatile uint32_t *serno1 = (volatile uint32_t *)UID_BASE;
|
||||||
|
volatile uint32_t *serno2 = (volatile uint32_t *)UID_BASE+4;
|
||||||
|
volatile uint32_t *serno3 = (volatile uint32_t *)UID_BASE+8;
|
||||||
|
volatile uint32_t m1 = *serno1;
|
||||||
|
volatile uint32_t m2 = *serno2;
|
||||||
|
volatile uint32_t m3 = *serno3;
|
||||||
|
mac[0] = 0xBE;
|
||||||
|
mac[1] = 0xEF;
|
||||||
|
mac[2] = m1 ^ m3 >> 24;
|
||||||
|
mac[3] = m1 ^ m3 >> 16;
|
||||||
|
mac[4] = m1 ^ m3 >> 8;
|
||||||
|
mac[5] = m1 ^ m3 >> 0;
|
||||||
|
//DIAG(F("MAC: %P:%P:%P:%P:%P:%P"),mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
|
||||||
|
|
||||||
|
}
|
||||||
|
volatile int DCCTimer::minimum_free_memory=__INT_MAX__;
|
||||||
|
|
||||||
|
// Return low memory value...
|
||||||
|
int DCCTimer::getMinimumFreeMemory() {
|
||||||
|
noInterrupts(); // Disable interrupts to get volatile value
|
||||||
|
int retval = freeMemory();
|
||||||
|
interrupts();
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
extern "C" char* sbrk(int incr);
|
||||||
|
|
||||||
|
int DCCTimer::freeMemory() {
|
||||||
|
|
||||||
|
char top;
|
||||||
|
unsigned int tmp = (unsigned int)(&top - reinterpret_cast<char*>(sbrk(0)));
|
||||||
|
return (int)(tmp / 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DCCTimer::reset() {
|
||||||
|
//Watchdog &watchdog = Watchdog::get_instance();
|
||||||
|
//Watchdog::stop();
|
||||||
|
//Watchdog::start(500);
|
||||||
|
|
||||||
|
//while(true) {};
|
||||||
|
}
|
||||||
|
|
||||||
|
int * ADCee::analogvals = NULL;
|
||||||
|
|
||||||
|
int16_t ADCee::ADCmax()
|
||||||
|
{
|
||||||
|
return 1023;
|
||||||
|
}
|
||||||
|
|
||||||
|
AdvancedADC adc(A0, A1);
|
||||||
|
int ADCee::init(uint8_t pin) {
|
||||||
|
adc.begin(AN_RESOLUTION_10, 16000, 1, 512);
|
||||||
|
return 123;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read function ADCee::read(pin) to get value instead of analogRead(pin)
|
||||||
|
*/
|
||||||
|
int ADCee::read(uint8_t pin, bool fromISR) {
|
||||||
|
static SampleBuffer buf = adc.read();
|
||||||
|
int retVal = -123;
|
||||||
|
if (adc.available()) {
|
||||||
|
buf.release();
|
||||||
|
buf = adc.read();
|
||||||
|
}
|
||||||
|
return (buf[pin - A0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Scan function that is called from interrupt
|
||||||
|
*/
|
||||||
|
#pragma GCC push_options
|
||||||
|
#pragma GCC optimize ("-O3")
|
||||||
|
void ADCee::scan() {
|
||||||
|
}
|
||||||
|
#pragma GCC pop_options
|
||||||
|
|
||||||
|
void ADCee::begin() {
|
||||||
|
noInterrupts();
|
||||||
|
|
||||||
|
interrupts();
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -31,12 +31,12 @@
|
||||||
#include "Sensors.h"
|
#include "Sensors.h"
|
||||||
#include "Turnouts.h"
|
#include "Turnouts.h"
|
||||||
|
|
||||||
#if defined(ARDUINO_ARCH_SAMC)
|
#if defined(ARDUINO_ARCH_SAMC) || defined(ARDUINO_GIGA)
|
||||||
ExternalEEPROM EEPROM;
|
ExternalEEPROM EEPROM;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void EEStore::init() {
|
void EEStore::init() {
|
||||||
#if defined(ARDUINO_ARCH_SAMC)
|
#if defined(ARDUINO_ARCH_SAMC) || defined(ARDUINO_GIGA)
|
||||||
EEPROM.begin(0x50); // Address for Microchip 24-series EEPROM with all three
|
EEPROM.begin(0x50); // Address for Microchip 24-series EEPROM with all three
|
||||||
// A pins grounded (0b1010000 = 0x50)
|
// A pins grounded (0b1010000 = 0x50)
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
|
||||||
#if defined(ARDUINO_ARCH_SAMC)
|
#if defined(ARDUINO_ARCH_SAMC) || defined(ARDUINO_GIGA)
|
||||||
#include <SparkFun_External_EEPROM.h>
|
#include <SparkFun_External_EEPROM.h>
|
||||||
extern ExternalEEPROM EEPROM;
|
extern ExternalEEPROM EEPROM;
|
||||||
#else
|
#else
|
||||||
|
|
2003
GigaHardwareTimer.cpp
Normal file
2003
GigaHardwareTimer.cpp
Normal file
File diff suppressed because it is too large
Load Diff
220
GigaHardwareTimer.h
Normal file
220
GigaHardwareTimer.h
Normal file
|
@ -0,0 +1,220 @@
|
||||||
|
/****************************************************************************************************************************
|
||||||
|
HardwareTimer.h
|
||||||
|
|
||||||
|
For Portenta_H7 boards
|
||||||
|
Written by Khoi Hoang
|
||||||
|
|
||||||
|
Built by Khoi Hoang https://github.com/khoih-prog/Portenta_H7_TimerInterrupt
|
||||||
|
Licensed under MIT license
|
||||||
|
|
||||||
|
Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by
|
||||||
|
unsigned long miliseconds), you just consume only one Portenta_H7 STM32 timer and avoid conflicting with other cores' tasks.
|
||||||
|
The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers
|
||||||
|
Therefore, their executions are not blocked by bad-behaving functions / tasks.
|
||||||
|
This important feature is absolutely necessary for mission-critical tasks.
|
||||||
|
|
||||||
|
Version: 1.4.0
|
||||||
|
|
||||||
|
Version Modified By Date Comments
|
||||||
|
------- ----------- ---------- -----------
|
||||||
|
1.2.1 K.Hoang 15/09/2021 Initial coding for Portenta_H7
|
||||||
|
1.3.0 K.Hoang 17/09/2021 Add PWM features and examples
|
||||||
|
1.3.1 K.Hoang 21/09/2021 Fix warnings in PWM examples
|
||||||
|
1.4.0 K.Hoang 22/01/2022 Fix `multiple-definitions` linker error. Fix bug
|
||||||
|
*****************************************************************************************************************************/
|
||||||
|
|
||||||
|
// Modified from stm32 core v2.0.0
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright (c) 2017 Daniel Fekete
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
||||||
|
Copyright (c) 2019 STMicroelectronics
|
||||||
|
Modified to support Arduino_Core_STM32
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||||
|
#ifndef GIGAHARDWARETIMER_H_
|
||||||
|
#define GIGAHARDWARETIMER_H_
|
||||||
|
#if defined(ARDUINO_GIGA)
|
||||||
|
/* Includes ------------------------------------------------------------------*/
|
||||||
|
#include "Gigatimer.h"
|
||||||
|
|
||||||
|
#if defined(HAL_TIM_MODULE_ENABLED) && !defined(HAL_TIM_MODULE_ONLY)
|
||||||
|
|
||||||
|
#define TIMER_CHANNELS 4 // channel5 and channel 6 are not considered here has they don't have gpio output and they don't have interrupt
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
TIMER_DISABLED, // == TIM_OCMODE_TIMING no output, useful for only-interrupt
|
||||||
|
// Output Compare
|
||||||
|
TIMER_OUTPUT_COMPARE, // == Obsolete, use TIMER_DISABLED instead. Kept for compatibility reason
|
||||||
|
TIMER_OUTPUT_COMPARE_ACTIVE, // == TIM_OCMODE_ACTIVE pin is set high when counter == channel compare
|
||||||
|
TIMER_OUTPUT_COMPARE_INACTIVE, // == TIM_OCMODE_INACTIVE pin is set low when counter == channel compare
|
||||||
|
TIMER_OUTPUT_COMPARE_TOGGLE, // == TIM_OCMODE_TOGGLE pin toggles when counter == channel compare
|
||||||
|
TIMER_OUTPUT_COMPARE_PWM1, // == TIM_OCMODE_PWM1 pin high when counter < channel compare, low otherwise
|
||||||
|
TIMER_OUTPUT_COMPARE_PWM2, // == TIM_OCMODE_PWM2 pin low when counter < channel compare, high otherwise
|
||||||
|
TIMER_OUTPUT_COMPARE_FORCED_ACTIVE, // == TIM_OCMODE_FORCED_ACTIVE pin always high
|
||||||
|
TIMER_OUTPUT_COMPARE_FORCED_INACTIVE, // == TIM_OCMODE_FORCED_INACTIVE pin always low
|
||||||
|
|
||||||
|
//Input capture
|
||||||
|
TIMER_INPUT_CAPTURE_RISING, // == TIM_INPUTCHANNELPOLARITY_RISING
|
||||||
|
TIMER_INPUT_CAPTURE_FALLING, // == TIM_INPUTCHANNELPOLARITY_FALLING
|
||||||
|
TIMER_INPUT_CAPTURE_BOTHEDGE, // == TIM_INPUTCHANNELPOLARITY_BOTHEDGE
|
||||||
|
|
||||||
|
// Used 2 channels for a single pin. One channel in TIM_INPUTCHANNELPOLARITY_RISING another channel in TIM_INPUTCHANNELPOLARITY_FALLING.
|
||||||
|
// Channels must be used by pair: CH1 with CH2, or CH3 with CH4
|
||||||
|
// This mode is very useful for Frequency and Dutycycle measurement
|
||||||
|
TIMER_INPUT_FREQ_DUTY_MEASUREMENT,
|
||||||
|
|
||||||
|
TIMER_NOT_USED = 0xFFFF // This must be the last item of this enum
|
||||||
|
} TimerModes_t;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
TICK_FORMAT, // default
|
||||||
|
MICROSEC_FORMAT,
|
||||||
|
HERTZ_FORMAT,
|
||||||
|
} TimerFormat_t;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
RESOLUTION_1B_COMPARE_FORMAT = 1, // used for Dutycycle: [0 .. 1]
|
||||||
|
RESOLUTION_2B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 3]
|
||||||
|
RESOLUTION_3B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 7]
|
||||||
|
RESOLUTION_4B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 15]
|
||||||
|
RESOLUTION_5B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 31]
|
||||||
|
RESOLUTION_6B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 63]
|
||||||
|
RESOLUTION_7B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 127]
|
||||||
|
RESOLUTION_8B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 255]
|
||||||
|
RESOLUTION_9B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 511]
|
||||||
|
RESOLUTION_10B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 1023]
|
||||||
|
RESOLUTION_11B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 2047]
|
||||||
|
RESOLUTION_12B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 4095]
|
||||||
|
RESOLUTION_13B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 8191]
|
||||||
|
RESOLUTION_14B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 16383]
|
||||||
|
RESOLUTION_15B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 32767]
|
||||||
|
RESOLUTION_16B_COMPARE_FORMAT, // used for Dutycycle: [0 .. 65535]
|
||||||
|
|
||||||
|
TICK_COMPARE_FORMAT = 0x80, // default
|
||||||
|
MICROSEC_COMPARE_FORMAT,
|
||||||
|
HERTZ_COMPARE_FORMAT,
|
||||||
|
PERCENT_COMPARE_FORMAT, // used for Dutycycle
|
||||||
|
} TimerCompareFormat_t;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
using callback_function_t = std::function<void(void)>;
|
||||||
|
|
||||||
|
/* Class --------------------------------------------------------*/
|
||||||
|
class HardwareTimer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
HardwareTimer(TIM_TypeDef *instance);
|
||||||
|
~HardwareTimer(); // destructor
|
||||||
|
|
||||||
|
void pause(void); // Pause counter and all output channels
|
||||||
|
void pauseChannel(uint32_t channel); // Timer is still running but channel (output and interrupt) is disabled
|
||||||
|
void resume(void); // Resume counter and all output channels
|
||||||
|
void resumeChannel(uint32_t channel); // Resume only one channel
|
||||||
|
|
||||||
|
void setPrescaleFactor(uint32_t prescaler); // set prescaler register (which is factor value - 1)
|
||||||
|
uint32_t getPrescaleFactor();
|
||||||
|
|
||||||
|
void setOverflow(uint32_t val, TimerFormat_t format =
|
||||||
|
TICK_FORMAT); // set AutoReload register depending on format provided
|
||||||
|
uint32_t getOverflow(TimerFormat_t format = TICK_FORMAT); // return overflow depending on format provided
|
||||||
|
|
||||||
|
void setPWM(uint32_t channel, PinName pin, uint32_t frequency, uint32_t dutycycle,
|
||||||
|
callback_function_t PeriodCallback = nullptr,
|
||||||
|
callback_function_t CompareCallback = nullptr); // Set all in one command freq in HZ, Duty in percentage. Including both interrup.
|
||||||
|
void setPWM(uint32_t channel, uint32_t pin, uint32_t frequency, uint32_t dutycycle,
|
||||||
|
callback_function_t PeriodCallback = nullptr, callback_function_t CompareCallback = nullptr);
|
||||||
|
|
||||||
|
void setCount(uint32_t val, TimerFormat_t format =
|
||||||
|
TICK_FORMAT); // set timer counter to value 'val' depending on format provided
|
||||||
|
uint32_t getCount(TimerFormat_t format =
|
||||||
|
TICK_FORMAT); // return current counter value of timer depending on format provided
|
||||||
|
|
||||||
|
void setMode(uint32_t channel, TimerModes_t mode,
|
||||||
|
PinName pin = NC); // Configure timer channel with specified mode on specified pin if available
|
||||||
|
void setMode(uint32_t channel, TimerModes_t mode, uint32_t pin);
|
||||||
|
|
||||||
|
TimerModes_t getMode(uint32_t channel); // Retrieve configured mode
|
||||||
|
|
||||||
|
void setPreloadEnable(bool value); // Configure overflow preload enable setting
|
||||||
|
|
||||||
|
uint32_t getCaptureCompare(uint32_t channel,
|
||||||
|
TimerCompareFormat_t format = TICK_COMPARE_FORMAT); // return Capture/Compare register value of specified channel depending on format provided
|
||||||
|
void setCaptureCompare(uint32_t channel, uint32_t compare,
|
||||||
|
TimerCompareFormat_t format = TICK_COMPARE_FORMAT); // set Compare register value of specified channel depending on format provided
|
||||||
|
|
||||||
|
void setInterruptPriority(uint32_t preemptPriority, uint32_t subPriority); // set interrupt priority
|
||||||
|
|
||||||
|
//Add interrupt to period update
|
||||||
|
void attachInterrupt(callback_function_t
|
||||||
|
callback); // Attach interrupt callback which will be called upon update event (timer rollover)
|
||||||
|
void detachInterrupt(); // remove interrupt callback which was attached to update event
|
||||||
|
bool hasInterrupt(); //returns true if a timer rollover interrupt has already been set
|
||||||
|
//Add interrupt to capture/compare channel
|
||||||
|
void attachInterrupt(uint32_t channel,
|
||||||
|
callback_function_t callback); // Attach interrupt callback which will be called upon compare match event of specified channel
|
||||||
|
void detachInterrupt(uint32_t
|
||||||
|
channel); // remove interrupt callback which was attached to compare match event of specified channel
|
||||||
|
bool hasInterrupt(uint32_t channel); //returns true if an interrupt has already been set on the channel compare match
|
||||||
|
void timerHandleDeinit(); // Timer deinitialization
|
||||||
|
|
||||||
|
// Refresh() is usefull while timer is running after some registers update
|
||||||
|
void refresh(
|
||||||
|
void); // Generate update event to force all registers (Autoreload, prescaler, compare) to be taken into account
|
||||||
|
|
||||||
|
uint32_t getTimerClkFreq(); // return timer clock frequency in Hz.
|
||||||
|
|
||||||
|
static void captureCompareCallback(TIM_HandleTypeDef
|
||||||
|
*htim); // Generic Caputre and Compare callback which will call user callback
|
||||||
|
static void updateCallback(TIM_HandleTypeDef
|
||||||
|
*htim); // Generic Update (rollover) callback which will call user callback
|
||||||
|
|
||||||
|
// The following function(s) are available for more advanced timer options
|
||||||
|
TIM_HandleTypeDef *getHandle(); // return the handle address for HAL related configuration
|
||||||
|
int getChannel(uint32_t channel);
|
||||||
|
int getLLChannel(uint32_t channel);
|
||||||
|
int getIT(uint32_t channel);
|
||||||
|
int getAssociatedChannel(uint32_t channel);
|
||||||
|
#if defined(TIM_CCER_CC1NE)
|
||||||
|
bool isComplementaryChannel[TIMER_CHANNELS];
|
||||||
|
#endif
|
||||||
|
private:
|
||||||
|
TimerModes_t _ChannelMode[TIMER_CHANNELS];
|
||||||
|
timerObj_t _timerObj;
|
||||||
|
callback_function_t callbacks[1 +
|
||||||
|
TIMER_CHANNELS]; //Callbacks: 0 for update, 1-4 for channels. (channel5/channel6, if any, doesn't have interrupt)
|
||||||
|
};
|
||||||
|
|
||||||
|
extern timerObj_t *HardwareTimer_Handle[TIMER_NUM];
|
||||||
|
|
||||||
|
extern timer_index_t get_timer_index(TIM_TypeDef *htim);
|
||||||
|
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#endif // HAL_TIM_MODULE_ENABLED && !HAL_TIM_MODULE_ONLY
|
||||||
|
#endif
|
||||||
|
#endif // GIGAHARDWARETIMER_H_
|
950
Gigatimer.c
Normal file
950
Gigatimer.c
Normal file
|
@ -0,0 +1,950 @@
|
||||||
|
/****************************************************************************************************************************
|
||||||
|
timer.c
|
||||||
|
|
||||||
|
For Portenta_H7 boards
|
||||||
|
Written by Khoi Hoang
|
||||||
|
|
||||||
|
Built by Khoi Hoang https://github.com/khoih-prog/Portenta_H7_TimerInterrupt
|
||||||
|
Licensed under MIT license
|
||||||
|
|
||||||
|
Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by
|
||||||
|
unsigned long miliseconds), you just consume only one Portenta_H7 STM32 timer and avoid conflicting with other cores' tasks.
|
||||||
|
The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers
|
||||||
|
Therefore, their executions are not blocked by bad-behaving functions / tasks.
|
||||||
|
This important feature is absolutely necessary for mission-critical tasks.
|
||||||
|
|
||||||
|
Version: 1.4.0
|
||||||
|
|
||||||
|
Version Modified By Date Comments
|
||||||
|
------- ----------- ---------- -----------
|
||||||
|
1.2.1 K.Hoang 15/09/2021 Initial coding for Portenta_H7
|
||||||
|
1.3.0 K.Hoang 17/09/2021 Add PWM features and examples
|
||||||
|
1.3.1 K.Hoang 21/09/2021 Fix warnings in PWM examples
|
||||||
|
1.4.0 K.Hoang 22/01/2022 Fix `multiple-definitions` linker error. Fix bug
|
||||||
|
*****************************************************************************************************************************/
|
||||||
|
|
||||||
|
// Modified from stm32 core v2.0.0
|
||||||
|
/*
|
||||||
|
*******************************************************************************
|
||||||
|
Copyright (c) 2019, STMicroelectronics
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
This software component is licensed by ST under BSD 3-Clause license,
|
||||||
|
the "License"; You may not use this file except in compliance with the
|
||||||
|
License. You may obtain a copy of the License at:
|
||||||
|
opensource.org/licenses/BSD-3-Clause
|
||||||
|
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
#if defined(ARDUINO_GIGA)
|
||||||
|
#include "Gigatimer.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
#if defined(HAL_TIM_MODULE_ENABLED) && !defined(HAL_TIM_MODULE_ONLY)
|
||||||
|
|
||||||
|
/* Private Functions */
|
||||||
|
/* Aim of the function is to get _timerObj pointer using htim pointer */
|
||||||
|
/* Highly inspired from magical linux kernel's "container_of" */
|
||||||
|
/* (which was not directly used since not compatible with IAR toolchain) */
|
||||||
|
timerObj_t *get_timer_obj(TIM_HandleTypeDef *htim)
|
||||||
|
{
|
||||||
|
timerObj_t *obj;
|
||||||
|
obj = (timerObj_t *)((char *)htim - offsetof(timerObj_t, handle));
|
||||||
|
return (obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief TIMER Initialization - clock init and nvic init
|
||||||
|
@param htim_base: TIM handle
|
||||||
|
@retval None
|
||||||
|
*/
|
||||||
|
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim_base)
|
||||||
|
{
|
||||||
|
timerObj_t *obj = get_timer_obj(htim_base);
|
||||||
|
enableTimerClock(htim_base);
|
||||||
|
|
||||||
|
// configure Update interrupt
|
||||||
|
HAL_NVIC_SetPriority(getTimerUpIrq(htim_base->Instance), obj->preemptPriority, obj->subPriority);
|
||||||
|
HAL_NVIC_EnableIRQ(getTimerUpIrq(htim_base->Instance));
|
||||||
|
|
||||||
|
if (getTimerCCIrq(htim_base->Instance) != getTimerUpIrq(htim_base->Instance))
|
||||||
|
{
|
||||||
|
// configure Capture Compare interrupt
|
||||||
|
HAL_NVIC_SetPriority(getTimerCCIrq(htim_base->Instance), obj->preemptPriority, obj->subPriority);
|
||||||
|
HAL_NVIC_EnableIRQ(getTimerCCIrq(htim_base->Instance));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief TIMER Deinitialization - clock and nvic
|
||||||
|
@param htim_base: TIM handle
|
||||||
|
@retval None
|
||||||
|
*/
|
||||||
|
void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef *htim_base)
|
||||||
|
{
|
||||||
|
disableTimerClock(htim_base);
|
||||||
|
HAL_NVIC_DisableIRQ(getTimerUpIrq(htim_base->Instance));
|
||||||
|
HAL_NVIC_DisableIRQ(getTimerCCIrq(htim_base->Instance));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Initializes the TIM Output Compare MSP.
|
||||||
|
@param htim: TIM handle
|
||||||
|
@retval None
|
||||||
|
*/
|
||||||
|
void HAL_TIM_OC_MspInit(TIM_HandleTypeDef *htim)
|
||||||
|
{
|
||||||
|
timerObj_t *obj = get_timer_obj(htim);
|
||||||
|
enableTimerClock(htim);
|
||||||
|
|
||||||
|
// configure Update interrupt
|
||||||
|
HAL_NVIC_SetPriority(getTimerUpIrq(htim->Instance), obj->preemptPriority, obj->subPriority);
|
||||||
|
HAL_NVIC_EnableIRQ(getTimerUpIrq(htim->Instance));
|
||||||
|
|
||||||
|
if (getTimerCCIrq(htim->Instance) != getTimerUpIrq(htim->Instance))
|
||||||
|
{
|
||||||
|
// configure Capture Compare interrupt
|
||||||
|
HAL_NVIC_SetPriority(getTimerCCIrq(htim->Instance), obj->preemptPriority, obj->subPriority);
|
||||||
|
HAL_NVIC_EnableIRQ(getTimerCCIrq(htim->Instance));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief DeInitialize TIM Output Compare MSP.
|
||||||
|
@param htim: TIM handle
|
||||||
|
@retval None
|
||||||
|
*/
|
||||||
|
void HAL_TIM_OC_MspDeInit(TIM_HandleTypeDef *htim)
|
||||||
|
{
|
||||||
|
disableTimerClock(htim);
|
||||||
|
HAL_NVIC_DisableIRQ(getTimerUpIrq(htim->Instance));
|
||||||
|
HAL_NVIC_DisableIRQ(getTimerCCIrq(htim->Instance));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Initializes the TIM Input Capture MSP.
|
||||||
|
@param htim: TIM handle
|
||||||
|
@retval None
|
||||||
|
*/
|
||||||
|
void HAL_TIM_IC_MspInit(TIM_HandleTypeDef *htim)
|
||||||
|
{
|
||||||
|
enableTimerClock(htim);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief DeInitialize TIM Input Capture MSP.
|
||||||
|
@param htim: TIM handle
|
||||||
|
@retval None
|
||||||
|
*/
|
||||||
|
void HAL_TIM_IC_MspDeInit(TIM_HandleTypeDef *htim)
|
||||||
|
{
|
||||||
|
disableTimerClock(htim);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Exported functions */
|
||||||
|
/**
|
||||||
|
@brief Enable the timer clock
|
||||||
|
@param htim: TIM handle
|
||||||
|
@retval None
|
||||||
|
*/
|
||||||
|
void enableTimerClock(TIM_HandleTypeDef *htim)
|
||||||
|
{
|
||||||
|
// Enable TIM clock
|
||||||
|
#if defined(TIM1_BASE)
|
||||||
|
if (htim->Instance == TIM1)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM1_CLK_ENABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TIM2_BASE)
|
||||||
|
|
||||||
|
if (htim->Instance == TIM2)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM2_CLK_ENABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TIM3_BASE)
|
||||||
|
|
||||||
|
if (htim->Instance == TIM3)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM3_CLK_ENABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TIM4_BASE)
|
||||||
|
|
||||||
|
if (htim->Instance == TIM4)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM4_CLK_ENABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TIM5_BASE)
|
||||||
|
|
||||||
|
if (htim->Instance == TIM5)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM5_CLK_ENABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TIM6_BASE)
|
||||||
|
|
||||||
|
if (htim->Instance == TIM6)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM6_CLK_ENABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TIM7_BASE)
|
||||||
|
|
||||||
|
if (htim->Instance == TIM7)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM7_CLK_ENABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TIM8_BASE)
|
||||||
|
|
||||||
|
if (htim->Instance == TIM8)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM8_CLK_ENABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TIM9_BASE)
|
||||||
|
|
||||||
|
if (htim->Instance == TIM9)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM9_CLK_ENABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TIM10_BASE)
|
||||||
|
|
||||||
|
if (htim->Instance == TIM10)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM10_CLK_ENABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TIM11_BASE)
|
||||||
|
|
||||||
|
if (htim->Instance == TIM11)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM11_CLK_ENABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TIM12_BASE)
|
||||||
|
|
||||||
|
if (htim->Instance == TIM12)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM12_CLK_ENABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TIM13_BASE)
|
||||||
|
|
||||||
|
if (htim->Instance == TIM13)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM13_CLK_ENABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TIM14_BASE)
|
||||||
|
|
||||||
|
if (htim->Instance == TIM14)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM14_CLK_ENABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TIM15_BASE)
|
||||||
|
|
||||||
|
if (htim->Instance == TIM15)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM15_CLK_ENABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TIM16_BASE)
|
||||||
|
|
||||||
|
if (htim->Instance == TIM16)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM16_CLK_ENABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TIM17_BASE)
|
||||||
|
|
||||||
|
if (htim->Instance == TIM17)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM17_CLK_ENABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TIM18_BASE)
|
||||||
|
|
||||||
|
if (htim->Instance == TIM18)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM18_CLK_ENABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TIM19_BASE)
|
||||||
|
|
||||||
|
if (htim->Instance == TIM19)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM19_CLK_ENABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TIM20_BASE)
|
||||||
|
|
||||||
|
if (htim->Instance == TIM20)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM20_CLK_ENABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TIM21_BASE)
|
||||||
|
|
||||||
|
if (htim->Instance == TIM21)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM21_CLK_ENABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TIM22_BASE)
|
||||||
|
|
||||||
|
if (htim->Instance == TIM22)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM22_CLK_ENABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Disable the timer clock
|
||||||
|
@param htim: TIM handle
|
||||||
|
@retval None
|
||||||
|
*/
|
||||||
|
void disableTimerClock(TIM_HandleTypeDef *htim)
|
||||||
|
{
|
||||||
|
// Enable TIM clock
|
||||||
|
#if defined(TIM1_BASE)
|
||||||
|
if (htim->Instance == TIM1)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM1_CLK_DISABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TIM2_BASE)
|
||||||
|
|
||||||
|
if (htim->Instance == TIM2)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM2_CLK_DISABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TIM3_BASE)
|
||||||
|
|
||||||
|
if (htim->Instance == TIM3)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM3_CLK_DISABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TIM4_BASE)
|
||||||
|
|
||||||
|
if (htim->Instance == TIM4)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM4_CLK_DISABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TIM5_BASE)
|
||||||
|
|
||||||
|
if (htim->Instance == TIM5)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM5_CLK_DISABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TIM6_BASE)
|
||||||
|
|
||||||
|
if (htim->Instance == TIM6)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM6_CLK_DISABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TIM7_BASE)
|
||||||
|
|
||||||
|
if (htim->Instance == TIM7)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM7_CLK_DISABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TIM8_BASE)
|
||||||
|
|
||||||
|
if (htim->Instance == TIM8)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM8_CLK_DISABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TIM9_BASE)
|
||||||
|
|
||||||
|
if (htim->Instance == TIM9)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM9_CLK_DISABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TIM10_BASE)
|
||||||
|
|
||||||
|
if (htim->Instance == TIM10)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM10_CLK_DISABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TIM11_BASE)
|
||||||
|
|
||||||
|
if (htim->Instance == TIM11)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM11_CLK_DISABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TIM12_BASE)
|
||||||
|
|
||||||
|
if (htim->Instance == TIM12)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM12_CLK_DISABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TIM13_BASE)
|
||||||
|
|
||||||
|
if (htim->Instance == TIM13)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM13_CLK_DISABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TIM14_BASE)
|
||||||
|
|
||||||
|
if (htim->Instance == TIM14)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM14_CLK_DISABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TIM15_BASE)
|
||||||
|
|
||||||
|
if (htim->Instance == TIM15)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM15_CLK_DISABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TIM16_BASE)
|
||||||
|
|
||||||
|
if (htim->Instance == TIM16)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM16_CLK_DISABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TIM17_BASE)
|
||||||
|
|
||||||
|
if (htim->Instance == TIM17)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM17_CLK_DISABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TIM18_BASE)
|
||||||
|
|
||||||
|
if (htim->Instance == TIM18)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM18_CLK_DISABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TIM19_BASE)
|
||||||
|
|
||||||
|
if (htim->Instance == TIM19)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM19_CLK_DISABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TIM20_BASE)
|
||||||
|
|
||||||
|
if (htim->Instance == TIM20)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM20_CLK_DISABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TIM21_BASE)
|
||||||
|
|
||||||
|
if (htim->Instance == TIM21)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM21_CLK_DISABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TIM22_BASE)
|
||||||
|
|
||||||
|
if (htim->Instance == TIM22)
|
||||||
|
{
|
||||||
|
__HAL_RCC_TIM22_CLK_DISABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief This function return IRQ number corresponding to update interrupt event of timer instance.
|
||||||
|
@param tim: timer instance
|
||||||
|
@retval IRQ number
|
||||||
|
*/
|
||||||
|
IRQn_Type getTimerUpIrq(TIM_TypeDef *tim)
|
||||||
|
{
|
||||||
|
IRQn_Type IRQn = NonMaskableInt_IRQn;
|
||||||
|
|
||||||
|
if (tim != (TIM_TypeDef *)NC)
|
||||||
|
{
|
||||||
|
/* Get IRQn depending on TIM instance */
|
||||||
|
switch ((uint32_t)tim)
|
||||||
|
{
|
||||||
|
#if defined(TIM1_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM1_BASE:
|
||||||
|
IRQn = TIM1_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(TIM2_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM2_BASE:
|
||||||
|
IRQn = TIM2_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(TIM3_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM3_BASE:
|
||||||
|
IRQn = TIM3_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(TIM4_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM4_BASE:
|
||||||
|
IRQn = TIM4_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(TIM5_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM5_BASE:
|
||||||
|
IRQn = TIM5_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// KH
|
||||||
|
#if 0
|
||||||
|
#if defined(TIM6_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM6_BASE:
|
||||||
|
IRQn = TIM6_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
//////
|
||||||
|
|
||||||
|
#if defined(TIM7_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM7_BASE:
|
||||||
|
IRQn = TIM7_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(TIM8_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM8_BASE:
|
||||||
|
IRQn = TIM8_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(TIM9_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM9_BASE:
|
||||||
|
IRQn = TIM9_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(TIM10_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM10_BASE:
|
||||||
|
IRQn = TIM10_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(TIM11_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM11_BASE:
|
||||||
|
IRQn = TIM11_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(TIM12_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM12_BASE:
|
||||||
|
IRQn = TIM12_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(TIM13_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM13_BASE:
|
||||||
|
IRQn = TIM13_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(TIM14_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM14_BASE:
|
||||||
|
IRQn = TIM14_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(TIM15_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM15_BASE:
|
||||||
|
IRQn = TIM15_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(TIM16_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM16_BASE:
|
||||||
|
IRQn = TIM16_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(TIM17_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM17_BASE:
|
||||||
|
IRQn = TIM17_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(TIM18_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM18_BASE:
|
||||||
|
IRQn = TIM18_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(TIM19_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM19_BASE:
|
||||||
|
IRQn = TIM19_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(TIM20_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM20_BASE:
|
||||||
|
IRQn = TIM20_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(TIM21_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM21_BASE:
|
||||||
|
IRQn = TIM21_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(TIM22_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM22_BASE:
|
||||||
|
IRQn = TIM22_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default:
|
||||||
|
//_Error_Handler("TIM: Unknown timer IRQn", (int)tim);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return IRQn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief This function return IRQ number corresponding to Capture or Compare interrupt event of timer instance.
|
||||||
|
@param tim: timer instance
|
||||||
|
@retval IRQ number
|
||||||
|
*/
|
||||||
|
IRQn_Type getTimerCCIrq(TIM_TypeDef *tim)
|
||||||
|
{
|
||||||
|
IRQn_Type IRQn = NonMaskableInt_IRQn;
|
||||||
|
|
||||||
|
if (tim != (TIM_TypeDef *)NC)
|
||||||
|
{
|
||||||
|
/* Get IRQn depending on TIM instance */
|
||||||
|
switch ((uint32_t)tim)
|
||||||
|
{
|
||||||
|
#if defined(TIM1_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM1_BASE:
|
||||||
|
IRQn = TIM1_CC_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(TIM2_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM2_BASE:
|
||||||
|
IRQn = TIM2_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(TIM3_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM3_BASE:
|
||||||
|
IRQn = TIM3_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(TIM4_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM4_BASE:
|
||||||
|
IRQn = TIM4_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(TIM5_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM5_BASE:
|
||||||
|
IRQn = TIM5_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// KH
|
||||||
|
#if defined(TIM6_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM6_BASE:
|
||||||
|
IRQn = TIM6_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
//////
|
||||||
|
|
||||||
|
#if defined(TIM7_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM7_BASE:
|
||||||
|
IRQn = TIM7_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(TIM8_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM8_BASE:
|
||||||
|
IRQn = TIM8_CC_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(TIM9_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM9_BASE:
|
||||||
|
IRQn = TIM9_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(TIM10_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM10_BASE:
|
||||||
|
IRQn = TIM10_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(TIM11_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM11_BASE:
|
||||||
|
IRQn = TIM11_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(TIM12_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM12_BASE:
|
||||||
|
IRQn = TIM12_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(TIM13_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM13_BASE:
|
||||||
|
IRQn = TIM13_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(TIM14_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM14_BASE:
|
||||||
|
IRQn = TIM14_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(TIM15_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM15_BASE:
|
||||||
|
IRQn = TIM15_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(TIM16_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM16_BASE:
|
||||||
|
IRQn = TIM16_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(TIM17_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM17_BASE:
|
||||||
|
IRQn = TIM17_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(TIM18_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM18_BASE:
|
||||||
|
IRQn = TIM18_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(TIM19_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM19_BASE:
|
||||||
|
IRQn = TIM19_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(TIM20_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM20_BASE:
|
||||||
|
IRQn = TIM20_CC_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(TIM21_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM21_BASE:
|
||||||
|
IRQn = TIM21_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(TIM22_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM22_BASE:
|
||||||
|
IRQn = TIM22_IRQn;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
//_Error_Handler("TIM: Unknown timer IRQn", (int)tim);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return IRQn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief This function return the timer clock source.
|
||||||
|
@param tim: timer instance
|
||||||
|
@retval 1 = PCLK1 or 2 = PCLK2
|
||||||
|
*/
|
||||||
|
uint8_t getTimerClkSrc(TIM_TypeDef *tim)
|
||||||
|
{
|
||||||
|
uint8_t clkSrc = 0;
|
||||||
|
|
||||||
|
if (tim != (TIM_TypeDef *)NC)
|
||||||
|
#if defined(STM32F0xx) || defined(STM32G0xx)
|
||||||
|
/* TIMx source CLK is PCKL1 */
|
||||||
|
clkSrc = 1;
|
||||||
|
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
/* Get source clock depending on TIM instance */
|
||||||
|
switch ((uint32_t)tim)
|
||||||
|
{
|
||||||
|
#if defined(TIM2_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM2:
|
||||||
|
#endif
|
||||||
|
#if defined(TIM3_BASE)
|
||||||
|
case (uint32_t)TIM3:
|
||||||
|
#endif
|
||||||
|
#if defined(TIM4_BASE)
|
||||||
|
case (uint32_t)TIM4:
|
||||||
|
#endif
|
||||||
|
#if defined(TIM5_BASE)
|
||||||
|
case (uint32_t)TIM5:
|
||||||
|
#endif
|
||||||
|
#if defined(TIM6_BASE)
|
||||||
|
case (uint32_t)TIM6:
|
||||||
|
#endif
|
||||||
|
#if defined(TIM7_BASE)
|
||||||
|
case (uint32_t)TIM7:
|
||||||
|
#endif
|
||||||
|
#if defined(TIM12_BASE)
|
||||||
|
case (uint32_t)TIM12:
|
||||||
|
#endif
|
||||||
|
#if defined(TIM13_BASE)
|
||||||
|
case (uint32_t)TIM13:
|
||||||
|
#endif
|
||||||
|
#if defined(TIM14_BASE)
|
||||||
|
case (uint32_t)TIM14:
|
||||||
|
#endif
|
||||||
|
#if defined(TIM18_BASE)
|
||||||
|
case (uint32_t)TIM18:
|
||||||
|
#endif
|
||||||
|
clkSrc = 1;
|
||||||
|
break;
|
||||||
|
#if defined(TIM1_BASE)
|
||||||
|
|
||||||
|
case (uint32_t)TIM1:
|
||||||
|
#endif
|
||||||
|
#if defined(TIM8_BASE)
|
||||||
|
case (uint32_t)TIM8:
|
||||||
|
#endif
|
||||||
|
#if defined(TIM9_BASE)
|
||||||
|
case (uint32_t)TIM9:
|
||||||
|
#endif
|
||||||
|
#if defined(TIM10_BASE)
|
||||||
|
case (uint32_t)TIM10:
|
||||||
|
#endif
|
||||||
|
#if defined(TIM11_BASE)
|
||||||
|
case (uint32_t)TIM11:
|
||||||
|
#endif
|
||||||
|
#if defined(TIM15_BASE)
|
||||||
|
case (uint32_t)TIM15:
|
||||||
|
#endif
|
||||||
|
#if defined(TIM16_BASE)
|
||||||
|
case (uint32_t)TIM16:
|
||||||
|
#endif
|
||||||
|
#if defined(TIM17_BASE)
|
||||||
|
case (uint32_t)TIM17:
|
||||||
|
#endif
|
||||||
|
#if defined(TIM19_BASE)
|
||||||
|
case (uint32_t)TIM19:
|
||||||
|
#endif
|
||||||
|
#if defined(TIM20_BASE)
|
||||||
|
case (uint32_t)TIM20:
|
||||||
|
#endif
|
||||||
|
#if defined(TIM21_BASE)
|
||||||
|
case (uint32_t)TIM21:
|
||||||
|
#endif
|
||||||
|
#if defined(TIM22_BASE)
|
||||||
|
case (uint32_t)TIM22:
|
||||||
|
#endif
|
||||||
|
clkSrc = 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
////_Error_Handler("TIM: Unknown timer instance", (int)tim);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return clkSrc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* HAL_TIM_MODULE_ENABLED && !HAL_TIM_MODULE_ONLY */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
198
Gigatimer.h
Normal file
198
Gigatimer.h
Normal file
|
@ -0,0 +1,198 @@
|
||||||
|
/****************************************************************************************************************************
|
||||||
|
timer.h
|
||||||
|
|
||||||
|
For Portenta_H7 boards
|
||||||
|
Written by Khoi Hoang
|
||||||
|
|
||||||
|
Built by Khoi Hoang https://github.com/khoih-prog/Portenta_H7_TimerInterrupt
|
||||||
|
Licensed under MIT license
|
||||||
|
|
||||||
|
Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by
|
||||||
|
unsigned long miliseconds), you just consume only one Portenta_H7 STM32 timer and avoid conflicting with other cores' tasks.
|
||||||
|
The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers
|
||||||
|
Therefore, their executions are not blocked by bad-behaving functions / tasks.
|
||||||
|
This important feature is absolutely necessary for mission-critical tasks.
|
||||||
|
|
||||||
|
Version: 1.4.0
|
||||||
|
|
||||||
|
Version Modified By Date Comments
|
||||||
|
------- ----------- ---------- -----------
|
||||||
|
1.2.1 K.Hoang 15/09/2021 Initial coding for Portenta_H7
|
||||||
|
1.3.0 K.Hoang 17/09/2021 Add PWM features and examples
|
||||||
|
1.3.1 K.Hoang 21/09/2021 Fix warnings in PWM examples
|
||||||
|
1.4.0 K.Hoang 22/01/2022 Fix `multiple-definitions` linker error. Fix bug
|
||||||
|
*****************************************************************************************************************************/
|
||||||
|
|
||||||
|
// Modified from stm32 core v2.0.0
|
||||||
|
|
||||||
|
/*
|
||||||
|
*******************************************************************************
|
||||||
|
Copyright (c) 2019, STMicroelectronics
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
This software component is licensed by ST under BSD 3-Clause license,
|
||||||
|
the "License"; You may not use this file except in compliance with the
|
||||||
|
License. You may obtain a copy of the License at:
|
||||||
|
opensource.org/licenses/BSD-3-Clause
|
||||||
|
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||||
|
#ifndef __GIGATIMER_H
|
||||||
|
#define __GIGATIMER_H
|
||||||
|
#if defined(ARDUINO_GIGA)
|
||||||
|
/* Includes ------------------------------------------------------------------*/
|
||||||
|
#include "PinNames.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAL_TIM_MODULE_ENABLED) && !defined(HAL_TIM_MODULE_ONLY)
|
||||||
|
|
||||||
|
/* Exported constants --------------------------------------------------------*/
|
||||||
|
#ifndef TIM_IRQ_PRIO
|
||||||
|
#if (__CORTEX_M == 0x00U)
|
||||||
|
#define TIM_IRQ_PRIO 3
|
||||||
|
#else
|
||||||
|
#define TIM_IRQ_PRIO 14
|
||||||
|
#endif /* __CORTEX_M */
|
||||||
|
|
||||||
|
#endif /* TIM_IRQ_PRIO */
|
||||||
|
|
||||||
|
#ifndef TIM_IRQ_SUBPRIO
|
||||||
|
#define TIM_IRQ_SUBPRIO 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(TIM1_BASE) && !defined(TIM1_IRQn)
|
||||||
|
#define TIM1_IRQn TIM1_UP_IRQn
|
||||||
|
#define TIM1_IRQHandler TIM1_UP_IRQHandler
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(TIM8_BASE) && !defined(TIM8_IRQn)
|
||||||
|
#define TIM8_IRQn TIM8_UP_TIM13_IRQn
|
||||||
|
#define TIM8_IRQHandler TIM8_UP_TIM13_IRQHandler
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(TIM12_BASE) && !defined(TIM12_IRQn)
|
||||||
|
#define TIM12_IRQn TIM8_BRK_TIM12_IRQn
|
||||||
|
#define TIM12_IRQHandler TIM8_BRK_TIM12_IRQHandler
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(TIM13_BASE) && !defined(TIM13_IRQn)
|
||||||
|
#define TIM13_IRQn TIM8_UP_TIM13_IRQn
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(TIM14_BASE) && !defined(TIM14_IRQn)
|
||||||
|
#define TIM14_IRQn TIM8_TRG_COM_TIM14_IRQn
|
||||||
|
#define TIM14_IRQHandler TIM8_TRG_COM_TIM14_IRQHandler
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
#if defined(TIM1_BASE)
|
||||||
|
TIMER1_INDEX,
|
||||||
|
#endif
|
||||||
|
#if defined(TIM2_BASE)
|
||||||
|
TIMER2_INDEX,
|
||||||
|
#endif
|
||||||
|
#if defined(TIM3_BASE)
|
||||||
|
TIMER3_INDEX,
|
||||||
|
#endif
|
||||||
|
#if defined(TIM4_BASE)
|
||||||
|
TIMER4_INDEX,
|
||||||
|
#endif
|
||||||
|
#if defined(TIM5_BASE)
|
||||||
|
TIMER5_INDEX,
|
||||||
|
#endif
|
||||||
|
#if defined(TIM6_BASE)
|
||||||
|
TIMER6_INDEX,
|
||||||
|
#endif
|
||||||
|
#if defined(TIM7_BASE)
|
||||||
|
TIMER7_INDEX,
|
||||||
|
#endif
|
||||||
|
#if defined(TIM8_BASE)
|
||||||
|
TIMER8_INDEX,
|
||||||
|
#endif
|
||||||
|
#if defined(TIM9_BASE)
|
||||||
|
TIMER9_INDEX,
|
||||||
|
#endif
|
||||||
|
#if defined(TIM10_BASE)
|
||||||
|
TIMER10_INDEX,
|
||||||
|
#endif
|
||||||
|
#if defined(TIM11_BASE)
|
||||||
|
TIMER11_INDEX,
|
||||||
|
#endif
|
||||||
|
#if defined(TIM12_BASE)
|
||||||
|
TIMER12_INDEX,
|
||||||
|
#endif
|
||||||
|
#if defined(TIM13_BASE)
|
||||||
|
TIMER13_INDEX,
|
||||||
|
#endif
|
||||||
|
#if defined(TIM14_BASE)
|
||||||
|
TIMER14_INDEX,
|
||||||
|
#endif
|
||||||
|
#if defined(TIM15_BASE)
|
||||||
|
TIMER15_INDEX,
|
||||||
|
#endif
|
||||||
|
#if defined(TIM16_BASE)
|
||||||
|
TIMER16_INDEX,
|
||||||
|
#endif
|
||||||
|
#if defined(TIM17_BASE)
|
||||||
|
TIMER17_INDEX,
|
||||||
|
#endif
|
||||||
|
#if defined(TIM18_BASE)
|
||||||
|
TIMER18_INDEX,
|
||||||
|
#endif
|
||||||
|
#if defined(TIM19_BASE)
|
||||||
|
TIMER19_INDEX,
|
||||||
|
#endif
|
||||||
|
#if defined(TIM20_BASE)
|
||||||
|
TIMER20_INDEX,
|
||||||
|
#endif
|
||||||
|
#if defined(TIM21_BASE)
|
||||||
|
TIMER21_INDEX,
|
||||||
|
#endif
|
||||||
|
#if defined(TIM22_BASE)
|
||||||
|
TIMER22_INDEX,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TIMER_NUM,
|
||||||
|
UNKNOWN_TIMER = 0XFFFF
|
||||||
|
} timer_index_t;
|
||||||
|
|
||||||
|
|
||||||
|
// This structure is used to be able to get HardwareTimer instance (C++ class)
|
||||||
|
// from handler (C structure) specially for interrupt management
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
// Those 2 first fields must remain in this order at the beginning of the structure
|
||||||
|
void *__this;
|
||||||
|
TIM_HandleTypeDef handle;
|
||||||
|
uint32_t preemptPriority;
|
||||||
|
uint32_t subPriority;
|
||||||
|
} timerObj_t;
|
||||||
|
|
||||||
|
/* Exported functions ------------------------------------------------------- */
|
||||||
|
timerObj_t *get_timer_obj(TIM_HandleTypeDef *htim);
|
||||||
|
|
||||||
|
void enableTimerClock(TIM_HandleTypeDef *htim);
|
||||||
|
void disableTimerClock(TIM_HandleTypeDef *htim);
|
||||||
|
|
||||||
|
uint32_t getTimerIrq(TIM_TypeDef *tim);
|
||||||
|
uint8_t getTimerClkSrc(TIM_TypeDef *tim);
|
||||||
|
|
||||||
|
IRQn_Type getTimerUpIrq(TIM_TypeDef *tim);
|
||||||
|
IRQn_Type getTimerCCIrq(TIM_TypeDef *tim);
|
||||||
|
|
||||||
|
#endif /* HAL_TIM_MODULE_ENABLED && !HAL_TIM_MODULE_ONLY */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif /* __GIGATIMER_H */
|
||||||
|
|
||||||
|
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
|
@ -5,6 +5,7 @@
|
||||||
* © 2020-2023 Harald Barth
|
* © 2020-2023 Harald Barth
|
||||||
* © 2020-2021 Chris Harlow
|
* © 2020-2021 Chris Harlow
|
||||||
* © 2023 Colin Murdoch
|
* © 2023 Colin Murdoch
|
||||||
|
* © 2023 Travis Farmer
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This file is part of CommandStation-EX
|
* This file is part of CommandStation-EX
|
||||||
|
@ -57,6 +58,7 @@ MotorDriver::MotorDriver(int16_t power_pin, byte signal_pin, byte signal_pin2, i
|
||||||
getFastPin(F("SIG"),signalPin,fastSignalPin);
|
getFastPin(F("SIG"),signalPin,fastSignalPin);
|
||||||
pinMode(signalPin, OUTPUT);
|
pinMode(signalPin, OUTPUT);
|
||||||
|
|
||||||
|
#ifndef ARDUINO_GIGA // no giga
|
||||||
fastSignalPin.shadowinout = NULL;
|
fastSignalPin.shadowinout = NULL;
|
||||||
if (HAVE_PORTA(fastSignalPin.inout == &PORTA)) {
|
if (HAVE_PORTA(fastSignalPin.inout == &PORTA)) {
|
||||||
DIAG(F("Found PORTA pin %d"),signalPin);
|
DIAG(F("Found PORTA pin %d"),signalPin);
|
||||||
|
@ -88,13 +90,14 @@ MotorDriver::MotorDriver(int16_t power_pin, byte signal_pin, byte signal_pin2, i
|
||||||
fastSignalPin.shadowinout = fastSignalPin.inout;
|
fastSignalPin.shadowinout = fastSignalPin.inout;
|
||||||
fastSignalPin.inout = &shadowPORTF;
|
fastSignalPin.inout = &shadowPORTF;
|
||||||
}
|
}
|
||||||
|
#endif // giga
|
||||||
signalPin2=signal_pin2;
|
signalPin2=signal_pin2;
|
||||||
if (signalPin2!=UNUSED_PIN) {
|
if (signalPin2!=UNUSED_PIN) {
|
||||||
dualSignal=true;
|
dualSignal=true;
|
||||||
getFastPin(F("SIG2"),signalPin2,fastSignalPin2);
|
getFastPin(F("SIG2"),signalPin2,fastSignalPin2);
|
||||||
pinMode(signalPin2, OUTPUT);
|
pinMode(signalPin2, OUTPUT);
|
||||||
|
|
||||||
|
#ifndef ARDUINO_GIGA // no giga
|
||||||
fastSignalPin2.shadowinout = NULL;
|
fastSignalPin2.shadowinout = NULL;
|
||||||
if (HAVE_PORTA(fastSignalPin2.inout == &PORTA)) {
|
if (HAVE_PORTA(fastSignalPin2.inout == &PORTA)) {
|
||||||
DIAG(F("Found PORTA pin %d"),signalPin2);
|
DIAG(F("Found PORTA pin %d"),signalPin2);
|
||||||
|
@ -126,6 +129,7 @@ MotorDriver::MotorDriver(int16_t power_pin, byte signal_pin, byte signal_pin2, i
|
||||||
fastSignalPin2.shadowinout = fastSignalPin2.inout;
|
fastSignalPin2.shadowinout = fastSignalPin2.inout;
|
||||||
fastSignalPin2.inout = &shadowPORTF;
|
fastSignalPin2.inout = &shadowPORTF;
|
||||||
}
|
}
|
||||||
|
#endif // giga
|
||||||
}
|
}
|
||||||
else dualSignal=false;
|
else dualSignal=false;
|
||||||
|
|
||||||
|
@ -501,8 +505,16 @@ unsigned int MotorDriver::mA2raw( unsigned int mA) {
|
||||||
return (int32_t)mA * senseScale / senseFactorInternal;
|
return (int32_t)mA * senseScale / senseFactorInternal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MotorDriver::getFastPin(const FSH* type,int pin, bool input, FASTPIN & result) {
|
void MotorDriver::getFastPin(const FSH* type,int pin, bool input, FASTPIN & result) {
|
||||||
// DIAG(F("MotorDriver %S Pin=%d,"),type,pin);
|
// DIAG(F("MotorDriver %S Pin=%d,"),type,pin);
|
||||||
|
#if defined(ARDUINO_GIGA) // yes giga
|
||||||
|
(void)type;
|
||||||
|
(void)input; // no warnings please
|
||||||
|
|
||||||
|
result = pin;
|
||||||
|
|
||||||
|
#else // no giga
|
||||||
(void) type; // avoid compiler warning if diag not used above.
|
(void) type; // avoid compiler warning if diag not used above.
|
||||||
#if defined(ARDUINO_ARCH_SAMD)
|
#if defined(ARDUINO_ARCH_SAMD)
|
||||||
PortGroup *port = digitalPinToPort(pin);
|
PortGroup *port = digitalPinToPort(pin);
|
||||||
|
@ -517,6 +529,7 @@ void MotorDriver::getFastPin(const FSH* type,int pin, bool input, FASTPIN & res
|
||||||
result.inout = portOutputRegister(port);
|
result.inout = portOutputRegister(port);
|
||||||
result.maskHIGH = digitalPinToBitMask(pin);
|
result.maskHIGH = digitalPinToBitMask(pin);
|
||||||
result.maskLOW = ~result.maskHIGH;
|
result.maskLOW = ~result.maskHIGH;
|
||||||
|
#endif // giga
|
||||||
// DIAG(F(" port=0x%x, inoutpin=0x%x, isinput=%d, mask=0x%x"),port, result.inout,input,result.maskHIGH);
|
// DIAG(F(" port=0x%x, inoutpin=0x%x, isinput=%d, mask=0x%x"),port, result.inout,input,result.maskHIGH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* © 2021 Fred Decker
|
* © 2021 Fred Decker
|
||||||
* © 2020 Chris Harlow
|
* © 2020 Chris Harlow
|
||||||
* © 2022 Harald Barth
|
* © 2022 Harald Barth
|
||||||
|
* © 2023 Travis Farmer
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This file is part of CommandStation-EX
|
* This file is part of CommandStation-EX
|
||||||
|
@ -30,12 +31,21 @@
|
||||||
// use powers of two so we can do logical and/or on the track modes in if clauses.
|
// use powers of two so we can do logical and/or on the track modes in if clauses.
|
||||||
enum TRACK_MODE : byte {TRACK_MODE_NONE = 1, TRACK_MODE_MAIN = 2, TRACK_MODE_PROG = 4,
|
enum TRACK_MODE : byte {TRACK_MODE_NONE = 1, TRACK_MODE_MAIN = 2, TRACK_MODE_PROG = 4,
|
||||||
TRACK_MODE_DC = 8, TRACK_MODE_DCX = 16, TRACK_MODE_EXT = 32};
|
TRACK_MODE_DC = 8, TRACK_MODE_DCX = 16, TRACK_MODE_EXT = 32};
|
||||||
|
#if defined(ARDUINO_GIGA) // yes giga
|
||||||
|
|
||||||
|
#define setHIGH(fastpin) digitalWrite(fastpin,1)
|
||||||
|
#define setLOW(fastpin) digitalWrite(fastpin,0)
|
||||||
|
#else // no giga
|
||||||
#define setHIGH(fastpin) *fastpin.inout |= fastpin.maskHIGH
|
#define setHIGH(fastpin) *fastpin.inout |= fastpin.maskHIGH
|
||||||
#define setLOW(fastpin) *fastpin.inout &= fastpin.maskLOW
|
#define setLOW(fastpin) *fastpin.inout &= fastpin.maskLOW
|
||||||
|
#endif // giga
|
||||||
|
#if defined(ARDUINO_GIGA) // yes giga
|
||||||
|
#define isHIGH(fastpin) ((PinStatus)digitalRead(fastpin)==1)
|
||||||
|
#define isLOW(fastpin) ((PinStatus)digitalRead(fastpin)==0)
|
||||||
|
#else // no giga
|
||||||
#define isHIGH(fastpin) (*fastpin.inout & fastpin.maskHIGH)
|
#define isHIGH(fastpin) (*fastpin.inout & fastpin.maskHIGH)
|
||||||
#define isLOW(fastpin) (!isHIGH(fastpin))
|
#define isLOW(fastpin) (!isHIGH(fastpin))
|
||||||
|
#endif // giga
|
||||||
#define TOKENPASTE(x, y) x ## y
|
#define TOKENPASTE(x, y) x ## y
|
||||||
#define TOKENPASTE2(x, y) TOKENPASTE(x, y)
|
#define TOKENPASTE2(x, y) TOKENPASTE(x, y)
|
||||||
|
|
||||||
|
@ -117,12 +127,19 @@ typedef uint32_t portreg_t;
|
||||||
typedef uint8_t portreg_t;
|
typedef uint8_t portreg_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(ARDUINO_GIGA) // yes giga
|
||||||
|
typedef int FASTPIN;
|
||||||
|
|
||||||
|
|
||||||
|
#else // no giga
|
||||||
struct FASTPIN {
|
struct FASTPIN {
|
||||||
volatile portreg_t *inout;
|
volatile portreg_t *inout;
|
||||||
portreg_t maskHIGH;
|
portreg_t maskHIGH;
|
||||||
portreg_t maskLOW;
|
portreg_t maskLOW;
|
||||||
volatile portreg_t *shadowinout;
|
volatile portreg_t *shadowinout;
|
||||||
};
|
};
|
||||||
|
#endif // giga
|
||||||
|
|
||||||
// The port registers that are shadowing
|
// The port registers that are shadowing
|
||||||
// the real port registers. These are
|
// the real port registers. These are
|
||||||
// defined in Motordriver.cpp
|
// defined in Motordriver.cpp
|
||||||
|
@ -148,6 +165,12 @@ class MotorDriver {
|
||||||
// otherwise the call from interrupt context can undo whatever we do
|
// otherwise the call from interrupt context can undo whatever we do
|
||||||
// from outside interrupt
|
// from outside interrupt
|
||||||
void setBrake( bool on, bool interruptContext=false);
|
void setBrake( bool on, bool interruptContext=false);
|
||||||
|
#if defined(ARDUINO_GIGA) // yes giga
|
||||||
|
__attribute__((always_inline)) inline void setSignal( bool high) {
|
||||||
|
digitalWrite(signalPin, high);
|
||||||
|
if (dualSignal) digitalWrite(signalPin2, !high);
|
||||||
|
};
|
||||||
|
#else // no giga
|
||||||
__attribute__((always_inline)) inline void setSignal( bool high) {
|
__attribute__((always_inline)) inline void setSignal( bool high) {
|
||||||
if (trackPWM) {
|
if (trackPWM) {
|
||||||
DCCTimer::setPWM(signalPin,high);
|
DCCTimer::setPWM(signalPin,high);
|
||||||
|
@ -163,6 +186,7 @@ class MotorDriver {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
#endif // giga
|
||||||
inline void enableSignal(bool on) {
|
inline void enableSignal(bool on) {
|
||||||
if (on)
|
if (on)
|
||||||
pinMode(signalPin, OUTPUT);
|
pinMode(signalPin, OUTPUT);
|
||||||
|
@ -184,6 +208,12 @@ class MotorDriver {
|
||||||
int getCurrentRaw(bool fromISR=false);
|
int getCurrentRaw(bool fromISR=false);
|
||||||
unsigned int raw2mA( int raw);
|
unsigned int raw2mA( int raw);
|
||||||
unsigned int mA2raw( unsigned int mA);
|
unsigned int mA2raw( unsigned int mA);
|
||||||
|
#if defined(ARDUINO_GIGA) // yes giga
|
||||||
|
inline bool digitalPinHasPWM(int pin) {
|
||||||
|
if (pin!=UNUSED_PIN && pin>=2 && pin<=13) return true;
|
||||||
|
else return false;
|
||||||
|
}
|
||||||
|
#endif // giga
|
||||||
inline bool brakeCanPWM() {
|
inline bool brakeCanPWM() {
|
||||||
#if defined(ARDUINO_ARCH_ESP32)
|
#if defined(ARDUINO_ARCH_ESP32)
|
||||||
return (brakePin != UNUSED_PIN); // This was just (true) but we probably do need to check for UNUSED_PIN!
|
return (brakePin != UNUSED_PIN); // This was just (true) but we probably do need to check for UNUSED_PIN!
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
* © 2020-2022 Harald Barth
|
* © 2020-2022 Harald Barth
|
||||||
* © 2020-2022 Chris Harlow
|
* © 2020-2022 Chris Harlow
|
||||||
* © 2023 Nathan Kellenicki
|
* © 2023 Nathan Kellenicki
|
||||||
|
* © 2023 Travis Farmer
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This file is part of CommandStation-EX
|
* This file is part of CommandStation-EX
|
||||||
|
@ -57,6 +58,14 @@ Stream * WifiInterface::wifiStream;
|
||||||
#define SERIAL3 Serial3
|
#define SERIAL3 Serial3
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(ARDUINO_GIGA) // yes giga
|
||||||
|
#define NUM_SERIAL 5
|
||||||
|
#define SERIAL1 Serial1
|
||||||
|
#define SERIAL2 Serial2
|
||||||
|
#define SERIAL3 Serial3
|
||||||
|
#define SERIAL4 Serial4
|
||||||
|
#endif // giga
|
||||||
|
|
||||||
#if defined(ARDUINO_ARCH_STM32)
|
#if defined(ARDUINO_ARCH_STM32)
|
||||||
// Handle serial ports availability on STM32 for variants!
|
// Handle serial ports availability on STM32 for variants!
|
||||||
// #undef NUM_SERIAL
|
// #undef NUM_SERIAL
|
||||||
|
|
21
defines.h
21
defines.h
|
@ -5,6 +5,7 @@
|
||||||
* © 2021 Fred Decker
|
* © 2021 Fred Decker
|
||||||
* © 2020-2022 Harald Barth
|
* © 2020-2022 Harald Barth
|
||||||
* © 2020-2021 Chris Harlow
|
* © 2020-2021 Chris Harlow
|
||||||
|
* © 2023 Travis Farmer
|
||||||
*
|
*
|
||||||
* This file is part of CommandStation-EX
|
* This file is part of CommandStation-EX
|
||||||
*
|
*
|
||||||
|
@ -147,7 +148,25 @@
|
||||||
// #ifndef I2C_USE_WIRE
|
// #ifndef I2C_USE_WIRE
|
||||||
// #define I2C_USE_WIRE
|
// #define I2C_USE_WIRE
|
||||||
// #endif
|
// #endif
|
||||||
|
#elif defined(ARDUINO_GIGA)
|
||||||
|
#define ARDUINO_TYPE "Giga"
|
||||||
|
#ifndef GIGA_EXT_EEPROM
|
||||||
|
#define DISABLE_EEPROM
|
||||||
|
#endif
|
||||||
|
//#if !defined(I2C_USE_WIRE)
|
||||||
|
//#define I2C_USE_WIRE
|
||||||
|
//#endif
|
||||||
|
#define SDA I2C_SDA
|
||||||
|
#define SCL I2C_SCL
|
||||||
|
#define DCC_EX_TIMER
|
||||||
|
// these don't work...
|
||||||
|
//extern const uint16_t PROGMEM port_to_input_PGM[];
|
||||||
|
//extern const uint16_t PROGMEM port_to_output_PGM[];
|
||||||
|
//extern const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[];
|
||||||
|
//#define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) )
|
||||||
|
//#define portOutputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_output_PGM + (P))) )
|
||||||
|
//#define portInputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_input_PGM + (P))) )
|
||||||
|
|
||||||
/* TODO when ready
|
/* TODO when ready
|
||||||
#elif defined(ARDUINO_ARCH_RP2040)
|
#elif defined(ARDUINO_ARCH_RP2040)
|
||||||
#define ARDUINO_TYPE "RP2040"
|
#define ARDUINO_TYPE "RP2040"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user