|
|
View previous topic :: View next topic |
Author |
Message |
johnl
Joined: 30 Sep 2003 Posts: 120
|
Compiler output mystery |
Posted: Thu Dec 15, 2011 7:07 pm |
|
|
I have these files and time stamps from 12/8/11
A.BAK 12:20:38
A.COF 12:20:41
A.HEX 12:20:41
A.C 12:43:22 (Apparently saved after compiling.)
A.BAK and A.C are identical when compared.
When either A.BAK or A.C is compiled, a new .COF is produced, say B.COF and the checksums don't match.
When I compare the dissassembly listings, it appears that the compiler is giving a different result (for one line of C code) than it did a week ago. Shown below are the only differences between A.COF and B.COF.
The compiler is version 3.218. Windows XP SP3.
**** A.COF section ****
259: set_power_pwm4_duty(2000-value);
12F8 0ED0 MOVLW 0xd0
12FA 80D8 BSF 0xfd8, 0, ACCESS
12FC 5432 SUBFWB 0x32, W, ACCESS
12FE 6E4C MOVWF 0x4c, ACCESS
1300 0E07 MOVLW 0x7
1302 5433 SUBFWB 0x33, W, ACCESS
1304 6E4D MOVWF 0x4d, ACCESS
1306 0E00 MOVLW 0
1308 5434 SUBFWB 0x34, W, ACCESS
130A 0E00 MOVLW 0
130C 5435 SUBFWB 0x35, W, ACCESS
130E C04C MOVFF 0x4c, 0xf75
1312 C04D MOVFF 0x4d, 0xf74
1316 926E BCF 0xf6e, 0x1, ACCESS
260:
261:
262: if(!brake)
1318 B44A BTFSC 0x4a, 0x2, ACCESS
**** B.COF section *****
259: set_power_pwm4_duty(2000-value);
12F8 0ED0 MOVLW 0xd0
12FA 80D8 BSF 0xfd8, 0, ACCESS
12FC 5432 SUBFWB 0x32, W, ACCESS
12FE 6E4C MOVWF 0x4c, ACCESS
1300 0E07 MOVLW 0x7
1302 5433 SUBFWB 0x33, W, ACCESS
1304 6E4D MOVWF 0x4d, ACCESS
1306 0E00 MOVLW 0
1308 5434 SUBFWB 0x34, W, ACCESS
130A 0E00 MOVLW 0
130C 5435 SUBFWB 0x35, W, ACCESS
130E 826E BSF 0xf6e, 0x1, ACCESS *** New instruction
1310 C04C MOVFF 0x4c, 0xf75
1314 C04D MOVFF 0x4d, 0xf74
*** omitted instruction here
260:
261:
262: if(!brake)
1318 B44A BTFSC 0x4a, 0x2, ACCESS |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Dec 15, 2011 9:36 pm |
|
|
Post a copy-and-paste compilable test program. It must compile.
Post if you are using MPLAB or the CCS IDE. Post the version of
whichever one you are using. |
|
|
johnl
Joined: 30 Sep 2003 Posts: 120
|
|
Posted: Fri Dec 16, 2011 5:23 pm |
|
|
I am using the CCS IDE version 3.218. I am only using MPLAB (V7.60) to read the checksum of the .COF file. MPLAB is not integrated with the CCS IDE.
I did more testing to reproduce the problem. In each of 10 separate folders, I placed a copy of file A.C. I started the CCS IDE and loaded the first copy of A.C and compiled, then shut down CCS.
Then CCS was restarted and I compiled the second copy of A.C and again shut down CCS.
The sequence was repeated for every one of the 10 folders.
I then read the checksum for each of the 10 A.COF files and found that 7 had the sum 0x5A0D and the other 3 had 0x5A1D which is the desired checksum (of the machine code that runs correctly.)
The source, A.C is here: Code: |
#include <18F4431.h>
#include <string.h>
#include <stdlib.h>
#FUSES NOBROWNOUT, NOIESO, NOMCLR, NOPWMPIN, NOFCMEN
#FUSES NOWDT,NODEBUG,NOLVP,NOPROTECT,INTRC_IO
#FUSES NOEBTRB, NOPUT///, HPOL_LOW
#use delay(clock=8000000)
#use rs232(baud=9600, xmit=PIN_C6,rcv=PIN_C7,ERRORS)
#use standard_io(d)
//////// Macros
//////// Constants
///Macros
#define Hi(x) output_high(x)
#define Lo(x) output_low(x)
#define Y(x) input(x)
#define Tdelay delay_ms(10)
#define PASS_HALL output_bit(P_Phase1,!input(qea) );\
output_bit(P_Phase2,!input(qeb) );\
output_bit(P_Phase3,!input(indx))
#byte PORTA=0xF80
#byte PORTB=0xF81
#byte PORTC=0xF82
#byte PORTD=0xF83
#byte PORTE=0xF84
#byte ANSEL0=0xFB8
#byte ANSEL1=0xFB9
#BYTE QEICON=0xFB6 // quadrature configure
#bit QEICONDIR=0xFB6.5
#BYTE DFLTCON=0xF60 // quadrature noise filter configure
#BYTE CAP2BUFL=0xF66 // position counter
#BYTE CAP2BUFH=0xF67
#BYTE CAP3BUFL=0xF64 //max count
#BYTE CAP3BUFH=0xF65
#BYTE PWMCON1=0xF6E
#define PWM0 PIN_B0
#define PWM1 PIN_B1
#define PWM2 PIN_B2
#define PWM3 PIN_B3
#define PWM5 PIN_B4
#define PWM4 PIN_B5
#define ST PIN_D7
#define in1 PIN_C4
#define in2 PIN_C5
#define in3 PIN_E2
#define in4 PIN_A5
#define in5 PIN_B6
#define in6 PIN_B7
#define in7 PIN_A6
#define in8 PIN_A7
#define indx PIN_A2
#define qea PIN_A3
#define qeb PIN_A4
#define P_DrvOn PIN_C0
#define P_Phase1 PIN_C1
#define P_Phase2 PIN_C2
#define P_Phase3 PIN_C3
#define OPTION1 PIN_D0
#define OPTION2 PIN_D1
#define OPTION3 PIN_D2
#define OPTION4 PIN_D3
#define OPTION5 PIN_D4
#define LED PIN_D5
// OUT1-OUT2-OUT3-OUT4 (output states left to right)
// F=float, L=low, H=high
#define LHLH 0b00010111 //Bipolar stepper 1
#define HLLH 0b00011101 //Bipolar stepper 2
#define HLHL 0b00101101 //Bipolar stepper 3
#define LHHL 0b00100111 //Bipolar stepper 4
#define HLLL 0b00111101 //Unipolar stepper 1
#define LHLL 0b00110111 //Unipolar stepper 2
#define LLHL 0b00101111 //Unipolar stepper 3
#define LLLH 0b00011111 //Unipolar stepper 4
#define HFL 0b00110001 //Open Loop Brushless 1
#define FHL 0b00110100 //Open Loop Brushless 2
#define LHF 0b00000111 //Open Loop Brushless 3
#define LFH 0b00100011 //Open Loop Brushless 4
#define FLH 0b00101100 //Open Loop Brushless 5
#define HLF 0b00001101 //Open Loop Brushless 6
#define LLLL 0b00111111
void init(void);
void test(void);
void delay_100us(long);
void read_control_buttons(void);
char sw, i, ii=1, index=0;
char previous_chksum=0;
char chksum=0;
int32 ADC[8] = {0,0,0,0,0,0,0,0};
unsigned int32 value, value1, value2, raw, last_value, wait;
int1 start, stop, brake, direction=1, enable;
int1 speed0, speed1, speed2, speed_selected;
main()
{
init();
sw = PORTD & 0b11111 ;
while(1)
{
switch(sw)
{
case 1: //pass through
while(1)
{
chksum = (PORTC & 0b00110000) | (PORTB & 0b11000000) ;
chksum = chksum | ( (PORTE & 0b00000100) < 1 );
chksum = chksum | ( (PORTA & 0b11100000) > 5 );
if (previous_chksum != chksum) output_toggle(LED);
output_bit(PWM0, !input(in1) );
output_bit(PWM1, !input(in2) );
output_bit(PWM2, !input(in3) );
output_bit(PWM3, !input(in4) );
output_bit(PWM4, !input(in5) );
output_bit(PWM5, !input(in6) );
output_bit(ST, !input(in7) );
output_bit(P_DrvOn, input(in8) );
output_bit(P_Phase1,!input(qea) );
output_bit(P_Phase2,!input(qeb) );
output_bit(P_Phase3,!input(indx));
previous_chksum = chksum;
}
case 2: //Unipolar stepper
setup_adc_ports( sAN0|sAN1|sAN6|sAN7 | VSS_VDD );
setup_adc(ADC_CLOCK_INTERNAL );
set_adc_channel( 1 );
wait = 1;
Hi(ST);
while(1){
PORTB = HLLL;
delay_100us(wait);
value = 50000/((int32)read_adc()+1);
PORTB = LHLL;
delay_100us(wait);
value = value + 50000/((int32)read_adc()+1);
PORTB = LLHL;
delay_100us(wait);
value = value + 50000/((int32)read_adc()+1);
PORTB = LLLH;
delay_100us(wait);
value = (value + 50000/((int32)read_adc()+1)) >>2;
wait = (value/20)+10;
}
case 3: //Bipolar stepper
setup_adc_ports( sAN0|sAN1|sAN6|sAN7 | VSS_VDD );
setup_adc(ADC_CLOCK_INTERNAL );
set_adc_channel( 1 );
wait = 1;
Hi(ST);
while(1){
PORTB = LHLH ;
delay_100us(wait);
value = 50000/((int32)read_adc()+1);
PORTB = HLLH ;
delay_100us(wait);
value = value + 50000/((int32)read_adc()+1);
PORTB = HLHL ;
delay_100us(wait);
value = value + 50000/((int32)read_adc()+1);
PORTB = LHHL ;
delay_100us(wait);
value = (value + 50000/((int32)read_adc()+1)) >>2;
wait = (value/20)+10;
}
case 10:
Hi(ST);
while(1){
setup_power_pwm_pins(PWM_BOTH_ON, PWM_BOTH_ON, PWM_BOTH_ON, PWM_OFF);
setup_power_pwm(PWM_FREE_RUN ,1,0,503,0,1,0); //PWM freq = 2Khz // 0-2000 ~ 0-100% duty
set_power_pwm4_duty(2000);
//delay_ms(10000);
set_power_pwm_override(4, 1,1);
set_power_pwm_override(5, 0, 1);
delay_ms(5000);
set_power_pwm_override(4, 0,1);
set_power_pwm_override(5, 1, 1);
delay_ms(5000);
}
case 4: //DC motor open loop
Lo(ST);
setup_power_pwm_pins(PWM_BOTH_ON, PWM_BOTH_ON, PWM_BOTH_ON, PWM_OFF);
setup_power_pwm(PWM_FREE_RUN ,1,0,500,0,1,0); //PWM freq = 2Khz // 0-2000 ~ 0-100% duty
PWMCON1 = PWMCON1 & 0b11111101; //allow duty cycle update
while(1)
{
read_control_buttons(); delay_ms(10);
if(!enable)
{
Lo(ST);
start=0;
continue;
}
if (start & !stop) {
start = 0;
Hi(ST); }
if (stop) {
stop = 0; start=0;
Lo(ST); }
value = (int32)read_adc();
if (value>250) value = 250;
value = value<<3;
set_power_pwm4_duty(2000-value);
if(!brake)
{
if(direction) {
set_power_pwm_override(4, 1,1);
set_power_pwm_override(5, 0, 1); }
else {
set_power_pwm_override(4, 0,1);
set_power_pwm_override(5, 1, 1); }
}
if(brake) {
set_power_pwm_override(4, 1,1);
set_power_pwm_override(5, 1, 1); }
QEICON = 0b00011000;
CAP3BUFL = 0xFF;
CAP3BUFH = 0b110;
switch (CAP2BUFH & 0b0110)
{
case 0b00000000:
Lo(P_Phase1); Lo(P_Phase2); break;
case 0b0010:
Lo(P_Phase1); Hi(P_Phase2); break;
case 0b0100:
Hi(P_Phase1); Hi(P_Phase2); break;
case 0b0110:
Hi(P_Phase1); Lo(P_Phase2); break;
}
} /// end of whle(1) case 4
case 8: //BLDC open loop, no commutation feedback, square wave drive
setup_adc_ports( sAN0|sAN1|sAN6|sAN7 | VSS_VDD );
setup_adc(ADC_CLOCK_INTERNAL );
set_adc_channel( 1 );
wait = 1;
Hi(ST);
while(1){
PORTB = HFL ;
delay_100us(wait);
PASS_HALL;
value = 25000/((int32)read_adc()+1);
PORTB = FHL ;
delay_100us(wait);
PASS_HALL;
value = value + 25000/((int32)read_adc()+1);
PORTB = LHF ;
delay_100us(wait);
PASS_HALL;
value = value + 25000/((int32)read_adc()+1);
PORTB = LFH ;
delay_100us(wait);
PASS_HALL;
value = (value + 25000/((int32)read_adc()+1)) >>2;
PORTB = FLH ;
delay_100us(wait);
PASS_HALL;
value = value + 25000/((int32)read_adc()+1);
PORTB = HLF ;
delay_100us(wait);
PASS_HALL;
value = value + 25000/((int32)read_adc()+1);
wait = (value/20)+10;
}
case 15: //test -no signal to drivers; quiescient
PORTB = 0;
while(1);;;;;
case 5: //DC motor closed loop
case 6: //BLDC open loop with Hall sensor
case 7: //BLDC closed loop with Hall sensor
case 9: //Three phase AC motor, sine wave drive
case 31: //loopback test
test();
} //end of switch
}
} //end of main
void read_control_buttons(void)
{
enable= !input(in1);
if( !input(in2) )
{
delay_ms(50);
while( !input(in2) )
{delay_ms(10) ;
if( !input(in3) )
{ stop=1; start=0;
continue;
}
start=1;
}
}
if( !input(in3) ) { stop=1; }
brake= !input(in5) ;
direction = !input(in4) ;
speed0 = !input(in6) ;
speed1 = !input(in7) ;
speed2 = !input(in8) ;
speed_selected=false;
if(speed0) {set_adc_channel( 1 ); speed_selected=true;}
if(speed1) {set_adc_channel( 6 ); speed_selected=true;}
if(speed2) {set_adc_channel( 7 ); speed_selected=true;}
if( speed0 & speed2 ) {set_adc_channel( 0 ); speed_selected=true;}
delay_ms(50);
// while( !input(in2) )
{
delay_ms(10);
}
if(stop) start=0;
if(speed_selected==false) stop=1;
}
void delay_100us(long X)
{
long z;
for (z=0; z<X; z++)
delay_us(100);
}
void test(void)
{
//turn offsignals to all Optical inputs:
Hi(P_DrvOn); Hi(P_Phase1); Hi(P_Phase2); Hi(P_Phase3);
Lo(ST); //float motor outputs
PORTB = 0;
delay_ms(5);
//check that in1 - in8 are all hi:
if(!input(in1)) printf("\n\r in1 error"); if(!input(in2)) printf("\n\r in2 error");
if(!input(in3)) printf("\n\r in3 error"); if(!input(in4)) printf("\n\r in4 error");
if(!input(in5)) printf("\n\r in5 error"); if(!input(in6)) printf("\n\r in6 error");
if(!input(in7)) printf("\n\r in7 error"); if(!input(in8)) printf("\n\r in8 error");
//turn on one at a time:
Lo(P_DrvOn); Tdelay ;
if(input(in1)) printf("\n\r DrvOn --> in1 error");
Hi(P_DrvOn);
Lo(P_Phase3); Tdelay ;
if(input(in2)) printf("\n\r Phase3 --> in2 error");
Hi(P_Phase3);
Lo(P_Phase2); Tdelay ;
if(input(in3)) printf("\n\r Phase2 --> in3 error");
Hi(P_Phase2);
Lo(P_Phase1); Tdelay ;
if(input(in4)) printf("\n\r Phase1 --> in4 error");
Hi(P_Phase1);
PORTB = HLLL; Hi(ST); Tdelay ; //OUT1 Hi ----> IN5
if(input(in5)) printf("\n\r OUT1 --> in5 error");
PORTB = LLLL; Lo(ST);
PORTB = LHLL; Hi(ST); Tdelay ; //OUT2 Hi ----> IN6
if(input(in6)) printf("\n\r OUT2 --> in6 error");
PORTB = LLLL; Lo(ST);
PORTB = LLHL; Hi(ST); Tdelay ; //OUT3 Hi ----> IN7
if(input(in7)) printf("\n\r OUT3 --> in7 error");
PORTB = LLLL; Lo(ST);
PORTB = LLLH; Hi(ST); Tdelay ; //OUT4 Hi ----> IN8
if(input(in8)) printf("\n\r OUT4 --> in8 error");
PORTB = LLLL; Lo(ST);
set_tris_a(0b11100011); //A4,A3,A2 outputs for diff amp test
setup_adc(ADC_CLOCK_INTERNAL );
set_adc_channel( 0 );
delay_ms(10);
Lo(qeb); Lo(qea); Lo(indx); delay_ms(20);// 4.8V ... 244
value = read_adc();
printf("\r\n Expecting >240, read %ld ", value);
delay_ms(1000);
Lo(qeb); Lo(qea); Hi(indx);delay_ms(20); //3.58V ... 182
value = read_adc();
printf("\r\n Expecting 172-192, read %ld ", value);
delay_ms(1000);
Lo(qeb); Hi(qea); Lo(indx); delay_ms(20);//4.16v --- 211
value = read_adc();
printf("\r\n Expecting 201-221, read %ld ", value);
delay_ms(1000);
Hi(qeb); Lo(qea); Lo(indx); delay_ms(20);//4.45v --- 227
value = read_adc();
printf("\r\n Expecting 217-237, read %ld ", value);
delay_ms(1000);
Hi(qeb); Hi(qea); Hi(indx); delay_ms(20);//2.54v --- 127
value = read_adc();
printf("\r\n Expecting 120-134, read %ld ", value);
delay_ms(1000);
// delay_ms(10);//delay_ms(20);delay_ms(20);delay_ms(20);delay_ms(20);delay_ms(20);
}
void init(void)
{
ANSEL0 = 0b11000011;
ANSEL1 = 0;
output_low(ST );
output_low(ST );
setup_adc_ports( sAN0|sAN1|sAN6|sAN7 | VSS_VDD );
setup_adc(ADC_CLOCK_INTERNAL );
set_tris_a(0xFF);
set_tris_b(0xC0);
set_tris_c(0xB0);
set_tris_d(0x1F);
set_tris_e(0x07);
port_b_pullups(FALSE);
Lo(LED);
setup_power_pwm_pins(PWM_OFF, PWM_OFF, PWM_OFF, PWM_OFF);
delay_ms(20);
printf("\r\nMOTCONTROL 2");
sw = PORTD & 0b11111;
//Hi(LED);
//delay_ms(2000);
Lo(LED);
delay_ms(1000);
for (i=0; i<sw; i++)
{
Hi(LED);
delay_ms(25);
Lo(LED);
delay_ms(300);
}
delay_ms(1000);
Hi(LED);
}
//********************************************
/*
index =0;
while(1)
{
biphase =( (input_a()) & 0b1100 );
while ( biphase == input_a() & 0b1100 ) ;;;
index++;
Phase = (index & 0b11000000)
switch(Phase)
{
case 0b0000:
PORTC = 0b000;
break;
case 0b0100:
PORTC = 0b010;
break;
case 0b1000:
PORTC = 0b110;
break;
case 0b1100:
PORTC = 0b100;
break;
}
}
*/
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19499
|
|
Posted: Sat Dec 17, 2011 3:19 am |
|
|
3.218!....
Early 2005 compiler. Do you really mean this?.
I don't think compilers this early support some of the functions you are showing....
What the compiler generates, depends on all the code compiled, which means the contents of the .h files as well. unless you copy these with the code, then the compiler will be searching for these, and the result will depend on where it finds these. The path, network drives attached or not, etc. etc., can all affect what is found, and generated.
Best Wishes |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Sat Dec 17, 2011 5:42 am |
|
|
I had a chance to check the problem, because I'm using PCH V3.222 (only slightly newer than your version) in a project due to compatibility issues with newer PCH versions. Yes, these old compiler versions are already supporting PIC18F4431.
In a short, both assembly code versions of set_power_pwm4_duty(2000-value) are faulty respectively incomplete. Each omits one of two instructions that are both required. You can see this when comparing with the compile result of recent PCH versions.
Code: | .................... set_power_pwm4_duty(2000);
0FE6: BSF F6E.1 ; set UDIS
0FE8: MOVLW D0
0FEA: MOVWF F75
0FEC: MOVLW 07
0FEE: MOVWF F74
0FF0: BCF F6E.1 ; clear UDIS |
Code: | .................... set_power_pwm4_duty(2000-value);
10CA: MOVLW D0
10CC: BSF FD8.0
10CE: SUBFWB 31,W
10D0: MOVWF 4B
10D2: MOVLW 07
10D4: SUBFWB 32,W
10D6: MOVWF 4C
10D8: MOVLW 00
10DA: SUBFWB 33,W
10DC: MOVLW 00
10DE: SUBFWB 34,W
10E0: BSF F6E.1 ; set UDIS
10E2: MOVFF 4B,F75
10E6: MOVFF 4C,F74
10EA: BCF F6E.1 ; clear UDIS |
It can be seen most clearly in the fixed pwm4 set instruction. Before changing PWM duty cycle, the control bit UDIS (F6E.1) has to be set and cleared afterwards. I found no 3.222 code with both instructions present. The effect of omitting one or the other instruction are different. In the first case, occasional wrong PWM values may occur, in the latter, the update doesn't take place at all.
Apparently it's a bug of this PCH version. You can add the control bit manipulations manually to your code, if you don't want to refer to a newer PCH version.
Code: | #bit UDIS=0xF6E.1
...
UDIS=1;
set_power_pwm4_duty(2000-value);
UDIS=0; |
Once I realized, that set_power_pwm4_duty() is faulty in PCH V3.222, I didn't further investigate for the cause of different compilation results. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19499
|
|
Posted: Sat Dec 17, 2011 8:17 am |
|
|
Makes sense.
Set_power_pwmX_duty, is not in the manual for 3.219 (which was the closest I have). Nor is the setup_power_pwm function. They are also not documented in the 'readme' for this compiler. The earliest compiler with these functions documented, I have is 3.226. I suspect at this point they are 'just arriving' functions, and as always with CCS, should be treated as 'liable to be faulty' at this point.
Best Wishes |
|
|
johnl
Joined: 30 Sep 2003 Posts: 120
|
|
Posted: Mon Dec 19, 2011 8:37 pm |
|
|
I never knew a compiler to produce different outputs for one source file. It is unsettling. I'll now upgrade.
FvM, adding the lines around the function still produced two outputs and I'm not surprised.
Now I'm curious... by what mechanism could a compiler bug produce ambiguous output... uninitialized variable, OS interaction, or ??
Thanks much for your help. |
|
|
|
|
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
|