Keil Logo

Debugger hangs on Float instruction

Next Thread | Thread List | Previous Thread Start a Thread | Settings

Details Message
Author
Diya Eldin
Posted
8-Aug-2017 06:32 GMT
Toolset
ARM
New! Debugger hangs on Float instruction

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?

Author
Westonsupermare Pier
Posted
8-Aug-2017 16:31 GMT
Toolset
ARM
New! RE: Debugger hangs on Float instruction

Is it stuck in the Hard Fault Handler?
If you hit stop where is it stuck?

Author
Andrew Neil
Posted
8-Aug-2017 17:02 GMT
Toolset
ARM
New! RE: Is there's any special configuration for float ?

STM32L1 has no FP hardware, so you'd need to be using software emulation.

Are you?

Author
Westonsupermare Pier
Posted
8-Aug-2017 18:12 GMT
Toolset
ARM
New! RE: Is there's any special configuration for float ?

If the target cpu is correctly chosen it should be using software libraries, and not permitting the FPU to be selected. If FPU code existed it would likely fault much earlier than this.

Check other things like the firmware and drivers for your debug pod, not sure that is the issue, but you should be able to stop the debugger and see exactly where it is stuck, and not require a reset or power cycle.

Author
Diya Eldin
Posted
8-Aug-2017 18:52 GMT
Toolset
ARM
New! RE: Is there's any special configuration for float ?

Do I have to define it or mention the float library at the start of the code?
As of now I'm only including:
#include <stdio.h>
#include "stm32l1xx.h"

If yes, any idea what is the float software library for STM32Lxx?

Author
Diya Eldin
Posted
8-Aug-2017 18:55 GMT
Toolset
ARM
New! RE: Is there's any special configuration for float ?

@Andrew Neil
Would you be kind and explain or share a useful link on how to use software emulation, I would be thankful.

Author
Andrew Neil
Posted
8-Aug-2017 19:14 GMT
Toolset
ARM
New! RE: how to use software emulation?

As @Westonsupermare Pier said, If the target cpu is correctly chosen it should be OK.

Please answer the questions he asked.

What, exactly, do you mean by, "debugger hangs" ?

Where, exactly, does it "hang" ?

Author
Diya Eldin
Posted
9-Aug-2017 06:18 GMT
Toolset
ARM
New! RE: how to use software emulation?

What I mean by "debugger hangs" is that when I run code on the debugger, and move step by step, once I try to steps over the line Distance = (timespan /58.0); everything stops, the icons that are supposed to run the code lines one by one can no longer be presses , the only option I have is either to stop (by pressing the red icon) or reset. And if I don't press anything, it can stay as it is forever, only the seconds counter will keep counting how long did the instruction execution took.
and the only way to run the code again is by shutting off the debugger and open it again. because I tried running the code after stopping and reseting, but it doesn't run the debugger on the main.c anymore idk why. So I just turn off the debugger and run it again trying to figure out why this is happening.
I hope my explanation is clear.

Author
Westonsupermare Pier
Posted
9-Aug-2017 13:19 GMT
Toolset
ARM
New! RE: how to use software emulation?

>> the only option I have is either to stop (by pressing the red icon) or reset.

And the question asked was WHERE does it STOP. The details and specifics are important to understand what has happened.

Make sure the stack is sufficiently large, and that the flash has the correct number of wait states for the speed your are running.

Author
Diya Eldin
Posted
9-Aug-2017 19:38 GMT
Toolset
ARM
New! RE: how to use software emulation?

I checked the Start Up file and I found the stack size as following:

 Stack_Size      EQU     0x00000400

The STM32L1 has 256K RAM. Note that I'm using Timer interrupts, float, and delay in this code. I don't know how to calculate the recommended stack size.
what are the criteria of doing so, and what would be the suitable size for this code.
I hope I'm not asking for too much..

Author
Westonsupermare Pier
Posted
9-Aug-2017 19:47 GMT
Toolset
ARM
New! I hope I'm not asking for too much..

You not answering the questions is the problem I have.

The code looks reasonable enough, pretty sure I could paste it into a project and have it work out of the box. I lack sufficient and specific detail in your case to know where/why it stopped or crashed.

Make an effective presentation of what's happening, less narrative, more illustration.

Author
Diya Eldin
Posted
9-Aug-2017 19:57 GMT
Toolset
ARM
New! RE: I hope I'm not asking for too much..

I mentioned where and how, but maybe I misunderstood the question.
here's a screenshot that should clear it.

http://imgur.com/a/3qDtE

Author
Westonsupermare Pier
Posted
10-Aug-2017 03:18 GMT
Toolset
ARM
New! RE: I hope I'm not asking for too much..

You were asked to STOP to the debugger, and see where it was then. This is NOT what is portrayed in the image.

You've said where the tracing finished, not where it STOP, or where it was actually stuck. It tries to do the division, and doesn't return, the task in debugging this is to understand where it actually goes and becomes stuck.

You could also go into the disassembly view an STEP INTO rather than STEP OVER.

Author
Gunnar Bohlen
Posted
10-Aug-2017 16:19 GMT
Toolset
ARM
New! RE: I hope I'm not asking for too much..

You screenshot shows that the stackpointer points to 0x20000658.
Start the program and stop at main() and look at the SP value.
If the difference is close to 0x400 you know the stack might be too small and the problem is a stack overflow. For a test set stacksize to 0x800 in the startup file.

Author
Diya Eldin
Posted
10-Aug-2017 22:53 GMT
Toolset
ARM
New! RE: I hope I'm not asking for too much..

@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.

Author
Diya Eldin
Posted
10-Aug-2017 22:54 GMT
Toolset
ARM
New! RE: I hope I'm not asking for too much..
#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);

        }
    }

Author
Diya Eldin
Posted
10-Aug-2017 22:36 GMT
Toolset
ARM
New! RE: I hope I'm not asking for too much..

@Westonsupermare Pier

I'm really trying to understand what you're asking me to do here. please consider me as a beginner and give me a clear troubleshooting steps, I would be thankful.
I appreciate your support

Author
Westonsupermare Pier
Posted
10-Aug-2017 23:03 GMT
Toolset
ARM
New! RE: I hope I'm not asking for too much..

After it "crashes" press the RED STOP icon and take a screen shot of the code/disassembly window so you can see where it is stuck.

Author
Diya Eldin
Posted
10-Aug-2017 23:08 GMT
Toolset
ARM
New! RE: I hope I'm not asking for too much..

Ok, here's the screenshot:

http://imgur.com/a/xXDSD

Author
Westonsupermare Pier
Posted
10-Aug-2017 23:05 GMT
Toolset
ARM
New! RE: I hope I'm not asking for too much..

You enable interrupts that you don't service, that's unlikely to end well.

Author
Diya Eldin
Posted
10-Aug-2017 23:19 GMT
Toolset
ARM
New! RE: I hope I'm not asking for too much..

Can you be more specific. I'm using Timer interrupt to detect signal rising and falling edges and read the counter values at both ends. At least that's what I think I'm doing.

Author
Westonsupermare Pier
Posted
10-Aug-2017 23:55 GMT
Toolset
ARM
New! RE: I hope I'm not asking for too much..

You can't just randomly enable interrupts without the TIMx_IRQHandler() code to service them. Code you don't show, so assuming it is missing.

Your code is stuck in the Default_Handler code because you don't deal with the interrupt with your own routine.

The TIM will work without the interrupt being enabled.

When you first published your code none of this detail was presented, it is important to make a complete presentation.

Author
Diya Eldin
Posted
11-Aug-2017 06:13 GMT
Toolset
ARM
New! RE: I hope I'm not asking for too much..

I thought I already enabled TIM4 interrupt via the following lines:

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

What I'm I missing here..

Author
Westonsupermare Pier
Posted
11-Aug-2017 18:23 GMT
Toolset
ARM
New! What I'm I missing here..
void TIM4_IRQHandler(void)
{
  // Handle and clear the interrupt you've caused.

  if (TIM4->SR & TIM_SR_UIF)
  {
    TIM4->SR = ~TIM_SR_UIF;

    // Perhaps read registers or do something related to why you wanted interrupt?
  }
}

I don't believe these concepts are entirely unique to ARM or STM32 parts.

Author
Diya Eldin
Posted
12-Aug-2017 07:24 GMT
Toolset
ARM
New! RE: What I'm I missing here..

I can't believe I missed that. I changed the function name from TIM4_IRQHandler to TIM4_Echo_Read without changing it on the NVIC_EnableIRQ() line.
just changed the function name and everything worked, well the debugger doesn't hang anymore, however I still don't get the Distance value, I guess (according to the guys in Stackoverflow) it's because STM32L1 doesn't have FPU, But the LED did turn on when an object closer that 1 meter is detected, even with the float declaration.

@Westonsupermare Pier thank you for your patience & knowledge, you sure have a lot of both.

Next Thread | Thread List | Previous Thread Start a Thread | Settings

  Arm logo
Important information

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies.

Change Settings

Privacy Policy Update

Arm’s Privacy Policy has been updated. By continuing to use our site, you consent to Arm’s Privacy Policy. Please review our Privacy Policy to learn more about our collection, use and transfers
of your data.