First try fixing hardware timers STM32F407VE

This commit is contained in:
hoogendijkta 2019-02-19 23:28:13 +01:00
parent 21cd8609ea
commit fea93d4857
6 changed files with 632 additions and 69 deletions

View File

@ -1,6 +1,15 @@
#ifndef STM32_H
#define STM32_H
#if defined(CORE_STM32)
#if defined(STM32F4)
//These should really be in the stm32GENERIC libs, but for somereason they only have timers 1-4
// #include <stm32_TIM_variant_11.h>
// #include "src/HardwareTimers/HardwareTimer.h"
// HardwareTimer Timer5(TIM5, chip_tim5, sizeof(chip_tim5) / sizeof(chip_tim5[0]));
// HardwareTimer Timer8(TIM8, chip_tim8, sizeof(chip_tim8) / sizeof(chip_tim8[0]));
#else
#include "HardwareTimer.h"
#endif
/*
***********************************************************************************************************
@ -8,10 +17,13 @@
*/
#define PORT_TYPE uint8_t
#define micros_safe() micros() //timer5 method is not used on anything but AVR, the micros_safe() macro is simply an alias for the normal micros()
#define USE_SERIAL3
void initBoard();
uint16_t freeRam();
extern void oneMSIntervalIRQ(stimer_t *Timer);
extern void EmptyIRQCallback(stimer_t *Timer, uint32_t channel);
#if defined(USE_STM32GENERIC)
#define Serial Serial1
#endif
@ -292,4 +304,4 @@
*/
#endif //CORE_STM32
#endif //STM32_H
#endif //STM32_H

View File

@ -4,22 +4,47 @@
#include "auxiliaries.h"
#include "idle.h"
#include "scheduler.h"
#include "HardwareTimer.h"
#if defined(STM32F4)
#define NR_OFF_TIMERS 9
//stimer_t HardwareTimers[NR_OFF_TIMERS + 1];
stimer_t HardwareTimers_1;
stimer_t HardwareTimers_2;
stimer_t HardwareTimers_3;
stimer_t HardwareTimers_4;
stimer_t HardwareTimers_5;
stimer_t HardwareTimers_8;
//These should really be in the stm32GENERIC libs, but for somereason they only have timers 1-4
#include <stm32_TIM_variant_11.h>
HardwareTimer Timer5(TIM5, chip_tim5, sizeof(chip_tim5) / sizeof(chip_tim5[0]));
HardwareTimer Timer8(TIM8, chip_tim8, sizeof(chip_tim8) / sizeof(chip_tim8[0]));
// #include <stm32_TIM_variant_11.h>
// #include "src/HardwareTimers/HardwareTimer.h"
// HardwareTimer Timer5(TIM5, chip_tim5, sizeof(chip_tim5) / sizeof(chip_tim5[0]));
// HardwareTimer Timer8(TIM8, chip_tim8, sizeof(chip_tim8) / sizeof(chip_tim8[0]));
#else
#include "HardwareTimer.h"
#endif
extern void oneMSIntervalIRQ(stimer_t *Timer){oneMSInterval();}
extern void EmptyIRQCallback(stimer_t *Timer, uint32_t channel){}
void initBoard()
{
/*
* Initialize timers
*/
HardwareTimers_1.timer = TIM1;
HardwareTimers_2.timer = TIM2;
HardwareTimers_3.timer = TIM3;
HardwareTimers_4.timer = TIM4;
HardwareTimers_5.timer = TIM5;
HardwareTimers_8.timer = TIM8;
/*
***********************************************************************************************************
* General
*/
#define FLASH_LENGTH 8192
#define FLASH_LENGTH 8192
/*
***********************************************************************************************************
@ -31,10 +56,10 @@ void initBoard()
}
//This must happen at the end of the idle init
Timer1.setMode(4, TIMER_OUTPUT_COMPARE);
//Timer1.setMode(4, TIMER_OUTPUT_COMPARE);
//timer_set_mode(TIMER1, 4, TIMER_OUTPUT_COMPARE;
if(idle_pwm_max_count > 0) { Timer1.attachInterrupt(4, idleInterrupt);} //on first flash the configPage4.iacAlgorithm is invalid
Timer1.resume();
//if(idle_pwm_max_count > 0) { Timer1.attachInterrupt(4, idleInterrupt);} //on first flash the configPage4.iacAlgorithm is invalid
//Timer1.resume();
/*
@ -42,10 +67,8 @@ void initBoard()
* Timers
*/
#if defined(ARDUINO_BLACK_F407VE) || defined(STM32F4) || defined(_STM32F4_)
Timer8.setPeriod(1000); // Set up period
Timer8.setMode(1, TIMER_OUTPUT_COMPARE);
Timer8.attachInterrupt(1, oneMSInterval);
Timer8.resume(); //Start Timer
TimerHandleInit(&HardwareTimers_8, 1000, 168);
attachIntHandle(&HardwareTimers_8, oneMSIntervalIRQ);
#else
Timer4.setPeriod(1000); // Set up period
Timer4.setMode(1, TIMER_OUTPUT_COMPARE);
@ -63,11 +86,11 @@ void initBoard()
vvt_pwm_max_count = 1000000L / (2 * configPage6.vvtFreq * 2); //Converts the frequency in Hz to the number of ticks (at 2uS) it takes to complete 1 cycle
//Need to be initialised last due to instant interrupt
Timer1.setMode(2, TIMER_OUTPUT_COMPARE);
Timer1.setMode(3, TIMER_OUTPUT_COMPARE);
if(boost_pwm_max_count > 0) { Timer1.attachInterrupt(2, boostInterrupt);}
if(vvt_pwm_max_count > 0) { Timer1.attachInterrupt(3, vvtInterrupt);}
Timer1.resume();
// Timer1.setMode(2, TIMER_OUTPUT_COMPARE);
// Timer1.setMode(3, TIMER_OUTPUT_COMPARE);
// if(boost_pwm_max_count > 0) { Timer1.attachInterrupt(2, boostInterrupt);}
// if(vvt_pwm_max_count > 0) { Timer1.attachInterrupt(3, vvtInterrupt);}
// Timer1.resume();
/*
***********************************************************************************************************
@ -75,9 +98,9 @@ void initBoard()
*/
#if defined(ARDUINO_ARCH_STM32) // STM32GENERIC core
//see https://github.com/rogerclarkmelbourne/Arduino_STM32/blob/754bc2969921f1ef262bd69e7faca80b19db7524/STM32F1/system/libmaple/include/libmaple/timer.h#L444
Timer1.setPrescaleFactor((HAL_RCC_GetHCLKFreq() * 2U)-1); //2us resolution
Timer2.setPrescaleFactor((HAL_RCC_GetHCLKFreq() * 2U)-1); //2us resolution
Timer3.setPrescaleFactor((HAL_RCC_GetHCLKFreq() * 2U)-1); //2us resolution
// Timer1.setPrescaleFactor((HAL_RCC_GetHCLKFreq() * 2U)-1); //2us resolution
// Timer2.setPrescaleFactor((HAL_RCC_GetHCLKFreq() * 2U)-1); //2us resolution
// Timer3.setPrescaleFactor((HAL_RCC_GetHCLKFreq() * 2U)-1); //2us resolution
#else //libmaple core aka STM32DUINO
//see https://github.com/rogerclarkmelbourne/Arduino_STM32/blob/754bc2969921f1ef262bd69e7faca80b19db7524/STM32F1/system/libmaple/include/libmaple/timer.h#L444
#if defined (STM32F1) || defined(__STM32F1__)
@ -94,71 +117,60 @@ void initBoard()
Timer3.setPrescaleFactor((42 * 2U)-1); //2us resolution
#endif
#endif
Timer2.setMode(1, TIMER_OUTPUT_COMPARE);
Timer2.setMode(2, TIMER_OUTPUT_COMPARE);
Timer2.setMode(3, TIMER_OUTPUT_COMPARE);
Timer2.setMode(4, TIMER_OUTPUT_COMPARE);
TimerPulseInit(&HardwareTimers_2, 0xFFFF, 500, EmptyIRQCallback);
attachIntHandleOC(&HardwareTimers_2, fuelSchedule1Interrupt, 1, 0);
attachIntHandleOC(&HardwareTimers_2, fuelSchedule2Interrupt, 2, 0);
attachIntHandleOC(&HardwareTimers_2, fuelSchedule3Interrupt, 3, 0);
attachIntHandleOC(&HardwareTimers_2, fuelSchedule4Interrupt, 4, 0);
Timer3.setMode(1, TIMER_OUTPUT_COMPARE);
Timer3.setMode(2, TIMER_OUTPUT_COMPARE);
Timer3.setMode(3, TIMER_OUTPUT_COMPARE);
Timer3.setMode(4, TIMER_OUTPUT_COMPARE);
Timer1.setMode(1, TIMER_OUTPUT_COMPARE);
TimerPulseInit(&HardwareTimers_3, 0xFFFF, 500, EmptyIRQCallback);
attachIntHandleOC(&HardwareTimers_3, ignitionSchedule1Interrupt, 1, 0);
attachIntHandleOC(&HardwareTimers_3, ignitionSchedule2Interrupt, 2, 0);
attachIntHandleOC(&HardwareTimers_3, ignitionSchedule3Interrupt, 3, 0);
attachIntHandleOC(&HardwareTimers_3, ignitionSchedule4Interrupt, 4, 0);
// Timer1.setMode(1, TIMER_OUTPUT_COMPARE);
//Attach interupt functions
//Injection
Timer2.attachInterrupt(1, fuelSchedule1Interrupt);
Timer2.attachInterrupt(2, fuelSchedule2Interrupt);
Timer2.attachInterrupt(3, fuelSchedule3Interrupt);
Timer2.attachInterrupt(4, fuelSchedule4Interrupt);
TimerPulseInit(&HardwareTimers_5, 0xFFFF, 0, EmptyIRQCallback);
#if (INJ_CHANNELS >= 5)
Timer5.attachInterrupt(1, fuelSchedule5Interrupt);
attachIntHandleOC(&HardwareTimers_5, fuelSchedule5Interrupt, 1, 0);
//Timer5.attachInterrupt(1, fuelSchedule5Interrupt);
#endif
#if (INJ_CHANNELS >= 6)
Timer5.attachInterrupt(2, fuelSchedule6Interrupt);
attachIntHandleOC(&HardwareTimers_5, fuelSchedule6Interrupt, 2, 0);
//Timer5.attachInterrupt(2, fuelSchedule6Interrupt);
#endif
#if (INJ_CHANNELS >= 7)
Timer5.attachInterrupt(3, fuelSchedule7Interrupt);
attachIntHandleOC(&HardwareTimers_5, fuelSchedule7Interrupt, 3, 0);
//Timer5.attachInterrupt(3, fuelSchedule7Interrupt);
#endif
#if (INJ_CHANNELS >= 8)
Timer5.attachInterrupt(4, fuelSchedule8Interrupt);
attachIntHandleOC(&HardwareTimers_5, fuelSchedule8Interrupt, 4, 0);
//Timer5.attachInterrupt(4, fuelSchedule8Interrupt);
#endif
//Ignition
#if (IGN_CHANNELS >= 1)
Timer3.attachInterrupt(1, ignitionSchedule1Interrupt);
#endif
#if (IGN_CHANNELS >= 2)
Timer3.attachInterrupt(2, ignitionSchedule2Interrupt);
#endif
#if (IGN_CHANNELS >= 3)
Timer3.attachInterrupt(3, ignitionSchedule3Interrupt);
#endif
#if (IGN_CHANNELS >= 4)
Timer3.attachInterrupt(4, ignitionSchedule4Interrupt);
#endif
TimerPulseInit(&HardwareTimers_4, 0xFFFF, 0, EmptyIRQCallback);
#if (IGN_CHANNELS >= 5)
Timer4.attachInterrupt(1, ignitionSchedule5Interrupt);
attachIntHandleOC(&HardwareTimers_4, ignitionSchedule5Interrupt, 1, 0);
//Timer4.attachInterrupt(1, ignitionSchedule5Interrupt);
#endif
#if (IGN_CHANNELS >= 6)
Timer4.attachInterrupt(2, ignitionSchedule6Interrupt);
attachIntHandleOC(&HardwareTimers_4, ignitionSchedule6Interrupt, 2, 0);
//Timer4.attachInterrupt(2, ignitionSchedule6Interrupt);
#endif
#if (IGN_CHANNELS >= 7)
Timer4.attachInterrupt(3, ignitionSchedule7Interrupt);
attachIntHandleOC(&HardwareTimers_4, ignitionSchedule7Interrupt, 3, 0);
//Timer4.attachInterrupt(3, ignitionSchedule7Interrupt);
#endif
#if (IGN_CHANNELS >= 8)
Timer4.attachInterrupt(4, ignitionSchedule8Interrupt);
attachIntHandleOC(&HardwareTimers_4, ignitionSchedule8Interrupt, 4, 0);
//Timer4.attachInterrupt(4, ignitionSchedule8Interrupt);
#endif
Timer1.resume();
Timer2.resume();
Timer3.resume();
#if (IGN_CHANNELS >= 5)
Timer4.resume();
#endif
#if (INJ_CHANNELS >= 5)
Timer5.resume();
#endif
}
uint16_t freeRam()
@ -167,4 +179,4 @@ uint16_t freeRam()
return &top - reinterpret_cast<char*>(sbrk(0));
}
#endif
#endif

View File

@ -16,7 +16,8 @@ uint8_t Glow, Ghigh;
HardwareSerial &CANSerial = Serial3;
#elif defined(CORE_STM32)
#if defined(ARDUINO_ARCH_STM32) // STM32GENERIC core
SerialUART &CANSerial = Serial2;
HardwareSerial CANSerial(PD6,PD5);
//SerialUART &CANSerial = Serial2;
#else //libmaple core aka STM32DUINO
HardwareSerial &CANSerial = Serial2;
#endif

View File

@ -50,7 +50,7 @@
extern "C" char* sbrk(int incr); //Used to freeRam
#if defined(ARDUINO_ARCH_STM32) // STM32GENERIC core
inline unsigned char digitalPinToInterrupt(unsigned char Interrupt_pin) { return Interrupt_pin; } //This isn't included in the stm32duino libs (yet)
//inline unsigned char digitalPinToInterrupt(unsigned char Interrupt_pin) { return Interrupt_pin; } //This isn't included in the stm32duino libs (yet)
#define portOutputRegister(port) (volatile byte *)( &(port->ODR) )
#define portInputRegister(port) (volatile byte *)( &(port->IDR) )
#else //libmaple core aka STM32DUINO

View File

@ -0,0 +1,415 @@
/*
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.
*/
#include "HardwareTimer.h"
//#include CHIP_PERIPHERAL_INCLUDE
HardwareTimer *interruptTimers[18];
void (*pwm_callback_func)();
static void handleInterrupt(HardwareTimer *timer);
static const uint32_t OCMODE_NOT_USED = 0xFFFF;
HardwareTimer::HardwareTimer(TIM_TypeDef* timer) {
// this->tim_pin_list = pin_list;
// this->tim_pin_list_size = pin_list_size;
_timer.timer = timer;
//handle.Instance = timer;
// for(int i=0; i<4; i++) {
// channelOC[i].OCMode = OCMODE_NOT_USED;
// channelOC[i].OCPolarity = TIM_OCPOLARITY_HIGH;
// channelOC[i].OCNPolarity = TIM_OCNPOLARITY_HIGH;
// channelOC[i].OCFastMode = TIM_OCFAST_DISABLE;
// channelOC[i].OCIdleState = TIM_OCIDLESTATE_RESET;
// channelOC[i].OCNIdleState = TIM_OCNIDLESTATE_RESET;
// channelIC[i].ICPolarity = OCMODE_NOT_USED;
// channelIC[i].ICSelection = TIM_ICSELECTION_DIRECTTI;
// channelIC[i].ICPrescaler = TIM_ICPSC_DIV1;
// channelIC[i].ICFilter = 0;
// }
}
void HardwareTimer::pause() {
HAL_TIM_Base_Stop(&(_timer.handle));
}
void HardwareTimer::resume() {
HAL_TIM_Base_MspInit(_timer)
handle.Init.CounterMode = TIM_COUNTERMODE_UP;
handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
handle.Init.RepetitionCounter = 0;
HAL_TIM_Base_Init(&handle);
if (callbacks[0] != NULL) {
HAL_TIM_Base_Start_IT(&handle);
} else {
HAL_TIM_Base_Start(&handle);
}
resumeChannel(1, TIM_CHANNEL_1);
resumeChannel(2, TIM_CHANNEL_2);
resumeChannel(3, TIM_CHANNEL_3);
resumeChannel(4, TIM_CHANNEL_4);
}
void HardwareTimer::resumeChannel(int channel, int timChannel) {
if (channelOC[channel - 1].OCMode != OCMODE_NOT_USED) {
HAL_TIM_OC_ConfigChannel(&handle, &channelOC[channel - 1], timChannel);
if (callbacks[channel] != NULL) {
HAL_TIM_OC_Start_IT(&handle, timChannel);
} else {
HAL_TIM_OC_Start(&handle, timChannel);
}
}
if (channelIC[channel - 1].ICPolarity != OCMODE_NOT_USED) {
HAL_TIM_IC_ConfigChannel(&handle, &channelIC[channel - 1], timChannel);
if (callbacks[channel] != NULL) {
HAL_TIM_IC_Start_IT(&handle, timChannel);
} else {
HAL_TIM_IC_Start(&handle, timChannel);
}
}
}
uint32_t HardwareTimer::getPrescaleFactor() {
return handle.Init.Prescaler;
}
void HardwareTimer::setPrescaleFactor(uint32_t prescaler) {
handle.Init.Prescaler = prescaler;
}
uint32_t HardwareTimer::getOverflow() {
return handle.Init.Period;
}
void HardwareTimer::setOverflow(uint32_t overflow) {
handle.Init.Period = overflow;
}
uint32_t HardwareTimer::getCount(void) {
return __HAL_TIM_GET_COUNTER(&handle);
}
void HardwareTimer::setCount(uint32_t counter) {
__HAL_TIM_SET_COUNTER(&handle, counter);
}
#define MAX_RELOAD ((1 << 16) - 1) // Not always! 32 bit timers!
uint32_t HardwareTimer::getBaseFrequency() {
int freqMul = 2;
int freq2Mul = 2;
uint32_t pFreq = HAL_RCC_GetPCLK1Freq();
#ifdef STM32F1
freq2Mul = 1;
#endif
#ifdef TIM1
if (handle.Instance == TIM1) {
pFreq = HAL_RCC_GetPCLK2Freq();
freqMul = freq2Mul;
}
#endif
#ifdef TIM8
if (handle.Instance == TIM8) {
pFreq = HAL_RCC_GetPCLK2Freq();
freqMul = freq2Mul;
}
#endif
#ifdef TIM9
if (handle.Instance == TIM9) {
pFreq = HAL_RCC_GetPCLK2Freq();
freqMul = freq2Mul;
}
#endif
#ifdef TIM10
if (handle.Instance == TIM10) {
pFreq = HAL_RCC_GetPCLK2Freq();
freqMul = freq2Mul;
}
#endif
#ifdef TIM11
if (handle.Instance == TIM11) {
pFreq = HAL_RCC_GetPCLK2Freq();
freqMul = freq2Mul;
}
#endif
return pFreq * freqMul;
}
uint32_t HardwareTimer::setPeriod(uint32_t microseconds) {
if (!microseconds) {
this->setPrescaleFactor(1);
this->setOverflow(1);
return this->getOverflow();
}
uint32_t period_cyc = microseconds * (getBaseFrequency() / 1000000); //TODO!
uint32_t prescaler = (uint32_t)(period_cyc / MAX_RELOAD + 1);
uint32_t overflow = (uint32_t)((period_cyc + (prescaler / 2)) / prescaler);
this->setPrescaleFactor(prescaler);
this->setOverflow(overflow);
return overflow;
}
static bool isSameChannel(int channel, uint8_t signal) {
// switch(signal) {
// case TIM_CH1:
// case TIM_CH1N:
// return channel == 1;
// case TIM_CH2:
// case TIM_CH2N:
// return channel == 2;
// case TIM_CH3:
// case TIM_CH3N:
// return channel == 3;
// case TIM_CH4:
// case TIM_CH4N:
// return channel == 4;
// }
return false;
}
static const uint32_t PIN_NOT_USED = 0xFF;
void HardwareTimer::setMode(int channel, TIMER_MODES mode, uint8_t pin) {
int pinMode = PIN_NOT_USED;
int pull = GPIO_NOPULL;
switch(mode) {
case TIMER_PWM:
channelOC[channel - 1].OCMode = TIM_OCMODE_PWM1;
pinMode = GPIO_MODE_AF_PP;
break;
case TIMER_OUTPUT_COMPARE:
channelOC[channel - 1].OCMode = TIM_OCMODE_TIMING;
break;
case TIMER_OUTPUT_COMPARE_ACTIVE:
channelOC[channel - 1].OCMode = TIM_OCMODE_ACTIVE;
pinMode = GPIO_MODE_AF_PP;
break;
case TIMER_OUTPUT_COMPARE_INACTIVE:
channelOC[channel - 1].OCMode = TIM_OCMODE_ACTIVE;
pinMode = GPIO_MODE_AF_PP;
break;
case TIMER_OUTPUT_COMPARE_TOGGLE:
channelOC[channel - 1].OCMode = TIM_OCMODE_TOGGLE;
pinMode = GPIO_MODE_AF_PP;
break;
case TIMER_OUTPUT_COMPARE_PWM1:
channelOC[channel - 1].OCMode = TIM_OCMODE_PWM1;
pinMode = GPIO_MODE_AF_PP;
break;
case TIMER_OUTPUT_COMPARE_PWM2:
channelOC[channel - 1].OCMode = TIM_OCMODE_PWM2;
pinMode = GPIO_MODE_AF_PP;
break;
case TIMER_OUTPUT_COMPARE_FORCED_ACTIVE:
channelOC[channel - 1].OCMode = TIM_OCMODE_FORCED_ACTIVE;
pinMode = GPIO_MODE_AF_PP;
break;
case TIMER_OUTPUT_COMPARE_FORCED_INACTIVE:
channelOC[channel - 1].OCMode = TIM_OCMODE_FORCED_INACTIVE;
pinMode = GPIO_MODE_AF_PP;
break;
case TIMER_INPUT_CAPTURE_RISING:
channelIC[channel - 1].ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
pinMode = GPIO_MODE_AF_PP;
pull = GPIO_PULLDOWN;
break;
case TIMER_INPUT_CAPTURE_FALLING:
channelIC[channel - 1].ICPolarity = TIM_INPUTCHANNELPOLARITY_FALLING;
pinMode = GPIO_MODE_AF_PP;
pull = GPIO_PULLDOWN;
break;
}
if (pinMode != PIN_NOT_USED) {
//for(int i=0; i<tim_pin_list_size; i++) {
//if (isSameChannel(channel, tim_pin_list[i].signalType)) {
// if (pin == TIMER_DEFAULT_PIN ||
// (variant_pin_list[pin].port == tim_pin_list[i].port && variant_pin_list[pin].pin_mask == tim_pin_list[i].pinMask)) {
// stm32GpioClockEnable(tim_pin_list[i].port);
// GPIO_InitTypeDef GPIO_InitStruct;
// GPIO_InitStruct.Pin = tim_pin_list[i].pinMask;
// GPIO_InitStruct.Mode = pinMode;
// GPIO_InitStruct.Pull = pull;
// GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
// #ifdef STM32F1
// tim_pin_list[i].alternate();
// #else
// GPIO_InitStruct.Alternate = tim_pin_list[i].alternate;
// #endif
// HAL_GPIO_Init(tim_pin_list[i].port, &GPIO_InitStruct);
// return;
// }
//}
//}
}
}
void HardwareTimer::setCompare(int channel, uint32_t compare) {
channelOC[channel - 1].Pulse = compare;
}
uint32_t HardwareTimer::getCompare(int channel) {
if (channel == 1) return __HAL_TIM_GET_COMPARE(&handle, TIM_CHANNEL_1);
if (channel == 2) return __HAL_TIM_GET_COMPARE(&handle, TIM_CHANNEL_2);
if (channel == 3) return __HAL_TIM_GET_COMPARE(&handle, TIM_CHANNEL_3);
if (channel == 4) return __HAL_TIM_GET_COMPARE(&handle, TIM_CHANNEL_4);
return 0;
}
void HardwareTimer::attachInterrupt(void (*callback)(void)) {
callbacks[0] = callback;
}
void HardwareTimer::detachInterrupt() {
callbacks[0] = NULL;
}
void HardwareTimer::attachInterrupt(int channel, void (*callback)(void)) {
callbacks[channel] = callback;
}
void HardwareTimer::detachInterrupt(int channel) {
callbacks[channel] = NULL;
}
void HardwareTimer::refresh() {
HAL_TIM_GenerateEvent(&handle, TIM_EVENTSOURCE_UPDATE);
}
static void handleInterrupt(HardwareTimer *timer) {
if(__HAL_TIM_GET_FLAG(&timer->handle, TIM_FLAG_UPDATE) != RESET) {
__HAL_TIM_CLEAR_IT(&timer->handle, TIM_IT_UPDATE);
if (timer->callbacks[0] != NULL) timer->callbacks[0]();
}
if(__HAL_TIM_GET_FLAG(&timer->handle, TIM_FLAG_CC1) != RESET) {
__HAL_TIM_CLEAR_IT(&timer->handle, TIM_IT_CC1);
if (timer->callbacks[1] != NULL) timer->callbacks[1]();
}
if(__HAL_TIM_GET_FLAG(&timer->handle, TIM_FLAG_CC2) != RESET) {
__HAL_TIM_CLEAR_IT(&timer->handle, TIM_IT_CC2);
if (timer->callbacks[2] != NULL) timer->callbacks[2]();
}
if(__HAL_TIM_GET_FLAG(&timer->handle, TIM_FLAG_CC3) != RESET) {
__HAL_TIM_CLEAR_IT(&timer->handle, TIM_IT_CC3);
if (timer->callbacks[3] != NULL) timer->callbacks[3]();
}
if(__HAL_TIM_GET_FLAG(&timer->handle, TIM_FLAG_CC4) != RESET) {
__HAL_TIM_CLEAR_IT(&timer->handle, TIM_IT_CC4);
if (timer->callbacks[4] != NULL) timer->callbacks[4]();
}
}
#ifdef TIM1
HardwareTimer Timer1(TIM1);
#endif
#ifdef TIM2
HardwareTimer Timer2(TIM2);
#endif
#ifdef TIM3
HardwareTimer Timer3(TIM3);
#endif
#ifdef TIM4
HardwareTimer Timer4(TIM4);
#endif
#ifdef TIM5
HardwareTimer Timer5(TIM5);
#endif
#ifdef TIM8
HardwareTimer Timer8(TIM8);
#endif
//Timer interrupts:
// extern "C" void TIM1_CC_IRQHandler(void) {
// if (interruptTimers[0] != NULL) handleInterrupt(interruptTimers[0]);
// }
// extern "C" void TIM1_UP_IRQHandler(void) {
// if (interruptTimers[0] != NULL) handleInterrupt(interruptTimers[0]);
// }
// #ifndef TIM1_UP_TIM10_IRQHandler
// extern "C" void TIM1_UP_TIM10_IRQHandler(void) {
// if (interruptTimers[0] != NULL) handleInterrupt(interruptTimers[0]);
// if (interruptTimers[9] != NULL) handleInterrupt(interruptTimers[9]);
// }
// #endif
// in stm32_PWM.c
/*
extern "C" void TIM2_IRQHandler(void) {
handleInterrupt(interruptTimers[1]);
}*/
// extern "C" void TIM3_IRQHandler(void) {
// if (interruptTimers[2] != NULL) handleInterrupt(interruptTimers[2]);
// }
// extern "C" void TIM4_IRQHandler(void) {
// if (interruptTimers[3] != NULL) handleInterrupt(interruptTimers[3]);
// }

View File

@ -0,0 +1,123 @@
#ifndef HARDWARETIMER_H_
#define HARDWARETIMER_H_
#include "Arduino.h"
#include "timer.h"
//#include "stm32_gpio_af.h"
typedef enum {
//libmaple: // HAL compatible
TIMER_DISABLED,
TIMER_PWM, // == TIM_OCMODE_PWM1
TIMER_OUTPUT_COMPARE, // == TIM_OCMODE_TIMING no output, useful for only-interrupt
//other:
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
//PWM input capture on channel 1 + channel 2
//TIMER_INPUT_CAPTURE_PWM, // == TIM_INPUTCHANNELPOLARITY_RISING (channel 1) + TIM_INPUTCHANNELPOLARITY_FALLING (channel 2)
//Encoder mode
//TIMER_ENCODER // == TIM_ENCODERMODE_TI1
} TIMER_MODES;
#define TIMER_DEFAULT_PIN 0xFF
class HardwareTimer {
public:
HardwareTimer(TIM_TypeDef* timer);
void pause(void);
void resume(void);
uint32_t getPrescaleFactor();
void setPrescaleFactor(uint32_t factor);
uint32_t getOverflow();
void setOverflow(uint32_t val);
uint32_t getCount(void);
void setCount(uint32_t val);
uint32_t setPeriod(uint32_t microseconds);
void setMode(int channel, TIMER_MODES mode, uint8_t pin = TIMER_DEFAULT_PIN);
uint32_t getCompare(int channel);
void setCompare(int channel, uint32_t compare);
//Add interrupt to period update
void attachInterrupt(void (*handler)(void));
void detachInterrupt();
//Add interrupt to channel
void attachInterrupt(int channel, void (*handler)(void));
void detachInterrupt(int channel);
void refresh(void);
uint32_t getBaseFrequency();
TIM_HandleTypeDef handle = {0};
TIM_OC_InitTypeDef channelOC[4];
TIM_IC_InitTypeDef channelIC[4];
//Callbacks: 0 for update, 1-4 for channels
void (*callbacks[5])(void);
stimer_t _timer;
// //const stm32_tim_pin_list_type *tim_pin_list;
// int tim_pin_list_size;
private:
void resumeChannel(int channel, int timChannel);
};
#ifdef TIM1
extern HardwareTimer Timer1;
#endif
#ifdef TIM2
extern HardwareTimer Timer2;
#endif
#ifdef TIM3
extern HardwareTimer Timer3;
#endif
#ifdef TIM4
extern HardwareTimer Timer4;
#endif
#ifdef TIM5
extern HardwareTimer Timer5;
#endif
#ifdef TIM8
extern HardwareTimer Timer8;
#endif
#endif