Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

16f877a stack overflow

Status
Not open for further replies.

emperror123

Member level 5
Joined
Dec 11, 2010
Messages
86
Helped
1
Reputation
2
Reaction score
1
Trophy points
1,288
Activity points
1,880
since i have been doing a project i have used up a lot of CALL instruction, and it stack overflowed, how can i prevent this situation if i still continue do that
 

sadly the only way is to avoid the use of calls, and make your code via macros or use GOTO, (something like the inline in C)
 

What Kurenai_ryu says is true if you have too many NESTED calls (a call made when you are already in a subroutine). The actual number of calls in the program doesn't matter, what happens when you use the call instruction is the address to return to is saved on the stack. The return instruction goes back to that address and also releases a storage location on the stack again. If you nest too many calls the stack runs out of space and the error occurs. Firstly, check that each of your call instructions has a matching return instruction. If you can debug and watch the stack contents you should see if there is a mismatch. Secondly, if the code is OK and you really have just run out of space, consider using a software stack instead. This lets you use far more nesting but there is a substantial penalty in code size and speed.

Brian.
 

What Kurenai_ryu says is true if you have too many NESTED calls (a call made when you are already in a subroutine). The actual number of calls in the program doesn't matter, what happens when you use the call instruction is the address to return to is saved on the stack. The return instruction goes back to that address and also releases a storage location on the stack again. If you nest too many calls the stack runs out of space and the error occurs. Firstly, check that each of your call instructions has a matching return instruction. If you can debug and watch the stack contents you should see if there is a mismatch. Secondly, if the code is OK and you really have just run out of space, consider using a software stack instead. This lets you use far more nesting but there is a substantial penalty in code size and speed.

Brian.

How can solve it, I not good in doing macro for the pic, how can I do it?
 

Which assembler are you using? If it's MPLAB, use the built in simulator by selecting "Debugger" then "Select Tool" and click on MPSIM, this will give you extra tools to simulate and debug the program. Then click on "View" and "Hardware Stack" to open a window showing the return values currently on the stack. If you then step through the program or run it in animation mode you should see the stack change every time you use a call/return or there is an interrupt and you finish it with 'retfie'. If the same address starts appearing in the stack, the chances are you are not returning from a routine before it is called again. If you need to see where the offending call is in the program, the easiest way is to "View" then "Disassemble listing" and look for the code at that address.

Brian.
 

since i have been doing a project i have used up a lot of CALL instruction, and it stack overflowed, how can i prevent this situation if i still continue do that

When asking for advice concerning coding techniques it is often helpful to post your code so that we can examine it and make relevant recommendations.

Please use either CODE or SYNTAX tags when posting your code.

BigDog
 

dear all
below are the attachment of my program, it may be a bit confused

hopefully i can get help from u all
 

Attachments

  • programming.zip
    28.6 KB · Views: 47

The problem is that your delay routine "DELAY1" is in a different page of memory to the rest of the program. The address following the 'call' is stored on the stack correctly but the 'return' instruction ignores the upper bits in PCLATH. Instead of returning to address 212 it returns to address 012 near the beginning of the program and makes another call almost straight away.

The quick solution is to move the delay to the top of the program like this:
Code:
		org 00
		goto START

DELAY1  	;4999993 cycles
	movlw	0x2C
	movwf	d1
	movlw	0xE7
	movwf	d2
	movlw	0x0B
	movwf	d3
	decfsz	d1, f
	goto	$+2
	decfsz	d2, f
	goto	$+2
	decfsz	d3, f
	goto	$-5

			;3 cycles
	goto	$+1
	nop

			;4 cycles (including call)
	return

START		CLRF PORTB
		CLRF PORTD
		CLRF PORTC
		BANKSEL TRISA

This avoids the problem rather than fixing it but it will work. I would make three suggestions:
1. start by using a copy of the template Microchip supply for you. It gives you the structure of the program, including an ISR, for you to add to.
2. avoid using 'goto $+" and "goto $-" instructions because they work differently on other PIC processors, instead place a label and 'goto' it. This makes it work in all circumstances.
3. you spend most of your program loading values then delaying. Use a look-up table for the data, a single delay and put it all in a loop. The program would be much smaller.

Brian.
 

is it just move the delay subroutine after org 00
 

sorry @betwixt but your information is wrong!!! if the subroutine is in another page, you need to setup the page bits before (or use the LCALL macro) the PC is stored correctly in the stack and any return will restore CORRECTLY the stack value to the PC,thus returning to the appropiated page.... the trick is to setup the the pagebits in the status word EVERY TIME YOU SWITCH of BANK... (or change all your CALLs to LCALL macro)

also @emperror123 WHY did you cleared your pagebits inside the DELAY????

i recommend changing all the call to LCALL and change your delay rutine like:

Code:
DELAY1
        PAGESEL DELAY1 ; just in case but not clear!!!
	movlw	0x2C
	movwf	d1
	movlw	0xE7
	movwf	d2
	movlw	0x0B
	movwf	d3
	decfsz	d1, f
	goto	$+2
	decfsz	d2, f
	goto	$+2
	decfsz	d3, f
	goto	$-5

			;3 cycles
	nop

			;4 cycles (including call)
	return


---------- Post added at 11:21 ---------- Previous post was at 11:18 ----------

ah! and also some gotos from your main program... change them to LGOTO (not the ones in the delay unless you use proper labels and not $ shortcuts...)
 

erm, currently i had been confused and not understand for that and sorry i currently just beginner for that, what is LGOTO, LCALL? and do i need create macro? hopefully if u may help me editted some and send me back as reference, i would be much appreciated
 

LGOTO is a pseudo-instruction from MASM which adjust the pagebits in PCLATH according the label you use, before making the actual 'goto' jump... so instead of using

GOTO STYLE1

you use

LGOTO STYLE1

and you don't have to worry where is the STYLE1 label, (in which flash page it is)
(please read the datasheet (chapter 2.0 memory organization for more information about pages in the microcontroller))


the same thing you can do with CALL and LCALL

these pseudo instructions exists already and you don't need to create them... they are documented in the MASM reference: pic12/14 instruction set and pseudo-instructions
 

which mean that all CALL directly change to LCALL?
then the delay subroutine where shud i move?
 

I disagree with what I said being wrong! The explanation is correct and stepping through the program will prove it. I moved the Delay1 routine to the top of the program to avoid using LCALL every time. To explain to emperror123, LCALL is already a macro, it's built in to MPLAB but what it does is automatically sets bits in PCLATH according to the address of the call before making it. My solution uses one extra instruction, the 'goto START' to jump over the delay routine. If LCALL ( = LongCALL ) is used, it adds two instructions to every instance of 'call' and in your program that means a lot of extra instructions!

Brian.
 
PAGESEL delay1 it said that is not defined, build failed,
but when i see, the simulate until movwf d3 in sub routine it will reset back again after bank sel
 

ok ok... i took my time to debug this program and found that:

the program is small enough and it DOES NOT cross page boundaries. [even so, i'm still firm with the return instruction gets all the PC correctly and we only need to setup the pagebits before a call...]

THE ERROR: is the data definition...
of course using cblock could be acceptable data def, but by default it will assign the labels for d1,d2,d3, and count to addresses 0x00, 0x01, 0x02, and 0x03... if you check the datasheet you can see that the first 32 data registers are 'special function registers' or SFRs writting 0x2C to SFR0x00 (INDF) and 0xE7 to SFR 0x01 (TMR0) don't have and immediate connotation.. but writting 0x0B to SFR0x02 (PCL) makes it JUMP to address 0x000B (some instruction near the beginning and thus, making and uncontrollable loop)

THE SOLUTION:
ALWAYS set the initial address of CBLOCK to the general purpose registers.. (normal RAM) which starts at address 0x20

Code:
        cblock 0x20
	d1
	d2
	d3
	COUNT
	endc



anyway i don't like your DELAY1 subroutine, and i would change it to:


Code:
DELAY1
        movlw     .165 ; 0xA5
        movwf     d1   
PLoop0  movlw     .41  ;0x29
        movwf     d2   
PLoop1  movlw     .147 ;0x93
        movwf     d3   
PLoop2  nop       ;clrwdt         
        nop       ;clrwdt         
        decfsz    d3, 1
        goto      PLoop2
        decfsz    d2,  1
        goto      PLoop1
        decfsz    d1,  1
        goto      PLoop0
        return

5000000 cycles delay... with a 4MHZ crystal, exactly 5 secconds (too much exact for my taste)
 

, the coding is finally work for me
but last question, when i simulate in proteus, it mention that simulation will not run in real time due to excessive load, is there any solution to solve it before i send program to PIC16f877a
 

I think the SIMULATION won't run real time because of other things slowing your computer, the PIC runs at it's own clock speed so it shouldn't be a problem in real silicon.

Brian.
 
Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top