You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
340 lines
8.2 KiB
340 lines
8.2 KiB
#include "timer.h"
|
|
#include "interrupt.h"
|
|
#include "hwd_interrupt.h"
|
|
#include <stdlib.h>
|
|
#define BASE ((TIM_TypeDef *)timerBase_Addr_List[timer])
|
|
|
|
// debug notes: the makro works. what seems to not work is the indexing and calling the handler!
|
|
#define HANDLE_INT_FLAG(flagReg, flagMask, intType)\
|
|
do {if ((flagReg) & (flagMask)) {\
|
|
(flagReg) &= ~(flagMask);\
|
|
if(intHandlerArray[(intType)] == NULL) continue;\
|
|
intHandlerArray[(intType)]();\
|
|
}} while (0)
|
|
|
|
void timerReset(timerNo_t timer)
|
|
{
|
|
if(timerBus_No[timer]==1)
|
|
{
|
|
RCC->APB1RSTR |= (1<<timerBus_Rst_bitPos[timer]);
|
|
RCC->APB1RSTR &=~ (1<<timerBus_Rst_bitPos[timer]);
|
|
return;
|
|
}
|
|
RCC->APB2RSTR |= (1<<timerBus_Rst_bitPos[timer]);
|
|
RCC->APB2RSTR &=~ (1<<timerBus_Rst_bitPos[timer]);
|
|
}
|
|
|
|
void timerActivateBus(timerNo_t timer)
|
|
{
|
|
if(timerBus_No[timer]==1)
|
|
{
|
|
RCC->APB1ENR |= (1<<timerBus_En_bitPos[timer]);
|
|
return;
|
|
}
|
|
RCC->APB2ENR |= (1<<timerBus_En_bitPos[timer]);
|
|
}
|
|
|
|
void timerEnable(timerNo_t timer)
|
|
{
|
|
BASE->CR1 |= TIM_CR1_CEN; //all the timers have the same CEN bit in CR1 register pos 0
|
|
}
|
|
|
|
void timerDisable(timerNo_t timer)
|
|
{
|
|
BASE->CR1 &=~ TIM_CR1_CEN; //all the timers have the same CEN bit in CR1 register pos 0
|
|
}
|
|
|
|
void timerSetMode(timerNo_t timer, timerMode_t mode)
|
|
{
|
|
// Propably not needed
|
|
}
|
|
|
|
void timerSetCountDirection(timerNo_t timer, timerCountDirection_t direction)
|
|
{
|
|
if(direction == upCounting)
|
|
{
|
|
|
|
BASE->CR1 &=~ TIM_CR1_DIR;
|
|
return;
|
|
}
|
|
|
|
BASE->CR1 |= TIM_CR1_DIR;
|
|
}
|
|
|
|
void timerSetPrescaler(timerNo_t timer, uint32_t prescaler)
|
|
{
|
|
if(prescaler > timerRes_Prescaler[timer])
|
|
{
|
|
timerThrowError(prescalerOutOfRange);
|
|
return; // To prevent writing wrong value in to the Register
|
|
}
|
|
BASE->PSC = prescaler;
|
|
}
|
|
|
|
void timerSetPostscaler(timerNo_t timer, uint32_t postscaler)
|
|
{
|
|
timerThrowError(functionNotSupported);
|
|
}
|
|
|
|
void timerSetAutoReload(timerNo_t timer, uint32_t reload)
|
|
{
|
|
// TODO: implement error wen reload value exceeds the hardware register size (e.g. value > 16bit)
|
|
BASE->ARR = reload;
|
|
}
|
|
|
|
void timerClearCounter(timerNo_t timer)
|
|
{
|
|
BASE->CNT = 0;
|
|
}
|
|
|
|
uint8_t timerGetUpdateInterrupt(timerNo_t timer)
|
|
{
|
|
return (BASE->SR & 1);
|
|
}
|
|
|
|
void timerClearUpdateInterrupt(timerNo_t timer)
|
|
{
|
|
BASE->SR &= ~1;
|
|
}
|
|
|
|
/* Second stage configuration */
|
|
void timerInitCounter ( timerNo_t timer,
|
|
uint32_t prescaler,
|
|
uint32_t autoReload,
|
|
timerCountDirection_t direction)
|
|
{
|
|
timerActivateBus(timer);
|
|
timerSetMode(timer, counter);
|
|
timerSetCountDirection(timer,direction);
|
|
timerSetPrescaler(timer, prescaler);
|
|
timerSetAutoReload(timer, autoReload);
|
|
}
|
|
|
|
void timerInitOutputCompare( timerNo_t timer,
|
|
timerOutputCompareMode_t mode,
|
|
uint8_t timerIoChannel,
|
|
pinNo_t pinNo,
|
|
uint16_t altFunction,
|
|
uint8_t polarity,
|
|
uint32_t ccValue)
|
|
{
|
|
timerStop(timer);
|
|
pinSetMode(pinNo,alternate);
|
|
pinSetAlternate(pinNo,altFunction);
|
|
|
|
// TODO: check for value existing register size
|
|
//if(ccValue)
|
|
// timerThrowError(timerError_t error)
|
|
switch(timerIoChannel)
|
|
{
|
|
case 1:
|
|
BASE->CCMR1 &= ~TIM_CCMR1_OC1M;
|
|
BASE->CCMR1 |= mode << TIM_CCMR1_OC1M_Pos;
|
|
BASE->CCER |= TIM_CCER_CC1E;
|
|
BASE->CCER |= (1&&polarity) << TIM_CCER_CC1P_Pos;
|
|
BASE->CCER &= ~TIM_CCER_CC1NP;
|
|
BASE->CCR1 = (uint16_t)ccValue;
|
|
break;
|
|
case 2:
|
|
BASE->CCMR1 &= ~TIM_CCMR1_OC2M;
|
|
BASE->CCMR1 |= mode << TIM_CCMR1_OC2M_Pos;
|
|
BASE->CCER |= TIM_CCER_CC2E;
|
|
BASE->CCER |= (1&&polarity) << TIM_CCER_CC2P_Pos;
|
|
BASE->CCER &= ~TIM_CCER_CC2NP;
|
|
BASE->CCR2 = (uint16_t)ccValue;
|
|
break;
|
|
case 3:
|
|
BASE->CCMR2 &= ~TIM_CCMR2_OC3M;
|
|
BASE->CCMR2 |= mode << TIM_CCMR2_OC3M_Pos;
|
|
BASE->CCER |= TIM_CCER_CC3E;
|
|
BASE->CCER |= (1&&polarity) << TIM_CCER_CC3P_Pos;
|
|
BASE->CCER &= ~TIM_CCER_CC3NP;
|
|
BASE->CCR3 = (uint16_t)ccValue;
|
|
break;
|
|
case 4:
|
|
BASE->CCMR2 &= ~TIM_CCMR2_OC4M;
|
|
BASE->CCMR2 |= mode << TIM_CCMR2_OC4M_Pos;
|
|
BASE->CCER |= TIM_CCER_CC4E;
|
|
BASE->CCER |= (1&&polarity) << TIM_CCER_CC4P_Pos;
|
|
BASE->CCER &= ~TIM_CCER_CC4NP;
|
|
BASE->CCR4 = (uint16_t)ccValue;
|
|
break;
|
|
default:
|
|
timerThrowError(ccChannelNoOutOfRange);
|
|
break;
|
|
};
|
|
}
|
|
|
|
void timerSetCounterCompareValue(timerNo_t timer,
|
|
uint8_t timerIoChannel,
|
|
uint32_t ccValue)
|
|
{
|
|
switch(timerIoChannel) {
|
|
case 1:
|
|
BASE->CCR1 = (uint16_t)ccValue;
|
|
break;
|
|
case 2:
|
|
BASE->CCR2 = (uint16_t)ccValue;
|
|
break;
|
|
case 3:
|
|
BASE->CCR3 = (uint16_t)ccValue;
|
|
break;
|
|
case 4:
|
|
BASE->CCR4 = (uint16_t)ccValue;
|
|
break;
|
|
default:
|
|
timerThrowError(ccChannelNoOutOfRange);
|
|
break;
|
|
};
|
|
}
|
|
|
|
|
|
/* Bus Clock
|
|
* ------------------------------ = Duty (Hz)
|
|
* (Prescaler-1) * (Period-1)
|
|
*/
|
|
void timerSetHz(timerNo_t timer, uint16_t hz)
|
|
{
|
|
uint32_t prescaler = 8000000;
|
|
uint32_t period = 0;
|
|
uint32_t temp = 0;
|
|
|
|
do{
|
|
prescaler = prescaler / 10;
|
|
}while(prescaler > 0xffff);
|
|
|
|
|
|
do{
|
|
period = period + 1;
|
|
temp = 8000000/(prescaler*(period));
|
|
}while(temp >= hz);
|
|
|
|
timerSetPrescaler(timer, prescaler-1);
|
|
timerSetAutoReload(timer, period-1);
|
|
timerClearCounter(timer);
|
|
}
|
|
|
|
void timerSetMs(timerNo_t timer, uint16_t ms)
|
|
{
|
|
|
|
}
|
|
|
|
void timerSetNs(timerNo_t timer, uint16_t ns)
|
|
{
|
|
|
|
}
|
|
|
|
void timerSetPs(timerNo_t timer, uint16_t ps)
|
|
{
|
|
|
|
}
|
|
|
|
void timerStart(timerNo_t timer)
|
|
{
|
|
timerEnable(timer);
|
|
}
|
|
|
|
void timerHalt(timerNo_t timer)
|
|
{
|
|
timerDisable(timer);
|
|
}
|
|
|
|
void timerStop(timerNo_t timer)
|
|
{
|
|
timerDisable(timer);
|
|
timerClearCounter(timer);
|
|
}
|
|
|
|
|
|
uint32_t timerGetCount(timerNo_t timer)
|
|
{
|
|
return BASE->CNT;
|
|
}
|
|
|
|
|
|
void timerThrowError(timerError_t error)
|
|
{
|
|
while(1);
|
|
}
|
|
|
|
// Interrupt service routines
|
|
|
|
void TIM1_BRK_UP_TRG_COM_IRQHandler()
|
|
{
|
|
HANDLE_INT_FLAG(TIM1->SR,TIM_SR_BIF,TIM1_BREAK);
|
|
HANDLE_INT_FLAG(TIM1->SR,TIM_SR_UIF,TIM1_UPDATE);
|
|
HANDLE_INT_FLAG(TIM1->SR,TIM_SR_TIF,TIM1_TRIGGER);
|
|
HANDLE_INT_FLAG(TIM1->SR,TIM_SR_COMIF,TIM1_COMMUNICATION);
|
|
}
|
|
|
|
void TIM1_CC_IRQHandler()
|
|
{
|
|
HANDLE_INT_FLAG(TIM1->SR,TIM_SR_CC1IF,TIM1_COUNTERCOMPARE_1);
|
|
HANDLE_INT_FLAG(TIM1->SR,TIM_SR_CC2IF,TIM1_COUNTERCOMPARE_2);
|
|
HANDLE_INT_FLAG(TIM1->SR,TIM_SR_CC3IF,TIM1_COUNTERCOMPARE_3);
|
|
HANDLE_INT_FLAG(TIM1->SR,TIM_SR_CC4IF,TIM1_COUNTERCOMPARE_4);
|
|
}
|
|
|
|
void TIM2_IRQHandler()
|
|
{
|
|
/*
|
|
if(TIM2->SR & TIM_SR_UIF) {
|
|
TIM2->SR &= ~TIM_SR_UIF;
|
|
|
|
if(intHandlerArray[TIM2_UPDATE] == NULL) return;
|
|
|
|
//pinToggle(pinB3);
|
|
|
|
intHandlerArray[TIM2_UPDATE]();
|
|
|
|
// debug info: not working here!
|
|
//((intHandler_t)(intHandlerList[TIM2_UPDATE]))();
|
|
}
|
|
*/
|
|
|
|
HANDLE_INT_FLAG(TIM2->SR,TIM_SR_UIF,TIM2_UPDATE);
|
|
/*
|
|
HANDLE_INT_FLAG(TIM2->SR,TIM_SR_CC1IF,TIM2_COUNTERCOMPARE_1);
|
|
HANDLE_INT_FLAG(TIM2->SR,TIM_SR_CC2IF,TIM2_COUNTERCOMPARE_2);
|
|
HANDLE_INT_FLAG(TIM2->SR,TIM_SR_CC3IF,TIM2_COUNTERCOMPARE_3);
|
|
HANDLE_INT_FLAG(TIM2->SR,TIM_SR_CC4IF,TIM2_COUNTERCOMPARE_4);
|
|
HANDLE_INT_FLAG(TIM2->SR,TIM_SR_TIF,TIM2_TRIGGER);
|
|
HANDLE_INT_FLAG(TIM2->SR,TIM_SR_CC1OF,TIM2_CAPTURECOMPARE_1);
|
|
HANDLE_INT_FLAG(TIM2->SR,TIM_SR_CC2OF,TIM2_CAPTURECOMPARE_2);
|
|
HANDLE_INT_FLAG(TIM2->SR,TIM_SR_CC3OF,TIM2_CAPTURECOMPARE_3);
|
|
HANDLE_INT_FLAG(TIM2->SR,TIM_SR_CC4OF,TIM2_CAPTURECOMAPRE_4);
|
|
*/
|
|
}
|
|
|
|
void TIM3_IRQHandler()
|
|
{
|
|
HANDLE_INT_FLAG(TIM3->SR,TIM_SR_UIF,TIM3_UPDATE);
|
|
HANDLE_INT_FLAG(TIM3->SR,TIM_SR_CC1IF,TIM3_COUNTERCOMPARE_1);
|
|
HANDLE_INT_FLAG(TIM3->SR,TIM_SR_CC2IF,TIM3_COUNTERCOMPARE_2);
|
|
HANDLE_INT_FLAG(TIM3->SR,TIM_SR_CC3IF,TIM3_COUNTERCOMPARE_3);
|
|
HANDLE_INT_FLAG(TIM3->SR,TIM_SR_CC4IF,TIM3_COUNTERCOMPARE_4);
|
|
HANDLE_INT_FLAG(TIM3->SR,TIM_SR_TIF,TIM3_TRIGGER);
|
|
HANDLE_INT_FLAG(TIM3->SR,TIM_SR_CC1OF,TIM3_CAPTURECOMPARE_1);
|
|
HANDLE_INT_FLAG(TIM3->SR,TIM_SR_CC2OF,TIM3_CAPTURECOMPARE_2);
|
|
HANDLE_INT_FLAG(TIM3->SR,TIM_SR_CC3OF,TIM3_CAPTURECOMPARE_3);
|
|
HANDLE_INT_FLAG(TIM3->SR,TIM_SR_CC4OF,TIM3_CAPTURECOMAPRE_4);
|
|
}
|
|
|
|
void TIM16_IRQHandler()
|
|
{
|
|
HANDLE_INT_FLAG(TIM16->SR,TIM_SR_CC1OF,TIM16_CAPTURECOMPARE_1_OVERCAPTURE);
|
|
HANDLE_INT_FLAG(TIM16->SR,TIM_SR_BIF,TIM16_BREAK);
|
|
HANDLE_INT_FLAG(TIM16->SR,TIM_SR_COMIF,TIM16_COMMUNICATION);
|
|
HANDLE_INT_FLAG(TIM16->SR,TIM_SR_CC1IF,TIM16_CAPTURECOMPARE_1);
|
|
HANDLE_INT_FLAG(TIM16->SR,TIM_SR_UIF,TIM16_UPDATE);
|
|
}
|
|
|
|
void TIM17_IRQHandler()
|
|
{
|
|
HANDLE_INT_FLAG(TIM17->SR,TIM_SR_CC1OF,TIM17_CAPTURECOMPARE_1_OVERCAPTURE);
|
|
HANDLE_INT_FLAG(TIM17->SR,TIM_SR_BIF,TIM17_BREAK);
|
|
HANDLE_INT_FLAG(TIM17->SR,TIM_SR_COMIF,TIM17_COMMUNICATION);
|
|
HANDLE_INT_FLAG(TIM17->SR,TIM_SR_CC1IF,TIM17_CAPTURECOMPARE_1);
|
|
HANDLE_INT_FLAG(TIM17->SR,TIM_SR_UIF,TIM17_UPDATE);
|
|
}
|