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

Interesting phenomenon based on compiler versions

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
hello188



Joined: 02 Jun 2010
Posts: 74

View user's profile Send private message

Interesting phenomenon based on compiler versions
PostPosted: Sat Oct 20, 2012 2:54 am     Reply with quote

Hi. I had working code that was compiled using version PCM 4.137

I gave it to my colleague and he complained that it was not working.
I checked his compiler version, and it was 4.132.

So, after about an hour of debugging, I found out the problem.

On compiler version 4.132, the following set of codes seem to translate differently.

Below code works on PCM 4.137, but not on PCM 4.132. Simply put, arr[i] is not equal to TX1_buffer[i] when called except when i = 0.
Code:
//Not working code

void send_bytes1(uint8_t arr[], uint8_t length){
    uint8_t i;
    uint8_t buffer8;
    for(i=0; i<length; i++){
       buffer8 = arr[i];
       bputc1(buffer8);
    }   
}

send_bytes1(TX1_buffer, _BUFFER_LENGTH);


However, below code works fine on both compiler versions
Code:
//Working code

void send_bytes1(uint8_t * arr, uint8_t length){
    uint8_t i;
    uint8_t buffer8;
    for(i=0; i<length; i++){
       buffer8 = *(arr + i);
       bputc1(buffer8);
    }   
}

send_bytes1(&TX1_buffer[0], _BUFFER_LENGTH);


What's the difference between the two approach? other than the fact that they look different? Internally, when the are being translated, what happens differently that makes one code work and the other don't?

I thought it was interesting and worth letting you guys know.

Any ideas??

Thanks
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Sat Oct 20, 2012 4:01 am     Reply with quote

It suggests that the subroutine, does not think uint8_t is the same size as the main code does. This is defined in stdint.h. Is it possible that some file is getting included that changes the definitions of this?.
You don't say what chip?. On PCD, an 'int' is an int16, so an old include that has a line like:

typedef unsigned int uint8_t;

on this compiler would cause this type of problem. However you say PCM, which should not do this.

If you want to experiment, try using the 'internal' types, rather than the typedef ones, so 'int8', and see if the problem disappears. It may well be a problem with .132, which is a version I didn't download. Unfortunately CCS's 'fix list' is always so incomplete that it is basically useless, so something like this might have been fixed a version or two late. I tried on an older version, and both approaches seem the same, and on 4.134, where it also seems OK. Also make sure that the project is using the same stdint.h, though this seems to have been unchanged since 2008, and is the same in 3.137 at in much older compilers....
Do a project search and make sure there is not another definition for uint8_t anywhere.

Best Wishes
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Sat Oct 20, 2012 4:12 am     Reply with quote

The problem can't be determined unless you show your definition of uint8_t and TX1_buffer.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Oct 20, 2012 1:26 pm     Reply with quote

All of this really should have been kept in the orginal thread, but anyway...

I made a test program to test the two methods of passing an array,
and definitely vs. 4.132 has a problem. You can see that the array[]
method produces partial garbage as the output.

With vs. 4.137:
Quote:
array[] : 123
*array : 123


With vs. 4.132
Quote:
array[]: 13@@
*array: 123


Test program:
Code:

#include <18F4520.h>
#fuses HS, NOWDT
#use delay(clock=20M)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)

#define T1_BUFFER_SIZE 64

int8 t1_buffer[T1_BUFFER_SIZE] = {"123"};
int8 t1_next_in = 0;
int8 t1_next_out = 0;

//----------------------------------
void bputc1(int8 c)
{
putc(c);
}

//----------------------------------
void send_bytes1(int8 array[], int8 length)
{
int8 i;

for(i=0; i<length; i++)
    bputc1(array[i]);
}

//----------------------------------
void send_bytes2(int8 *array, int8 length)
{
int8 i;

for(i=0; i<length; i++)
    bputc1(array[i]);
}

//======================================
void main()
{

printf("array[ ]: ");
 send_bytes1(t1_buffer, sizeof(t1_buffer));
printf("\r");

printf("*array: ");
send_bytes2(t1_buffer, sizeof(t1_buffer));
printf("\r\r");

while(1);
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Sun Oct 21, 2012 2:13 am     Reply with quote

If you study the result, it looks like .132, is treating the array elements as being int16 in size. So the first entry returns '1', then it jumps forward _two_ bytes, and returns the '3' that is the third character, then goes two characters further, and gets to garbage....
Glad I avoided 132!....

Best Wishes
neil



Joined: 08 Sep 2003
Posts: 128

View user's profile Send private message

byte boundaries within words screwed up!
PostPosted: Wed Oct 24, 2012 6:32 am     Reply with quote

This is very interesting! I have not written any code for about 3 years and had to revisit an old project.
I found that I was getting garbage results for many of my functions which had previously worked. This was causing all sorts of headaches trying to track down the reason.
I found the reason to be similar to the problem in this post.

For years I have used direct addressing of bytes in an int16 (long) using the old macro:
Code:
 #define hi(x) *(&x+1)
Suddenly this no longer worked at all. Inspecting the ASM seemed to indicate that indirect addressing was being used (despite only being for 2 bytes - inefficient?) and the offset was being incremented as if an int8 was an int16, so pointing to the next variable in ram, rather than the high byte of the same variable.
I removed this code and instead implemented a union:
Code:
 union byteexchange{
      long word;
      int bytes[2];
   };

This then produced the kind of ASM I was expecting for the other method - directly accessing the bytes within the word.
I am using V4.093 and this problem exists both in PCM and PCH!
Has anyone experienced this with this compiler version?

Regards,
Neil.
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

Re: byte boundaries within words screwed up!
PostPosted: Wed Oct 24, 2012 7:12 am     Reply with quote

neil wrote:
This is very interesting! I have not written any code for about 3 years and had to revisit an old project.
I found that I was getting garbage results for many of my functions which had previously worked. This was causing all sorts of headaches trying to track down the reason.
I found the reason to be similar to the problem in this post.

For years I have used direct addressing of bytes in an int16 (long) using the old macro:
Code:
 #define hi(x) *(&x+1)
Suddenly this no longer worked at all. Inspecting the ASM seemed to indicate that indirect addressing was being used (despite only being for 2 bytes - inefficient?) and the offset was being incremented as if an int8 was an int16, so pointing to the next variable in ram, rather than the high byte of the same variable.
I removed this code and instead implemented a union:
Code:
 union byteexchange{
      long word;
      int bytes[2];
   };

This then produced the kind of ASM I was expecting for the other method - directly accessing the bytes within the word.
I am using V4.093 and this problem exists both in PCM and PCH!
Has anyone experienced this with this compiler version?

Regards,
Neil.


Your problem is different, and well documented. It is in the 'readme' that comes with the compiler...

The V4 compilers switched to being fully 'C' compliant in the way they handle pointers. So a pointer to a int16, if incremented, increments by the size of an int16. This is _standard_ in C. The older compilers were getting this wrong.

Code:

#define hi(x) *(((int8 *)&x)+1)

You have to tell the compiler you want to treat the pointer as being to individual bytes, so it then works.

Quote from the readme.txt:
"Users that have old code with expressions of the form:
*(&data + i)
need to change them to:
*((int8 *)(&data) + i)
A compiler change was made to be ANSI compliant. "

Best Wishes
neil



Joined: 08 Sep 2003
Posts: 128

View user's profile Send private message

PostPosted: Wed Oct 24, 2012 7:17 am     Reply with quote

Oops! Embarassed should have RTFM'd Thanks for clearing that up though!
Neil.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
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