[Solved] IO port bit access problem
IO port bit access problem
Compiler does not use “bset/bclr” to access BIT.B7 . It causes read-modify-write problem.
Compiler version: rx-elf-gcc.exe (GCC_Build_20170913) 4.8.4.201703-GNURX
1 .file “test.cpp”
2 .section P,”ax”
3 .Ltext0:
4 .global __Z4testv
6 __Z4testv:
7 .LFB0:
8 .file 1 “../src/test.cpp”
1:../src/test.cpp **** #include “iodefine.h”
2:../src/test.cpp ****
3:../src/test.cpp **** void test();
4:../src/test.cpp **** void test(){
9 .loc 1 4 0
5:../src/test.cpp **** PORTB.PODR.BIT.B1 = 1;
10 .loc 1 5 0
11 0000 FB 5E 0B C0 08 mov.L #0x8c00b, r5
12 0005 F1 51 20 bset #1, 32[r5].B
6:../src/test.cpp **** PORTB.PODR.BIT.B5 = 1;
13 .loc 1 6 0
14 0008 F1 55 20 bset #5, 32[r5].B
7:../src/test.cpp **** PORTB.PODR.BIT.B3 = 1;
15 .loc 1 7 0
16 000b F1 53 20 bset #3, 32[r5].B
8:../src/test.cpp **** PORTB.PODR.BIT.B7 = 1;
17 .loc 1 8 0
18 000e CD 54 20 mov.B 32[r5], r4
19 0011 75 34 80 or #0xffffff80, r4
20 0014 C7 54 20 mov.B r4, 32[r5]
9:../src/test.cpp **** PORTB.PODR.BIT.B2 = 1;
21 .loc 1 9 0
22 0017 F1 52 20 bset #2, 32[r5].B
10:../src/test.cpp **** PORTB.PODR.BIT.B6 = 1;
23 .loc 1 10 0
24 001a F1 56 20 bset #6, 32[r5].B
11:../src/test.cpp **** PORTB.PODR.BIT.B0 = 1;
25 .loc 1 11 0
26 001d F1 50 20 bset #0, 32[r5].B
12:../src/test.cpp **** PORTB.PODR.BIT.B4 = 1;
27 .loc 1 12 0
28 0020 F1 54 20 bset #4, 32[r5].B
29 0023 02 rts
Best answer
Hello,
There is no atomic access specific support in the C compiler, therefore GCC by default does not guarantee atomic access. Early on in the GCC development stages however, these problems were recognized and addressed with built-in functions. RX implementation is no different, therefore please try using our built-in bset function. Here is an example:
__builtin_rx_bset_mem (&PORTB.PODR.BYTE, 7)
(for setting a register bit)
__builtin_rx_bclr_mem (&PORTB.PODR.BYTE, 7)
(for clearing a register bit)
This should fix the problem described. For further assembly opcodes supported, please refer to <RX_toolchain_install_path>/doc/gcc.html
Using built-in functions is the preferred way to handle atomic register access. That is because, for example, one could compile with -O3 and check the assembly output, and that should list all of the register writes using the bset opcode, but then when trying to debug with -O0, mov instructions will be used instead.
As you may have noticed in assembly output, some of the bit accesses are optimized for the bset opcode, because it is more efficient. However, it does seem that not all instances are optimized to use bset adequately.
We would like, as a consequence, to attempt and address this situation. If possible, please upload a packed version of your project, so we can analyze what went wrong in the compiler’s optimization stages.
—
Best regards,
The GNU Tools Team
Hello,
We just wanted to let you know that have opened an internal ticket based on your finding, which we are pursuing to handle entirely in the upcoming release 2018q3 of the toolchain. If you prefer, once we have the fix in place, we can notify you by e-mail about it as well – just let us know please.
In your case, where the scope is atomic access, please use the preferred, builtin “bset” and “bclr” instructions for now.
Please try the suggested workaround and let us know if you continue to experience any issues.
– Best regards,
The GNU Tools Team
Hello,
Thank you for your patience!
A fix for this issue is available starting with GCC for Renesas 4.8.4.201803-GNURX Toolchain.
–
Best regards,
The GNU Tools Team