AURIX™ MCU: Write Access to multiple bitfields of an SFR - KBA235506
Accessing the Special Function Register (SFR) is not difficult, as it is memory-mapped. There is no difference from the programming point of view to access an SFR or a memory-mapped variable. These are laid out to contain multiple bitfields, where each have a different functionality to control or to report the status. This article focusses about the recommended method of write access to multiple bitfields of an SFR. The following conditions apply:
- The access action ensures read or write to the physical location each time
- The access action ensures protect read-modify-write operation from the race condition
- The access action is efficient during runtime, with smaller code size, or both depending on necessity
- The access action code is readable to show the purpose of access
- Make sure that the SFR access is within a code block. This ensures the following:
- Defines the C variable scope for the SFR local copy
- Allows you to define the protection or critical section
- Makes the code readable
- Open critical section (optional).
- Define a nonvolatile, local variable of SFR type because the SFR header file ensures this SFR type has no volatile member in it or that type itself is not volatile qualified.
- Read SFR from its physical location (optional). There is no need to read if:
- All the bitfields are to be written
- Other bitfields, which are not written and do not have a specific pattern. In such a scenario, initialize with such pattern
- To avoid read-modify-write operation and related data handling scenarios
- Write to individual bitfields using the following assignment statement:
<local SFR variable>.B.<bit-field>= <value>
- Now write back to the physical register.
- Close the critical section, if previously opened.
- Close the code block.
To illustrate the recommendation, let’s take an example from AURIX™ TC3xx.
Configure the marked bitfields of the SCU_CCUCON0 register to be written as shown in Figure 1:
Figure 1 Marked bitfields
Following is the code snippet to show the recommendations.
l_ScuCcuCon0= MODULE_SCU.CCUCON0; /* Read the register content */
/* Now write to individual register bit-fields as required */
l_ScuCcuCon0.B.FSIDIV= 1; /* fFSI = fSRI */
l_ScuCcuCon0.B.SPBDIV= 2; /* fSPB = fSource0 / 2 */
l_ScuCcuCon0.B.LPDIV= 1; /* fSPB = fSource0 / 30 */
l_ScuCcuCon0.B.STMDIV= 1; /* fFSI = fSource0 */
l_ScuCcuCon0.B.UP= 1; /* Update CCUCON0 and CCUCON5 */
MODULE_SCU.CCUCON0.U = l_ScuCcuCon0.U;
The disassembly of generated code is as shown below.
Starting disassembly of section 82 (.text.Test.MyExample_accessRegMultibit):
MyExampl: movh.a a15,#0xf003
8000172e: lea a15,[a15]0x6030
80001732: ld.w d15,[a15]
80001734: mov d0,#0x1
80001736: insert d15,d15,d0,#0x18,#0x2
8000173a: mov d0,#0x2
8000173c: insert d15,d15,d0,#0x10,#0x4
80001740: mov d0,#0x1
80001742: insert d15,d15,d0,#0xc,#0x3
80001746: mov d0,#0x1
80001748: insert d15,d15,d0,#0x0,#0x4
8000174c: mov d0,#0x1
8000174e: insert d15,d15,d0,#0x1e,#0x1
80001752: movh.a a15,#0xf003
80001756: st.w [a15]0x6030,d15
Note that@80001732, the SFR is read from its physical location and @80001756, the SFR is written to its physical location. Individual bitfields are updated locally, improving the runtime behavior and data consistency.
For more details, see the "Special Function Register (SFR)” section in the TriCore™ TC1.6.2 core architecture manual (volume 1).
Note: This KBA applies to the following series of AURIX™ MCUs:
- AURIX™ TC2xx series
- AURIX™ TC3xx series