| View previous topic :: View next topic | 
	
	
		| Author | Message | 
	
		| bilko 
 
 
 Joined: 17 Oct 2003
 Posts: 24
 Location: Dorset, UK
 
 
			    
 
 | 
			
				| union struct problem |  
				|  Posted: Mon Aug 29, 2011 2:56 am |   |  
				| 
 |  
				| I maybe being stupid but ..... the following code seems to compile to nonsense Using PCD
 
 
  	  | Code: |  	  | typedef union {
 struct {
 //As written by software
 uint16      Addr;
 unsigned    byteCount   :10;
 unsigned    BSTALL      :1;
 unsigned    DTSEN      :1;
 unsigned    n28         :2;
 unsigned    DTS         :1;
 unsigned    UOWN      :1;
 } softBits;
 struct {
 //As written by software
 uint16      Addr;
 uint16      config;
 } soft;
 struct {
 //As written by hardware
 uint16      Addr;
 unsigned    byteCount   :10;
 unsigned    PID         :4;
 unsigned    DTS         :1;
 unsigned    UOWN      :1;
 } hardbits;
 } usbBdType;
 
 typedef struct {
 usbBdType   rx[2];
 usbBdType   tx[2];
 } usbBdEpType;
 
 #define   usbBDTaddr   0x2000
 usbBdEpType   usbBDT[16];
 #LOCATE usbBDT=usbBDTaddr
 
 | 
 
 The following seems to compile correctly:
 
  	  | Quote: |  	  | .................... 	usbBDT[0].rx[0].soft.Addr=&Uep0RxBuf[0];
 041CA:  MOV     #AF8,W4
 041CC:  MOV     W4,2000
 
 | 
 
 BUT does the following make any sense to anybody??
 
  	  | Quote: |  	  | .................... 	usbBDT[0].rx[0].softbits.byteCount=0x10;
 041DA:  MOV     #FC00,W0
 041DC:  AND     2
 041DE:  MOV     #10,W0
 041E0:  IOR     2
 
 | 
 |  | 
	
		|  | 
	
		| jeremiah 
 
 
 Joined: 20 Jul 2010
 Posts: 1401
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Mon Aug 29, 2011 6:51 am |   |  
				| 
 |  
				| It depends on what PIC you are using (you didn't specify what PIC or what compiler rev you are using). 
 The 2nd and 3rd instruction you listed there do look kinda pointless, but depending on what the rest of the instructions you don't show do, it might be ok.
 
 #FC00 looks to be a mask value for all of the data fields except for byteCount.  The other instructions just put the value of #2 in the byteCount field.
 
 The:
 041DC: AND 2
 041DE: MOV #10,W0
 
 Look like they are just extra, but that's without knowing the PIC, the compiler revision, and the rest of your program.  It could just be a generic way of handling data going into a bitfield in a struct, which is overkill for most scenarios but necessary for some other edge case.   That's just speculation on my part, though.
 
 The one that looks ok looks better because you are copying to a bit field that is already 16 bits, so it has a cleaner instruction methodology.
 |  | 
	
		|  | 
	
		| bilko 
 
 
 Joined: 17 Oct 2003
 Posts: 24
 Location: Dorset, UK
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Mon Aug 29, 2011 9:04 am |   |  
				| 
 |  
				| FWIW it's a PIC24FJ256GB110 |  | 
	
		|  | 
	
		| ckielstra 
 
 
 Joined: 18 Mar 2004
 Posts: 3680
 Location: The Netherlands
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Mon Aug 29, 2011 4:24 pm |   |  
				| 
 |  
				| I don't know the PIC24 or it's hardware, but I've seen lot of assembler code for other processors and to me the code looks all right. 
 The code is incomplete, but address 2 is containing usbBDT[0].
 The first two instructions use the value 0xFC00 as a filter to set the lower 10 bits to zero, i.e. the ByteCount part.
 Then the instructions 3 and 4 are used to load the value 0x10 into ByteCount.
 
 The code is cryptic, but this is about the best you can expect. Working with bitfields results in efficient RAM use but requires a lot more code to set and extract the data. Aligning the bitfields to 8-bit boundaries will result in more efficient code.
 |  | 
	
		|  | 
	
		| bilko 
 
 
 Joined: 17 Oct 2003
 Posts: 24
 Location: Dorset, UK
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Tue Aug 30, 2011 5:12 am |   |  
				| 
 |  
				| usbBDT[0] is at address 0x2000 (see the #LOCATE in the code)
 |  | 
	
		|  | 
	
		| FvM 
 
 
 Joined: 27 Aug 2008
 Posts: 2337
 Location: Germany
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Tue Aug 30, 2011 8:03 am |   |  
				| 
 |  
				| Some of the above comments show a certain unawareness to PIC24 instruction set. 
 Actually the compiler is accessing data memory location 0x0002 (an SFR address!) instead of 0x2002. It's obviously a PCD bug, it can be still reproduced with most recent V4.124.
 
 The problem arises, if the variable is located in the 0x2000 to 0x21FF range and specific operations, in this case mask operations for bitfields are performed. The compiler erroneously acesses the variable with near data space instructions, stripping upper address bits.
 
 If you locate the variable at 0x2200, the problem disappears.
 
 You should file a bug report to CCS support.
 |  | 
	
		|  | 
	
		| bilko 
 
 
 Joined: 17 Oct 2003
 Posts: 24
 Location: Dorset, UK
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Tue Aug 30, 2011 8:44 am |   |  
				| 
 |  
				| Wilco, thank you. |  | 
	
		|  | 
	
		|  |