cancel
Showing results for 
Search instead for 
Did you mean: 

7 USART3 registers == 28 bytes. What are the other addresses in USART3 for?

MMust.5
Senior II

STM32F407 Discovery

 

 

typedef struct __UART_HandleTypeDef
{
USART_TypeDef *Instance;
UART_InitTypeDef Init;
const uint8_t *pTxBuffPtr;
uint16_t TxXferSize;
__IO uint16_t TxXferCount;
uint8_t *pRxBuffPtr;
uint16_t RxXferSize;
__IO uint16_t RxXferCount;
__IO HAL_UART_RxTypeTypeDef ReceptionType;
DMA_HandleTypeDef *hdmatx;
DMA_HandleTypeDef *hdmarx;
HAL_LockTypeDef Lock;
__IO HAL_UART_StateTypeDef gState;
__IO HAL_UART_StateTypeDef RxState;
__IO uint32_t ErrorCode;
} UART_HandleTypeDef;

 

I take the USART3 setting as an example.
The starting address for storing this UART_HandleTypeDef structure will be 0x4000 4800.
USART3 has 7 registers. Each register is 32 bits.
7*32==224/8==28 bytes
7 USART3 registers occupy 28 bytes.
These 7 registers are configured by the USART_TypeDef *Instance structure;
0x4000 4800 + 28 bytes== 4000 481C
0x4000 4800 ----- 4000 481C There are 7 registers in this address limit.

tim2.png

But USART3 is allocated a lot more addresses 0x4000 4800 - 0x4000 4BFF What's in there?
And most importantly, I'm wondering where it is stored:

 

UART_InitTypeDef Init;
const uint8_t *pTxBuffPtr;
uint16_t TxXferSize;
__IO uint16_t TxXferCount;
uint8_t *pRxBuffPtr;
uint16_t RxXferSize;
__IO uint16_t RxXferCount;
__IO HAL_UART_RxTypeTypeDef ReceptionType;
DMA_HandleTypeDef *hdmatx;
DMA_HandleTypeDef *hdmarx;
HAL_LockTypeDef Lock;
__IO HAL_UART_StateTypeDef gState;
__IO HAL_UART_StateTypeDef RxState;
__IO uint32_t ErrorCode;

 

And what does it set up? Or they are ordinary variables and are stored as ordinary data, while registers are not configured.
That is, there are only 7 registers in this address limit 0x4000 4800 - 0x4000 4BFF, right?
What is the rest of the space for?

1 ACCEPTED SOLUTION

Accepted Solutions

I understood everything, thanks.

tim2.png

If the address was stored in the UART_HandleTypeDef structure, then it would be as I described at the beginning))

I messed up something and thought that the address in the UART_HandleTypeDef structure is saved.

View solution in original post

15 REPLIES 15

It is not memory in the RAM sense, it is a window into combinational logic of the peripherals.

The sizes here are more about convenience of decoding address boundaries by looking at higher order address bits, in binary, and that's how the logic / machine works.

Each peripheral is given a 1KB (0x400 byte) window, and passed the low order 10-bit to decode in whatever fashion the logic choses. The UART peripheral is stepped-and-repeated for each instance implemented in hardware.

A subdivision of the ARM's 4GB (32-bit) address space, and accessed like all other memory, is a convenient and consistent method. You can use pointer, structures, and DMA to access it. The debugger can access via the same address bus and methods. If the address doesn't decode, the MCU can Hard Fault to indicate an access that is out-of-bounds, and likely erroneous. 

Perhaps you can find some college level texts covering computer, CPU, and peripheral architecture and design?

 

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

The UART_HandleTypeDef structure is a software/library side method of tracking settings, buffers, associated peripherals, DMA and callbacks.The USART_TypeDef *Instance; is a pointer to the hardware that implements the logic gates and register window to the peripheral.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Peter BENSCH
ST Employee

Indeed, this seems like an incredible waste of address space, but this is due to the fact that the starting address is as clear as possible and, above all, easily adaptable via the many derivatives.
In addition to what @Tesla DeLorean wrote:
If you take a look at the corresponding reference manual, you will usually find 0x400 (1KB) blocks, regardless of whether it is UART or USB. When the STM32 was defined many years ago and the drivers were to be built as homogeneously as possible, address blocks of the same size were defined for access. A block size of:

  • 0x10 = 16 bytes = 4 double words (registers) is much too small,
  • 0x100 = 256 bytes = 64 registers would have been just about enough,
  • 0x400 = 1024 bytes = 256 registers is completely sufficient for all current and expected peripherals

It should be noted that undefined address ranges are to be considered reserved.

Regards
/Peter

In order to give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Basically it trades lower transistor count and uniformity / orthogonal design.

In old MCU designs everything was tightly packed and decoded (see 8051) all the registers and peripherals. These were hard to expand on, and design methods became more automated, structured, and hierarchical so you'd design the UART logic once, and then drop repeated instances into the design with a decoded chip select from the next level up, and truncated address bus to decode the internal registers.

Depending on the number of transistors committed to the decode, the same registers might appear to be replicated every 32 bytes, or whatever,

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

I do not understand where everything is physically stored, except for register settings.
At what address is this stored:

 

UART_InitTypeDef Init;
const uint8_t *pTxBuffPtr;
uint16_t TxXferSize;
__IO uint16_t TxXferCount;
uint8_t *pRxBuffPtr;
uint16_t RxXferSize;
__IO uint16_t RxXferCount;
__IO HAL_UART_RxTypeTypeDef ReceptionType;
DMA_HandleTypeDef *hdmatx;
DMA_HandleTypeDef *hdmarx;
HAL_LockTypeDef Lock;
__IO HAL_UART_StateTypeDef gState;
__IO HAL_UART_StateTypeDef RxState;
__IO uint32_t ErrorCode;

 

This must be stored within USART3 addresses

LCE
Principal

> This must be stored within USART3 addresses

These are variables stored somewhere in SRAM.

The starting address for the UART_HandleTypeDef structure is 0x4000 4800
7 registers occupy 28 bytes.
Immediately after setting the registers, this is stored

UART_InitTypeDef Init;
const uint8_t *pTxBuffPtr;
uint16_t TxXferSize;
__IO uint16_t TxXferCount;
uint8_t *pRxBuffPtr;
uint16_t RxXferSize;
__IO uint16_t RxXferCount;
__IO HAL_UART_RxTypeTypeDef ReceptionType;
DMA_HandleTypeDef *hdmatx;
DMA_HandleTypeDef *hdmarx;
HAL_LockTypeDef Lock;
__IO HAL_UART_StateTypeDef gState;
__IO HAL_UART_StateTypeDef RxState;
__IO uint32_t ErrorCode;

This is not stored somewhere in SRAM, but immediately after the registers are adjusted.
Because in the UART_HandleTypeDef structure everything is stored in order.

0x4000 4800+28 bytes==4000 481C From this address 4000 481C the rest of the UART_HandleTypeDef structure must be stored.

One of us is completely on the wrong track.

IMHO you are confusing the variable struct UART_HandleTypeDef with the hardware registers for the UART, which is pointed to by Instance.
In UART_HandleTypeDef the first variable is:

USART_TypeDef *Instance;

And that is a pointer to the USART register start at  address 0x40004800.

This does not mean at all that the following variables in the struct are stored within that address area.

So you declare something like this:

UART_HandleTypeDef huart3;

Then you have the struct huart3 somewhere in SRAM, which includes a pointer to the peripheral = "Uart Instance".

This is usually set in some init function, like:

void Uart3_Init(void)
{
	huart3.Instance = USART3;

	huart3.Init.BaudRate 				= 921600;
	huart3.Init.WordLength 				= UART_WORDLENGTH_8B;
	huart3.Init.StopBits 				= UART_STOPBITS_1;
...