|
|
View previous topic :: View next topic |
Author |
Message |
TAMA25
Joined: 04 Dec 2022 Posts: 5
|
Multiple Compilation Problem? |
Posted: Sun Dec 04, 2022 9:02 pm |
|
|
Compiler: PCWH 5.110
Device: PIC18F57Q84
Use PICKIT4 and No debugger.
I am testing multiple file compilations because I need them for work.
I found that it did not work properly (LEDs did not light up) with LINK, so I compiled it in C without LINK and found that it works.
I also found that it works even if I stop including string.h and stdlib.h.
Comparing the list with the problematic state, the code in the main function is quite different and I think this is the cause of the problem.
The problem seems to occur when I pass main.o with string.h and stdlib.h included to LINKER.
Why does this happen?
(Translated by Deepl. Sorry if some parts are hard to read.)
[ main.c ]
----------
#include <18F57Q84.h>
#device ADC=12
#fuses NOWDT,NOPROTECT,NOLVP
#use delay(clock=64000000, crystal=16000000)
#byte PORTA = 0x04CE
#byte PORTB = 0x04CF
#byte PORTC = 0x04D0
#byte PORTD = 0x04D1
#byte PORTE = 0x04D2
#byte PORTF = 0x04D3
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
#use fast_io(D)
#use fast_io(E)
#use fast_io(F)
//#include <math.h>
//#include <stdlib.h>
#include <string.h>
void setup()
{
setup_oscillator(OSC_EXTOSC_PLL | OSC_CLK_DIV_BY_1 | OSC_PLL_ENABLED);
set_tris_a(0x30); // RA4,RA5 -input
set_tris_b(0x1f); // RB0-RB3 -input RB4 - CAN RX
set_tris_c(0x00);
set_tris_d(0xfd); // RD2-RD7 -input RD0 - SCI0 RX
set_tris_e(0x01); // RE0 -input
set_tris_f(0xf0); // RF4-RF7 -input
PORTA = 0;
PORTB = 0;
PORTC = 0;
PORTD = 0;
PORTE = 0;
PORTF = 0;
}
void main( void ){
setup();
while(1) {
PORTC = PORTB;
}
}
----------
[ build.bat ]( make project.hex and main.hex )
----------
"C:\Program Files (x86)\PICC\CCSC.exe" +FH +LN +STDOUT +EXPORT main.c
"C:\Program Files (x86)\PICC\CCSC.exe" +FH +EA +STDOUT -EW +PE +LN LINK="project.hex=main.o"
"C:\Program Files (x86)\PICC\CCSC.exe" +FH +LN +STDOUT main.c
----------
[ main.lst ](include string.h) -> work fine
----------
.................... void main( void ){
000A8: CLRF 4F8
000AA: BCF 4D6.5
000AC: BSF 507.7
000AE: CLRF xB0
000B0: CLRF xAF
000B2: CLRF xB3
000B4: CLRF xB1
000B6: MOVLW 20
000B8: MOVWF xAD
000BA: MOVLB 4
000BC: CLRF x00
000BE: CLRF x08
000C0: CLRF x10
000C2: CLRF x18
000C4: CLRF x20
000C6: CLRF x28
000C8: MOVLB 0
000CA: CLRF x71
000CC: CLRF x72
000CE: CLRF x73
000D0: CLRF x70
000D2: CLRF x75
000D4: CLRF x76
000D6: CLRF x77
000D8: CLRF x74
000DA: CLRF 51B
000DC: CLRF 51C
....................
.................... setup();
000DE: BRA 006E
....................
.................... while(1) {
.................... PORTC = PORTB;
000E0: MOVFF 4CF,4D0
000E4: BRA 00E0
.................... }
.................... }
000E6: SLEEP
----------
[ project.lst ](include string.h) -> Didnot work
----------
.................... void main( void ){
000A8: CLRF 4F8
000AA: BCF 4D6.5
000AC: BSF 507.7
000AE: CLRF xB0
000B0: CLRF xAF
000B2: CLRF xB3
000B4: CLRF xB1
000B6: MOVLW 20
000B8: MOVWF xAD
000BA: BRA 00C6
000BC: DATA 08,40
000BE: DATA 70,00
000C0: DATA 02,05
000C2: DATA 1B,00
000C4: DATA 00,00
000C6: MOVLW 00
000C8: MOVWF 4F8
000CA: MOVLW 00
000CC: MOVWF 4F7
000CE: MOVLW BC
000D0: MOVWF 4F6
000D2: TBLRD*+
000D4: MOVF 4F5,W
000D6: MOVWF 500
000D8: XORLW 00
000DA: BZ 0102
000DC: TBLRD*+
000DE: MOVF 4F5,W
000E0: MOVWF 501
000E2: BTFSC 4E8.7
000E4: BRA 00F0
000E6: ANDLW 3F
000E8: MOVWF 4EA
000EA: TBLRD*+
000EC: MOVFF 4F5,4E9
000F0: BTFSC 501.6
000F2: TBLRD*+
000F4: BTFSS 501.6
000F6: TBLRD*+
000F8: MOVFF 4F5,4EE
000FC: DCFSNZ 500,F
000FE: BRA 00D2
00100: BRA 00F4
00102: CLRF 4F8
....................
.................... setup();
00104: BRA 006E
....................
.................... while(1) {
.................... PORTC = PORTB;
00106: MOVFF 4CF,4D0
0010A: BRA 0106
.................... }
.................... }
....................
0010C: SLEEP
---------- |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19529
|
|
Posted: Mon Dec 05, 2022 1:43 am |
|
|
Learn to use the code buttons...
The include files are not 'passed'.
What is passed in the MCU, is only the functions it is told to export. Nothing
else.
If a second file wants to use stdlib.h and string.h, then these have to be
included in _it's_ compilation.
Look at the example.
This shows how to export the functions from each section, and then how to
import these into a final master compilation.
The example is mcu.zip in the examples directory. Expand this and look
at how it is done.
Note importantly that _each_ part of the project has to include the 'master'
clock and fuse settings, and also any include files. #INCLUDE's like
stdlib and string, are _not_ exported in the built .o file.
You currently don't have anything putting the stuff together. Even though
you only have a single section, it still needs to have a final linking to
actually work. |
|
|
TAMA25
Joined: 04 Dec 2022 Posts: 5
|
|
Posted: Mon Dec 05, 2022 3:45 am |
|
|
Thanks, mr.Ttelmah.
I'll be careful to use the code button.
Ttelmah wrote: | The example is mcu.zip in the examples directory. Expand this and look at how it is done. |
I have checked the contents of mcu.zip and the CCS site description (http://www.ccsinfo.com/faq.php?page=multi_comp_units), and the first project I started writing had master clock, fuse, and settings in "project.h" and included them all source files. settings in "project.h" and included them all c-files. However, that did not work, so I created a test code with a minimal configuration of just main.c.
(I did this to verify the minimal configuration, although it is not necessary to use LINK since it is only in main.c. There is no indication that using LINK in a single o-file will cause problems.)
When I actually compiled the main.c shown above and checked the list file, I found that the implementation code for the functions included in string.h had been expanded to the main.c include location.
However, since the functions in string.h are not used in main.c and there is no other c file to integrate, no assembly code related to string.h is output in the list file. I believe this is correct.
However, only the assembly code at the beginning of the main function has increased as shown in the list file above, and the operation is not working properly.
I have additionally tried.
1. actually calling the strcmp function in main.c with the possibility that it is the code for resource initialization of the function in string.h
Result: the strcmp code developed in main.c is valid assembly code in the list file.
However, main.hex works, but project.hex does not.
2. #include the contents up to "string.h" into project.h and include it.
Result: No change. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19529
|
|
Posted: Mon Dec 05, 2022 7:21 am |
|
|
The point is you seem to be trying to build a single file project. Key in
MCU, is 'Multiple'. I don't think the linker supports building just one element.
You need to have multiple units, and link these together. I just tried a
copy of your project, but put setup, into a separate setup.c with a
setup.h. I then told the linker to link main.o, and setup.o
It merrily compiled (with string.h included), and linked, and in the
MPLAB sim, the resulting program ran. |
|
|
TAMA25
Joined: 04 Dec 2022 Posts: 5
|
|
Posted: Mon Dec 05, 2022 8:53 pm |
|
|
In the course of multi-file testing, I discovered something.
project.h
Code: | #include <18F57Q84.h>
#device ADC=12
#fuses NOWDT,NOPROTECT,NOLVP
#use delay(clock=64000000, crystal=16000000)
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
#use fast_io(D)
#use fast_io(E)
#use fast_io(F)
#byte PORTA = 0x04CE
#byte PORTB = 0x04CF
#byte PORTC = 0x04D0
#byte PORTD = 0x04D1
#byte PORTE = 0x04D2
#byte PORTF = 0x04D3
|
setup.h
setup.c
Code: | #include "project.h"
#include "setup.h"
void setup()
{
setup_oscillator(OSC_EXTOSC_PLL | OSC_CLK_DIV_BY_1 | OSC_PLL_ENABLED);
set_tris_a(0x30); // RA4,RA5 -input
set_tris_b(0x1f); // RB0-RB3 -input RB4 - CAN RX
set_tris_c(0x00);
set_tris_d(0xfd); // RD2-RD7 -input RD0 - SCI0 RX
set_tris_e(0x01); // RE0 -input
set_tris_f(0xf0); // RF4-RF7 -input
PORTA = 0;
PORTB = 0;
PORTC = 0;
PORTD = 0;
PORTE = 0;
PORTF = 0;
}
|
main.c
Code: | #include "project.h"
#include "setup.h"
void main( void ){
setup();
while(1) {
PORTC = PORTB;
}
} |
When I compiled and linked this normally, it didn't work.
build.bat (not working)
Code: | "C:\Program Files (x86)\PICC\CCSC.exe" +FH +LN +STDOUT +EXPORT setup.c
"C:\Program Files (x86)\PICC\CCSC.exe" +FH +LN +STDOUT +EXPORT main.c
"C:\Program Files (x86)\PICC\CCSC.exe" +FH +EA +STDOUT -EW +PE +LN LINK="project.hex=setup.o,main.o" |
However, it worked when I turned off the optimization to try it out. (+Y0)
build.bat (work fine)
Code: | "C:\Program Files (x86)\PICC\CCSC.exe" +FH +Y0 +LN +STDOUT +EXPORT setup.c
"C:\Program Files (x86)\PICC\CCSC.exe" +FH +Y0 +LN +STDOUT +EXPORT main.c
"C:\Program Files (x86)\PICC\CCSC.exe" +FH +EA +STDOUT -EW +PE +LN LINK="project.hex=setup.o,main.o" |
The following is a comparison of the listing files for the main function portion.
not working.
Code: | .................... void main( void ){
0003E: CLRF 4F8
00040: BCF 4D6.5
00042: CLRF xB0
00044: CLRF xAF
00046: CLRF xB3
00048: CLRF xB1
0004A: MOVLW 20
0004C: MOVWF xAD
0004E: BRA 0056
00050: DATA 08,40
00052: DATA 70,00
00054: DATA 00,00
00056: MOVLW 00
00058: MOVWF 4F8
0005A: MOVLW 00
0005C: MOVWF 4F7
0005E: MOVLW 50
00060: MOVWF 4F6
00062: TBLRD*+
00064: MOVF 4F5,W
00066: MOVWF 500
00068: XORLW 00
0006A: BZ 0092
0006C: TBLRD*+
0006E: MOVF 4F5,W
00070: MOVWF 501
00072: BTFSC 4E8.7
00074: BRA 0080
00076: ANDLW 3F
00078: MOVWF 4EA
0007A: TBLRD*+
0007C: MOVFF 4F5,4E9
00080: BTFSC 501.6
00082: TBLRD*+
00084: BTFSS 501.6
00086: TBLRD*+
00088: MOVFF 4F5,4EE
0008C: DCFSNZ 500,F
0008E: BRA 0062
00090: BRA 0084
00092: CLRF 4F8
....................
.................... setup();
00094: BRA 0004
....................
.................... while(1) {
.................... PORTC = PORTB;
00096: MOVFF 4CF,4D0
0009A: BRA 0096
.................... }
.................... }
....................
0009C: SLEEP |
works fine.
Code: | .................... void main( void ){
0003E: CLRF 4F8
00040: BCF 4D6.5
00042: CLRF xB0
00044: CLRF xAF
00046: CLRF xB3
00048: CLRF xB1
0004A: MOVLW 20
0004C: MOVWF xAD
0004E: MOVLW 00
00050: MOVLB 3
00052: MOVWF xF8
00054: MOVLW 00
00056: MOVLB 4
00058: MOVWF x00
0005A: MOVLW 00
0005C: MOVWF x08
0005E: MOVLW 00
00060: MOVWF x10
00062: MOVLW 00
00064: MOVWF x18
00066: MOVLW 00
00068: MOVWF x20
0006A: MOVLW 00
0006C: MOVWF x28
0006E: MOVLB 0
00070: CLRF x71
00072: CLRF x72
00074: CLRF x73
00076: CLRF x70
00078: CLRF x75
0007A: CLRF x76
0007C: CLRF x77
0007E: CLRF x74
....................
.................... setup();
00080: GOTO 0004
....................
.................... while(1) {
.................... PORTC = PORTB;
00084: MOVFF 4CF,4D0
00088: GOTO 0084
.................... }
.................... }
....................
0008C: SLEEP |
When optimization is turned off, TBLRD and other instructions are missing, and the code is similar to that compiled from a C file alone.
(I thought it would have worked if I had not included string.h, but I could have been mistaken.)
Some models seem to have errata with the TBLRD instruction, but I do not know the cause, as it may simply be a compiler problem.
I tried to run it with MPLAB simulator, but I am not familiar with PIC itself and it did not go well.
I am not sure if the problem has been solved or not, but I would like to proceed with the verification without optimization for the time being.
Thank you for your help. |
|
|
TAMA25
Joined: 04 Dec 2022 Posts: 5
|
|
Posted: Tue Dec 06, 2022 2:59 am |
|
|
This is the result of the verification by combining a total of 6 o-files, although it is still short of the desired scale.
Up to optimization level 8 (+Y8), TBLRD does not appear in the assembly code at the head of main() and seems to work.
When +Y9 is specified or not specified, TBLRD appears and it does not work.
It's a mystery. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19529
|
|
Posted: Tue Dec 06, 2022 6:12 am |
|
|
There was a problem with one particular maths operation and optimisation
with 5.105 (in the 'known issues' section of the forum). Your compiler should
have this fixed. However it is likely that something specific about your code
is triggering something similar. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19529
|
|
Posted: Tue Dec 06, 2022 8:10 am |
|
|
OK.
That is repeatable, and does it even with the latest compiler.
You need to report this to CCS, since it is obviously an issue on this
chip at least (on a much older chip it doesn't seem to be doing this), when
using MCU's.
Send them these examples and hopefully they will have a fix soon.
Meantime run with the optimisation turned down. |
|
|
TAMA25
Joined: 04 Dec 2022 Posts: 5
|
|
Posted: Wed Dec 07, 2022 7:14 pm |
|
|
Thank you for the advice.
I just tried it with the latest version of the compiler (5.113),
and it outputs the same assembly code as 5.110,
and the result of running it is the same.
I have reported this to CCS.
I will post again if there is progress. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19529
|
|
Posted: Thu Dec 08, 2022 2:52 am |
|
|
As I said "and does it even with the latest compiler".
Understand that MCU's with CCS, are really a bad idea. CCS was built as
a single pass compiler. Never designed to support linking. Working single
pass allows better optimisation, so most people never get involved with
trying to use MCU's. CCS added the capability a while ago, but for me it
has never worked 100%. Given how fast the compiler actually works,
compiling as a single entity, this is really the approach to use.
Now your phrasing at the start suggests that you have some specific need
for using MCU's. Difficult to really work out what this might be?.
Hopefully CCS will fix this issue for you, but do expect MCU's to still
have problems. They really are not the way to work with the CCS compiler. |
|
|
BrianF
Joined: 12 Dec 2020 Posts: 10
|
|
Posted: Fri Feb 24, 2023 8:59 am |
|
|
Ttelmah wrote: |
Understand that MCU's with CCS, are really a bad idea...They really are not the way to work with the CCS compiler. |
That's an interesting observation.
I've been considering CCS for the last year or so as I really like the environment BUT not being able to reliably use multiple C files may well be a show stopper.
I've just looked at the commercial project I'm currently working on and it's 12 C files and 46,000 lines. My coding style is fairly relaxed so that's probably around 15,000 lines of code. I really can't see that working in a single file. OK, it will work but it'll not be fun to code. |
|
|
gaugeguy
Joined: 05 Apr 2011 Posts: 303
|
|
Posted: Fri Feb 24, 2023 9:43 am |
|
|
Having multiple C files is quite normal and is not the same as MCU |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1908
|
|
Posted: Fri Feb 24, 2023 10:28 am |
|
|
BrianF wrote: | I've been considering CCS for the last year or so as I really like the environment BUT not being able to reliably use multiple C files may well be a show stopper.
I've just looked at the commercial project I'm currently working on and it's 12 C files and 46,000 lines. My coding style is fairly relaxed so that's probably around 15,000 lines of code. I really can't see that working in a single file. OK, it will work but it'll not be fun to code. |
It's just a mindset. I cut my teeth using what is standard compiler - linker multiple object file style, then I migrated to CCS. I must admit that in the beginning, the "one big file" style proved to be a frustrating challenge. However, I've since come up with my own coding style which, when followed, doesn't present any obstacles to that approach.
The project I'm currently working on has 16 different files and many thousands of lines of code. In the past I've developed CCS projects comprising as many as 30+ files (can't remember the exact amount, but was somewhere around 32-34 if memory serves).
My standard approach is to go with a more-or-less standard CCS package which consists of the main project file.c and main project file.h. The header file includes the processor.h file, the fuses, pin select stuff, #use whatever stuff, and key things like #use fast_io.
The main project.c file is usually no more than 30 or so lines long. At the top I #include the project declarations.h, then follows the main function of the project. First 3 function calls are, in order: init processor, init globals, and finally init interrupts. Then into the program's while (TRUE) superloop. Inside that loop are typically 4 - 12 or so function calls.
The project declarations.h file carries all declarations (variables, structs, functions and #defines), or includes other header files where the division is appropriate. I place my function declarations near the end of this file, and right at the bottom I include the other .c files.
...Works for me, and I've found that CCS newbies can quite easily follow the flow. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19529
|
|
Posted: Fri Feb 24, 2023 11:15 am |
|
|
Dead right.
Your approach is pretty much what every one of the experienced users does.
Perhaps a file with the CPU setup, fuses & peripherals, then one with
global variables, then all the library includes, and then the files for each
section of the program (comms, memory, storage, different types of I/O,
etc. etc..). I often have a 'comments' file, included near the top, with details
of problems found with particular chips, and versions, with notes of what
changed. Also says what compiler was used. Makes coming 'back' to code
in many years time, vastly easier. Current project uses 3*DsPIC's, and the
code for each has perhaps 20 files. Compiles to just over 500KB of code
in total. One is handling a particular sensor, with a lot of nasty maths
(has to use logs and powers in the calculation of the polynomial to correct
the sensor). Second one handles the graphic display, and the main one
handles the user interface, storage, I/O, etc. etc.. |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1351
|
|
Posted: Fri Feb 24, 2023 11:33 am |
|
|
BrianF wrote: | Ttelmah wrote: |
Understand that MCU's with CCS, are really a bad idea...They really are not the way to work with the CCS compiler. |
That's an interesting observation.
I've been considering CCS for the last year or so as I really like the environment BUT not being able to reliably use multiple C files may well be a show stopper.
I've just looked at the commercial project I'm currently working on and it's 12 C files and 46,000 lines. My coding style is fairly relaxed so that's probably around 15,000 lines of code. I really can't see that working in a single file. OK, it will work but it'll not be fun to code. |
You don't literally put all the code in a single file, you just need to #include the other C files at the bottom of your main C file. It's technically single file compilation but you still use multiple C files. It just doesn't separately compile each C file this way.
Code: |
#include <your_pic.h>
#fuses ...
#use delay(...)
#include "file1.h"
#include "file2.h"
void main void(){
...
}
#include "file1.c"
#include "file2.c"
|
|
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|