This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Watch window error (stack variable)

Could you please have a look at the following source code:

#include <stm32f10x.h>                       /* STM32F103 definitions         */


class Test  {
public:
  static int i1;
  static int i2;
  static int i3;
  static int TestFunc( long l1, long l2);
  static void foo( long* pl);
  static long foo2();
};

void Test::foo( long* pl){
  pl[1]= pl[0];
}
long Test::foo2( ){
  return i1+i2+i3;
}

int Test::TestFunc( long l1, long l2)  {
  long al[8];
  if( l1 != foo2())
    return 1;
  al[0]= 1;
  al[1]= l2;
  foo( al);
  return 0;
}

Test T;
int Test::i1 = 1;
int Test::i2 = 0;
int Test::i3 = 0;

int main(void)  {
  T.TestFunc( 1, 2);
  while(1);
}

(sorry that it is a bit long - see the comments below. I used STM32F1xx with define STM32F10X_MD and selected chip STM32F103RB, because with this setting I get the simulator to run - unfortunately the simulator does not run with my STM32F4 projects (see other thread, I just generated)).

I compiled with optimization level -O1, is used uVision V4.70.0.0 (ArmCC V5.03.0.24).

When I put a breakpoint to the function "TestFunc", and then watch the variable "al" in either the window "Watch1" or "Call Stack - locals", then something very strange happens after the line "if (l1 != foo2())". The watch addresses then somehow re-organize, because arter this point the variable "l1" shows "<not in scope>" - which really is smart.

Just stupidly the address of "al" then switches back from 0x658 (which is correct, and identical to the stack pointer address at this point) to 0x638. Then of course "al" is not displayed any more correctly.

This strangely requires some very bizarre preconditions, this is why this test program has to be quite long:
- The function TestFunc has to have 2 variables (if I strip l2, this does NOT happen any more).
- In the function foo2 it is required to add 3 variables "i1+i2+i3" - if I instead try with "return i1;" or "return i1+i2;", again this does NOT happen any more.
- The instruction "if( l1 != foo2()) return; " of course is required, as this somehow produces the trouble (if I replace it by "long l4= foo2(); if( l1 != l4) return; " again this problem does NOT occur.

This really is very strange - I needed about 4 hours to strip a very large software to this smaller test program - at first I suspected some stack problem in my larger software (of course I must admit, that watching local variables in optimized code is a very challenging task, and Keil uVision is doing really very well, but such a behaviour is NOT very nice ...).

  • You agree that l1 is out-of-scope beyond the 'if'.

    Watching an out-of-scope variable is not meaningful, so you should not attempt to assign any meaning to whatever you may happen to see - other than that it is undefined!

  • I am not watching the "l1".

    I am watching the "al" array.

  • try this for me.

    #include "system_stm32f4xx.c" #include <stdio.h>
    #include "main.h"

    #define DATA_PORT GPIOC->ODR // PC6,PC7,PC8,PC9
    #define CMD_PORT GPIOB->ODR

    #define DATA 6
    #define DATA_CLR 0xFFFFFC3F

    #define LCD_E 0x100 // PB8
    #define LCD_RS 0x200 // PB9

    #define CMD 0
    #define TXT 1

    #define LINE1 0x80
    #define LINE2 0xC0
    #define ADC_CDR_ADDRESS ((uint32_t)0x40012308)
    __IO uint32_t ADC1ConvertedValue;
    __IO uint32_t ADC1ConvertedVoltage = 0;
    char adc_data[16];

    /* Private variables ---------------------------------------------------------*/
    GPIO_InitTypeDef GPIO_InitStructure;
    ADC_InitTypeDef ADC_InitStructure;
    ADC_InitTypeDef ADC_InitStructure;
    ADC_CommonInitTypeDef ADC_CommonInitStructure;
    DMA_InitTypeDef DMA_InitStructure;

    static __IO uint32_t TimingDelay;
    char harf[30];
    unsigned int i=0;
    float sayi2=3.1415926789654123;

    //--------------------------------------------------------------------------------//
    void WaitLCDBusy(void){ Delay(2);
    }

    //--------------------------------------------------------------------------------//
    void LCD_KONTROL(unsigned char veri,unsigned char type){ DATA_PORT &= DATA_CLR; //LCD_PORT &= 0xF0; DATA_PORT |= (veri<<DATA); //LCD_PORT |= (veri & 0x0F);

    if(type == CMD){ CMD_PORT &= ~(LCD_RS); } else { CMD_PORT |= LCD_RS; }

    CMD_PORT |= LCD_E; //LCD_E = 1; Delay(1); CMD_PORT &= ~(LCD_E); //LCD_E = 0;
    }

    //--------------------------------------------------------------------------------//
    void LCD_DATA(unsigned char data,unsigned char type){

    WaitLCDBusy();

    if(type == CMD){ CMD_PORT &= ~(LCD_RS); } else { CMD_PORT |= LCD_RS; }

    LCD_KONTROL(data>>4,type); LCD_KONTROL(data,type);
    }

    //--------------------------------------------------------------------------------//
    void LCD_STR(const char *text){ while(*text){ LCD_DATA(*text++,1); }
    }

    //--------------------------------------------------------------------------------//
    void LCD_LINE(char line){ switch(line){ case 0: case 1: LCD_DATA(LINE1,0); break; case 2: LCD_DATA(LINE2,0); break; }
    }

    void lcd_init()
    {

    CMD_PORT &= ~(LCD_E); //LCD_E = 0; CMD_PORT &= ~(LCD_RS); //LCD_RS = 0;

    Delay(30); //delay for LCD to initialise. LCD_KONTROL(0x30,0); //Required for initialisation Delay(5); //required delay LCD_KONTROL(0x30,0); //Required for initialisation Delay(1); //required delay LCD_DATA(0x02,0); //set to 4 bit interface, 1 line and 5*7 font LCD_DATA(0x28,0); //set to 4 bit interface, 2 line and 5*10 font LCD_DATA(0x0c,0); //set to 4 bit interface, 2 line and 5*7 font LCD_DATA(0x01,0); //clear display LCD_DATA(0x06,0); //move cursor right after write
    }

    void STM32F4Discovery_init(void)
    {

    /* Enable peripheral clocks */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_DMA2 |RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2 |RCC_APB2Periph_ADC3, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9| GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOC, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOB, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; GPIO_Init(GPIOC, &GPIO_InitStructure);

    DMA_InitStructure.DMA_Channel = DMA_Channel_0; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC_CDR_ADDRESS; DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC1ConvertedValue; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; DMA_InitStructure.DMA_BufferSize = 3; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_Init(DMA2_Stream0, &DMA_InitStructure);

    /* DMA2_Stream0 enable */ DMA_Cmd(DMA2_Stream0, ENABLE);

    }

    int main(void)
    {

    if (SysTick_Config(SystemCoreClock / 1000)) { while (1); }

    STM32F4Discovery_init(); lcd_init(); LCD_DATA(0x01,0); LCD_LINE(1); LCD_STR((const char*)"Hello"); LCD_LINE(2); LCD_STR((const char*)"MARCH 2013"); Delay(2000);

    while (1) {

    ADC_SoftwareStartConv(ADC1); ADC1ConvertedValue=ADC_GetConversionValue(ADC1); ADC1ConvertedVoltage = ADC1ConvertedValue *3300/0xFFF;

    LCD_LINE(2); sprintf(adc_data," ADC= %4d",ADC1ConvertedVoltage); LCD_STR((const char*)adc_data);

    }
    }

  • "try this for me."

    Why would anyone care about some random code posted in a thread about problems with the watch window in the debugger?

  • Hi Jambuk,
    very sorry - but this is too much for me. If you want support on such problems, it is necessary that you strip your code to the crucial part - it has to be as small as possible. So that you just recognize the problem most easily.