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.
KED/csl/stm32f042k6t6/implementation/imp_timer.c

387 lines
9.3 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)
static const uint32_t DIER_list[TIM16_UPDATE - TIM1_BREAK] = {
TIM_DIER_BIE,// timer 1
TIM_DIER_UIE,
TIM_DIER_TIE,
TIM_DIER_COMIE,
TIM_DIER_CC1IE,
TIM_DIER_CC2IE,
TIM_DIER_CC3IE,
TIM_DIER_CC4IE,
TIM_DIER_UIE,// timer 2
TIM_DIER_CC1IE,
TIM_DIER_CC2IE,
TIM_DIER_CC3IE,
TIM_DIER_CC4IE,
TIM_DIER_TIE,
TIM_DIER_CC1IE,
TIM_DIER_CC2IE,
TIM_DIER_CC3IE,
TIM_DIER_CC4IE,
TIM_DIER_UIE, // timer 3
TIM_DIER_CC1IE,
TIM_DIER_CC2IE,
TIM_DIER_CC3IE,
TIM_DIER_CC4IE,
TIM_DIER_TIE,
TIM_DIER_CC1IE,
TIM_DIER_CC2IE,
TIM_DIER_CC3IE,
TIM_DIER_CC4IE,
TIM_DIER_CC1IE,// timer 14
TIM_DIER_CC1IE,
TIM_DIER_UIE,
TIM_DIER_CC1IE,// tiemr 16
TIM_DIER_BIE,
TIM_DIER_COMIE,
TIM_DIER_CC1IE,
TIM_DIER_UIE,
TIM_DIER_CC1IE,// tiemr 17
TIM_DIER_BIE,
TIM_DIER_COMIE,
TIM_DIER_CC1IE,
TIM_DIER_UIE
};
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 timerEnableInterrupt(
timerNo_t timer,
intrType_t timerInterrupt)
{
// check for the correct interrupt index
if(timerInterrupt < TIM1_BREAK) return;
if(timerInterrupt >TIM17_UPDATE) return;
// set the corresponding bit in the corresponding timers DIER register
BASE->DIER |= DIER_list[timerInterrupt - TIM1_BREAK];
}
void timerDissableInterrupt(
timerNo_t timer,
intrType_t timerInterrupt)
{
// check for the correct interrupt index
if(timerInterrupt < TIM1_BREAK) return;
if(timerInterrupt >TIM17_UPDATE) return;
// set the corresponding bit in the corresponding timers DIER register
BASE->DIER &= ~DIER_list[timerInterrupt - TIM1_BREAK];
}
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()
{
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);
}