STM32F756VGH6 problem running 2 timers at the same time
Hi,
I am a newbie learning to program STM32 via registers only. I have been doing step after step progress and managed to test and run the led blink program, timer delay, external interrupt etc. So hardware, core clock and other configurations are already tested. Now I ran into a problem of running 2 timers at the same time. I am using Timer1 as my blocking delay source (timer 1 is tested and works well), but when I entered interrupts, the need for second timer was imminent to implement timer interrupts etc.
The problem arises in the first line of Timer8 setup. I have done countless test, skipping the timer 8 setup and usage results in perfectly working code (except the timer 8 of course), but as soon as I try to even enable the clock for timer 8 (or do an further timer8 and its interrupt setup) whole code jams without any response. I have been reading the datasheet for a good few days now, but after so many tests I can not resolve it on my own. Any ideas or obvious mistakes? Thank you in advance.
#include "main.h"
void Core_Clock_Setup (void){
RCC->CR |= RCC_CR_HSEON; //Set the clock source to external crystal/resonator (HSE)
while (!(RCC->CR & RCC_CR_HSEON)); //Wait until clock gets stable
RCC->APB1ENR |= RCC_APB1ENR_PWREN; //Enable power interface clock
PWR->CR1 &= ~(1U << 14);
PWR->CR1 &= ~(1U << 15); //Set internal voltage regulator to is reset value (scale 1)
FLASH->ACR &= ~FLASH_ACR_ARTEN; //Disable ART accelerator
FLASH->ACR &= ~FLASH_ACR_ARTRST; //Reset ART accelerator
FLASH->ACR |= FLASH_ACR_PRFTEN; //Enable prefetch
FLASH->ACR |= FLASH_ACR_LATENCY_6WS; //Set 7 CPU clock cycle flash memory access time (in order to get 200 MHz core clock)
//@ 25 MHz crystal, 200 MHz core clock configuration down below
RCC->CFGR &= 0x0F; //--------------------------------------------------------
RCC->CFGR &= ~(1 << 4); //Core clock division by 1 (core clock is not devided)
RCC->CFGR &= ~(1 << 5);
RCC->CFGR &= ~(1 << 6);
RCC->CFGR &= ~(1 << 7);
RCC->PLLCFGR |= RCC_PLLCFGR_PLLSRC_HSE;//HSE is set to be PLL entry
RCC->PLLCFGR &= ~(1 << 16); //PLLP Setting corresponding PLL prescalers (division by 2)
RCC->PLLCFGR &= ~(1 << 17);
RCC->PLLCFGR |= (16 << 0);
RCC->PLLCFGR &= 0x7F;//-----------------------------------------------------------------
RCC->PLLCFGR |= (256 << 6); //PLLN Setting corresponding PLL prescalers ( multiplication by 256)
RCC->CFGR |= RCC_CFGR_PPRE1_DIV4; //APB1 Low speed prescaler of 4 (50 MHz, max is 54 Mhz)
RCC->CFGR |= RCC_CFGR_PPRE2_DIV2; //APB2 High speed prescaler of 2 (100 MHz, max is 108 Mhz)
RCC->CR |= RCC_CR_PLLON; //Enable PLL
while (!(RCC->CR & RCC_CR_PLLRDY)); //Wait until PLL gets stable
RCC->CFGR |= RCC_CFGR_SW_PLL; //PLL is set to be core clock
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL); // Wait until PLL indeed becomes core clock source
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------
void Timer1_Setup(void){ //16 bit advanced timer
RCC->DCKCFGR1 &= ~ (1 << 24); //TIMxCLK = 2xPCLKx
//TIM1 CLK is HCLK in this case
RCC->APB2ENR = (1 << 0); //Enable Timer 1 clock
TIM1->PSC = 99; //APB1 is 50 Mhz and 100 MHZ for timer (The number is set: Clock in MHz - 1) 1 full period equals 1 MHZ
TIM1->ARR = 0xFFFF; //Auto reload at 100 ticks -> (around 100 micro seconds at 100 MHz timer clock)/2
TIM1->CR1 = (1 << 0); //Enable Timer 1 counter
while(!(TIM1->SR & (1<<0))); //Wait until timer update bit is set
//TIM1->CR1 &= ~(1 << 0); //Disable Timer 1 counter
//TIM1->CNT = 0;
}
void Timer8_Setup(void){ //16 bit advanced timer
//THIS LINE ALREADY JAMS THE CODE ---------------------------------------------------------------
//RCC->APB2ENR |= (1 << 1); //Enable Timer 8 clock
//---------------------------------------------------------------
//TIM8->PSC = 99; //APB1 is 50 Mhz and 100 MHZ for timer (The number is set: Clock in MHz - 1) 1 full period equals 1 MHZ
//TIM8->ARR = 0xFFFF;
//TIM8->CR1 = (1 << 2); //Only counter overflow/underflow generates an update interrupt or DMA request if enabled
//TIM8->DIER = (1 << 0); //Update interrupt enabled
//TIM8->EGR = (1 << 0);
//NVIC_SetPriority(TIM1_UP_TIM10_IRQn, 1);
//NVIC_EnableIRQ (TIM1_UP_TIM10_IRQn);
//TIM8->CR1 = (1 << 0); //Enable Timer 1 counter
//while(!(TIM8->SR & (1<<0))); //Wait until timer update bit is set
//TIM8->CR1 &= ~(1 << 0); //Disable Timer 1 counter
//TIM8->CNT = 0;
}
void delay_ms (uint16_t ms){
TIM1->CR1 = (1 << 0); //Enable Timer 1 counter
for(uint16_t i = 0; i<ms; i++)
{
TIM1->CNT = 0; //Reset counter
while (TIM1->CNT < 2000); //Wait until counter reaches desired value
}
TIM1->CR1 &= ~(1 << 0); //Disable Timer 1 counter
TIM1->CNT = 0;
}
void TIM1_UP_TIM10_IRQnHandler(void){
//If multiple timer interrupts are enabled, have to check the status bits, to determine, which of the 1-10 timer interrupts have occurred
if(TIM8->SR & (1<<0)){
TIM8->CR1 &= ~(1 << 0); //Disable Timer 1 counter
TIM8->CNT = 0;
GPIOC->BSRR = (1 << 15);
delay_ms(1000);
GPIOC->BSRR = (1 << 31);
TIM8->SR &= ~(1<<0);
}
}
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void GPIO_Setup(void){
//PC14 OUTPUT //LEDS
RCC->AHB1ENR |= (1 << 2); //Enable clock for GPIO bank C
RCC->AHB1ENR |= (1 << 4); //Enable clock for GPIO bank E
delay_ms(1);
GPIOC->MODER |= (0b01 << 28); //PC14 General purpose output mode
GPIOC->OTYPER &= ~ (1 << 14); //PC14 Output push-pull (reset state)
GPIOC->OSPEEDR |= (0b11 << 28); //PC14 very high GPIO speed
GPIOC->PUPDR |= (0b10 << 28); //PC14 pull down resistors
//PC15 OUTPUT
GPIOC->MODER |= (0b01 << 30); //PC15 General purpose output mode
GPIOC->OTYPER &= ~ (1 << 15); //PC15 Output push-pull (reset state)
GPIOC->OSPEEDR |= (0b11 << 30); //PC15 very high GPIO speed
GPIOC->PUPDR |= (0b10 << 30); //PC15 pull down resistors
//PE4 OUTPUT
GPIOE->MODER |= (0b01 << 8); //PE4 General purpose output mode
GPIOE->OTYPER &= ~ (1 << 4); //PE4 Output push-pull (reset state)
GPIOE->OSPEEDR |= (0b11 << 8); //PE4 very high GPIO speed
GPIOE->PUPDR |= (0b10 << 8); //PE4 pull down resistors
//PE0 OUTPUT
GPIOE->MODER |= (0b01 << 0); //PE0 General purpose output mode
GPIOE->OTYPER &= ~ (1 << 0); //PE0 Output push-pull (reset state)
GPIOE->OSPEEDR |= (0b11 << 0); //PE0 very high GPIO speed
GPIOE->PUPDR |= (0b10 << 0); //PE0 pull down resistors
//-----------------------------------------------------------------------------------
//PE5 INPUT ALL BUTTONS EXTERNALLY PULLED UP
GPIOE->MODER |= (0b00 << 10); //PE5 General purpose input mode
//PE6 INPUT
GPIOE->MODER |= (0b00 << 12); //PE6 General purpose input mode
/*
//PH0 INPUT
RCC->AHB1ENR |= (1 << 7);
GPIOH->MODER |= (0b00 << 0); //PH0 General purpose input mode
//PH1 INPUT
GPIOH->MODER |= (0b00 << 2); //PH1 General purpose input mode
*/
}
int main (void){
Core_Clock_Setup();
Timer1_Setup();
GPIO_Setup();
Timer8_Setup();
GPIOC->BSRR = 0x4000;
while(1){
GPIOC->BSRR = (1 << 15);
delay_ms(200);
GPIOC->BSRR = (1 << 31);
delay_ms(200);
}
}
