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

Problem with struct fields with pointers

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








Problem with struct fields with pointers
PostPosted: Thu Jun 19, 2008 2:13 pm     Reply with quote

I am trying to write a driver for the CAN module for the dsPic30F6012A (because there is no support for it that I am aware of). I am using PCD version 4.068.

I have unions/structs defined for the registers of the CAN module like this:
Code:
typedef union {
   struct {
      int1 void0:1;//bit0 read as 0
      int ICODE:3;//Interrupt Flag code bits
      int void4:1;//bit4 read as 0
      int OPMODE:3;//Operation mode bits
      int REQOP:3;//Request operation mode
      int CANCKS:1;//CAN Master Clock select
      int ABAT:1;//Abort all pending transmissions bit
      int CSIDL:1;//Stop in idle mode bit
      int void14:1;
      int CANCAP:1;//CAN message receive capture enable bit
   } ;
   int16 Word;
}CiCTRL;
CiCTRL C1CTRL;
#word C1CTRL = 0x0390


I then try to access the register via a pointer as follows for example...

Code:
CiCTRL * ctrl;
ctrl = &C1CTRL;
ctrl->CANCAP = 1;


This does not work. trying to modify CANCAP by using C1CTRL.CANCAP = 1 works just fine.

Looking at the assembled code from the list file, it is obvious that it will not work.

Code:
....................    ctrl->CANCAP = 1;
004F2:  MOV     #1,W0
004F4:  ADD     8CE,W0  //8CE is the address of the pointer 'ctrl' I think
004F6:  MOV     W0,W5
004F8:  MOV     #FFFF,W0
004FA:  AND     57
004FC:  SL      W5,#E,W0
004FE:  AND     #3FF,W0
00500:  IOR     57


nowhere in that assembled code does it even try to do any form of indirect addressing, which would be necessary to modify data from a pointer.

It should be able to just do something like this:
Code:
MOV 8CE,W0
BSET [W0],#F


if I try to access a different field, perhaps one that is not just one bit:
Code:
int16 op;
op = 2;
ctrl->REQOP = op;

Code:
....................    ctrl->REQOP = op;
00582:  MOV     #1,W0
00584:  ADD     8CE,W0 //Add 1 to ctrl pointer, OK, now at upper byte of C1CTRL word
00586:  MOV     W0,W5
00588:  MOV     #FFF8,W0          //OK, clears the 3 bits associated with REQOP
0058A:  AND.B   W0L,[W5],[W5] //preparing to write in the new value...
0058C:  MOV.B   8D0,W0L   //move 'op' to W0L
0058E:  AND.B   #F8,W0L    //clears the 3 bits I need for REQOP?? this should be AND.B #07,W0L
00590:  IOR.B    W0L,  [W5],[W5]

The problem with this is that it ands the 'op' value with #F8, when it should be ANDing it with the inverse of #F8 (Actually even if it did, that this code would still not functionally work because of the nature of this control register, but that is besides the point).

If I try to change REQOP directly by doing
ctrl->REQOP = 2;
that works fine.

Also doing ctrl->CANCAP vs. (*ctrl).CANCAP makes no difference

One more example: (*ctrl).Word |= 0x8000;
Code:
....................    (*ctrl).Word |=0x8000;
0054C:  MOV     8CE,W0 //put pointer address in W0
0054E:  MOV     W0,W5 //move W0 to W5...?
00550:  ADD     W5,#0,W5  //add 0 to W5....??
00552:  MOV     W5,W6  //.....move W5 to W6......?
00554:  MOV     #8000,W0  //OK, put 0x8000 in W0
00556:  IOR      W0,  [W6],W0 //OR 0x8000 with [W6] this is good...
00558:  SUB.B   W6L,#2,W6L //subtract 2 from my pointer address....why?
0055A:  MOV.B   W6L,[W6] //put the low byte of the pointer address in the pointer location???
0055C:  MOV.B   #0,W0L //put 0 in W0L
0055E:  MOV.B   W0L,[W6+#0]//put W0L (0) in [W6]?? what?

I have stepped through with the debugger while observing the RAM and this definitely does not work.

Has anyone else had any problems using pointers with structs/unions?
Is this actually a compiler problem or am I just doing something stupid?
Ttelmah
Guest







PostPosted: Thu Jun 19, 2008 3:11 pm     Reply with quote

What happens if you simplify the declarations without using typedef?. I have had problems at times with typedef, and pointers, and feel it is safer to run without it, especially for pointer operations. So:
Code:

union Cictrl {
   struct {
      int void0:1;//bit0 read as 0
      int ICODE:3;//Interrupt Flag code bits
      int void4:1;//bit4 read as 0
      int OPMODE:3;//Operation mode bits
      int REQOP:3;//Request operation mode
      int CANCKS:1;//CAN Master Clock select
      int ABAT:1;//Abort all pending transmissions bit
      int CSIDL:1;//Stop in idle mode bit
      int void14:1;
      int CANCAP:1;//CAN message receive capture enable bit
   };
   int16 Word;
}C1CTRL;
//As a comment, use _either_ int1, or a bit field, not both

union Cictrl C1CTRL;
#word C1CTRL = 0x0390

union Cictrl *ctrl;

ctrl = &C1CTRL;
ctrl->fields.CANCAP = 1;


I'd quite expect it to be a compiler problem.
Does it change if you use *, rather than -> to access the element?.

So:

(*ctrl).CANCAP=1;

Even on the more mature versions of the compiler, operations wit pointers and typedef, sometimes go completely potty, s I'm not at all surprised f the 'D' version is even worse here.... :-(

Try giving the structure a name. The 'anonymous' form you are using, is a relatively recent addition to the compiler's (supposed) abilities, and I'd not be surprised if this caused problems. So:
Code:

typedef union {
   struct {
      int void0:1;//bit0 read as 0
      int ICODE:3;//Interrupt Flag code bits
      int void4:1;//bit4 read as 0
      int OPMODE:3;//Operation mode bits
      int REQOP:3;//Request operation mode
      int CANCKS:1;//CAN Master Clock select
      int ABAT:1;//Abort all pending transmissions bit
      int CSIDL:1;//Stop in idle mode bit
      int void14:1;
      int CANCAP:1;//CAN message receive capture enable bit
   } fields;
   int16 Word;
}CiCTRL;
CiCTRL C1CTRL;
#word C1CTRL = 0x0390

CiCTRL * ctrl;
ctrl = &C1CTRL;
ctrl->fields.CANCAP = 1;

You may well find this forces the compiler to understand what is wanted.

Best Wishes
kemp05jeff



Joined: 19 Jun 2008
Posts: 1

View user's profile Send private message

PostPosted: Thu Jun 19, 2008 3:28 pm     Reply with quote

Thanks for your reply,
I have tried this:
Code:
union CiCTRL{
   struct {
      int1 void0:1;//bit0 read as 0
      int ICODE:3;//Interrupt Flag code bits
      int void4:1;//bit4 read as 0
      int OPMODE:3;//Operation mode bits
      int REQOP:3;//Request operation mode
      int CANCKS:1;//CAN Master Clock select
      int ABAT:1;//Abort all pending transmissions bit
      int CSIDL:1;//Stop in idle mode bit
      int void14:1;
      int CANCAP:1;//CAN message receive capture enable bit
   }Fields ;
   int16 Word;
};
union CiCTRL C1CTRL;
#word C1CTRL = 0x0390
............
union CiCTRL *ctrl
........
ctrl->Fields.CANCAP = 1;

this generates:
Code:
....................    ctrl->Fields.CANCAP = 1;
0049A:  MOV     #1,W0
0049C:  ADD     8CE,W0
0049E:  MOV     W0,W5
004A0:  MOV     #FFFF,W0
004A2:  AND     57
004A4:  SL      W5,#E,W0
004A6:  AND     #3FF,W0
004A8:  IOR     57

which Is exactly the same as before.

Here is (*ctrl).Fields.CANCAP = 1:
Code:
....................    (*ctrl).Fields.CANCAP = 1;
004CA:  MOV     8CE,W0
004CC:  MOV     W0,W5
004CE:  ADD     W5,#1,W5
004D0:  MOV     W5,W6
004D2:  MOV     #FFFF,W0
004D4:  AND     77
004D6:  SL      W6,#E,W0
004D8:  AND     #3FF,W0
004DA:  IOR     77

It is slightly different, but just as wrong...
Ttelmah
Guest







PostPosted: Fri Jun 20, 2008 2:02 am     Reply with quote

You still have the int1 and field width definitions, used together, which is not really 'legal'. However I doubt if this is the problem.
You need to make an error report to CCS.

Best Wishes
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