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