[TUT] Modularizing C Code: Managing large projects

Go To Last Post
145 posts / 0 new

Pages

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Is agreeing with the positive comments on this thread

-Jd from the land of the Pacman

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi there guys

I have used this tutorial as a basis for splitting up my code for larger projects, however my compiler (GCC) is grumpy and coming up with the following warnings regarding the static function declarations:

Quote:
../SDCard.h:108: warning: 'SendCommand_SDC' declared 'static' but never defined

//In .h file
static BOOL SendCommand_SDC(uint8_t uchCommand, uint32_t uiArgument, uint8_t *puchResponse);
//In .c file
static BOOL SendCommand_SDC(uint8_t uchCommand, uint32_t uiArgument, uint8_t *puchResponse)
{
...code 
}

The function definition is definitely in the .c file with a declaration in the .h file.

If need be I can include the full code, however I get this with all of my static functions and do not think it is necessary.

Does anyone know what this warning is about? I have searched for a list of warnings, but have had little success. I obviously prefer to not have any warnings, even if they are not hazardous to the codes execution.

I would like to find out more about the compiler warnings, for future reference, as in a complete list of warnings and there meanings. As well as a work around for this problem.

Thank you in advance.

Regards,

Derek

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I suppose you are including the header file into more than one source file, but only define (implement) the static function in one of them.

If the function is static, this means that it is only visible inside the source file where it is defined, and thus it's function prototype needs not be in the header file at all. For me the primary reason for header files is tha they are "contracts" between proucers and consumers of eg functions. In your case the producer and the consumer is the same source file, so the contract can be in that file itself.

You can of-course place such a prototype in a header file, but you will need a separate such heaer file for each source file that declares static functions.

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What we do for any given module TLA is to have both a tla.h which is Johan's public "contract" and also a tlai.h (i=internal) which is a private header file for information that only needs to be used amongst the components of the module. However we wouldn't put a static function declaration into even the tlai.h. The thole point of "static" is that they are private to the one .c file where they are defined so if the function needs to be announced before it is used a simple declaration would be made within the early sections of the .c

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks - sounds good to me. The project now compiles and links with out any errors.

Thank you again.
D

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

spliting is very nice idea, as one said you'll especially benefit when using OO languages. The disadvantage is that with separate compilations compiler has much less oportunities to optimize program. For example (AFAIK) it doesn't inline code compiled in other module, it pushes more registers then needed or just leaves unused functions in generated header. Therefore after such spliting user usually should be more compilator-aware - for example ISR that call function should be in same module - function we'll be inlined, or at least only needed registers we'll go to the stack.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This is the makefile I'm using with CrossPack for OS X:

# Name: Makefile
# Author: 
# Copyright: 
# License: 

# This is a prototype Makefile. Modify it according to your needs.
# You should at least check the settings for
# DEVICE ....... The AVR device you compile for
# CLOCK ........ Target AVR clock rate in Hertz
# OBJECTS ...... The object files created from your source files. This list is
#                usually the same as the list of source files with suffix ".o".
# PROGRAMMER ... Options to avrdude which define the hardware you use for
#                uploading to the AVR and the interface where this hardware
#                is connected.
# FUSES ........ Parameters for avrdude to flash the fuses appropriately.

DEVICE     = atmega8
CLOCK      = 8000000
PROGRAMMER = -c stk500v2 -P /dev/tty.usbserial-A3000HDB
OBJECTS    = main.o
FUSES      = -U hfuse:w:0xd9:m -U lfuse:w:0x24:m
# ATMega8 fuse bits (fuse bits for other devices are different!):
# Example for 8 MHz internal oscillator
# Fuse high byte:
# 0xd9 = 1 1 0 1   1 0 0 1 <-- BOOTRST (boot reset vector at 0x0000)
#        ^ ^ ^ ^   ^ ^ ^------ BOOTSZ0
#        | | | |   | +-------- BOOTSZ1
#        | | | |   +---------- EESAVE (set to 0 to preserve EEPROM over chip erase)
#        | | | +-------------- CKOPT (clock option, depends on oscillator type)
#        | | +---------------- SPIEN (if set to 1, serial programming is disabled)
#        | +------------------ WDTON (if set to 0, watchdog is always on)
#        +-------------------- RSTDISBL (if set to 0, RESET pin is disabled)
# Fuse low byte:
# 0x24 = 0 0 1 0   0 1 0 0
#        ^ ^ \ /   \--+--/
#        | |  |       +------- CKSEL 3..0 (8M internal RC)
#        | |  +--------------- SUT 1..0 (slowly rising power)
#        | +------------------ BODEN (if 0, brown-out detector is enabled)
#        +-------------------- BODLEVEL (if 0: 4V, if 1: 2.7V)

# Example for 12 MHz external crystal:
# Fuse high byte:
# 0xc9 = 1 1 0 0   1 0 0 1 <-- BOOTRST (boot reset vector at 0x0000)
#        ^ ^ ^ ^   ^ ^ ^------ BOOTSZ0
#        | | | |   | +-------- BOOTSZ1
#        | | | |   +---------- EESAVE (set to 0 to preserve EEPROM over chip erase)
#        | | | +-------------- CKOPT (clock option, depends on oscillator type)
#        | | +---------------- SPIEN (if set to 1, serial programming is disabled)
#        | +------------------ WDTON (if set to 0, watchdog is always on)
#        +-------------------- RSTDISBL (if set to 0, RESET pin is disabled)
# Fuse low byte:
# 0x9f = 1 0 0 1   1 1 1 1
#        ^ ^ \ /   \--+--/
#        | |  |       +------- CKSEL 3..0 (external >8M crystal)
#        | |  +--------------- SUT 1..0 (crystal osc, BOD enabled)
#        | +------------------ BODEN (if 0, brown-out detector is enabled)
#        +-------------------- BODLEVEL (if 0: 4V, if 1: 2.7V)


# Tune the lines below only if you know what you are doing:

AVRDUDE = avrdude $(PROGRAMMER) -p $(DEVICE)
COMPILE = avr-gcc -Wall -Os -DF_CPU=$(CLOCK) -mmcu=$(DEVICE)

# symbolic targets:
all:	main.hex

.c.o:
	$(COMPILE) -c $< -o $@

.S.o:
	$(COMPILE) -x assembler-with-cpp -c $< -o $@
# "-x assembler-with-cpp" should not be necessary since this is the default
# file type for the .S (with capital S) extension. However, upper case
# characters are not always preserved on Windows. To ensure WinAVR
# compatibility define the file type manually.

.c.s:
	$(COMPILE) -S $< -o $@

flash:	all
	$(AVRDUDE) -U flash:w:main.hex:i

fuse:
	$(AVRDUDE) $(FUSES)

# Xcode uses the Makefile targets "", "clean" and "install"
install: flash fuse

# if you use a bootloader, change the command below appropriately:
load: all
	bootloadHID main.hex

clean:
	rm -f main.hex main.elf $(OBJECTS)

# file targets:
main.elf: $(OBJECTS)
	$(COMPILE) -o main.elf $(OBJECTS)

main.hex: main.elf
	rm -f main.hex
	avr-objcopy -j .text -j .data -O ihex main.elf main.hex
# If you have an EEPROM section, you must also create a hex file for the
# EEPROM and add it to the "flash" target.

# Targets for code debugging and analysis:
disasm:	main.elf
	avr-objdump -d main.elf

cpp:
	$(COMPILE) -E main.c

How can I edit this to allow adding additional .c files? Right now, I have to do #include "uart.c" to get it to work; which simply embeds said code in main.c rather than having the compiler link it in.

Tried to see if the makefile could first make uart.o from uart.c and then link uart.o and main.o to yield main.hex; not making much progress in this as aspect though.

Thanks in advance for your advice :)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The clue seems to be here

Quote:

# OBJECTS ...... The object files created from your source files. This list is
#                usually the same as the list of source files with suffix ".o".


It's late, so I wont test it but you could try to add the names of other object to be built to this variable. Eg if your project consists of main.c and uart.c then

OBJECTS    = main.o uart.o

You will of-course also have to edit up a uart.h with the things (eg function prototypes, extern declarations of "shared" variables etc) that needs to be seen from both main.c and uart.c and #include that file in both main.c and uart.c .

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

JohanEkdahl wrote:
...

You will of-course also have to edit up a uart.h with the things (eg function prototypes, extern declarations of "shared" variables etc) that needs to be seen from both main.c and uart.c and #include that file in both main.c and uart.c .

Thanks Johan! I did try having uart.o in the OBJECT definition but I was getting this strange error:

expected '=', ',', ';', 'asm' or '__attribute__' before

The reason is that the 'uart.h' header needed the avr/io.h header to be included. For the ref of others, here are my two files as they stand:

uart.h

#ifndef USART_H
#define USART_H 

#include 
#include 

uint8_t uart_putchar (char data);
uint8_t uart_getchar (void);
void uart_putstring(char *s);

#endif

uart.c

#include "uart.h"

uint8_t uart_putchar (char data)
{
	while ( !( UCSRA & (1<<UDRE)) ); // Wait for empty transmit buffer           
	UDR = data;  // Putting data into the buffer, forces transmission                               
	return 0;
}

uint8_t uart_getchar (void)
{
	while ( !(UCSRA & (1<<RXC)) );  // Wait for data to be received           
	return (UDR);        // Return Data                         
}

void uart_putstring(char *s)
{
	while(*s) uart_putchar(*s++);
	
} 

and the beginning of my main.c. It is possible that I could leave out some of them.

#include 
#include 
#include 
#include 
#include 
#include  
#include "uart.h"
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Personally, when there's a lot of common system headers included in each .c I'd put the #includes in a syshdr.h and then just #include "syshdr.h" in each .c to reduce the "noise". On the occasion that the interrupt header file changes from to I'd then just need to make the change in one place - not edit every .c where it is included.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
Personally, when there's a lot of common system headers included in each .c I'd put the #includes in a syshdr.h and then just #include "syshdr.h" in each .c to reduce the "noise".

You might want to rename it to syshdr.inc, perhaps, to stress the fact that it is *not* a *header* (i.e. "interface description of a *.c") as such.

JW

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

You might want to rename it to syshdr.inc, perhaps, to stress the fact that it is *not* a *header* (i.e. "interface description of a *.c") as such.

Perhaps. Perhaps not. The use of ".h" as the extension even for nested includes is quite wide-spread.

AFAICR this is the first time I see the notion of making the super-include-files have a filetype of ".inc". Is this a cultural thing, where eg U*ix people do it, and others (eg MS) don't?

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In our coding standard it would most definitely be a .h, we do have the concept of ".i" to but that's for the very specific purpose of a block of externally generated const data that MUST only be #include'd in one .c file - the .i rather than .h makes this clear to the casual reader.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

wek wrote:
clawson wrote:
Personally, when there's a lot of common system headers included in each .c I'd put the #includes in a syshdr.h and then just #include "syshdr.h" in each .c to reduce the "noise".

You might want to rename it to syshdr.inc, perhaps, to stress the fact that it is *not* a *header* (i.e. "interface description of a *.c") as such.

JW

During my C/C++ classes at Uni and even most books I have always seen the use of ".h" and never the use of ".inc".

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

During my C/C++ classes at Uni and even most books I have always seen the use of ".h" and never the use of ".inc".

Doesn't matter what extension you use on a file #include'd in your code -- the preprocessor will process it just the same. That said, personally I think it extremely poor form to use anything other than the .h unless it's something very unusual, like a giant array of PCM audio data which needs to be embedded. Even then, I'd make the embedding of resource files a compile step, and not part of the actual code.

Each to his own, but don't be surprised if you get fired for naming all your C header files "Includes.jpg".

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

JohanEkdahl wrote:
Quote:

You might want to rename it to syshdr.inc, perhaps, to stress the fact that it is *not* a *header* (i.e. "interface description of a *.c") as such.

Perhaps. Perhaps not. The use of ".h" as the extension even for nested includes is quite wide-spread.

AFAICR this is the first time I see the notion of making the super-include-files have a filetype of ".inc". Is this a cultural thing, where eg U*ix people do it, and others (eg MS) don't?

It most definitely isn't a *nix thing. A quick journey through the system headers in a linux install will reveal that many are simply includes of other headers, usually architecture specific. I too have never seen the suggestion to use an extension other than .h for this purpose. Just because a file is used to consolidate common includes, does not make it "not a header".

.inc from my experience is usually reserved for includes in assembly projects.

But as Dean stated, the C compiler does not care what the extension is. #include is simply a text insertion.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Johann wrote:
The use of ".h" as the extension even for nested includes is quite wide-spread.

A poor practice, however widespread, is still a poor practice. Replace "sub-optimal" for "poor" in the above if you find it offensive.
glitch wrote:
.inc from my experience is usually reserved for includes in assembly projects.

The choice of extension is arbitrary, but I agree that defacto standards have to be respected. As you might have noticed, I don't have that much of an experience with projects invoving C (I try to avoid them, in fact, being a dedicated C-hater ;-) ). Any other extension would do - fancy .hh?

glitch wrote:
But as Dean stated, the C compiler does not care what the extension is. #include is simply a text insertion.
And that's the problem. The C/*nix folks are not known for being meticulous to the detail, are they. And, if they have chance to take a shortcut, they take it. So it's upon the poor programmer to maintain a discipline, so that the gun won't fire in the direction of the toes.

While it's very easy to implement literal inclusion, it's hard to do it in the proper way. So there's no enforcement of binding the header to the actual source, nor of rejecting irrelevant information from it. There is no syntactical distinction between "include your own header for making sure it matches the body of module", "include a header of the module to be able to link to its functions and variables", and "include an arbitrary text - possibly a collection of headers".

And this is why it is hard to explain to the novices the concept of headers. This thread is in a tutorial section after all, isn't it.

Jan Waclawek

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Jan,

You may want to take a look at in AVR-LibC ;-)

Even \Program Files\Microsoft Visual Studio\VC98\include\windows.h is little more than a bunch of #include's

And, as has already been stated, the technique is used a LOT in the Linux kernel tree.

It may not be "good practice" but it's what C programmers have actually been doing in large projects since time immemorial. In fact that includes me in large in-house projects (one with 57,000 .c files) - some are "meta headers" that just group the inclusion of a bunch of other headers.

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
You may want to take a look at in AVR-LibC ;-)
Well, that might be a collection, but of what are not headers either. I would assign them a .def :-) OK, this is stretching the things a bit further than you traditionalists would be willing to accept... :-)

clawson wrote:
Even \Program Files\Microsoft Visual Studio\VC98\include\windows.h is little more than a bunch of #include's
Oh, are you trying to tell us that M$ sets the benchmark in good programming practices? :-P

Jan

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Oh, are you trying to tell us that M$ sets the benchmark in good programming practices?

Well, yes, actually I do believe that. While people decry Microsoft their own source code is very good quality. The reason people call Windows "buggy" is that it does not isolate driver code enough and when Tom, Dick or Harry get a copy of the DDK and write their own webcam or scanner driver it has the ability to crash the kernel (in fact the same is true of anything that is insmod/modprobe'd into the Linux kernel too). The end user's experience is that "Windows has crashed" but more often than not it's 3rd party driver code that has crashed.

In fact a lot of the coding standard we adhere too is based on the writings of Steve Maguire in Writing Solid Code:

http://www.amazon.com/Writing-So...

He outlines the techniques that Microsoft use internally to avoid the more obvious code faults. If you like it's a bit like a cut-down, less stringent MISRA rule book. That is a very very good book and I highly recommend it to anyone programming in C. While I've had office "purges" over the years and had to discard a lot of books to make room, this remains one of the core books (like K&R, the Borland C reference and Charles Petzold on programming Windows) that I'll retain for all time.

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have never seen anyone who uses a .inc extension for included files in C. In fact, the only variation I have ever really seen other than .h is to use no extension at all (an older practice that has gone out of favor). So I'm not sure how you can say in one breath that you should follow the de facto standard, but in another say to throw the de facto standard out the window only to advocate something else that virtually no one else does.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Koshchi wrote:
So I'm not sure how you can say in one breath that you should follow the de facto standard, but in another say to throw the de facto standard out the window only to advocate something else that virtually no one else does.

Well, using an already "assigned" extension for a different purpose would cause confusion; while using an already "unassigned" extension for the non-interface headers would cause at worst a mild attention.

But of course there's no point to push it beyond reason. There are many controversial items in various coding standards to add one more. The thinking programmer develops his own little variations anyway.

I rest the case.

JW

PS. I googled for "file name extension .i" and learned that it is likely to be an INTERCALC file... :-P

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

wek wrote:
There are many controversial items in various coding standards to add one more.
This is not a controversial item, you are just trying to make it into one, pulling arguments out of thin air.

You seriously underestimate the value of established conventions and traditions. The existence of a convention is a value as such, even if the convention is (in your imagination) not optimal. You forgot that there isn't black and white only, but that engineering is a string of compromises and most results are grey. You forgot that it is usually a huge waste of time and money to do things perfect (the 80/20 rule of thumb). Engineering is not about perfection.

Stealing Proteus doesn't make you an engineer.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ArnoldB wrote:
You forgot that there isn't black and white only, but that engineering is a string of compromises and most results are grey. You forgot that it is usually a huge waste of time and money to do things perfect (the 80/20 rule of thumb). Engineering is not about perfection.

[wek, standing ashamed in the corner of the room, nodding quietly while concentrating on his yet unshot toes, letting out a sob now and then...]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Well, using an already "assigned" extension for a different purpose would cause confusion;

How is it a different purpose? #include is used to include other files, and that is what is being done. There is nothing in the designation ".h" that implies what the content of the file is other than that it is intended to be included by other files.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There is a simple cure for case problems: Don't Capitalize!

main(), printf(), int, static, avr/interrupt.h, _asm_, _delay_us... See the pattern? Just say no. And in case you feel like a JavaRebel, ok, but at least be consistent.

The exceptions are things already mentioned, constants, macros, classes, header top ifdef's. F_CPU, DEBUG, DDRA, //FIXME, M_PI, RAND_MAX...

A few outstanding conventions exist, like Makefile with a capital M so it stands out from code and README(.txt) in all caps because that's the first thing that should stand out at a glance.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am following this tutorial in order to manage my code...but I did not find the make file? where should I find it??

Thanks,

Ashish

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

but I did not find the make file?

There isn't one. But what's the problem? You take the Mfile template. Edit the names of all the C (.c) source files onto the SRC= line, the name of Asm (.S) source files into the ASRC= line and the name of all the C++ (.C) files onto the CPPSRC= line and that's it. Job done.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have numbers of global variables in my projects. Is it possible to put all the global variables in one .h file and include this file in all the .c file ?

I am defining the global variables using extern word.

If I am doing this way then it is giving me error
"

(.text.avr-libc.fplib+0x0): multiple definition of `__floatunsisf'
"

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I do this but not how you suggested. As this article hopefully explained there should never be any definitions in a .h file, only declarations. So create a new .c file called something like:
globals.c

int n;
char c;
long l;

and add it to the list of source files to be compiled. Then also create:
globals.h

extern int n;
extern char c;
extern long l;

and #include this in any file that needs access to 'n', 'c' or 'l'

In fact I often take this one stage further and group all the globals in a struct. So I have in the .h file:

typedef struct
{ 
	volatile uint8_t	*recv_ptr;
	volatile uint32_t	spi_byte_count;
	volatile uint16_t	df_page;
	volatile uint16_t	buf_ptr;
	volatile uint16_t	samples_per_motor;
	volatile uint16_t	uart_bit_len;
	volatile uint16_t	start_len;
	volatile uint16_t 	sample1;
	volatile uint16_t 	sample2;
	volatile uint16_t 	motor_count;
	volatile uint8_t	last_flash_byte;
	volatile uint8_t	t1_timed_out; //false or 0x37 ??
	volatile uint8_t	packet_number;
	volatile uint8_t	nak_count;
	volatile uint8_t	use_of_timer;
	volatile uint8_t	sample_count;
	volatile uint8_t	sample_limit;
	volatile uint8_t	sample_shift;
	volatile uint8_t	orig_OSCCAL;
	volatile uint16_t	tim0_count;
	volatile uint8_t	ignore_button;
	volatile uint8_t  	adpcm; // 0 or 1
	volatile uint8_t  	debug; // 0 and !0
	volatile uint8_t	play_one;
	volatile uint8_t	play_two;
} global;

extern global gl;

then in the global.c I have:

#include "global.h"

global gl;

and I access the globals as:

gl.packet_number = 30;
if (gl.ignore_button) {
   // something
}

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I have numbers of global variables in my projects. Is it possible to put all the global variables in one .h file and include this file in all the .c file ?

No, this will not work. As I'm sure has been explained earlier in this thread you will get duplicate definitions of those variables, and the linker generating errors.

What you should do has also most likely been described earlier in this thread:
- Place definitions of your global variables in one .c source file.
- Add that .c source file to the project so that it gets compiled.
- Put extern declarations of the ame variables in a .h header file.
- Include that .h header file into all .c source files that needs to see the variables.

Example:

// globals.c
#include "globals.h"
int aGlobalInt;
// globals.h
extern int aGlobalInt;
// userOfGlobals.c
#include "globals.h"
.
.
.
   aGlobalInt = 42;
.
.
.

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

By the way I just looked back at your post and the __floatunsisf error is actually because you are using FP functions without linking with libm.a, nothing to do with your own variables (in the case of that particular error message)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I follow the same.. but still I am getting the same error..

(.text.avr-libc.fplib+0x0): multiple definition of `__floatunsisf'

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

By the way I just looked back at your post and the __floatunsisf error is actually because you are using FP functions without linking with libm.a, nothing to do with your own variables (in the case of that particular error message)

Could you please explain how to eliminate this error?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

So add a "-lm" to your LDFLAGS or, if using AVR Studio go into project config and under "Libraries" copy libm.a from the left to the right pane.

I followed this solution given by clawson sir in some other thread and now it is not giving me that error.

Thank you so much....

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I have numbers of global variables in my projects. Is it possible to put all the global variables in one .h file and include this file in all the .c file ?

Yes, you can have all your "extern" (publically visible) globals listed in one header file. However, you will still need to place them in one of your .c files as well without the "extern" modifier, otherwise you will receive undefined reference errors.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am trying to write a header file and put up everything related to TWI in it, leaving only the main processing to the main.c and functions being called as and when required. I want the TWI ISRs to be contained by this header. The program compiles fine, but somehow the ISR just isn't executing. Could you please help me out with this?

And, should I be using a .c file instead of the .h file.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

An ISR is effectively just a fancy regular function - and anything that results in actual executable code in the binary should be a .c file rather than a .h file. Try creating a TWI.c and TWI.h pair, with the ISRs in the C file.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

The program compiles fine, but somehow the ISR just isn't executing. Could you please advise me something on this?

The snide remark is that you are yet another one that has a problem on line 42 of your source code.

Seriously: We can't say much unless you post your code. It helps boost interest in helping you if you reduce the code to the smallest possible that still builds and executes and displays the problem.

Quote:
And, should I be using a .c file instead of the .h file.

The usual case is a .c file and a .h file. Go read the tutorial here on "Managing large projects".

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Go read the tutorial here on "Managing large projects".

Irony. I love it!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Blimey! Didn't notice we where already there. :roll:

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you for the quick response :) Got it working.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Dean,

You Did not mention where to define ISR routines when splitting a large project into different .c and .h files. Is it in the same file where main() function defined?

-Partha

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'd put it inside the module where it is most relevant, i.e. the module that sets up the ISR.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

One key thing is if the ISR() calls any functions then either make them static inline - in which case they could actually be located in a .h file - otherwise put them in the same .c file where the ISR() is located so the compiler has some chance of determining register usage and will not be forced to save/restore the entire context.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
I'd put it inside the module where it is most relevant, i.e. the module that sets up the ISR.
To be more specific, it is up to you where you put it, the compiler doesn't care.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hey Guys,
Quick question. With custom data types how does the extern tag work? For something like the following:

In the .c file:

typedef struct
{
	uint8_t one;
	uint8_t two;
	uint8_t three;
} MyStructure;

MyStructure myStructureArray [12];

How would you declare the .h file? I have tried different extern syntax and can't seem to get right.
I have tried the following:

.h file:

extern typedef struct MyStructure;
extern MyStructure myStructureArray [];

I get the following errors:

Following warning on the structure call:
warning: useless keyword or type name in empty declaration

Following error on the custom MyStructure call:
error: syntax error before "outputsArray"

Thanks in advance!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Try:

typedef struct 
{ 
   uint8_t one; 
   uint8_t two; 
   uint8_t three; 
} MyStructure; 

extern MyStructure myStructureArray [12];

You want the variable definition of that type to be extern, not the declaration of the type.

- Dean :twisted:

(EDIT: Fixed wrong definition/declaration terminology - always get it round the wrong way!)

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

Last Edited: Mon. Feb 21, 2011 - 09:48 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

To add to what Dean says. A typedef does not create any storage. A definition of the array of struct does. The only things you want to avoid in a header file are anything that leads to storage being allocated. So it's the variable definition that needs to be turned into a declaration only. You do this by adding 'extern'.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry if this was already asked.
Not explicitly said this tutorial seems to indicate that say "usart.h" does not need to include "usart.c" is that true?

Pages