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

16-bit MCUs

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



Joined: 18 Jul 2007
Posts: 427
Location: Montreal,Quebec

View user's profile Send private message

16-bit MCUs
PostPosted: Sun Jan 03, 2016 12:14 pm     Reply with quote

Hi,

I'm still learning the PCD related world regarding optimization.

I was wondering when reading the PIC24 platform datasheet:

I comes with a ALU dealing with multiplying 16 bit ints and dividing too.

It makes me wonder if they are any performance restriction using ONLY 16-bit ints in place where normally I only need a 8-bit one?

I know 16-bit MCUs work/store natively on 16-bit wide data.

Bad idea (beside taking more space)?


Thanks!
_________________
Regards,
Laurent

-----------
Here's my first visual theme for the CCS C Compiler. Enjoy!
Ttelmah



Joined: 11 Mar 2010
Posts: 19497

View user's profile Send private message

PostPosted: Sun Jan 03, 2016 1:03 pm     Reply with quote

Worry more about the data access...

DIV is the big gain MUL has byte wide versions.

However, to access a byte on an odd address, is slower, and more complex than accessing a byte/word on an even address.

The compiler knows and will correctly handle switching to use byte access if you access a byte size object, but if you use a word size object and then try to access this on an odd boundary, you will cause an address error.
So (for instance):
Code:

    char array[6] = { 0, 1, 2, 3, 4, 5 };
    int16 val;
    val=*(int16 *) array+1; //will cause an address error....

This can cause problems when building data arrays for accessing things being passed to/from the outside world. It'll work fine if you use a char pointer (since then byte access will be used), but to access a 16bit value on an odd address, it needs to be read as two byte accesses and then re-constructed.

The same applies with most 'bigger' chips (Intel etc.).

You can use the 'packed' attribute to create data structures for such outside world accesses, but you then have to remember to make sure you do not bypass the compiler's 'knowledge' of the sizes involved (as shown above).
If you use a packed structure for instance, and place an int16 on an odd boundary, the compiler will automatically access this using byte accesses.

The default integer size on PCD, is the int16. CCS here follow the original C manual exactly, by using the basic processor integer size on each chip.
ELCouz



Joined: 18 Jul 2007
Posts: 427
Location: Montreal,Quebec

View user's profile Send private message

PostPosted: Sun Jan 03, 2016 5:15 pm     Reply with quote

Ttelmah wrote:
Worry more about the data access...

DIV is the big gain MUL has byte wide versions.

However, to access a byte on an odd address, is slower, and more complex than accessing a byte/word on an even address.

The compiler knows and will correctly handle switching to use byte access if you access a byte size object, but if you use a word size object and then try to access this on an odd boundary, you will cause an address error.
So (for instance):
Code:

    char array[6] = { 0, 1, 2, 3, 4, 5 };
    int16 val;
    val=*(int16 *) array+1; //will cause an address error....

This can cause problems when building data arrays for accessing things being passed to/from the outside world. It'll work fine if you use a char pointer (since then byte access will be used), but to access a 16bit value on an odd address, it needs to be read as two byte accesses and then re-constructed.

The same applies with most 'bigger' chips (Intel etc.).

You can use the 'packed' attribute to create data structures for such outside world accesses, but you then have to remember to make sure you do not bypass the compiler's 'knowledge' of the sizes involved (as shown above).
If you use a packed structure for instance, and place an int16 on an odd boundary, the compiler will automatically access this using byte accesses.

The default integer size on PCD, is the int16. CCS here follow the original C manual exactly, by using the basic processor integer size on each chip.


Thanks Ttelmah for the explanation!

I've stumbled upon this today when reading the CCS Book (embedded c programming).

Quote:
Structure Layout in Memory

[...]
In a structure with an int8 followed by an int16, the compiler may insert an unused int8 between the two.
[...]
Using packed will prevent any gaps; however, there could also be some implementation problems so care should be used.

** quote is from a copyrighted book but however is very relevant and use fair use.


From your post, packing a struct is not safe because if you access a int which the address is odd (because there is no padding), it will fail??

From what I've understood that normally PCD will manage the "struct alignment" (take more space in RAM/ROM) unless forced to packed attribute but I should be careful with that.

I'm getting confused by the book and your post Embarassed

Thanks!
_________________
Regards,
Laurent

-----------
Here's my first visual theme for the CCS C Compiler. Enjoy!
Ttelmah



Joined: 11 Mar 2010
Posts: 19497

View user's profile Send private message

PostPosted: Mon Jan 04, 2016 1:58 am     Reply with quote

If you access an int16 in a packed structure, then it'll work OK. The compiler will 'know' that it is an int16 on an odd boundary and automatically add the extra code to access it using two byte accesses, and re-construct the data.
However quite significant code/time overhead.
I use these for things like USB, where the data placement is forced upon you.

Where the problem comes is if instead you try to access an item, and override the compiler's 'knowledge' (as I did by changing the pointer to be to an int16, when it was designed to access an int8). So if (for instance) you built a data buffer, and retrieved data from serial, and then tried to retrieve larger objects from this using a pointer as I show.

On the maths, the compiler is smart enough to know that (for instance) performing int8/int8, is done with less code and faster, by actually using the int16 DIV.

Other thing to beware of is that the default integer is signed in PCD. This has varied with some older compiler versions, and is a very good reason to always be explicit on your integer types.

As another comment, it is worth deliberately arranging things to be more efficient, if the locations are not forced by other things. So:
Code:

struct {
   int8 value;
   int16 value1;
   int8 value2;
} demo;

//will be inefficient in it's memory use, actually using 6 bytes, where:
struct {
   int16 value1;
   int8 value;
   int8 value2;
} demo;
//will only use four bytes

So when designing structures etc., always put the elements that are multiples of the alignment size first.
ELCouz



Joined: 18 Jul 2007
Posts: 427
Location: Montreal,Quebec

View user's profile Send private message

PostPosted: Mon Jan 04, 2016 3:16 pm     Reply with quote

Thanks Ttelmah, it's very clear in my head now Smile


After so many years of following this forum, PCM Programmer and you should write a book.

You've got deeper knowledge of PICs that what's found in books! Very Happy
_________________
Regards,
Laurent

-----------
Here's my first visual theme for the CCS C Compiler. Enjoy!
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