Lundin wrote:
It would be great if Freescale made their registers compatible with the C language. C programmers clearing flag registers with read-modify-write
is a very common bug I see in code written for Freescale processors. From a C programming point-of-view, the programmer has done nothing wrong. His code can be fully compatible with ISO C, as well as a bunch
of programming standards for safety-critical systems, yet it contains this bug.
The same applies to oddities such as the SPI and SCI status flags that are cleared by reading the register. The C standard does not cover that.
A read instruction can never be a write instruction, or so you thought before writing code for Freescale micros. Plus, all the debugger
manufacturers are unaware of these registers and like to read them as often as possible, ruining your debug-session. Codewarrior is one example of this.
You can always argue and say that the programmer should know the hardware. But it would be a whole lot easier for people to learn the
hardware if a flag was cleared in a sane way, ie by writing 0 to it. Not by writing 1 to it, or reading it. All three combinations exist in the S12.
IIC1S_IICIF=1; // clear the interrupt event flag;
IIC0_IBSR_IBIF=1; // clear the interrupt event flag;
61: FPROT = 0xFF; /* Disable all protection (only in special modes)*/ 002a c6ff LDAB #255 002c 7b0000 STAB _FPROT 62: 63: FSTAT |= (FSTAT_PVIOL|FSTAT_ACCERR); /* Clear any errors */ 002f 1e00002002 BRSET _FSTAT,#32,*+7 ;abs = 0036 0034 87 CLRA 0035 8f SKIP2 0036 8601 LDAA #1 0038 1e00001002 BRSET _FSTAT,#16,*+7 ;abs = 003f 003d c7 CLRB 003e 21 SKIP1 003f 50 NEGB 0040 37 PSHB 0041 aab4 ORAA 5,SP+ 0043 ba0000 ORAA _FSTAT 0046 7a0000 STAA _FSTAT 64: }
FSTAT |= (FSTAT_PVIOL|FSTAT_ACCERR)
code works out I have attached the Codewarrior listing.
You will see that you end up evaluating the current status of the individual bits into ACCA (result = 0 or 1) and then ORing this into FSTAT.
Now FSTAT bit 0 is not writable so all that effort is wasted. The code still works due to the read modify write sequence on the register.
You may as well just go FSTAT = FSTAT if thats want you really wanted (assuming the optimiser didn't get too smart)
The side effect of this implementation is that the CBEIF flag also gets cleared but this is not immediately obvious looking at the code.
Better still - just code it as FSTAT = (FSTAT_ACCERR_MASK | FSTAT_PVIOL_MASK);:
Cheers
Colin