Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Why use pointers?

Status
Not open for further replies.
Can anyone tell me the advatages of using pointers on a PIC Micro. Would using global var. be just as effective? I understand there are suppose to improve efficency, but how? any explanation would help. or cases were I should use a pointer.
 
The Real MicroMan said:
Can anyone tell me the advatages of using pointers on a PIC Micro. Would using global var. be just as effective? I understand there are suppose to improve efficency, but how? any explanation would help. or cases were I should use a pointer.

As a pointer adds an extra layer of code it seems unlikely it's going to improve efficency?, I would have thought exactly the opposite would be true?.

I also presume you're talking about C?.
 
On PCs, pointers would have saved a lot of memory since you pass addresses instead of replicating whole blocks of data to be passed by value. But for microcontroller systems, where there's no dynamic memory allocation, I too share the thought that pointers actually lead to inefficiency. (Addresses do make up memory space too!)

But on the other hand, I still use them for modularization and more readable code. A reader would get lost easily when all variables are declared global, and functions no longer need input arguments.
 
for me it depends upon the problem. but i use global variable as a last resort because if you are in a huge project (lots of C files and header files), it will be difficult to debug if too many functions access the variable and sometimes can lead to accidental writes. and also, as far as i know, global variables can take up the RAM as long as the program is running, and as long as the compiler doesnt create it as ROMable variables(some C compilers do support it).

also it will be more efficient to pass the address specially when using huge array size to be passed/used on functions. also it is more efficient to use pointers especially in strings for example:
char a[5][5]={"test","hey","go","best","win"};

it will be better to write:
char *a[5]={"test","hey","go","best","win"};
 
It depends largely on data size and whether the use of that data would require copying.

For example, if you have a data string or struct 100 bytes long, it is disadvantageous to pass this literally to the function. This would require copying the entire 100 bytes into the space a function uses for this argument before jumping to the function. If it's a pointer, then it's 3 bytes (I think) for the address. Depending on how much access the function does, it's possible the copying would still have been quicker though.

The pointer method will also allow RAM objects to be altered. Copied objects obviously will not reflect the changes in the original object.

Pointers allow an array of unspecified length to be passed, which cannot be done when copying an array directly. The function will of course still need some way to understand the length and dimensions of the data residing at the passed pointer.

If you are not using this in a function there are still reasons a pointer may be more efficient, but it depends on the exact circumstances and chosen style of coding.
 
I have used pointers a number of times in various PIC projects. I use tables of pointers to point into a list of strings. I had a project that had 4 independent channels to process and so passed a pointer to each channels data to the code. And always in assembler.

Here is an implementation of a FIFO buffer that uses two pointers to keep track of the start and end points of a circular buffer. I don't know of any other way to implement this code without using pointers.

Code:
PutFifo	      movwf   FifoTemp
                movfw   FifoEnd
                addlw   FifoBuffer-100h
                movwf   FSR;		indirect addr
                movfw   FifoTemp
                movwf	INDF;		Write indirect
WaitFifo        movfw   FifoEnd
                addlw   1
                andlw   FifoLength-1
                subwf   FifoStart,W
                btfsc   STATUS,Z
                goto    WaitFifo;	fifo is full so wait
                movfw   FifoEnd
                addlw   1
                andlw   FifoLength-1
                movwf   FifoEnd
                return

In the above code, FifoBuffer is 16 bytes long and on a 16 byte boundary in bank 1 and so IRP = 1. The buffer is emptied in the Interrupt which is why it waits.

Mike.
 
Joel Rainville said:
Nice little piece of code. How do you avoid an interrupt being called in the middle of an update to FifoEnd and possibly crapping the whole thing?

The interrupt can come along at anytime and not cause a problem. The interrupt compares fifostart to fifoend and if they are different then it takes a byte from [buffer+start] and increments fifostart.

Edit, the interrupt also has to preserve FSR.

Mike.
 
Code:
PutFifo	      movwf   FifoTemp
                movfw   FifoEnd
                addlw   FifoBuffer-100h
                movwf   FSR;		indirect addr
                movfw   FifoTemp
                movwf	INDF;		Write indirect
WaitFifo        movfw   FifoEnd
                addlw   1
                andlw   FifoLength-1
                subwf   FifoStart,W
                btfsc   STATUS,Z
                goto    WaitFifo;	fifo is full so wait
                movfw   FifoEnd
                addlw   1
                andlw   FifoLength-1
          <<<say interrupt happens here>>>
                movwf   FifoEnd
                return

Not sure I get it. What if the interrupt happens after you've calculated the new FifoEnd value but before you've updated FifoEnd itself (see in code above)?...

What does the code in the interrupt look like?
 
Joel Rainville said:
Not sure I get it. What if the interrupt happens after you've calculated the new FifoEnd value but before you've updated FifoEnd itself (see in code above)?...

What does the code in the interrupt look like?

The secret is that the putfifo routine only alters fifoend and the getfifo only alters fifostart.

PutFifo writes to [buffer+end] and increments end.
GetFifo reads from [buffer+start] and increments start.

The code in the interupt is:-

Code:
GetFifo         btfss   PIR1,TXIF
                goto    DoneFifo;	hardware fifo full
                movfw   FifoStart
                subwf   FifoEnd,W
                btfsc   STATUS,Z
                goto    DoneFifo;	fifo empty
                movfw   FifoStart
                addlw   FifoBuffer-100h
                movwf   FSR
                movfw   FifoStart
                addlw   1
                andlw   FifoLength-1
                movwf   FifoStart
                movfw   INDF
                movwf   TXREG
                goto    GetFifo
DoneFifo

As you can see, the above doesn't write to FifoEnd.

If the interrupt happened where you indicated then one of the following would happen (start = fifostart etc)

if start=end then the fifo has 1 valid byte in it but the ISR thinks it's empty and does nothing. (because end hasn't been updated yet)

if start<>end then at least 2 valid bytes are in the buffer and the ISR will take the first even though start-end may only equal 1. The ISR will then increment start and the main code will then increment end.

I don't know if I explained that very well. Let me know.

Mike.
 
Pommie said:
PutFifo writes to [buffer+end] and increments end.
GetFifo reads from [buffer+start] and increments start.

Ah, I get it. For some reason, everytime I read FIFO, I imagined a stack-like structure, which is actually a "LIFO" if that acronym even exists...

Thanks for sharing that code, I'm gonna play with it a little!... :)
 
Joel Rainville said:
Thanks for sharing that code, I'm gonna play with it a little!... :)

Play away. Make sure you set both fifostart and fifoend to zero at initiation. The ISR needs to be timer driven. I do have the same code that uses the TX1 interrupt, but it's a bit more complex.

Mike.
 
Joel Rainville said:
Cool, thanks.

Shouldn't you be sleeping? What time is it in Australia?

:D

Not at all sleepy, it's 11:40 A.M. here, nearly lunch time.

Mike.
 
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top