cancel
Showing results for 
Search instead for 
Did you mean: 

Byte, half-word and word accesses to peripheral registers

John Adriaan
Associate III

I am reading the STM32Lxxxx Reference manual (RM0394 Rev 4, October 2018, DM00151940).

On page 267, section 8.4 "GPIO registers" says "The peripheral registers can be written in word, half word or byte mode." Sure enough, any access works.

On page 308, section 11.6 "DMA registers" says "The DMA registers have to be accessed by words (32-bit)." Sure enough, if I attempt to access them by byte or half-word, I get an exception - I suspect Bus Error, but I didn't look too deeply.

However, the document says nothing about accesses to many other peripherals. For example, if I do a byte write to USART_CR1 to enable the USART (UE=0b1), I don't get an exception. Instead, the register also sets the bottom bit of the other three bytes (PEIE, DEDT[0] and DEAT[3]) in the register!

This is similar to what is described in section 11.4.5 "Addressing AHB peripherals not supporting byte/half-word write transfers":

"...any AHB byte or half-word transfer is changed into a 32-bit APB

transfer as described below:

• An AHB byte write transfer of 0xB0 to one of the 0x0, 0x1, 0x2 or 0x3 addresses, is

converted to an APB word write transfer of 0xB0B0B0B0 to the 0x0 address.

• An AHB half-word write transfer of 0xB1B0 to the 0x0 or 0x2 addresses, is converted to

an APB word write transfer of 0xB1B0B1B0 to the 0x0 address."

My question is: Should I ensure that all register accesses are full words all of the time (except where the document explicitly says I can use bytes)? A perfect example is USART_RDR and USART_TDR (page 1259). Only the bottom 9 bits are defined, and I want to be able to read and write byte characters. But that means that I'd be setting some of the high Reserved bits. Do I need to zero-extend the character to a full word before writing the whole register?

2 REPLIES 2

In the vast majority of cases, reserved bits are unimplemented, and the rule not to change them (*) is intended to maintain forward compatibility, i.e. if you'd reuse the code in a newer model with more bits implemented, there might be a problem.

Most of the time it's a non-issue, e.g. the data register will remain to be a data register and writing higher bits to whatever value won't hurt as long as only the lowermost byte gets actually used.

There is a slightly different gotcha with the write widths, e.g. in SPI where with the "data packing" feature added somewhere between 'F2/'F4 and 'F0 resulted in that with bit-widths lower than 8 it actually does matter whether you write the data register as a byte or as a halfword.

JW

(*) Note that this rule does not say "write zero". Also note, that this rule is nonsense in registers where writing a given value clears the given bit. So this rule can't be taken literally, must be taken liberally.

@Amel NASRI​  ,

can we consider this as a request to review *all* RMs and add the register access width consistently to the beginning of *all* the peripherals' registers chapters?

Thanks,

Jan