Why are logically related bit fields in MCU registers often in separate locations?
Is this for legacy design reasons, such as a new feature was inserted into previously reserved space?
In this particular case (and in similar cases I've seen) yes, it's done to help keep backward compatibility with older devices and minimise any changes required to the (perhaps well-tested and qualified / certified) code already written for those older devices. New features and functionality (requiring new register bits for control & configuration) therefore have to use non-contiguous bits, if the adjacent bits to the original register bits are already used.
For example, here is the USART_CR1
register of the old STM32F1xx family.
Figure 1. STM32F10xxx USART_CR1 register usage
Image source: STM32F10xxx family reference manual RM0008, section 27.6.4
That older USART (with only 2 word length options) needs only one M
bit to configure the USART word length between the two options, and that is bit 12. Notice how bits 11 and 13 are also used, and therefore unavailable for future "expansion".
As you said, on the newer STM32F7 (and, for example, also the STM32F4) the USART now has 3 word length options (7, 8 and 9 bits) and so needs another configuration bit - bit 12 is M0
, with M1
now in bit 28 (previously reserved in the STM32F1 register map, as you see above).
Figure 2. STM32F74xxx USART_CR1 register usage
Image source: STM32F75xxx and STM32F74xxx family reference manual RM0385, section 31.8.1
They couldn't put the new M1
bit into register bits 11 or 13, without moving register bits already used for other functions, and so removing backwards compatibility with existing code (e.g. for the STM32F1) which used them.
So they have tried to keep some backwards compatibility, which leads to new register bits being added in unexpected places.
Maintaining register mapping for standalone UARTs, from the 8250 to the 16550, with new registers added elsewhere in the register map, was another example.
You are right with
"..for legacy design reasons, such as a new feature was inserted into previously reserved space..".
As far as I know, bit positions themselves have almost no design impact (in chip implementation I mean) in most cases. Designers usually try to utilise whatever is available. And in some cases like when you're trying to extend widths etc.
That said, there are however some cases where the bit positions are intentionally kept far apart. Specifically for bits that are critical and are NOT to be modified by unintentional writes (due to wrong position/masks, or scrambled for security) that can cause the system to end up in an undesired state.