| Details |
Message |
|
Read-Only
Author Sebastien CARRIERE
Posted 17-Apr-2012 16:14 GMT
Toolset ARM
|
 Problem on debugger with extern variable
Sebastien CARRIERE
Hello everybody,
I have a problem with a global variable. This variable is declared as
extern.
It is reset to 0 automatically inside the Keil µVisionb 4
debugger when used in a function written in different C file.
I make deeper reference.
I declared variable in a header like this
#ifdef __VAR_G
#define __DEF
#else
#define __DEF extern
#endif
__DEF uint32_t SystemCoreClock;
__DEF uint32_t Init_OK;
I use this variable twice :
Firstly in a.c file
#define __VAR_G
#include "stm32f4xxiut.h"
void SystemInit()
{
Init_OK = Init_OK | HSE_FAIL;
SystemCoreClock=16000000;
}
Secondly in b.c file
#include "stm32f4xxiut.h"
void main()
{
int b=0;
if (Init_OK==1)
b=2;
}
My problem is the following.
In the keil debugger, with STM32F4XX, first, system init is executed.
The both variable are declared as global and a value is assigned to
them. Then, the core branch to main and the both variable are reset
to zero in spite of the extern keyword used inside the
definition.
Do you know why there is this strange behaviour.
Thank you.
|
|
|
Read-Only
Author erik malund
Posted 17-Apr-2012 16:19 GMT
Toolset ARM
|
 normal behaviour
erik malund
Then, the core branch to main and the both variable are reset
to zero in spite of the extern keyword used inside the
definition
ALL variables, except those in noinit (I)RAM segments will be set to
zero on the entry of main.
I do not see what "the extern keyword" has to do with it
Erik
|
|
|
Read-Only
Author S Steve
Posted 17-Apr-2012 20:12 GMT
Toolset ARM
|
 RE: normal behaviour
S Steve
ALL variables, except those in noinit (I)RAM segments will be
set to zero on the entry of main.
I think you meant to say that all variables, except those in
noinit, will be initialised just prior to the entry of main (and not
necessarily set to zero).
|
|
|
Read-Only
Author Sebastien CARRIERE
Posted 18-Apr-2012 07:57 GMT
Toolset ARM
|
 RE: normal behaviour
Sebastien CARRIERE
Ok, it is a normal behaviour.
I don't know that the entry in main has this kind of effect.
Then, how can I do to avoid this problem and locate variable in
noinit (I)RAM segments ?
Thanks.
|
|
|
Read-Only
Author Hans-Bernhard Broeker
Posted 18-Apr-2012 17:38 GMT
Toolset ARM
|
 RE: normal behaviour
Hans-Bernhard Broeker
It's not so much the behaviour of main() that should have you
surprised. That's perfectly ordinary, well-defined behaviour of
every C program.
The thing you should wonder about is that System_Init() is called
before main(). That's not something a C program usually
allows. So this function SystemInit() must be rather special.
The question you should have asked yourself earlier is: what
limitations are documented in your system manual about what
you can and cannot do in this function? In particular, are you sure
you're supposed to use ordinary C variables in there, as opposed to,
say, only set up some special purpose registert to configure clocks,
enable peripherals, etc.?
|
|
|
Read-Only
Author Sebastien CARRIERE
Posted 19-Apr-2012 07:28 GMT
Toolset ARM
|
 RE: normal behaviour
Sebastien CARRIERE
I found a solution by making these variables in noinit zone with
zero_init option in declaration.
This avoid resetting selected variable at the entry inside main
function.
Thanks a lot for your help and this amount of knownledge you bring
to me.
|
|
|
Read-Only
Author erik malund
Posted 19-Apr-2012 14:26 GMT
Toolset ARM
|
 clarification
erik malund
This avoid resetting selected variable at the entry inside main
function.
this is not done "inside main function" it is done by the "secret
sauce initializer code" that the linker insert before
main()
Erik
|
|
|
Read-Only
Author Per Westermark
Posted 19-Apr-2012 14:35 GMT
Toolset ARM
|
 RE: clarification
Per Westermark
Just note that the Cortex chips have a design where the processor
sets up the stack, allowing a C function to get activate directly on
reset with zero assembler instructions involved. And the core
performs the required background stuff to allow interrupt handlers to
be ordinary C functions - no interrupt keyword needed.
But if the reset code is written in C, that code must still be
written based on the knowledge that the processor hasn't been fully
configured yet and that C libraries etc can't be used.
The C standard doesn't really consider C functions called before
main() - it considers main() to be the entry function and specifies a
number of rules that must be fulfilled at entry to main().
|
|
|
Read-Only
Author Hans-Bernhard Broeker
Posted 19-Apr-2012 20:42 GMT
Toolset ARM
|
 RE: normal behaviour
Hans-Bernhard Broeker
I found a solution by making these variables in noinit zone
with zero_init option in declaration.
I contest your assessment of that being a "solution". It's
actually more of the same problematic behaviour piled upon what's
already there. But two wrongs don't make a right.
The real problem is that you're doing stuff in the wrong place.
SystemInit() is a special function that exists for a couple of very
specific purposes. Initializing ordinary C variables is not
one of those. You ignore such details at your own peril.
The solution is for you to stop fighting your tools and
just use them as they're meant to. Leave initialization of C
variables to the C compiler and linker or, if you really think you
have to do it manually, do it in main().
In other words, you created that problem yourself. All it woould
take to solve it is to stop creating it.
|
|
|
Read-Only
Author Sebastien CARRIERE
Posted 20-Apr-2012 07:25 GMT
Toolset ARM
|
 RE: normal behaviour
Sebastien CARRIERE
I constest your assesment.
System_Init() initializes clock.
These two variables are to save clock frequency and the second is a
kind of register to know what is working or not inside initialization
without checking every register.
It is not classical C variable for my program which them will be
declare and initialize inside main.
|
|
|
Read-Only
Author Tamir Michael
Posted 20-Apr-2012 10:34 GMT
Toolset ARM
|
 RE: normal behaviour
Tamir Michael
I found a solution by making these variables in noinit zone
with zero_init option in declaration.
This avoid resetting selected variable at the entry inside main
function.
This is absurd!
Here is reset handler of my LPC1788 bootloader:
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT SystemInit
IMPORT __main
IF :DEF:MBOOT
IMPORT sdram_init
ENDIF
LDR R0, =SystemInit
BLX R0
IF :DEF:MBOOT
; init SDRAM before scatter loading starts...
LDR R0, =sdram_init
BLX R0
ENDIF
LDR R0, =__main
BX R0
ENDP
SystemInit call call _BEFORE_ scatter loading (__main...)!
There is no justification for making that variable non-zero init.
I suggest to you that you actually listen to us, instead of going
into a tail spin...
|
|
|
Read-Only
Author Hans-Bernhard Broeker
Posted 20-Apr-2012 19:58 GMT
Toolset ARM
|
 RE: normal behaviour
Hans-Bernhard Broeker
System_Init() initializes clock.
Exactly. And that's all you're supposed to do in there.
Writing normal C variables is stricly outside the set of things
you're allowed to do in there.
These two variables are to save clock frequency
And why on earth would you need a variable to store this
in, although it is beyond all reasonable doubt a compile-time
constant?
and the second is a kind of register to know what is working or
not inside initialization without checking every register.
Except that it's not any kind of register. It's a C variable.
It is not classical C variable for my program which them will
be declare and initialize inside main.
Now you're being ridiculous. Well, either that, or you have not
the slightest idea what the words you're using actually mean.
Because, in contrast to what you say now, that's exactly what
those things are: plain ordinary C variables. Your own code treats
them every bit as if it were one: you set the variable to some value
in one place, and expect it to keep that value until modified by an
assignment later.
|
|
|
Read-Only
Author Andrew Neil
Posted 21-Apr-2012 20:33 GMT
Toolset ARM
|
 Is this all ST's doing...?
Andrew Neil
The following is straight from ST's system_stm32f0xx.c (my
emphasis added) - I imagine that the OP's STM32F4xx would be
similar:
/**
******************************************************************************
* @file system_stm32f0xx.c
* @author MCD Application Team
* @version V1.0.0
* @date 23-March-2012
* @brief CMSIS Cortex-M0 Device Peripheral Access Layer System Source File.
* This file contains the system clock configuration for STM32F0xx devices,
* and is customized for use with STM32F0-DISCOVERY Kit.
* The STM32F0xx is configured to run at 48 MHz, following the three
* configuration below:
* - PLL_SOURCE_HSI (default): HSI (~8MHz) used to clock the PLL, and
* the PLL is used as system clock source.
* - PLL_SOURCE_HSE : HSE (8MHz) used to clock the PLL, and
* the PLL is used as system clock source.
* - PLL_SOURCE_HSE_BYPASS : HSE bypassed with an external clock
* (8MHz, coming from ST-Link) used to clock
* the PLL, and the PLL is used as system
* clock source.
*
*
* 1. This file provides two functions and one global variable to be called from
* user application:
* - SystemInit(): Setups the system clock (System clock source, PLL Multiplier
* and Divider factors, AHB/APBx prescalers and Flash settings),
* depending on the configuration selected (see above).
* This function is called at startup just after reset and
* before branch to main program. This call is made inside
* the "startup_stm32f0xx.s" file.
*
* - SystemCoreClock variable: Contains the core clock (HCLK), it can be used
* by the user application to setup the SysTick
* timer or configure other parameters.
*
* - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must
* be called whenever the core clock is changed
* during program execution.
So they do seem to be suggesting that the user code
can just read this global?!
This will work provided you call
SystemCoreClockUpdate() before the user code first uses
the SystemCoreClock variable - but the documentation above certainly
doesn't make that clear!
|
|