SV: [Icc-avr] Are 'local' vars in main automatuc or in bss?
David Brown
david_brown at hotpop.com
Fri Oct 26 04:37:16 PDT 2007
Bengt Ragnemalm wrote:
> David, can you show us in an example how it should be done? I try to do just
> as you describe but I often step into problems with error like double
> defines and so on.
> I have tried using the typical #ifdef MAIN and so on but have failed making
> it work properly. I usually have a header file for every c file (that should
> be the very basics) and in that header file I put declarations on the
> functions. The header file is included in every other file that uses the
> functions. I think one reason for my problems may be that I usually in the
> "project.h" (there my main is) have a lot of constants and maybe some
> typedef that I want the other files be aware of so I include it in all other
> project files (not reused files like drivers). The compiler do not like that
> I put extern everywhere, as it is used even in my project.c. I do not want
> to explicity write in every global variable in the c-files (extern nn), I
> want to just include a .h file, I hope that is the normal procedure.
>
> You can expand my little example in any way you like. I tried to use
> self-descriptional names. There should I put the extern and there should I
> put the typedef customType?
>
> /Bengt
>
>
> To be placed somewhere:
> typedef customType...
> #define A_VALUE 1
>
>
> Project.h
> =========
> ??? what should be in here?
>
>
> Project.c
> =========
> static char projectFileGlobalVar;
> char globalVar1;
>
> customType globalCustomVar;
>
> void AFunctionInProject(void)
> {
> }
>
> void main(void)
> {
> char projectFunctionLocalVar;
>
> projectFunctionLocalVar = A_VALUE;
> projectFileGlobalVar = A_VALUE;
> globalVar1 = A_VALUE;
> globalVar2 = A_VALUE;
> globalCustomVar = A_VALUE;
> }
>
>
> Module.h
> ========
> ??? what should be in here?
>
>
> Module.c
> ========
> static char moduleFileGlobalVar;
> char globalVar2;
>
> void AFunction(void)
> {
> Char moduleFunctionLocalVar;
>
> moduleFunctionLocalVar = A_VALUE;
> moduleFileGlobalVar = A_VALUE;
> globalVar1 = A_VALUE;
> globalVar2 = A_VALUE;
> globalCustomVar = A_VALUE;
> }
>
First, a point about terminology - "global" data is data that has global
linkage, and is thus visible throughout the program (using an "extern"
declaration). There is no such thing as a "file-level global" - if it
is declared "static", it is accessible throughout the module, but it is
not global.
Let's do a little example with two modules named "time" and "alarm", and
a main program - giving semi-realistic names might make things clearer
to some people.
First, we have a common include file:
//-------------------
// base.h
#ifndef base_h__ // This stops the file being processed
#define base_h__ // more than once
// Some <stdint.h> types - I don't know if iccavr has <stdint.h> yet
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef signed short int16_t;
typedef unsigned short uint16_t;
typedef uint8_t bool;
#define true 1
#define false 0
...
#endif // End #ifndef base_h__
//-----------------------
Then we have the module "time":
//-----------------------
// time.h
#ifndef time_h__
#define time_h__
#include "base.h" // Almost all files will #include this
typedef int16_t delay_t; // Custom type for future-proofing
extern void delay(delay_t x);
extern void initTime(void);
#endif
//-----------------------
//-----------------------
// time.c
#include "base.h" // Technically unnecessary, but it's best to be //
explicit
#include "time.h"
static volatile delay_t ticker; // File-local variable
static delay_t atomicTicker(void) { // File-local function
delay_t a, b;
a = ticker;
while (true) {
b = ticker;
if (a == b) return a;
a = b;
};
}
#pragma interrupt_handler timer1tick:iv_TIMER1_COMPA
static void timer1tick(void) {
ticker++;
}
void delay(delay_t x) { // Global function
// Note that this algorithm only works if delay_t is a signed type!
delay_t start = atomicTicker();
while ((atomicTicker() - start) < x) ;
}
void initTime(void) {
...
}
//-----------------------
// alarm.h
#ifndef alarm_h__
#define alarm_h__
#include "base.h" // Almost all files will #include this
#include "time.h" // Since we'll be using a time.h type in the //
header file
extern delay_t onTime; // Global variables
extern delay_t offTime;
extern void alarm(uint8_t repeats);
#endif
//-----------------------
//-----------------------
// alarm.c
#include "base.h"
#include "alarm.h"
#include "time.h" // Redundant, but best to be explicit
// Note that header file order does not matter!
delay_t onTime = 10; // Explicit initialisation
delay_t offTime; // Defaults to 0
static void setAlarm(bool on); // Forward declarations of file-local
void alarm(uint8_t repeats) {
while (repeats--) {
alarmOn();
delay(onTime);
alarmOff();
delay(offTime);
}
}
static void setAlarm(bool on) {
static bool alarmIsOn = false; // Function-local static
if (on && !alarmIsOn) {
// Turn on
alarmIsOn = true;
} else if (!on && alarmIsOn) {
// Turn off
alarmIsOn = false;
};
}
//-----------------------
//-----------------------
// main.c
#include "base.h"
#include "time.h"
#include "alarm.h" // Include most other modules in main.c
static void runMain(void) {
uint8_t alarmCount;
for (alarmCount = 1; alarmCount < 10; alarmCount++) {
onTime = alarmCount * 10;
offTime = alarmCount * 5;
alarm(5);
}
}
// main() is implicitly "extern"
void main(void) {
initTime(); // Initialise other modules
runMain();
}
//-----------------------
None of this is tested, so there might be typos, but it should make it
clear that every variable and function is either declared "static" in
its module, or it has a corresponding "extern" in its header file. The
only C file without a header is main.c (or a similar file containing
main() ), since it does not export any data or functions.
mvh.,
David
More information about the Icc-avr
mailing list