Memory mapped register

Thread Starter

MTech1

Joined Feb 15, 2023
147
I have a generic question that apply to microcontroller programming.

I'm looking to deepen my understanding of how memory register addresses are stored within a program, particularly in c programming scenarios.

Let's say we have PORT1 which has register address 0x01, TMR1 which has register address 0x02, so I believe these addresses must be stored in a memory map or memory layout.
 

nsaspook

Joined Aug 27, 2009
12,286
I have a generic question that apply to microcontroller programming.

I'm looking to deepen my understanding of how memory register addresses are stored within a program, particularly in c programming scenarios.

Let's say we have PORT1 which has register address 0x01, TMR1 which has register address 0x02, so I believe these addresses must be stored in a memory map or memory layout.
What's the actual programming question?
 

BobTPH

Joined Jun 5, 2013
8,094
I have a generic question that apply to microcontroller programming.

I'm looking to deepen my understanding of how memory register addresses are stored within a program, particularly in c programming scenarios.

Let's say we have PORT1 which has register address 0x01, TMR1 which has register address 0x02, so I believe these addresses must be stored in a memory map or memory layout.
If the register is not used in a program it does not need to be stored in memory anywhere.

If it is used by a program it might be stored in the instructions that access it, or it might be computed in a register and then accessed by indirect addressing, or it might be stored in a pointer variable in RAM.
 

geekoftheweek

Joined Oct 6, 2013
1,096
Generally with microcontrollers there is a range of memory addresses that correlate to various peripherals and chip settings. Each one is different and the specifics can be found in the datasheet. Those addresses are separate from the actual program RAM, but are accessed and manipulated the same as RAM.
 

WBahn

Joined Mar 31, 2012
29,497
I have a generic question that apply to microcontroller programming.

I'm looking to deepen my understanding of how memory register addresses are stored within a program, particularly in c programming scenarios.

Let's say we have PORT1 which has register address 0x01, TMR1 which has register address 0x02, so I believe these addresses must be stored in a memory map or memory layout.
They are generally hardwired. They may or may not have a register address associated with them, it depends on the specifics of the microcontroller hardware. This is independent of how might think you are accessing them via a higher-level programming language, which typically abstracts at least some of the details of the underlying implementation away.
 

boostbuck

Joined Oct 5, 2017
416
Your question is unclear. Are you asking: how does the compiler resolve register references in generating executable object from your source, or do you mean: how does the address in the executable object instruction resolve to a location in the processor hardware?
 

ronsimpson

Joined Oct 7, 2019
2,795
There are many different types of computers (microcomputers) with very different ways of doing things.
I worked on some microcontroller where everything is addresses on the same bus. All data, all instructions and all I/O lived on the same bus and has 64000 locations total.
Some microcontrollers, have data memory and program memory separate. So data at location 5 is not the same as an instruction at location 5.
Some microcontroller have I/O in the first 128 locations of data memory. But some have 256 I/O locations that include timers, and UART and ADCs etc. all using a different bus. So IO location 5 is not in memory.
I cannot say all microcontrollers do (something) because each type has a very different way of thinking.
PORT1 which has register address 0x01, TMR1 which has register address 0x02
Using your example, it is very likely that Timer2 is at 0x03. There must be a way of addressing each device.
What computer are you thinking about?
 

Thread Starter

MTech1

Joined Feb 15, 2023
147

WBahn

Joined Mar 31, 2012
29,497
I've reviewed some of the code provided in the attached links, and I noticed that it directly accesses timer and port registers. In my understanding, these memory addresses should be stored when writing a program so that when the program runs on hardware, it can access these registers using their respective memory addresses.

Could you clarify if my understanding is correct?

https://www.electronicwings.com/8051/8051-timers

https://www.electronicwings.com/pic/pic18f4550-timer
What, in that code, hints at anything like storing some memory address so that something can be accessed using it?

The Instruction Set Architecture, ISA, for each chip defines how to access the peripherals. How that is physically done is completely up to the designer of the hardware and they are free to implement it however they want to as long as the behavior defined by the ISA is adhered to.

Unless the ISA specifies that instructions access peripherals by writing to specific addresses (which neither the 8051 nor the PIC4550 do), then the programmer neither knows nor cares what address a peripheral is at or whether nor not it is even accessed via an address at all. Some microcontrollers don't place special function registers on the address bus at all, but instead use read/write control lines generated directly from the instruction decode logic.
 

geekoftheweek

Joined Oct 6, 2013
1,096
Using this code:
Code:
#include "osc_config.h"        /* Configuration header file */
#include <pic18f4550.h>        /* Contains PIC18F4550 specifications */

#define Pulse LATB /* Define Pulse as LATB to output on PORTB */

void Timer1_delay();

void main()
{
OSCCON=0x72; /* Configure oscillator frequency to 8MHz */
TRISB=0; /* Set as output port */
Pulse=0xff; /* Send high on PortB */

while(1)
{
Pulse=~Pulse; /* Toggle PortB at 500 Hz */
Timer1_delay(); /* Call delay which provide desired delay */
}
}

void Timer1_delay()
{
/* Enable 16-bit TMR1 register, No pre-scale, internal clock,timer OFF */
T1CON=0x80;

TMR1=0xf830; /* Load count for generating delay of 1ms */
T1CONbits.TMR1ON=1; /* Turn ON Timer1 */
while(PIR1bits.TMR1IF==0); /* Wait for Timer1 overflow interrupt flag */
TMR1ON=0; /* Turn OFF timer */
TMR1IF=0; /* Make Timer1 overflow flag to '0' */
}
The registers OSCCON, TRISB, T1CON, TMR1, and any others I missed are defined in the header file (pic18f4550.h). They are numerical constants that are substituted in by the compiler. If you are asking if you need to define these values in your program the answer is no since they are defined by the header file. These addresses and bits are hard coded into the chip design and will never change.

Although I have not worked with the 8051 the same principles apply.
 

Thread Starter

MTech1

Joined Feb 15, 2023
147
I got the point that I was trying to understand. When we write code for a microcontroller, we include header files that provide symbolic names for these registers along with their memory addresses. These header files are usually provided by the microcontroller manufacturer or the development environment.

Instead of using raw memory addresses (e.g., 0x01 or 0x02), we use symbolic names defined in the header files. For example, we might see something like PORT1 or TMR1 in code. These names are mapped to the actual memory addresses in the microcontroller's memory space.
 

BobTPH

Joined Jun 5, 2013
8,094
So you actual question was, “how does the compiler know to access the register at hardware location 2 when I write TMR1 in my C program?”
 

WBahn

Joined Mar 31, 2012
29,497
I got the point that I was trying to understand. When we write code for a microcontroller, we include header files that provide symbolic names for these registers along with their memory addresses. These header files are usually provided by the microcontroller manufacturer or the development environment.

Instead of using raw memory addresses (e.g., 0x01 or 0x02), we use symbolic names defined in the header files. For example, we might see something like PORT1 or TMR1 in code. These names are mapped to the actual memory addresses in the microcontroller's memory space.
This is still assuming that these registers have memory addresses to begin with. Often they do, but not always.
 

Thread Starter

MTech1

Joined Feb 15, 2023
147
So you actual question was, “how does the compiler know to access the register at hardware location 2 when I write TMR1 in my C program?”
Yes, So the compiler doesn't know in the human sense; rather, it has been programmed to recognize certain symbols (like TMR1) and replace them with the appropriate memory addresses during the compilation process. This is part of how embedded C programming abstracts the low-level hardware details
 

Thread Starter

MTech1

Joined Feb 15, 2023
147
This is still assuming that these registers have memory addresses to begin with. Often they do, but not always.
I understand that the presence or absence of memory addresses for registers can vary based on the microcontroller's design and the peripherals it integrates. While it's common for microcontroller registers to have memory addresses, but it's not an absolute rule
 

nsaspook

Joined Aug 27, 2009
12,286
Yes, So the compiler doesn't know in the human sense; rather, it has been programmed to recognize certain symbols (like TMR1) and replace them with the appropriate memory addresses during the compilation process. This is part of how embedded C programming abstracts the low-level hardware details
and it's not just memory addresses, you don't want 'magic' (value that should be given a symbolic name, but was instead slipped into the code as a literal) numbers randomly scattered in your program source that can be easily missed during software changes and can confuse what the code is doing.

https://dev.to/mortoray/stop-waving-the-wand-of-magic-numbers-3b1n
Stop waving the wand of magic numbers
 
Top