CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Array
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
bschriek



Joined: 18 Dec 2007
Posts: 80

View user's profile Send private message Send e-mail

Array
PostPosted: Sat Oct 24, 2020 3:46 am     Reply with quote

IDE 5.092 PCW 16F1939

I do a compare between two array's, bit by bit to detect if something is changed.
This worked fine 2 years ago and now with the latest compiler it doesn't.

This instruction doesn't work anymore: if ( (out_ [i]) != (out_backup [i]) )

Small piece of code because I know exactly what line causes the problem:
//----------------------------------------------------------------------

Code:
short out_ [17]  =  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
short out_backup [17] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int test=0, surge_counter=0;
int   i, y=0, z=0;       
 
for    (i=16; i>=1; i--)         // 16 to 1.
        {
         printf("%u ",out_ [i]);
         printf("%u ",out_backup [i]);
         printf(",");
                     
         if    ( (out_ [i]) != (out_backup [i]) )
                            {
                            set_pwm1_duty(0);   
                            surge_counter = 0;
                            }

         out_backup [i] = out_ [i];

         if    (out_ [i] == 1)
               output_high(SER_IN);
         else
              output_low (SER_IN);
         delay_us(20); 
         output_high(SRCK);        // Serial-in clock at rising edge.
         delay_us(20); 
         output_low(SRCK);         // Serial-in clock at rising edge
         }


//----------------------------------------------------------------------
If I replace the variable by a constant like the line underneath it works well again.
if ( (out_ [8]) != (out_backup [8]) )

The name of the variable "out_" and "out_backup" are not the problem.
I replaced the name of these variables and the problem is still there.

short or int1 for i has no effect.


Serial monitor output:
surge_counter: 10 ,
1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,0 0 ,0 0 ,1 1 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,
1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,0 0 ,0 0 ,0 1 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,
1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,
1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,
1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,0 0 ,0 0 ,1 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,
surge_counter: 10 ,
1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,0 0 ,0 0 ,1 1 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,
1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,0 0 ,0 0 ,1 1 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,
1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,0 0 ,0 0 ,1 1 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,
1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,0 0 ,0 0 ,0 1 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,
1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,
surge_counter: 10 ,
1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,0 0 ,0 0 ,1 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,
1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,0 0 ,0 0 ,1 1 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,
1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,0 0 ,0 0 ,1 1 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,
1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,0 0 ,0 0 ,1 1 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,
1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,0 0 ,0 0 ,1 1 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,


You can see the code: if ( (out_ [i]) != (out_backup [i]) ) doesn't work because the variable "surge_counter" is not changed.


Who has an idea?
temtronic



Joined: 01 Jul 2010
Posts: 9228
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sat Oct 24, 2020 4:48 am     Reply with quote

I don't see where surge_counter became 10 or printed out...
then again your code WAS black and text 1st time I saw it, 10 minutes later, it's now green and 'code'.....

Jay
bschriek



Joined: 18 Dec 2007
Posts: 80

View user's profile Send private message Send e-mail

PostPosted: Sat Oct 24, 2020 8:21 am     Reply with quote

Hello Temtronic,

I know, this is just a few lines of code.

Code:

i=8;
if    ( (out_ [i]) != (out_backup [i]) )       doesn't work.
And
if    ( (out_ [8]) != (out_backup [8]) )       does work.


But I will start a new project with only a few lines of code so I can post the whole program.

Thank you in advance,
bschriek



Joined: 18 Dec 2007
Posts: 80

View user's profile Send private message Send e-mail

Short Code
PostPosted: Sat Oct 24, 2020 9:19 am     Reply with quote

Who can tell me why it doesn't print "SOLVED" ??


Code:

#include <16F1939.H>

#Fuses HS,NOWDT,PLL_SW
#Fuses PUT,NOMCLR,NOPROTECT,NOCPD
#Fuses BROWNOUT,NOCLKOUT,NOIESO
#Fuses NOFCMEN,NOWRT
#Fuses NOVCAP,NOSTVREN,BORV25
#Fuses NODEBUG,NOLVP

#use delay(clock=12000000)

int i=0;
short out_ [17] =       {0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0};                    // [8] is different.
short out_backup [17] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};                    //
//////////////////////////////// MAIN LOOP /////////////////////////////////////
void main()
{
setup_oscillator(OSC_PLL_OFF);
SETUP_DAC(DAC_OFF);
setup_comparator(NC_NC_NC_NC);
#use rs232(ICD, xmit=PIN_B7)      // Dit werkt met ICD-U64 en Telnet input 38400b.  5 Sec delay!
     
delay_ms(1000);
printf("Start");
printf("\r\n");   

while(1)
       { 
       delay_ms(1000);
       for    (i=16; i>=1; i--)         //   16 t/m 1.
              {
              printf("%u ",i);
              printf("%u ",out_ [i]);
              printf("%u ",out_backup [i]);
              printf(", ");
              if    ( (out_ [i]) != (out_backup [i]) )
                    {
                    printf("SOLVED");
                    }
              }
              if    ( (out_ [8]) != (out_backup [8]) )         //Different
                    {
                    printf("8");
                    } 
              if    ( (out_ [7]) == (out_backup [7]) )         //Same
                    {
                    printf("7");
                    }       
              printf("\r\n");       
      }
}


RS232 output:

Start
16 0 0 , 15 0 0 , 14 0 0 , 13 0 0 , 12 0 0 , 11 0 0 , 10 0 0 , 9 0 0 , 8 1 0 , 7 0 0 , 6 0 0 , 5 0 0 , 4 0 0 , 3 0 0 , 2 0 0 , 1 0 0 , 87
16 0 0 , 15 0 0 , 14 0 0 , 13 0 0 , 12 0 0 , 11 0 0 , 10 0 0 , 9 0 0 , 8 1 0 , 7 0 0 , 6 0 0 , 5 0 0 , 4 0 0 , 3 0 0 , 2 0 0 , 1 0 0 , 87
16 0 0 , 15 0 0 , 14 0 0 , 13 0 0 , 12 0 0 , 11 0 0 , 10 0 0 , 9 0 0 , 8 1 0 , 7 0 0 , 6 0 0 , 5 0 0 , 4 0 0 , 3 0 0 , 2 0 0 , 1 0 0 , 87
16 0 0 , 15 0 0 , 14 0 0 , 13 0 0 , 12 0 0 , 11 0 0 , 10 0 0 , 9 0 0 , 8 1 0 , 7 0 0 , 6 0 0 , 5 0 0 , 4 0 0 , 3 0 0 , 2 0 0 , 1 0 0 , 87
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Oct 24, 2020 11:59 am     Reply with quote

For those who want to work on this problem, I have striped his program
down to a simplified version that shows the problem. (I can't do anymore
now because I have an appointment soon).

This program will print the following when compiled with CCS vs. 5.096
and run in MPLAB vs. 8.92 simulator:
Quote:

Start
Done

Changing the int1 arrays to int8 makes it work OK (ie., it prints SOLVED).

Test program:
Code:
#include <16F1939.H>
#use delay(crystal=12M)
#use rs232(baud=9600, UART1, ERRORS)

int8 i=0;
int1 out[1] = 1; 
int1 out_backup[1] = 0;

//==============================
void main()
{
printf("Start \r");

i = 0;

if(out[i] != out_backup[i])
   printf("SOLVED \r");

printf("Done \r");
printf("\r");

while(TRUE);
}
temtronic



Joined: 01 Jul 2010
Posts: 9228
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sat Oct 24, 2020 2:15 pm     Reply with quote

My gut was telling me it HAS to be a 'bit' problem, and PCMP's 'byte' version works, kinda proves that.
While using 17 bytes to store 17 bits of inforamtion may be wasteful, that PIC does have 1024 of RAM, so it shouldn't be a problem.
I did the same thing, 2 decades ago. It was just easier than trying to keep the bits straight.
One possible cause 'might' be that the array isn't on a page of memory ? I don't know if the compiler is putting all 17 bits into 3 contiguous bytes but 'something' is wrong. A dump of the listing to see what the actual code is should prove useful...
For the time being, I'd use bytes and move on......
leave the 'head scratching - 3rd pot of coffee' for another day....

Jay
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Oct 24, 2020 8:01 pm     Reply with quote

It's a bug in ASM code for the comparison line. (CCS vs. 5.096)
CCS would probably call this an optimization bug.
This bug should be reported to CCS.
Code:
...... i = 0;
003C:  CLRF   i
......
...... if(out[i] != out_backup[i])
003D:  MOVF   i,W
003E:  MOVWF  array_index
003F:  MOVLW  out+-2
0040:  MOVWF  @READBITA.P1+1
0041:  MOVLW  out+-32
0042:  MOVWF  @READBITA.P1
0043:  CALL   @READBITA  // Read value of out[i]
0044:  MOVF   @78,W      // It is returned in @78
0045:  MOVWF  @@25  // Save value of out[i] in @@25

0046:  MOVF   i,W
0047:  MOVWF  array_index
0048:  MOVLW  out_backup+-3
0049:  MOVWF  @READBITA.P1+1
004A:  MOVLW  out_backup+-32
004B:  MOVWF  @READBITA.P1
004C:  CALL   @READBITA  // Read value of out_backup[i]
                         // It is returned in @78

004D:  MOVF   25,W  // w = value of out[i]
004E:  ANDLW  01    // w = w & 1

004F:  MOVWF  @78  // *** Bug: result of out_backup[i] is over-written
                   // *** by value of out[i]
0050:  ANDLW  01

0051:  SUBWF  @78,W  // Compare the two array values
0052:  BTFSC  STATUS.Z  // Skip next line if they are !=
0053:  GOTO   056
....................    result = TRUE; // if they are !=   
0054:  MOVLW  01       
0055:  MOVWF  result
....................
.................... while(TRUE);
0056:  GOTO   056
....


A work-around is to put the result of out1[i] in a temporary variable as
shown below in bold. Then it works.
Quote:

#include <16F1939.H>
#use delay(crystal=12M)
#use rs232(baud=9600, UART1, ERRORS)

int8 i=0;
int1 out[1] = 0;
int1 out_backup[1] = 1;

//==============================
void main()
{
int8 result = FALSE;
int1 temp1;
i = 0;

temp1 = out[i];

if(temp1 != out_backup[i])
result = TRUE;

printf("result = %u \r", result);

while(TRUE);
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19516

View user's profile Send private message

PostPosted: Sun Oct 25, 2020 1:58 am     Reply with quote

PCM, he says he is using 5.092. I tested with this version, and it has a slightly different error!...
The result of the READBITA call is read from the wrong register on the
second call on this version. Sad
There is a 'sneaky' fix that applies in both cases:

Code:

#include <16F1939.H>

#Fuses HS,NOWDT,PLL_SW
#Fuses PUT,NOMCLR,NOPROTECT,NOCPD
#Fuses BROWNOUT,NOCLKOUT,NOIESO
#Fuses NOFCMEN,NOWRT
#Fuses NOVCAP,NOSTVREN,BORV25
#Fuses NODEBUG,NOLVP

#use delay(clock=12000000)

int i=0;
short out_ [24] =       {0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0};                    // [8] is different.
short out_backup [24] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};                    //
//////////////////////////////// MAIN LOOP /////////////////////////////////////
void main()
{
setup_oscillator(OSC_PLL_OFF);
SETUP_DAC(DAC_OFF);
setup_comparator(NC_NC_NC_NC);
#use rs232(UART1, ERRORS)      // Dit werkt met ICD-U64 en Telnet input 38400b.  5 Sec delay!
     
delay_ms(1000);
printf("Start");
printf("\r\n");   

while(TRUE)
       {
       delay_ms(1000);
       for    (i=16; i>=1; i--)         //   16 t/m 1.
              {
              printf("%u ",i);
              printf("%u ",out_ [i]);
              printf("%u ",out_backup [i]);
              printf(", ");
              if    ( (out_ [i]==TRUE) != (out_backup [i]) )
                    {
                    printf("SOLVED");
                    }
              }
              if    ( (out_ [8]) != (out_backup [8]) )         //Different
                    {
                    printf("8");
                    }
              if    ( (out_ [7]) == (out_backup [7]) )         //Same
                    {
                    printf("7");
                    }       
              printf("\r\n");       
      }
}


Forcing the logic level test makes it store the value correctly.
It is interesting that this has been wrong for a while. It's OK in 5.070,
but wrong in 5.080.

It is interesting, since I have seen 'issues' with using logic tests on bit
variables several times recently, and have started to always use a
test against TRUE/FALSE like this to avoid the problem.
bschriek



Joined: 18 Dec 2007
Posts: 80

View user's profile Send private message Send e-mail

PostPosted: Sun Oct 25, 2020 3:28 am     Reply with quote

Thank you all for your help!

I'm happy it's not because of me but because of a stupid bug.
And it's not the fist time a new Compiler version causes problems

I will use the suggested extra variable for now.
Thanks again,
temtronic



Joined: 01 Jul 2010
Posts: 9228
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Oct 25, 2020 4:43 am     Reply with quote

yeesh, this is a 'bit' much for me....depending on the compiler version a DIFFERENT bug appears.....sigh.
My concern is WHAT happens when the next upgrade is done.....will it work or not ???

While there are 'fixes' to do the bit by bit testing, it seems to me easier to just use bytes. Although it takes 14 more bytes of RAM, it does work and I suspect actual codespace is far less AND faster testing.

Jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19516

View user's profile Send private message

PostPosted: Sun Oct 25, 2020 7:16 am     Reply with quote

You don't need to waste an extra variable. Just do the logic test as I show.
It actually generates what is effectively a 'temporary' variable to hold the
result of the test, but it is in the scratch area, so doesn't waste any RAM. Smile

In fact there is another solution, use XOR (^) instead of !=.
The XOR operator, returns '1' (TRUE), if the two values are different,
but '0' if they are the same. So:

if (out_[i] ^ out_backup [i]) //true if different

Merrily solves the problem, adds no extra variable, and is smaller than
the other solutions. Smile
It actually gives exactly the same code size as the faulty version, but works.
bschriek



Joined: 18 Dec 2007
Posts: 80

View user's profile Send private message Send e-mail

PostPosted: Sun Oct 25, 2020 1:18 pm     Reply with quote

Perfect, thanks.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Nov 02, 2020 3:59 pm     Reply with quote

CCS support says the bug discussed in this thread has been fixed,
per their message below:
Quote:
It has already been fixed for the 5.097 release.
bschriek



Joined: 18 Dec 2007
Posts: 80

View user's profile Send private message Send e-mail

PostPosted: Tue Nov 03, 2020 2:31 am     Reply with quote

Ok but the message "already been fixed" is a bit predictive.
The latest PCW version for download is 5.096.

But let's wait and see when the new version is available.
Many thanks,
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Nov 03, 2020 4:51 am     Reply with quote

They have multiple bugs to fix. They've fixed this one.
They are working on others. When the get them all done, they
will release them as vs. 5.097.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
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