Understanding # define sreg (* (volatile unsigned char *) 0x5f)

Source: Internet
Author: User
Tags what bit

Understanding # define sreg (* (volatile unsigned char *) 0x5f)
 

Understanding # define sreg (* (volatile unsigned char *) 0x5f)
This definition is always very strange. I don't know why. I have a little bit of experience today. Please submit more bricks to the prawns ~~~

Embedded system programming requires programmers to use C language to access a fixed memory address. Since it is an address, according to the syntax rules of the C language, the number of addresses should be pointer type. Therefore, after knowing the memory address to be accessed, such as 0x5f,
The first step is to forcibly convert it to the pointer type.
(Unsigned char *) 0x5f, The sreg of AVR is an eight-bit register, so 0x5f is forcibly converted to the unsigned char type.
The volatile keyword indicates that the variable may be unexpectedly changed, so that the compiler will not assume the value of the variable. This "unexpected change" is not changed by the program, but by the hardware-Unexpected.
Step 2: unreference the pointer variable to operate the content of the address pointed to by the pointer.
* (Volatile unsigned char *) 0x5f
Step 3: carefully enclose the parameters in the # define macro in brackets. This is a good habit, so # define sreg (* (volatile unsigned char *) 0x5f)

Similarly, if a 32-bit processor is used to access a 32-bit memory address, you can define # define ram_addr (* (volatile unsigned long *) 0x0000555f) as follows)
Then you can use the C language to read and write the memory address.
Read: TMP = ram_addr;
Write: ram_addr = 0x55;

Define volatile because its value may change and everyone knows why it has changed;
If you need to constantly judge a memory data in a loop operation, such as waiting for the I flag position of sreg, because sreg is also mapped to the SRAM space, in order to speed up, the compiler may compile the code to read the sreg into Register, and then constantly judge the corresponding bit of register. Instead of reading the sreg, this is certainly not good, because the program or other events (such as interruptions) will change the sreg, and the result is probably an endless loop. If it is defined as a volatile variable, the compiled code is as follows: each time a variable is operated, it is read from the memory.
# Define sreg (* (volatile unsigned char *) 0x5f)
After,

You can perform the following basic operations,
Unsigned char temp, * PTR;
Temp = sreg; Save the sreg value to temp
Sreg = temp; assign the Temp value to sreg
PTR = & sreg; do not know whether or not, please try it.

 

 

 

 

 

# Define rgpacon (* (volatile unsigned long *) 0x56000000)

For different computer architectures, devices may be port ing or memory ing. If the system structure supports independent I/O address space and port ing, you must use the assembly language to implement actual device control, because the C language does not provide the concept of a true "Port. For memory ing, it is much more convenient.

For example, if data is written to 0x01 like register a (the address is assumed to be 0x48000000), you can set it like this.

# Define a (* (volatile
UnsignedLong X) 0x48000000)
...
A = 0x01;
...


This is actually the convenience of the memory ing mechanism. Among them, the volatile keyword is an important feature of embedded system development. The above expressions are separated for analysis, first (volatile
UnsignedLong *) 0x48000000 indicates converting 0x48000000 to volatile.
UnsignedLong TYPE pointer, temporarily recorded as P, is # define a * P, that is, a is the content where the P Pointer Points to position. In this example, register a can be accessed through memory addressing and read/write operations can be performed.

During GCC compilation. The registers indicated by volatile are not optimized !!!

 

 

 

# Define u0rbr (* (volatile unsigned char *) 0xe000c000 ))

This is common in single chip microcomputer,

(Volatile unsigned char *) 0xe000c000)
Is to forcibly convert 0xe000c000

Store the address that may be updated at any time (for volatile ).

* Is added to indicate the value pointing to the address, which is the same as other commonly defined pointers, such as char X, Y, * P; P = & X; * P = y; y = * P

Just like a variable, the value can be read from or assigned. It should be noted that the content in this address value can be read and written, this should be defined in Datasheet or what he does in the program.

# Define u0rbr (* (volatile unsigned char *) 0xe000c000 ))
This is macro definition, that is, uorbr replacement (* (volatile unsigned char *) 0xe000c000). macro definition is for the convenience of program writing, because there may be many places in the program to use (* (volatile unsigned char
*) 0xe000c000). It is always troublesome to write so many things during use.

 

(1 <16). Yes, this is also the Left shift, but not to shift the number in the variable to the left, but to directly shift 1 to the left of 16 bits, that is, to change the highest position of the 16 bits to 1.

0000 0000 0000 0001 // 1

After migration

1000 0000 0000 0000 // 0x8000

 

# Define direct1 1 <10 // receives low data and raises the sending data

# Define direct0 1 <16 // receives low data and raises the sending data

 

Assign values to the register with these two macros, either bitwise AND or bitwise with the register, or so on.

This should be understood. It should be set to 1 for digits 9 and 15 (starting from digits 0 ).

I guess what bit 9 should control is the sending data, while bit 15 controls the sending data.

 

 

 

Understanding # define rrtccon (* (volatile unsigned char *) 0x57000043) // RTC Control

This definition is always strange. Today, I finally have a little bit of experience. Embedded system programming requires programmers to use C language to access a fixed memory address. Since it is an address, according to the syntax rules of the C language, the number of addresses should be pointer type. Therefore, after knowing the memory address to be accessed, such as 0x57000043,


The first step is to forcibly convert it to the pointer type.

(Unsigned char *) 0x57000043, rrtccon of S3C2410 is accessed in a single byte, so 0x5745043 is forcibly converted to pointing to unsigned
Char type.
The volatile keyword indicates that the variable may be unexpectedly changed, so that the compiler will not assume the value of the variable. This "unexpected change" is not changed by the program, but by the hardware-Unexpected.


Step 2: unreference the pointer variable to operate the content of the address pointed to by the pointer.

* (Volatile unsigned char *) 0x57000043


Step 3: carefully enclose the parameters in the # define macro in brackets. This is a good habit.

Volatile is often used in embedded systems.

I will elaborate on the following based on my own understanding. I hope you can post comments:

In C, the volatile keyword is a type modifier,
The declared type variable indicates that the variable can be changed by some external factors unknown to the compiler (such as the operating system, hardware, or other threads.
When the variable declared by this keyword is met, the compiler will not optimize the code that accesses the variable, so as to provide stable access to the special address (the address of the defined variable in the memory.

The Optimization of the Code by the compiler refers:

In the process of CPU execution, because the speed of memory access is far less than the speed of CPU execution, in order to improve efficiency, the high-speed cache is introduced.
If the C compiler does not know that the variable will be modified by other external factors (operating system, hardware, or other threads) during compilation, the variable will be identified, that is, optimized. this variable will be placed in the cache during the execution of the CPU to achieve quick access to the variable.
After understanding the concept of optimization, imagine if we knew in advance that the variable would be changed by external factors, then we would add volatile before the definition of the variable, in this way, the compiler will not optimize the variable. in this way, the variable will not be placed in the cache during CPU processing.

Why don't variables be put into the Cache during execution?

If the variable is changed by external factors, the CPU cannot determine whether the variable has been changed. If the variable is used during execution, it will continue to use the variable in the cache, but this variable has actually been changed. you need to update the content in the memory address.

Another reason is that some register variables or data ports are used because register variables are also processed by cache. To avoid errors, you can also use the volatile modifier.

 

To put it simply, the purpose of using volatile is:

Enable volatile
The access to variables cannot be cached in registers. You need to re-access them each time you use them.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.