Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which way is faster in initializing registers in a microcontroller?

This question came to my mind while writing some firmware for a PIC microcontroller.

There are two methods I know to initialize registers in a microcontroller. Say for an example, if we are initializing a port as outputs, one way is to write a command like the following and it will assign 1 to every bit in TRISx register

Method 1

TRISX = 0xFF;

The same thing can be done by assigning bits individually.

Method 2

_TRISX0 = 1;
_TRISX1 = 1;
_TRISX2 = 1;
...
_TRISX7 = 1;

My question is, will it get treated as same by compiler and the time taken to complete both the operations are same? Or does method 1 take one clock cycle while method 2 takes 8 (I mean ~8 times slower)?

I tried reading X16 compiler guide but couldn't find any tips.

like image 371
Padmal Avatar asked Jun 18 '19 05:06

Padmal


People also ask

What is initialization in microcontroller?

Initialization code (or boot code) takes the processor from the reset state to a state where the operating system can run. It usually configures the memory controller and processor caches and initializes some devices. In a simple system the operating system might be replaced by a simple scheduler or debug monitor.

What are the registers in the microcontroller?

C Programming Basics For Microcontrollers & Embedded System The most widely used registers of the 8051 are A (accumulator), B, R0-R7, DPTR (data pointer), and PC (program counter). All these registers are of 8-bits, except DPTR and PC.

What value are registers initialised to?

You can initialize a register to any value you wish (including zero). Some programs do not use all of the registers. Some may only use a few. You don't have to initialize registers your program may not use.

Which register in a microcontroller is used to hold next instruction?

The register which stores the address of the next instruction is called the program counter. Usually after each instruction is executed, the program counter increases by one (hence the use of the word counter) so that it contains the address of the next instruction.


2 Answers

Hardware registers are always volatile qualified and the compiler is not allowed to optimize code containing volatile access. So if you write to them 8 times, then 8 writes is what you get. This is of course much slower than 1 write.

In addition, it is very bad practice to write to registers several times in a row just as if they were a temporary variable in RAM. Hardware registers tend to have all manner of subtle side-effects. They can have "write-once" attribute or only accept writes in certain modes. By writing to them in several steps, you make a habit of creating all manner of crazy, subtle problems caused by incorrect register setups.

Correct practice is to write to registers once, or as few times as necessary.

For example, you may think that a data direction register as in your example is a pretty dumb one with no side-effects. But often GPIO hardware needs some time to toggle the port circuits, from the point where you write to the data direction register to the point where you access the I/O port. So it is possible that several writes would stall the port needlessly.

Assuming REGISTER is the name of the memory-mapped, volatile-qualified hardware register, then...

Don't do this:

MASK1 = calculation();
REGISTER |= MASK1;
MASK2 = calculation();
REGISTER |= MASK2;

Do this:

uintx_t reg_val=0; // temp variable in RAM
MASK1 = calculation();
reg_val |= MASK1;
MASK2 = calculation();
reg_val |= MASK2;
REGISTER = reg_val; // single write to the actual register
like image 193
Lundin Avatar answered Oct 11 '22 16:10

Lundin


It will depend on the processor instruction set and the compiler. For the PIC18F45K20, for example, the sdcc compiler compiles the following

TRISDbits.TRISD0 = 1;

to

BSF _TRISDbits, 0

while it compiles

TRISD = 0xFF;

to

MOVLW   0xff
MOVWF   _TRISD

So in this case setting an individual bit is faster, because it does not involve placing a temporary value in the working register.

Not all instruction sets include a BSF instruction however, and some architectures would not require the use of the working register for the latter task.

P.S. The above examples are based on the output of the sdcc compiler, but I imagine the xc8 and xc16 compilers yield similar results.

P.P.S. When inspecting the generated assembly, bear in mind that some instructions consume more processor cycles than others. See datasheet for details.

like image 23
David Collins Avatar answered Oct 11 '22 14:10

David Collins