This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

bitfield in union and compile problem

Dear Sir, I have a problem about the union and bitfiled. I always suffer a strange problem in my system.
After I check the M51 file, I start to doubt that it is the bitfield and union problem in compile stage.
please see my code as below, I declare the union and macros in header file.

Question:
Please see the line 1198, I call the macro Drv_ClearRxEnd(). At C:0x1AE3, it calls the C:269D.
At C:0x269E ANL A,#IRCON2(0xBF)
I don't know why to use the SFR register(IRCON2) to clear it.

Could you give me some clues? Thank you.

In Header file: 
typedef union{
    U8 u8IsrStatus;
    struct{
        U8 cc_tx_start:1; //set by ISR, clear by SW  //LSB
        U8 cc_tx_end:1; //set by ISR, clear by SW
        U8 busbusy:1; //set by ISR, clear by SW
        U8 HardResetSignaling:1;
        U8 CableResetSignaling:1;
        U8 cc_rx_start:1; //set by ISR, clear by SW
        U8 cc_rx_end:1; //set by ISR, clear by SW
        U8 pluginout:1; //set and clear by ISR        //MSB
    }Bits;
}ISR_STATUS;

extern ISR_STATUS volatile sISR_Status;
#define Drv_GetCableRst()     (sISR_Status.Bits.CableResetSignaling)
#define Drv_GetHardRst()      (sISR_Status.Bits.HardResetSignaling)
#define Drv_GetRxEnd()        (sISR_Status.Bits.cc_rx_end)
#define Drv_ClearRxStart()    {sISR_Status.Bits.cc_rx_start=0;}
#define Drv_ClearRxEnd()      {sISR_Status.Bits.cc_rx_end=0;}

#define Drv_ClearRxStart()    {WRITE_SFR_REG(LCD_LN0_4,0xBB);WRITE_SFR_REG(LCD_LN0_4,0xBB);sISR_Status.Bits.cc_rx_start=0;WRITE_SFR_REG(LCD_LN0_4,0xBB);WRITE_SFR_REG(LCD_LN0_4,0xBB);}
#define Drv_ClearRxEnd()      {WRITE_SFR_REG(LCD_LN0_4,0xBC);WRITE_SFR_REG(LCD_LN0_4,0xBC);sISR_Status.Bits.cc_rx_end=0;WRITE_SFR_REG(LCD_LN0_4,0xBC);WRITE_SFR_REG(LCD_LN0_4,0xBC);}



In M51 file:
C:0x1A72    900368   MOV      DPTR,#sISR_Status(0x0368) 
C:0x1A75    E0       MOVX     A,@DPTR
C:0x1A76    F5B4     MOV      LCD_LN0_4(0xB4),A
C:0x1A78    E0       MOVX     A,@DPTR
C:0x1A79    F5B4     MOV      LCD_LN0_4(0xB4),A
  1179:             WRITE_SFR_REG(LCD_LN0_4,0xFD);WRITE_SFR_REG(LCD_LN0_4,0xFD);
  1180: #endif
  1181:
  1182:
C:0x1A7B    75B4FD   MOV      LCD_LN0_4(0xB4),#0xFD
C:0x1A7E    75B4FD   MOV      LCD_LN0_4(0xB4),#0xFD
  1183:             if(Drv_GetRxEnd() && !Drv_GetHardRst() && !Drv_GetCableRst()) 
C:0x1A81    E0       MOVX     A,@DPTR
C:0x1A82    20E603   JB       0xE0.6,C:1A88 
C:0x1A85    021C5F   LJMP     C:1C5F
C:0x1A88    E0       MOVX     A,@DPTR
C:0x1A89    30E303   JNB      0xE0.3,C:1A8F 
C:0x1A8C    021C5F   LJMP     C:1C5F
C:0x1A8F    E0       MOVX     A,@DPTR
C:0x1A90    30E403   JNB      0xE0.4,C:1A96 
C:0x1A93    021C5F   LJMP     C:1C5F
  1184:             {
  1185:                 DEBUG_PRLRX(0xAF);
  1186:
  1187:               #if PRINTF_MSG_HEADER_RX
C:0x1A96    75B5AF   MOV      LCD_LN0_5(0xB5),#0xAF

......Omit.......

  1198:                 Drv_ClearRxEnd(); 
C:0x1ADD    1226A1   LCALL    L?0396(C:26A1)
C:0x1AE0    900368   MOV      DPTR,#sISR_Status(0x0368)
C:0x1AE3    12269D   LCALL    L?0395(C:269D)
  1199:                 Drv_ClearRxStart();
  1200:
  1201:
C:0x1AE6    75B4BB   MOV      LCD_LN0_4(0xB4),#S1RELH(0xBB)
C:0x1AE9    75B4BB   MOV      LCD_LN0_4(0xB4),#S1RELH(0xBB)
C:0x1AEC    E0       MOVX     A,@DPTR
C:0x1AED    54DF     ANL      A,#0xDF
C:0x1AEF    F0       MOVX     @DPTR,A
C:0x1AF0    75B4BB   MOV      LCD_LN0_4(0xB4),#S1RELH(0xBB)
C:0x1AF3    75B4BB   MOV      LCD_LN0_4(0xB4),#S1RELH(0xBB)


C:0x26A1    75B4BC   MOV      LCD_LN0_4(0xB4),#0xBC
C:0x26A4    75B4BC   MOV      LCD_LN0_4(0xB4),#0xBC
C:0x26A7    22       RET


C:0x269D    E0       MOVX     A,@DPTR
C:0x269E    54BF     ANL      A,#IRCON2(0xBF)
C:0x26A0    F0       MOVX     @DPTR,A
C:0x26A1    75B4BC   MOV      LCD_LN0_4(0xB4),#0xBC
C:0x26A4    75B4BC   MOV      LCD_LN0_4(0xB4),#0xBC
C:0x26A7    22       RET

  • I don't know why to use the SFR register(IRCON2) to clear it.

    It doesn't. The disassembler just referred to IRCON2 as a possible interpration of the raw value 0xBF. Whatever your undisclosed "strange problem" might be: this is has nothing to do with it.

  • Thanks for your reply.
    After I change the declaration as below,
    the system is more stable and I don't see the problem happened.
    Could I use union in 8051? Or should I do anything for union? Thanks.

    typedef union{
        U8 u8IsrStatus;
        struct{
            U8 cc_tx_start:1; //set by ISR, clear by SW  //LSB
            U8 cc_tx_end:1; //set by ISR, clear by SW
            U8 busbusy:1; //set by ISR, clear by SW
            U8 HardResetSignaling:1;
            U8 CableResetSignaling:1;
            U8 cc_rx_start:1; //set by ISR, clear by SW
            U8 cc_rx_end:1; //set by ISR, clear by SW
            U8 pluginout:1; //set and clear by ISR        //MSB
        }Bits;
    }ISR_STATUS;
    
    Change to....
    
    typedef struct{
        U8 u8IsrStatus;
        struct{
            U8 cc_tx_start; //set by ISR, clear by SW  //LSB
            U8 cc_tx_end; //set by ISR, clear by SW
            U8 busbusy; //set by ISR, clear by SW
            U8 HardResetSignaling;
            U8 CableResetSignaling;
            U8 cc_rx_start; //set by ISR, clear by SW
            U8 cc_rx_end; //set by ISR, clear by SW
            U8 pluginout; //set and clear by ISR        //MSB
        }Bits;
    }ISR_STATUS;
    
    
    

  • Your code could be a lot easier to follow:

    typedef union{
        U8 u8IsrStatus;
        struct{
            U8 cc_tx_start:1;         //set by ISR, clear by SW  //LSB
            U8 cc_tx_end:1;           //set by ISR, clear by SW
            U8 busbusy:1;             //set by ISR, clear by SW
            U8 HardResetSignaling:1;
            U8 CableResetSignaling:1;
            U8 cc_rx_start:1;         //set by ISR, clear by SW
            U8 cc_rx_end:1;           //set by ISR, clear by SW
            U8 pluginout:1;           //set and clear by ISR     //MSB
        }Bits;
    }ISR_STATUS;
    
    Change to....
    
    typedef struct{
        U8 u8IsrStatus;
        struct{
            U8 cc_tx_start;         //set by ISR, clear by SW  //LSB
            U8 cc_tx_end;           //set by ISR, clear by SW
            U8 busbusy;             //set by ISR, clear by SW
            U8 HardResetSignaling;
            U8 CableResetSignaling;
            U8 cc_rx_start;         //set by ISR, clear by SW
            U8 cc_rx_end;           //set by ISR, clear by SW
            U8 pluginout;           //set and clear by ISR     //MSB
        }Bits;
    }ISR_STATUS;
    

    You have made two major changes there:
    1. Changing 'Bits' from a bitfield to a "plain" structure;
    2. Changing 'ISR_Status' from a union to a structure.

    "I don't see the problem happened"

    I'm still not clear what actual "problem" you were having?

    "Could I use union in 8051?"

    Keil C51 certainly supports unions.

    Whether its support of bitfields is particularly effecient is another question.

    If you're after efficiency in grouping this collection of bits, then use a bit-addressable object:

    http://www.keil.com/support/man/docs/c51/c51_le_bitaddrobj.htm