PIC Code Uncertainty: Why Does Placement Matter?

  • Thread starter Thread starter El Moriana
  • Start date Start date
  • Tags Tags
    Code Uncertainty
Click For Summary

Discussion Overview

The discussion revolves around the placement of a Delay subroutine in PIC assembly code and its impact on the functionality of a program that controls an LED. Participants explore the implications of code organization, particularly concerning the reset vector and how it affects program execution.

Discussion Character

  • Technical explanation
  • Debate/contested

Main Points Raised

  • One participant describes two methods of coding for a PIC16F690, noting that only the second method, where the Delay subroutine is placed after the main code, works as intended.
  • Another participant asserts that the reset vector for PICs is 0x0000, suggesting that the first method may lead to a stack overflow reset due to improper execution flow.
  • Some participants express uncertainty about the implications of the reset vector and whether the placement of the subroutine affects execution.
  • One participant mentions that executing "retlw" without a prior "call" could lead to fetching an uninitialized value from the stack, which may explain the success of the second method.
  • There is a discussion about the error encountered when attempting to set the reset vector to 0x0000, indicating a misunderstanding of how to properly organize the code.
  • Another participant clarifies that the placement of the code does not inherently matter as long as the execution flow is correct.

Areas of Agreement / Disagreement

Participants express differing views on the importance of the reset vector and the implications of subroutine placement. While some agree on the potential issues with the first method, there is no consensus on the best approach to resolve the coding issues presented.

Contextual Notes

Participants note limitations in understanding the behavior of the PIC16F690, particularly regarding stack behavior and reset conditions. There are unresolved questions about how to properly structure the code to avoid errors.

Who May Find This Useful

This discussion may be useful for individuals learning PIC assembly programming, particularly those interested in understanding the implications of code structure and execution flow in embedded systems.

El Moriana
Messages
33
Reaction score
0
Hi, I have just managed to make a PIC light blink. My question has to do with the syntax. In my code, I use a Delay subroutine that is called in between turning the LED on and turning it off.

I tried two codes. The first had my Delay subroutine being placed before my main code. The second had the subroutine placed after my main code (but before END). Only the second code worked. Why? What is the problem with the first method?

Below are the two codes I used:

************************************
1st METHOD
************************************

list p=16F690 ; defines chip that will be used
#include <p16F690.inc> ; imports instructions specific to PIC used

;================
;configuration

__CONFIG _CP_OFF & _CPD_OFF & _BOR_OFF & _MCLRE_ON & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _FCMEN_OFF & _IESO_OFF

;================
;declarations

org 1FFh ; reset
goto start ;
org 0 ;



count1 equ 20h ; general purpose registers used in the delay
counta equ 21h ;
countb equ 22h ;

;================
;subroutines

Init ; initialisation subroutine
clrf PORTA ; clears the port file registers
clrf PORTB ;
clrf PORTC ;

bsf STATUS,RP0 ; selects bank 1
bcf STATUS,RP1 ;

clrf TRISC ; sets all of portC to output

bcf STATUS,RP0 ; selects bank 0
bcf STATUS,RP1 ;

retlw 0

Delay movlw d'250' ;delay 250 ms (4 MHz clock)
movwf count1
d1 movlw 0xC7
movwf counta
movlw 0x01
movwf countb
Delay_0
decfsz counta, f
goto $+2
decfsz countb, f
goto Delay_0

decfsz count1, f
goto d1
retlw 0

;================
;main code

start call Init ; calls the intitialization subroutine

main bsf PORTC,0 ; LED on
call Delay
bcf PORTC,0 ; LED off
call Delay
goto main ; infinite loop
END ; end of program

;================



************************************
2nd METHOD
************************************

list p=16F690 ; defines chip that will be used
#include <p16F690.inc> ; imports instructions specific to PIC used

;================
;configuration

__CONFIG _CP_OFF & _CPD_OFF & _BOR_OFF & _MCLRE_ON & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _FCMEN_OFF & _IESO_OFF

;================
;declarations

org 1FFh ; reset
goto start ;
org 0 ;



count1 equ 20h ; general purpose registers used in the delay
counta equ 21h ;
countb equ 22h ;

;================
;subroutines

Init ; initialisation subroutine
clrf PORTA ; clears the port file registers
clrf PORTB ;
clrf PORTC ;

bsf STATUS,RP0 ; selects bank 1
bcf STATUS,RP1 ;

clrf TRISC ; sets all of portC to output

bcf STATUS,RP0 ; selects bank 0
bcf STATUS,RP1 ;

retlw 0

;================
;main code

start call Init ; calls the intitialization subroutine

main bsf PORTC,0 ; LED on
call Delay
bcf PORTC,0 ; LED off
call Delay
goto main ; infinite loop

Delay movlw d'250' ;delay 250 ms (4 MHz clock)
movwf count1
d1 movlw 0xC7
movwf counta
movlw 0x01
movwf countb
Delay_0
decfsz counta, f
goto $+2
decfsz countb, f
goto Delay_0

decfsz count1, f
goto d1
retlw 0

END ; end of program

;================
 
Engineering news on Phys.org
I can't see how either of your two codes would work
since the reset vector for all PIC's is 0x0000, not 0x01FF.

The PIC will execute the init method without being called, and when it reaches the
'retlw' instruction that will cause a stack overflow reset.
 
That may be. I am only beginning to code PICs and know very little on the subject.

However I have written both those exact codes to a PIC16F690 and the second code worked, with the LED physically turning on and off.

I will keep in mind for future that the reset vector is 0x0000, but is there anything else that could cause the difference?
 
JimmyAlz said:
I can't see how either of your two codes would work
since the reset vector for all PIC's is 0x0000, not 0x01FF.

The PIC will execute the init method without being called, and when it reaches the
'retlw' instruction that will cause a stack overflow reset.

Possibly what I have done is (quite uselessly) placed the instruction "goto start" at 0x01FF and mislabeled it "reset", which has little overall bearing on the working of the code... does this sound correct?
 
I'm sorry it sounded like I didn't believe you. (English is not my first language)

I'm still leaning towards the reset vector. It is a clear problem.
What happens if you rewrite using 0x0000 as reset vector?
 
Possibly what I have done is (quite uselessly) placed the instruction "goto start" at 0x01FF and mislabeled it "reset", which has little overall bearing on the working of the code... does this sound correct?

Yes this sound correct. And would not affect the code. Executing "retlw" without first executing "call" is I think what causes the problems.
 
Firstly,coding:

org 0x0000
goto start
org 0

Does indeed give me an error:

Error[118] G:\...\MYFILE.ASM 61 : Overwriting previous address contents (0000)

Secondly:
JimmyAlz said:
Executing "retlw" without first executing "call" is I think what causes the problems.

In this case, why is it that I am able to call the 'Init' subroutine (which is placed before the call) successfully, as I do in the 2nd method?
 
Checked the data sheet ... 16F690 doesn't *have* stack overflow reset ... :/

So what happens is that the "retlw" instruction fetches an uninitialized value from the stack and jumps to it.
So your code #2 works because you are "lucky".
The uninitialized value just happens to point inside your program code in #2.
 
JimmyAlz said:
The uninitialized value just happens to point inside your program code in #2.

Ok, this makes sense. =) So what do I need to change to code this properly?
 
  • #10
In this case, why is it that I am able to call the 'Init' subroutine (which is placed before the call) successfully, as I do in the 2nd method?
I'm confused, what do you mean by "(which is placed before the call)"?
The placement of the code does not matter.

this will work:

org 0 ; or 0x0000 or 000h (all mean the same thing)
goto start

init
<some code>
retlw

start
call init
main
call something_else
goto main


this will not work:

org 0

init
<some code>
retlw

start
call init
main
call something_else
goto main


I hope I have helped somewhat, going to bed now ... it's 3am here in Sweden.
 
  • #11
Ah, I see! It all makes sense now =), thank you *very* much for your help. Go well.
 

Similar threads

  • · Replies 2 ·
Replies
2
Views
3K
  • · Replies 9 ·
Replies
9
Views
3K
  • · Replies 5 ·
Replies
5
Views
3K
  • · Replies 2 ·
Replies
2
Views
3K
  • · Replies 2 ·
Replies
2
Views
3K
  • · Replies 4 ·
Replies
4
Views
2K
Replies
6
Views
4K
  • · Replies 1 ·
Replies
1
Views
3K
  • · Replies 3 ·
Replies
3
Views
2K
Replies
2
Views
4K