Electronic – Why are logically related bit fields in MCU registers often in separate locations

embeddedmicrocontrollerstm32

Forgive me if this question has already been answered, but I was unable to find an answer either on this page or in the wider Internet.

I'm an experienced developer with decent knowledge regarding low-level programming, but relatively new to embedded development. I've been teaching myself embedded systems development using an ST-NUCLEO144 board, which features an STM32F746ZG MCU. One question that seems non-obvious to me is that why logically related bit fields in a register may be in different locations.

One example is the USART_CR1 register on the STM32746ZG. The M0 and M1 bit fields together control the word length in USART TX/RX, a combined 2-bit value of 0b00 specifies 8-bits, 0b01 specifies 9-bits, etc. This is all quite straightforward, except that M0 is at bit 12 and M1 is at bit 28… why is this?

Is this for legacy design reasons, such as a new feature was inserted into previously reserved space? Is it for reasons related to the chip design, that I'm not considering, or is there a greater purpose to this that I'm not seeing?

Obviously this is pretty trivial to overcome with bit-masking, but I'm just curious.

Best Answer

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.


STM32F1xx register USART_CR1 bit usage

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).


STM32F74xxx register USART_CR1 bit usage

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.