Hallo Ich habe ein grösseres Projekt, welches mehrere - von verschiedenen Leuten erstellte - Hardwarelibraries verwendet. Mir fiel nun auf, dass in jeder dieser Libs typedefs verwendet werden (entweder wurden sie direkt implementiert oder als h-File eingebunden). Ich dachte mir, es sei sinnvoll, alle diese typedefs in einem einzigen File zusammen zu nehmen. Das habe ich auch gemacht und das File LibDefines.h genannt. Es ist so, dass ich ein Hauptprogramm habe (nennen wir es main.c) und darin binde ich meine Hauptlibrary (lib.h) ein. Und in lib.h binde ich dann wiederum die oben erwähnten Hardware-Libraries (a.h/b.h/c.h) ein. Also habe ich mein LibDefines.h einfach zuoberst in meiner Hauptlibrary lib.h eingebunden, sodass dem Compiler bevor er a.h/b.h/c.h aufruft, die typedefs schon bekannt sind. Leider funktioniert das nicht, der Compiler (msp-gcc) zeigt solche Fehlermeldungen: In file included from ../../Library/ff.c:76: ../../Library/ff.h:429: error: expected specifier-qualifier-list before 'BYTE' ../../Library/ff.h:466: error: expected specifier-qualifier-list before 'WORD' Etc etc. Ich interpretiere das so, dass die typedefs dem Compiler nicht bekannt sind. Ich habe dann LibDefines.h direkt in a.h/b.h/c.h eingebunden (wobei LibDefines.h einen Include-Guard hat). Dann funktioniert die Software fehlerfrei. Ich verstehe jedoch nicht, warum es dann im ersten Fall nicht funktioniert. Ich bedanke mich im voraus für Eure Hilfe!
Lief Erickson schrieb: > Ich verstehe jedoch nicht, warum es dann im ersten Fall nicht > funktioniert. Ohne ein bischen nachvollziehbaren Code wird dir da auch hier keiner helfen können. Aber ein Tip: Wenn ich mir nicht sicher bin, ob ein Header File überhaupt eingebunden wird, dann mach ich ganz gerne mal folgenden Test: Ich provoziere im Header File einen Fehler. Einfach am Anfang irgendeinen Text "hsdf8uzcinerwb" einfügen. Die Erwartungshaltung ist: Wenn dieses Header File eingebunden wird (egal über welche dubiosen Wege), dann muss ich den von mir provozierten Fehler beim Compilieren sehen. Kommt KEIN Fehler vom Compiler, dann kann ich sicher sein, dass dieses Header File nicht eingebunden wurde und mache mich auf die Suche, warum nicht. Das können dann zb irgendwelche #define / #ifdef Kombinationen sein, die diesen #include auslassen. Das können Namenskonflikte bei Include-Guards sein. Das kann alles mögliche sein. Dieser 'Fehler provizier' Test ist meistens ziemlich wirkungsvoll, vor allen Dingen dann, wenn man dann anfängt den 'Fehler' zu verschieben um nachzuvollziehen, welcher Weg durch einen #ifdef Dschungel eigentlich genommen wird.
Ohne den konkreten Code zu sehen, ist das reines Raetselraten. Abgesehen davon ist es eine kluge Strategie, dass jedes File selbst das included, was es braucht und nicht in irgendwelchen Implementationsfiles Headerfiles includet werden, damit andere, spaeter includete Headerfiles funktionieren - wer soll darueber langfristig den Ueberblick behalten?
Also hier das erwähnte main:
1 | // File: 13_Stoppuhr.c
|
2 | // Date: 12.12.2009
|
3 | |
4 | #include <lib_v2.h> // Hauptlib |
5 | |
6 | //---------------------------------------------------------------------------
|
7 | //Hauptprogramm
|
8 | //---------------------------------------------------------------------------
|
9 | int main(void) |
10 | {
|
11 | |
12 | }
|
Lib_v2.h :
1 | //#####################################################################
|
2 | // Target....: TI MSP430F1611 microcontroller
|
3 | // Date......: 2010.06.08
|
4 | // Purpose...: Headerfile for Lib_v2.c.
|
5 | //######################################################################
|
6 | |
7 | //================================================================== includes
|
8 | //------------------------------------------ compiler's include path
|
9 | #include <io.h> |
10 | #include <signal.h> |
11 | #include <stdio.h> |
12 | |
13 | //--------------------- module headers for used modules defined in Hardware.h
|
14 | #include <LibDefines.h> //Lib mit den typedefs |
15 | #include <Hardware.h> //Hier werden die unten geprueften defines gesetzt |
16 | |
17 | //------------------------------------------------------------- TimerA module
|
18 | #ifdef HwUSE_TIMER_A
|
19 | #include <LibTimerA.h> |
20 | #endif
|
21 | |
22 | //-------------------------------------------------- analog/digital converter
|
23 | #ifdef HwUSE_ADC
|
24 | #include <LibAdc.h> |
25 | #endif
|
26 | |
27 | //-------------------------------------------------- digital/analog converter
|
28 | #ifdef HwUSE_DAC
|
29 | #include <LibDac.h> |
30 | #endif
|
31 | |
32 | //-------------------------------------------------------------- UART1 module
|
33 | #ifdef HwUSE_UART1
|
34 | #include <LibUart1.h> |
35 | #endif
|
36 | |
37 | //-------------------------------------------------------------- UART0 module
|
38 | #ifdef HwUSE_UART0
|
39 | #include <LibUart0.h> |
40 | #endif
|
41 | |
42 | //-------------------------------------------------------- LCD display module
|
43 | #ifdef HwUSE_LCD
|
44 | #include <LibLcd.h> //Benoetigt LibDefines.h |
45 | #endif
|
46 | |
47 | //-------------------------------------------------------- SD Card
|
48 | #ifdef HwUSE_SDCard
|
49 | #include <ff.h> //Benoetigt LibDefines.h |
50 | #include <fat.h> //Benoetigt LibDefines.h |
51 | #endif
|
LibDefines.h
1 | //#####################################################################
|
2 | // Target....: TI MSP430F1611 microcontroller
|
3 | // Date......: 05.06.2012
|
4 | // Purpose...: Global #defines and type definition in this file
|
5 | //###########################################################################
|
6 | #ifndef _LIBDEFINES
|
7 | #define _LIBDEFINES
|
8 | //******************************************************** global definitions
|
9 | //======================================================= common data types
|
10 | // Due to the fact that not every compiler treats the standard C datatypes
|
11 | // the same way (e.g. unsigned short may be 8 bits wide on some compilers,
|
12 | // 16 bits on others), it is useful to define own types, which can be made
|
13 | // the same across all platforms. The code will get more portable.
|
14 | //=========================================================================
|
15 | |
16 | typedef unsigned char BYTE; // 8 bits |
17 | typedef unsigned char UCHAR; // 8 bits used for SD Card |
18 | |
19 | typedef unsigned int WORD; // 16 bits |
20 | typedef unsigned int UINT; // 16 bits used for SD Card |
21 | typedef unsigned short USHORT; // 16 bits used for SD Card |
22 | typedef unsigned short WCHAR; // 16 bits used for SD Card |
23 | |
24 | typedef unsigned long DWORD; // 32 bits |
25 | typedef unsigned long ULONG; // 32 bits used for SD Card |
26 | typedef unsigned long long QWORD; // 64 bits |
27 | |
28 | typedef char SBYTE; // 8 bits signed |
29 | |
30 | typedef int INT; // 16 bits used for SD Card |
31 | typedef short SWORD; // 16 bits signed |
32 | typedef short SHORT; // 16 bits used for SD Card |
33 | |
34 | typedef long SDWORD; // 32 bits signed |
35 | typedef long LONG; // 32 bits used for SD Card |
36 | typedef long long SQWORD; // 64 bits signed |
37 | |
38 | #ifndef NULL
|
39 | #define NULL ((void*)0)
|
40 | #endif
|
41 | |
42 | //========================================================= boolean constants
|
43 | typedef enum { FALSE = 0, TRUE } BOOL; |
44 | //==================================================== input/output constants
|
45 | #define INPUT 0x00 // set ports as input
|
46 | #define OUTPUT 0xFF // set ports as output
|
47 | |
48 | #endif /*_LIBDEFINES */ |
Und in den Files LibLcd.h/ff.h und fat.h nichts eingebunden. >Wenn ich mir nicht sicher bin, ob ein Header File überhaupt eingebunden >wird, dann mach ich ganz gerne mal folgenden Test: >Ich provoziere im Header File einen Fehler. >Einfach am Anfang irgendeinen Text "hsdf8uzcinerwb" einfügen. Das habe ich auch gemacht, er hat bei jeder Headerdatei, die ich modifiziert habe, eine Fehlermeldung gebracht. >es eine kluge Strategie, dass jedes File selbst das included, >was es braucht und nicht in irgendwelchen Implementationsfiles >Headerfiles includet werden Da geb ich Dir Recht, das macht eigentlich mehr Sinn. Ich würde einfach gerne wissen, wo der Unterschied liegt, wenn ich das File wie oben einbinde oder halt einzeln bei jedem der drei Libraries. Wenn der Compiler die Files überstetzt, dann kommt er ja im oberen Fall ziemlich schnell einmal zum LibDefines.h. Er sieht die typedefs und speichert diese (irgendwo?) ab. Warum sind dann diese den anderen h-Files so nicht bekannt. Wenn ich LibDefines.h jedoch in jedem File einzeln einbinde, dann geht der Compiler ja auch nur einmal hindurch (wegen dem Include-Guard) im Gegensatz zum ersten Fall funktioniert es jedoch.
> Es ist so, dass ich ein Hauptprogramm habe (nennen wir es main.c) und > darin binde ich meine Hauptlibrary (lib.h) ein. Du solltest dringendst Deine Terminologie ändern. Es geht hier nicht um Libraries, sondern um Headerdateien oder meinetwegen "Includedateien". Der Begriff "Library" aber ist ein feststehender Begriff mit einer feststehenden Bedeutung, wenn Du den falsch verwendest, kommt es zu Irritationen. </pedanterie, wichtige>
Lief Erickson schrieb: > Ich würde einfach gerne wissen, wo der Unterschied liegt, wenn ich das > File wie oben einbinde oder halt einzeln bei jedem der drei Libraries. Keinen. Da muss es noch irgendeine Zusatzbedingung geben, die du übersiehst und auf die hier keiner kommt. Kann es sein, dass du deinen Include-Guard zb beim Compiler Aufruf vorbelegt hast?
>Kann es sein, dass du deinen Include-Guard zb beim Compiler Aufruf >vorbelegt hast? Ich weiss nicht genau, was Du damit meinst. Mein Makefile sieht so aus:
1 | ####################################################################
|
2 | # Platform..: TI-MSP430
|
3 | # Date......: 07.07.2009
|
4 | # Input.....: The following commandline parameters are required for the
|
5 | # compile and build jobs. The examples use variables (%var%) as
|
6 | # they are provided by PsPad programming editor. This
|
7 | # commandline must be provided for build operations:
|
8 | #
|
9 | # make JOB=%Ext% SOURCE=%Name%%Ext% TOOLS="D:\Program Files\MspGcc"
|
10 | #
|
11 | # make.exe JOB=%Ext% SOURCE=%Name%%Ext% TOOLS=<MspGccPath>
|
12 | # [DLAUTO=yes]
|
13 | #
|
14 | # EXT=%Ext% Is used for build operations. It is the
|
15 | # file extension of the active file in the
|
16 | # editor.
|
17 | #
|
18 | # SOURCE=%Name%%Ext% Is the name and extension of the active
|
19 | # file in the editor. It is used for single
|
20 | # file compilations.
|
21 | #
|
22 | # TOOLS=<MspGccPath> Root directory of MspGcc installation.
|
23 | # Must be enclosed in quotes if the path
|
24 | # contains spaces.
|
25 | #
|
26 | # DLAUTO=yes Tells the make job if the object file
|
27 | # shall be downloaded immediately after a
|
28 | # a successful build.
|
29 | #
|
30 | # For non-compile or build jobs (makehex, makelst, download,
|
31 | # debug and clean) the syntax is
|
32 | #
|
33 | # make.exe [makehex | makelst | download | debug | clean]
|
34 | #
|
35 | # Note that these jobs can also perform a build operation,
|
36 | # depending on the job settings.
|
37 | #
|
38 | # Remarks...: The current path when executing this makefile has to be in
|
39 | # the folder, where the objects go (e.g. ./Obj). In PsPad, it
|
40 | # can be set in the compiler dialog, e.g. %ProjectDir%\Obj.
|
41 | #############################################################################
|
42 | |
43 | #===================================================== customizable section
|
44 | #-------------------project name, will also be the name of the output file
|
45 | PROJECT = 13_stoppuhr_Dev3 |
46 | |
47 | #--------------------------- paths relative to object path (%ProjectDir%\Obj)
|
48 | SRCPATH = ../Src/ |
49 | BINPATH = ../Bin/ |
50 | LSTPATH = ../Lst/ |
51 | LIBPATH = ../../Library/ |
52 | #---------------------------------- list of all main and library source files
|
53 | MAINSOURCES = 13_Stoppuhr.c |
54 | LIBSOURCES = Lib_v2.c fat.c ff.c diskio.c LibLcd.c |
55 | |
56 | #---------------------------------- paths for executables and system includes
|
57 | MSPINST = $(TOOLS)/ |
58 | MSPINC = "$(MSPINST)msp430/include" |
59 | MSPEXE = $(MSPINST)Bin/ |
60 | CC = "$(MSPEXE)msp430-gcc" |
61 | RM = rm.exe |
62 | |
63 | #------------------------------------ COM port for iProg FTDI chip (COMx - 1)
|
64 | BSLPORT = 4 |
65 | |
66 | #------------------------------------- automatic download on successful build
|
67 | DLAUTO = no |
68 | |
69 | #================================================ end of customizable section
|
70 | |
71 | #------------------------------------------------------- environment settings
|
72 | SOURCES = $(MAINSOURCES) $(LIBSOURCES) |
73 | |
74 | DEPSSRC = $(addprefix $(SRCPATH), $(MAINSOURCES)) \ |
75 | $(addprefix $(LIBPATH), $(LIBSOURCES)) |
76 | |
77 | INCLUDES = -I $(SRCPATH) -I $(LIBPATH) -I $(MSPINC) |
78 | |
79 | VPATH = $(SRCPATH) $(LIBPATH) |
80 | |
81 | #---------------------------------------------------------- compiler settings
|
82 | MCU = msp430x1611 |
83 | LDFLAGS = -mmcu=$(MCU) |
84 | CFLAGS = -mmcu=$(MCU) $(INCLUDES) -g -O0 -Wall |
85 | |
86 | #======================================================== command line parser
|
87 | # Call job depending on filename on commandline
|
88 | #============================================================================
|
89 | ifeq "$(suffix $(JOB))" ".c" |
90 | EXEC = compile |
91 | |
92 | endif
|
93 | |
94 | ifeq "$(basename $(JOB))" "makefile" |
95 | |
96 | ifeq "$(DLAUTO)" "yes" |
97 | EXEC = download |
98 | else
|
99 | EXEC = build |
100 | endif
|
101 | |
102 | endif
|
103 | |
104 | job: $(EXEC) |
105 | # Debug @echo $(SOURCE): successJOB
|
106 | #============================================================================
|
107 | |
108 | #============================================================== job 'compile'
|
109 | # A single file gets compiled. The file is the active file in the editor.
|
110 | #============================================================================
|
111 | OBJECT = $(SOURCE:.c=.o) |
112 | |
113 | compile: $(SOURCE) |
114 | $(CC) $(CFLAGS) -c -o $(OBJECT) $< |
115 | @echo $(SOURCE): success1 compile |
116 | #============================================================================
|
117 | |
118 | #================================================================ job 'build'
|
119 | # The whole project gets compiled and linked
|
120 | # Syntax: Either 'make.exe build' or 'make.exe job=%Ext%' with 'makefile'
|
121 | # as active file in the editor
|
122 | #============================================================================
|
123 | OBJECTS = $(SOURCES:.c=.o) |
124 | |
125 | $(PROJECT): $(OBJECTS) |
126 | $(CC) $(LDFLAGS) $(OBJECTS) -o $(BINPATH)$(PROJECT).elf |
127 | "$(MSPEXE)msp430-size" $(BINPATH)$(PROJECT).elf |
128 | |
129 | $(SOURCES): |
130 | $(CC) $(CFLAGS) $< -o $@ |
131 | |
132 | build: $(SOURCES) $(PROJECT) |
133 | @echo $(PROJECT): success2 Build |
134 | #============================================================================
|
135 | |
136 | #============================================================= job 'download'
|
137 | # Download .elf file onto target. A successful build has to be done before.
|
138 | # To check for this automatically, add 'build' to download: line.
|
139 | # Syntax: make.exe download
|
140 | #============================================================================
|
141 | download: build |
142 | "$(MSPEXE)msp430-bsl" -c $(BSLPORT) -e --invert-test --invert-reset \ |
143 | $(BINPATH)$(PROJECT).elf |
144 | # Debug: rma wenn an dieser Stelle = Fehler. @echo $(PROJECT): success3 Download build
|
145 | #============================================================================
|
146 | |
147 | #============================================================== job 'makehex'
|
148 | # Create .HEX file out of .ELF
|
149 | # Syntax: make.exe makehex
|
150 | #============================================================================
|
151 | makehex: build |
152 | "$(MSPEXE)msp430-objcopy" -O ihex $(BINPATH)$(PROJECT).elf \ |
153 | $(BINPATH)$(PROJECT).hex |
154 | @echo $(PROJECT).hex created success6 |
155 | #============================================================================
|
156 | |
157 | #============================================================== job 'makelst'
|
158 | # Create .LST file out of .ELF
|
159 | # Syntax: make.exe makelst
|
160 | #============================================================================
|
161 | LSTOBJ = $(SOURCES:.c=.o) |
162 | |
163 | makelst: build |
164 | "$(MSPEXE)msp430-objdump" -dSt $(LSTOBJ) >$(LSTPATH)$(PROJECT).lst |
165 | @echo $(PROJECT).lst created |
166 | #============================================================================
|
167 | |
168 | #================================================================ job 'debug'
|
169 | # Start Insight debugger
|
170 | # Syntax: make.exe debug
|
171 | #============================================================================
|
172 | debug: build |
173 | @echo loading... |
174 | @cmd.exe /C start "gdbproxy" /MIN $(MSPEXE)Msp430-gdbproxy msp430 TIUSB |
175 | @echo target remote localhost:2000 >gdb.ini |
176 | @echo erase all >>gdb.ini |
177 | @echo file $(BINPATH)$(PROJECT).elf >>gdb.ini |
178 | @echo load $(BINPATH)$(PROJECT).elf >>gdb.ini |
179 | @echo break main >>gdb.ini |
180 | @echo continue >>gdb.ini |
181 | "$(MSPEXE)Msp430-insight" --command=gdb.ini |
182 | @del gdb.ini |
183 | @taskkill /F /IM msp430-gdbproxy.exe |
184 | |
185 | #================================================================ job 'clean'
|
186 | # Delete all auto-generated files
|
187 | # Syntax: make.exe clean
|
188 | #============================================================================
|
189 | clean: |
190 | $(RM) *.o *.a43 dependencies.in \ |
191 | $(BINPATH)*.elf \ |
192 | $(BINPATH)*.hex \ |
193 | $(LSTPATH)*.lst |
194 | @echo clean success4 |
195 | #============================================================================
|
196 | |
197 | #=============================================================== dependencies
|
198 | -include dependencies.in |
199 | dependencies.in: |
200 | $(CC) -MM $(CFLAGS) $(DEPSSRC) >$@ |
201 | @echo dependencies update complete |
202 | #============================================================================
|
203 | |
204 | ############################################################ EOF makefile
|
Ich habe schon das Gefuehl, dass es am Kompiliervorgang selber liegt. Ich weiss nur nicht genau, wie ich heraus finden kann, welches File er als erstes kompiliert und wie die Objectfiles dann linkt.
Ich habe den Fehler gefunden, danke für die Hilfe und die Tips :)
Lief Erickson schrieb: > Ich habe den Fehler gefunden, danke für die Hilfe und die Tips :) Und, was wars? (Jetzt hast du mich neugierig gemacht)
Lief Erickson schrieb: > Ich habe den Fehler gefunden, danke für die Hilfe und die Tips :) Nun schmeiß deine altertümlichen Datentypen noch weg und ersetz sie durch die C99-Pendants aus <stdint.h>. Schließlich wurde gerade der C11-Standard verabschiedet, da wäre es Zeit, sich zumindest an den vorherigen mal zu gewöhnen ...
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.