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

peripheral register access RMW vs Bit Banding

Hello Forum,

I'am porting a USB base driver from 16Bit CISC MCU to Cortex M3 MCU.

For set/clear peripheral registers at the CISC MCU I've used C-Standard RMW Operations (|=, &=) which resulted in atomic bit operations.

During porting I’ve used the also the RMW operations, because some registers are used exclusively in the interrupt context, there is no context switch. So my thought is that RMW is sufficient for set/clear bits in peripheral register.

Example this shows the problem:

This instruction sequence ( Bit Clear) fails to clear the interrupt factor (including asm mixed mode view)

*EPnS0 &= ~MASK_EPS_DRQ;      //  Interrupt bestätigen
       0x4ea8: 0xf8ba 0x1000  LDRH.W    R1, [R10]
       0x4eac: 0xf64f 0x30ff  MOVW      R0, #64511              ; 0xfbff
       0x4eb0: 0x4001         ANDS      R1, R1, R0
       0x4eb2: 0xf8aa 0x1000  STRH.W    R1, [R10]
*EPnS0 |= MASK_EPS_DRQIE;      //  Sendeinterrupt einschalten
       0x4eb6: 0xf8ba 0x0000  LDRH.W    R0, [R10]
       0x4eba: 0xf450 0x4080  ORRS.W    R0, R0, #16384          ; 0x4000
       0x4ebe: 0xf8aa 0x0000  STRH.W    R0, [R10]

This instruction sequence do the job correctly:

bFM3_USB0_EP1S_DRQ = 0;
       0x4ec2: 0x2000         MOVS      R0, #0
       0x4ec4: 0xf8df 0x17e4  LDR.W     R1, [PC, #0x7e4]        ; 0x428429a8 (1115957672)
       0x4ec8: 0x6008         STR       R0, [R1]
bFM3_USB0_EP1S_DRQIE = 1;
       0x4eca: 0x2001         MOVS      R0, #1
       0x4ecc: 0xf8df 0x17e0  LDR.W     R1, [PC, #0x7e0]        ; 0x428429b8 (1115957688)
       0x4ed0: 0x6008         STR       R0, [R1]
       0x4ed2: 0xe00c         B.N       0x4eee

The MPU Setup for the MCU peripheral Area is

    //  Peripherals + 32Mbyte Bit band alias

    MPU->RBAR = ARM_MPU_RBAR(3, 0x40000000);       

    MPU->RASR = ARM_MPU_RASR(1, ARM_MPU_AP_FULL, 0, 1, 0, 1, 0, ARM_MPU_REGION_SIZE_64MB);

 

As far as I know bit banding is necessary to prevent race conditions between shared context accesses of any memory/peripheral area. The section decribed above is only access during the peripherals interrupt Handler.

Why the RMW Operations fails and bit band operation do the correct job in this case?

 

Regards

Lorenz

*EPnS0 &= ~MASK_EPS_DRQ;      //  Interrupt bestätigen
       0x4ea8: 0xf8ba 0x1000  LDRH.W    R1, [R10]
       0x4eac: 0xf64f 0x30ff  MOVW      R0, #64511              ; 0xfbff
       0x4eb0: 0x4001         ANDS      R1, R1, R0
       0x4eb2: 0xf8aa 0x1000  STRH.W    R1, [R10]
*EPnS0 |= MASK_EPS_DRQIE;      //  Sendeinterrupt einschalten
       0x4eb6: 0xf8ba 0x0000  LDRH.W    R0, [R10]
       0x4eba: 0xf450 0x4080  ORRS.W    R0, R0, #16384          ; 0x4000
       0x4ebe: 0xf8aa 0x0000  STRH.W    R0, [R10]