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 support@ccsinfo.com

How to locate a union at a specific location in memory?
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
matrixofdynamism



Joined: 06 Dec 2010
Posts: 25

View user's profile Send private message

How to locate a union at a specific location in memory?
PostPosted: Mon Mar 21, 2016 5:43 pm     Reply with quote

I want a method by which I can write an SFR as a single byte, as well as write to its individual fields that may or may not be 1 bit in size. An example is the SSP1CON1 SFR. It has 5 fields. The first is 4 bits and is called SSPM while the rest are 1 bit long.

If the SSPM was not 4 bits long, I would have just used #byte and #bit and not even posted this question.

I think that by creating a union I can write to this SFR as SSP1CON1 = 0x00 and also write to its field SSP1CON1.SSPM = 0 or SSP1CON1.CKP = 1. Please correct me if I am thinking wrong. How do I achieve this in CCS PIC C?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Mar 21, 2016 6:52 pm     Reply with quote

This can be done with struct and #byte. Look at this file to see how
it has been done for the CAN bus registers:
Quote:
c:\program files\picc\drivers\can-18f4580.h


If you have the CCS IDE, you can use it to make a register header file:
http://www.ccsinfo.com/forum/viewtopic.php?t=54022&start=1
Ttelmah



Joined: 11 Mar 2010
Posts: 19378

View user's profile Send private message

PostPosted: Tue Mar 22, 2016 1:53 am     Reply with quote

As a general slightly further comment, #byte, can locate any variable at a memory location. So just create the union (if you require this rather than a structure), and then use #byte to locate it. So:
Code:

//Processor setups

typedef struct {
   int8 SSPM:4; //four bits for SSPM
   int8 CKP:1; //one bit for CKP
   int8 SSPEN:1; //SSPEN
   int8 SSPOV:1; //SSPOV
   int8 WCOL:1; //WCOL
} sspcon_layout;

union {
   sspcon_layout smalls; //smalls accesses the bits etc..
   int8 whole; //whole accesses the whole register
} SSPCON;

#byte SSPCON = getenv("SFR:SSPCON1")
//This locates this union at the required address

void main()
{
   //Now you can write a byte to the SSPCON1 register with
   SSPCON.whole = 0x23;
   //Or to the parts with
   SSPCON.smalls.SSPM=0x3;
   SSPCON.smalls.SSPEN=TRUE;
   //and similarly read the parts
   if (SSPCON.smalls.WCOL)
   {
      //here the WCOL bit was set
   }

   while(TRUE)
   {
   }
}
matrixofdynamism



Joined: 06 Dec 2010
Posts: 25

View user's profile Send private message

PostPosted: Tue Mar 22, 2016 2:51 am     Reply with quote

That is interesting I must say. I do not understand why these identifiers for the SFRs do not already exist in the file generated by CCS for their compiler. When I read PIC C programs they often write directly to SFRs as if they were variables.

Could you just clarify 1 thing. When I learnt C language and read about unions which was far into the book and was treated like an archaic topic, it said that bitfields are not used much now since they are "slow" among a few other reasons that make them of little use today. In embedded systems the situation is different and we need to use them often.

Do you think that using bitfields (through #bit or defining them in union or struct as you have done) is slow or that they generate code that is not fully optimized for what it is intended to achieve?
Ttelmah



Joined: 11 Mar 2010
Posts: 19378

View user's profile Send private message

PostPosted: Tue Mar 22, 2016 4:37 am     Reply with quote

Single bit bitfields are fast. The PIC has single instruction operations to access fixed bits in a variable. Makes these code as single instructions.
Multi bit bitfields can be slow. You have to read the variable, mask the rest of the bits, take the value you want to write, rotate this to the right location, and OR this into place. Can be several instructions.

Generally, in CCS C, there is almost no need to ever access a register directly. This is why they don't as standard include the defines for these. You can write in excess of 99% of code, and never have to do this. This is an area where CCS differs wildly from any other compiler. So one answer to your question, is 'learn to program in CCS'.....

Every operation needed on the SSP, can be done without such access.
newguy



Joined: 24 Jun 2004
Posts: 1903

View user's profile Send private message

PostPosted: Tue Mar 22, 2016 7:08 am     Reply with quote

Ttelmah wrote:
Generally, in CCS C, there is almost no need to ever access a register directly. This is why they don't as standard include the defines for these. You can write in excess of 99% of code, and never have to do this. This is an area where CCS differs wildly from any other compiler. So one answer to your question, is 'learn to program in CCS'.....


Just last week I encountered such a situation.

Created an "AC" cable tester. The tester it replaces simply ensures that there are no DC shorts/opens. Problem is that in practice, a cable that tests okay can fail when placed into a real system, carrying data.

I had to tailor the code to do a "DC" sweep of the cable, and if good, proceed to an "AC" sweep. There are only 2 data lines, so I chose a PIC with 2 UARTS and looped the TX to RX for each UART through one of the data lines being tested. The AC test starts at the maximum possible baud rate, then ratchets down the speed if the data can't be discerned at the receiving end.

Could not employ the standard CCS #use rs232(), which I needed to turn on, do the test, then disable. I had to instead take direct control of the UART registers.
Ttelmah



Joined: 11 Mar 2010
Posts: 19378

View user's profile Send private message

PostPosted: Tue Mar 22, 2016 8:36 am     Reply with quote

Actually the standard CCS function can allow you to turn the UART's on/off. Do the standard #USE RS232 function, but set the baud rate to zero.

Then 'setup_uart(baud,stream)' with a baud rate, will enable the UART. setup_uart(FALSE,stream), will disable the UART/stream.
newguy



Joined: 24 Jun 2004
Posts: 1903

View user's profile Send private message

PostPosted: Tue Mar 22, 2016 8:49 am     Reply with quote

Didn't know about the 0 baud trick to disable. Tried just setting the relevant enable bits off.

Main issue was the #use rs232() would set up the serial ports before I wanted them turned on, which prevented accessing those bits individually for the DC test. This was a problem even if the function where the #use rs232() was placed wasn't actually called, only defined.
Ttelmah



Joined: 11 Mar 2010
Posts: 19378

View user's profile Send private message

PostPosted: Tue Mar 22, 2016 9:36 am     Reply with quote

This is where setting it up with baud=0 in the #USE comes in. This doesn't enable the port at the setup time. Only when you then call the uart_setup. Smile
You can also use the option 'NOINIT', and then the baud rate will be setup, but the UART will still not be enabled.
You can then just use setup_uart(TRUE,STREAM); to start it.
matrixofdynamism



Joined: 06 Dec 2010
Posts: 25

View user's profile Send private message

PostPosted: Sun Apr 03, 2016 2:41 pm     Reply with quote

how does one do the following:

(1) How do I create a constant value of arbitrary bit length in this struct e.g how to have two permanent high bits between CKP and SSPEN?

(2) If the struct is not aligned to byte boundary, how do I find out how the final struct shall be like? e.g if I have a 9 bit long struct with the last field being 1 bit long, will it go into the MSB of the second byte or LSB?

(3) Also, what if the last field is 4 bits long and split between the first and second bytes? Will the 2 MSB of this 4 bit field be contiguous with the first 2 bits under all compilers or will they be split apart?

Everyone tells me that the answer to these questions is dependant on the target hardware i.e PIC18 in this case and the compiler. Thus, I am forced to ask this here.
temtronic



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

View user's profile Send private message

PostPosted: Sun Apr 03, 2016 5:21 pm     Reply with quote

The easy answer, one that gains you the most knowledge that you'll remember, is to cut minimal code, compile and look at the listing.
Really, maybe 20 lines fo code and you'll see what is happening.
Not trying to be a smart alec but as you've found out what works for one series of PICs doesn't necessrily hold for another. The listing WILL show you.
Within an hour, after 2 or 3 programs, you'll see your answer AND understand it.

Jay
matrixofdynamism



Joined: 06 Dec 2010
Posts: 25

View user's profile Send private message

OK I will write test programs
PostPosted: Sun Apr 03, 2016 5:29 pm     Reply with quote

I will write test programs and get to the bottom of this. When you say that what holds for one PIC may not hold for another, does that refer to PIC families like PIC10, PIC16, PIC18, PIC24, dsPIC e.t.c?

Don't they all have the same "architecture" so in these specific things they must behave identically?
temtronic



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

View user's profile Send private message

PostPosted: Sun Apr 03, 2016 7:07 pm     Reply with quote

re:
Don't they all have the same "architecture" so in these specific things they must behave identically?

Nope. 16 bit PICs are different than 8 bits and dsPICs, well they are 'fun'. I don't have enough days left to figure out the 'details' of the families, that's why I settled on one 16F and one 18F PIC. Haven't found a product I can't make with them, saves on endless hours of head scratching.

Jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19378

View user's profile Send private message

PostPosted: Mon Apr 04, 2016 12:08 am     Reply with quote

Bitfields fill from the bottom up.
LSb -> MSb
LSB -> MSB

You can't declare bits as 'permanently high'. You just have to declare dummy bits, and _initialise_ these to the value you want.
RF_Developer



Joined: 07 Feb 2011
Posts: 839

View user's profile Send private message

PostPosted: Mon Apr 04, 2016 2:06 am     Reply with quote

matrixofdynamism wrote:
When I learnt C language and read about unions which was far into the book and was treated like an archaic topic, it said that bitfields are not used much now since they are "slow" among a few other reasons that make them of little use today.

and
Quote:
Do you think that using bitfields (through #bit or defining them in union or struct as you have done) is slow


With modern hardware whether they are "slow" or is far less relevant today than it was historically, when processor speeds were far slower an memory far more limited than today.

The speed of implemenation of bitfields, and other stuff, is hgihly dependant on the hardware of the target processor. Processors that provide hardware or microcoded support for single bits, which is reasonably common and very common/standard on processors intended for embedded use, will support some faster bit fields, and probably some slower. I don't know of any processor that ever provided hardware support for arbitrary length bit fields. So, probably, dealing with a seven bit field spread part in one byte and part in another is never going to be "fast", no matter what processor you target. Modern general purpose processors have far less need to process small numbers of bits, so they often don't support it in hardare. Instead they are based around much longer bit data. In most PC processors, dealing with bytes is considerably slower than dealing with 32 or even 64 bit words: for overall portability it's best to use int for loop counters even for counts of tess than ten as the int, regardless of what the actual length, will generally be the "native" and most efficient of all the data types.

But, I repeat, speed is - generally - not all that important. A lot of beginning embedded coders seem to be obsessed with speed, and treat it as the only thing that matters. They use "fast_io", generally without understanding what it does and what is required for it's use, because, presumably, it is "fast". Whereas experienced CCS programmers almost never use it, and will only use it if its absolutely necessary.

Quote:
In embedded systems the situation is different and we need to use them often.


I'm not so sure that's really the case. Yes, they can be useful, but they can also be confusing, suffer from alignment issues and limitations, and are often not portable without modification from one architecture to another. Multiple bit fields (fields of more than one bit) suffer from implementation peculiarities, such as requiring hidden behind the scenes read-modify-writes which can mess up their use, especially with SFRs.

I rarely use bitfields. When I do, I tend to soon change to another method of implementation for one reason or another.

Quote:
they generate code that is not fully optimized for what it is intended to achieve?


No matter what you do, using any high level language will produce code that is not "fully optimised". There are also optimisation tradeoffs, generally memory for speed. As I said above, raw speed is generally not worth chasing. Optimisation is not the be all and end all of coding. The best "optimisation" gains are most often acheived not by worrying about the detail, but by developing efficient algorithms and avoiding unnecessary work. Essentially, what I am saying is that its best to learn how to program efficiently, and only then is it worth worrying about fine tweaking code for optimal performance.

So, why do you need "optimal" handling of bitfields? Note I write "need", not "want".
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