When I run this code on my STM32L1 board, the debugger hangs once it reaches to a Float (in this case the variable 'Distance') or Delay, I mean it seems like it's processing, however it never goes through, and I have to close it and run the debugger again, which hangs of course again. Note that the code builds without errors or warnings. Is there's any special configuration for float ?
The following is the related part of the code:
void Delay(int x){ //input milliseconds, delay that number of milliseconds int a,b; for(a=0; a<x; a++){ for(b=0; b<1000; b++){ } } } . . . volatile int timespan = 0; // Total pulse width int main(void){ float Distance; // actual distance in cm . . . while(1){ TIM4_Echo_Read(); Distance = (timespan / 58.0); if (Distance <= 100){ GPIOB->BSRRL = (1<<7); } else { GPIOB->BSRRH = (1<<7); } Delay(10); }
timespan is declared as a global int. Note that none of this happens when I declare Distance as int instead of float.
Any idea why the debugger keeps getting stuck on float instructions?
@Gunnar Bohlen
When I first run the debugger, the first line it execute is the first line after the main(), which is the function SetHSI(). the SP value at that point is 0X20000670. So I increased the Stack to 0x00000800 and the SP value shows 0X20000A60 when executing the Distance line. Similarly, when I increased the stack to 0x000001000, the SP value showed 0X200001260 when executing the Distance line. Not sure what's happening to be honest.
I'll share the complete code in my next post, so you will know what I'm talking about. The code is supposed to calculate the distance by interfacing an ultrasonic sensor, and turn ON a LED if an object closer than 100cm is detected.
#include <stdio.h> #include "stm32l1xx.h" // Keil::Device:Startup //Initialize the timers variables. volatile int timespan = 0; // Total pulse width volatile int lastcounter = 0; // Timer counter value of the last event volatile int newcounter = 0; // Timer counter value of the current event volatile int overflow = 0; // Count the number of overflows void SetHSI(void); void Delay(int); void GPIO_config(void); void TIM2_Trigger(void); void TIM4_Init(void); void TIM4_Echo_Read(void); void LED (void); int main(void){ SetHSI(); GPIO_config(); TIM2_Trigger(); TIM4_Init(); while(1){ TIM4_Echo_Read(); LED(); Delay(100); } } void Delay(int x){ //input milliseconds, delay that number of milliseconds int a,b; for(a=0; a<x; a++){ for(b=0; b<1000; b++){ } } } //set HSI as SystemCoreClock (HSE is not populated on STM32L-Discovery board)// void SetHSI(void) { // Turn on HSI (16MHz) RCC->CR |= RCC_CR_HSION; // Wait until HSI is ready while( (RCC->CR & RCC_CR_HSIRDY) == 0); // Select HSI as system clock RCC->CFGR &= ~RCC_CFGR_SW_HSI; RCC->CFGR |= RCC_CFGR_SW_HSI; while( (RCC->CFGR & RCC_CFGR_SWS)!=RCC_CFGR_SWS_HSI ); // Wait till HSI } // Configure GPIO Port B void GPIO_config(void){ RCC->AHBRSTR |= RCC_AHBRSTR_GPIOBRST; // Reset GPIOB clock RCC->AHBRSTR &= ~RCC_AHBRSTR_GPIOBRST; // Clear Reset RCC->AHBENR |= RCC_AHBENR_GPIOBEN; // Enable GPIOB clock //PB6 Echo Pin GPIOB->MODER &= ~(0x03 << 12); // Clear bit 12 & 13 Alternate function mode GPIOB->MODER |= (0x02 << 12); // set as Alternate function mode GPIOB->OSPEEDR &= ~(0x03<< 12); // 40 MHz speed GPIOB->OSPEEDR |= (0x03<< 12); // 40 MHz speed GPIOB->PUPDR &= ~(0X3<<12); // NO PULL-UP PULL-DOWN GPIOB->OTYPER &= ~(1<<6); // PUSH-PULL GPIOB->AFR[0] &= ~GPIO_AFRL_AFRL6; // Clear pin 6 for alternate function GPIOB->AFR[0] |= 0x2 << (4*6); // set PB pin 6 as AF2 (TIM4_CH1) //PB10 Pluse Generating Pin GPIOB->MODER &= ~(0x03 << (2*10)); // Clear bit 12 & 13 Alternate function mode GPIOB->MODER |= 0x02 << (2*10); // set as Alternate function mode GPIOB->OSPEEDR &= ~(0x03<< (2*10)); // 40 MHz speed GPIOB->OSPEEDR |= 0x03<< (2*10); // 40 MHz speed GPIOB->PUPDR &= ~(1<<10); // NO PULL-UP PULL-DOWN GPIOB->OTYPER &= ~(1<<10); // PUSH-PULL GPIOB->AFR[1] |= 0x1 << (4*2); // set PB pin 10 as AF1 (TIM2_CH3) //PB7 LED ON/OFF GPIOB->MODER |= GPIO_MODER_MODER7_0; // General purpose output mode GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR7; // Max High speed 50MHz } // CONFIGURE TIM2 FOR SENDING OUTPUT SIGNAL void TIM2_Trigger(void){ RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; // ENABLE TIM2 CLOCK TIM2->PSC = 159; // SET APPROPRAIT PRESCALER TO SLOW DOWN THE CLOCK TIM2->ARR = 0XFFFF; // SET MAX PULSE WIDTH OF 65536us FOR 16-BIT TIMER TIM2->CCMR2 |= TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_2; // 111: PWM mode 1 TIM2->CCMR2 |= TIM_CCMR2_OC3PE; // CH3 Output Preload Enable TIM2->CR1 |= TIM_CR1_ARPE; // Auto-reload Prelaod Enable TIM2->CCER |= TIM_CCER_CC3E; // Enable Output for CH3 TIM2->EGR |= TIM_EGR_UG; // Force Update TIM2->SR &= ~TIM_SR_UIF; // Clear the Update Flag TIM2->DIER |= TIM_DIER_UIE; // Enable Interrupt on Update TIM2->CR1 &= ~TIM_CR1_DIR; // Set upcounting counter direction TIM2->CCR3 &= ~(TIM_CCR3_CCR3); // Clear CCR3 (Channel 3) TIM2->CCR3 |= 0x1; // Load the register TIM2->CR1 |= TIM_CR1_CEN; // Enable the counter } // CONFIGURE TIM4 FOR RECEIVING INPUT SIGNAL void TIM4_Init(void){ RCC->APB1ENR |= RCC_APB1ENR_TIM4EN; // ENABLE TIM4 CLOCK TIM4->PSC = 15; // SET APPROPRAIT PRESCALER TO SLOW DOWN THE CLOCK TIM4->ARR = 0xFFFF; // SET MAX PULSE WIDTH OF 65536us FOR 16-BIT TIMER TIM4->CCMR1 &= ~TIM_CCMR1_CC1S; // CLEAR CAPTURE/COMPARE REGISTER TIM4->CCMR1 |= 0X1; // SELECT CH1 INPUTE CAPTURE TIM4->CCMR1 &= ~TIM_CCMR1_IC1F; // DISABLE DIGITAL FILTERING TIM4->CCER |= (1<<1 | 1<<3); // SELECT BOTH RISING AND FALLING EDGE DETECTION CC1P & CC1NP TIM4->CCMR1 &= ~(TIM_CCMR1_IC1PSC); // INPUT PRESCALER 0 TO CAPTURE EACH VALID EDGE TIM4->DIER |= TIM_DIER_UIE; // UPDATE INTERRUPT ENABLE TIM4->CCER |= TIM_CCER_CC1E; // ENABLE COUNTER CAPTURE TIM4->DIER |= TIM_DIER_CC1IE; // ENABLE CH1 CAPTURE/COMPARE INTERRUPT TIM4->CR1 |= TIM_CR1_CEN; // Enable the counter NVIC_SetPriority(TIM4_IRQn, 1); // SET PRIORITY TO 1 NVIC_EnableIRQ(TIM4_IRQn); //ENABLE TIM4 INTERRUPT IN NVIC } void TIM4_Echo_Read(void){ if ((TIM4->SR & TIM_SR_UIF) != 0){ // Check the update event flag overflow++; // if UIF = 1, increment overflow counter TIM4->SR &= ~TIM_SR_UIF; // clear UIF } if ((TIM4->SR & TIM_SR_CC1IF) != 0){ // Check capture event flag newcounter = TIM4->CCR1; // read capture value, store as newcounter timespan = (newcounter - lastcounter)+(65536 * overflow); // calculate the total pulse width lastcounter = newcounter; // save the value of newcounter as lastcounter to be used for the next cycle overflow = 0; // clear overflow counter } } void LED (void){ float Distance; // actual distance in cm Distance = (timespan / 58.0); if (Distance <= 100.0){ GPIOB->BSRRL = (1<<7); } else { GPIOB->BSRRH = (1<<7); } }