EmbeddedRelated.com
Forums
Memfault Beyond the Launch

What am I doing wrong?

Started by Julian Morrison September 16, 2005
--nextPart2912043.rat7JAi7FX
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 8Bit

I'm trying to code a very simple LED flasher as a starter app, and I
can't get the damn thing to work. (This is on PIC16F627 and simulated on
MPLAB.) The timer1 rollover never fires. Code follows as attachment.

Can someone tell me what I'm doing wrong?
--nextPart2912043.rat7JAi7FX
Content-Type: text/plain; name="FlashLed.asm"
Content-Transfer-Encoding: 8Bit
Content-Disposition: attachment; filename="FlashLed.asm"

;----

; Purpose:				Flash LED once per second

; Written by:			Julian Morrison

; Date:					6/Sep/2005

; Version:				0.1

; File saved as:		FlashLed.asm

; For PIC:				16F627

; For board:			Velleman K8048

; Clock frequency:		4 megahertz

;----



;				processor p16f627 ; for gpasm

				processor 16f627

		

;----

; Declarations

				

		; reset vector

				org		0x00

				goto	Start

				

		; interrupt vector

				org		0x04

				goto	ISR

		

		; SFRs for p16f627

		

		; ...shared

indirect		equ		0x00 ; address to indirect via FSR

pcl				equ		0x02 ; program counter low byte

status			equ		0x03

fsr				equ		0x04 ; indirection pointer

pclath			equ		0x0A ; program counter high 5 bits

intcon			equ		0x0B

				

		; ...bank 0

tmr0			equ		0x01

porta			equ		0x05

portb			equ		0x06

pir1			equ		0x0C

tmr1_lo			equ		0x0E

tmr1_hi			equ		0x0F

t1con			equ		0x10

tmr2			equ		0x11

t2con			equ		0x12

ccpr1_lo		equ		0x15 ; capture/compare low byte

ccpr1_hi		equ		0x16 ; capture/compare high byte

ccp1con			equ		0x17

txreg			equ		0x19 ; USART transmit

rcreg			equ		0x1A ; USART recieve

cmcon			equ		0x1F

user_regs_0		equ		0x20

		

		; ...bank 1

option_reg		equ		0x01

trisa			equ		0x05

trisb			equ		0x06

pie1			equ		0x0C

pcon			equ		0x0E

pr2				equ		0x12

txsta			equ		0x18

spbrg			equ		0x19

eedata			equ		0x1A

eeadr			equ		0x1B

eecon1			equ		0x1C

eecon2			equ		0x1D

vrcon			equ		0x1F

user_regs_1		equ		0x20

		

		; ...bank 2

portb			equ		0x06

user_regs_2		equ		0x20

		

		; ...bank 3

trisb			equ		0x06

		

		; custom registers

rollover_count	equ		user_regs_0 + 0x00

		

		; constants

ticks_per_10ms	equ		d'10000' ; 4 megahertz, 4 cycles per tick

t1rollover		equ		d'65536' - ticks_per_10ms

		

;----

; Subroutines

				org		0x05

Init			clrf	porta

				clrf	portb

				bsf		status,5    ; bank 1 to access tris

				movlw	b'00001111'

				movwf	trisa       ; porta is connected to switches

				movlw	b'00000000'

				movwf	trisb       ; portb is connected to LEDs

				movlw	b'00001000' ; prescale 1:1 for WDT, none for tmr0

				movwf	option_reg

				bcf		status,5    ; bank 0

				movlw	b'00000000'

				movwf	intcon

				return

		

ISR				btfss	pir1, 0        ; only interested in timer 1 overflow

				retfie

				bcf		pir1, 0        ; reset timer 1 interrupt

				decfsz	rollover_count, f

				retfie

				movlw	b'00000001'

				xorwf	portb, f       ; flip the LED

				call	ResetClock

				retfie

				

ResetClock		movlw	HIGH t1rollover

				movwf	tmr1_hi

				movlw	LOW t1rollover

				movwf	tmr1_lo

				movlw	d'100'

				movwf	rollover_count

				return

				

SetClock		call	ResetClock

				bcf		pir1, 0        ; reset timer 1 interrupt

				bsf		status, 5

				bsf		pie1, 0   ; enable tmr1 rollover interrupt

				bcf		status, 5

				bsf		intcon, 7 ; global interrupt enable

				movlw	b'00000001'

				movwf	t1con     ; start clock with no prescaling

				return

		

;----

; Main program

		

Start			call	Init

				call	SetClock

Main			clrwdt

				goto	Main ; loop for interrupt

		

				end

		


--nextPart2912043.rat7JAi7FX--
"Julian Morrison" <julian@extropy.demon.co.uk> wrote in message 
news:dgfkjk$j3b$1$8300dec7@news.demon.co.uk...
> I'm trying to code a very simple LED flasher as a starter app, and I > can't get the damn thing to work. (This is on PIC16F627 and simulated on > MPLAB.) The timer1 rollover never fires. Code follows as attachment. > > Can someone tell me what I'm doing wrong?
I don't know that CPU, but I saw this:
>>
; interrupt vector org 0x04 goto ISR ... ; Subroutines org 0x05 Init clrf porta << You sure you're leaving enough room for the "goto ISR"? Also, are there any other vectors that map to 0x05 etc? Steve http://www.fivetrees.com
Steve at fivetrees wrote:

> You sure you're leaving enough room for the "goto ISR"? Also, are there > any other vectors that map to 0x05 etc?
AFAIK (could be wrong, but I think not) the program memory addresses are counted in whole-instruction increments, not in bytes. So 0x05 is the instruction after. Still, I commented the "org 0x05" out, rebuilt and reran, unfortunately with no more success. The same result: the rollover bit in PIR1 gets set as the timer runs, but the ISR is never called.
On Sat, 17 Sep 2005 00:31:00 +0100, the renowned Julian Morrison
<julian@extropy.demon.co.uk> wrote:

>I'm trying to code a very simple LED flasher as a starter app, and I >can't get the damn thing to work. (This is on PIC16F627 and simulated on >MPLAB.) The timer1 rollover never fires. Code follows as attachment. > >Can someone tell me what I'm doing wrong?
You need to set PEIE, as well as GIE for the TMR1 interrupts to work. Best regards, Spehro Pefhany -- "it's the network..." "The Journey is the reward" speff@interlog.com Info for manufacturers: http://www.trexon.com Embedded software/hardware/analog Info for designers: http://www.speff.com
Spehro Pefhany wrote:

> You need to set PEIE, as well as GIE for the TMR1 interrupts to work.
Thanks! It works now. Damn, who writes these chip manuals anyhow? They buried that info in a boolean-gate diagram on page 103. No thought to mention "actually, timer1 needs PEIE" in the section actually about timer1! At least it wasn't any worse mistake. Again, thanks :-)
On Sat, 17 Sep 2005 02:39:07 +0100, the renowned Julian Morrison
<julian@extropy.demon.co.uk> wrote:

>Spehro Pefhany wrote: > >> You need to set PEIE, as well as GIE for the TMR1 interrupts to work. > >Thanks! It works now. > >Damn, who writes these chip manuals anyhow? They buried that info in a >boolean-gate diagram on page 103. No thought to mention "actually, >timer1 needs PEIE" in the section actually about timer1! > >At least it wasn't any worse mistake. > >Again, thanks :-)
No problem. Another hint you'll find in Microchip's datasheets is that they often summarize the various SFR bits and registers required for a given function, in the section related to the function (in this case TMR1). You'd probably have to search to find the function of that bit if you hadn't run into it before, but at least you'd know to look. I have a datasheet here with that info in Table 7-2. The relevant stuff to TMR1 is spread over 6 bytes in 2 banks. Also, the midrange reference manual provides more detail organized differently (although it may not always match newer chips exactly, it can be helpful). Best regards, Spehro Pefhany -- "it's the network..." "The Journey is the reward" speff@interlog.com Info for manufacturers: http://www.trexon.com Embedded software/hardware/analog Info for designers: http://www.speff.com
On Sat, 17 Sep 2005 02:39:07 +0100, the renowned Julian Morrison
<julian@extropy.demon.co.uk> wrote:

>Spehro Pefhany wrote: > >> You need to set PEIE, as well as GIE for the TMR1 interrupts to work. > >Thanks! It works now.
P.S. You probably know this already, but just in case, you are not saving and restoring context in the ISR. That means that most anything beyond your simple loop at Main: will fail because things will be corrupted by the ISR. Don't bother trying to figure out the save/restore stuff yourself, just look it up. It requires the use of the swapf (swap nibbles) instruction... and there are some banking issues (code and data) <ugh>. Let's not even get into nested ISRs. You have to admire an architecture that requires an application note to explain how to do a table lookup. Best regards, Spehro Pefhany -- "it's the network..." "The Journey is the reward" speff@interlog.com Info for manufacturers: http://www.trexon.com Embedded software/hardware/analog Info for designers: http://www.speff.com
Spehro Pefhany wrote:

> P.S. > > You probably know this already, but just in case, you are not saving > and restoring context in the ISR.
D'oh! As you can see I'm still new to this.
> That means that most anything beyond > your simple loop at Main: will fail because things will be corrupted > by the ISR.
There's a design approach I've been using to minimize that: "either spin and poll without using interrupts, or do everything inside the ISR". This was mainly practise code at interrupt handling.
> Don't bother trying to figure out the save/restore stuff > yourself, just look it up. It requires the use of the swapf (swap > nibbles) instruction... and there are some banking issues (code and > data) <ugh>.
Thanks, now I know what to look for, google makes finding it easy. Banking issues? I'm guessing, switch off GIE before changing banks away from 0, then run the ISR manually after switching back so as to avoid dropping interrupts. Is that right?
> Let's not even get into nested ISRs. You have to admire > an architecture that requires an application note to explain how to do > a table lookup.
"brought to you by the folks who did INTERCAL and Malbolge"
"Julian Morrison" <julian@extropy.demon.co.uk> wrote in message 
news:dggcv5$gm2$1$8300dec7@news.demon.co.uk...
> Spehro Pefhany wrote: > >> P.S. >> >> You probably know this already, but just in case, you are not saving >> and restoring context in the ISR. > > D'oh! As you can see I'm still new to this. > >> That means that most anything beyond >> your simple loop at Main: will fail because things will be corrupted >> by the ISR. > > There's a design approach I've been using to minimize that: "either spin > and poll without using interrupts, or do everything inside the ISR". > This was mainly practise code at interrupt handling. > >> Don't bother trying to figure out the save/restore stuff >> yourself, just look it up. It requires the use of the swapf (swap >> nibbles) instruction... and there are some banking issues (code and >> data) <ugh>. > > Thanks, now I know what to look for, google makes finding it easy. > Banking issues? I'm guessing, switch off GIE before changing banks away > from 0, then run the ISR manually after switching back so as to avoid > dropping interrupts. Is that right? > >> Let's not even get into nested ISRs. You have to admire >> an architecture that requires an application note to explain how to do >> a table lookup. >
The 16Cxxx PIC architecture requires the programmer to be aware of a lot of things that are not very obvious. There are some pretty clunky things about interrupts in particular. First, the stack is used only for return address information. You cannot push data onto it. Second, the MOVFW instruction affects the ZERO flag. This means that when an ISR needs to save the context it must: Save the W register to a file register location that is allocated at the same offset in all banks. Save the status register into the W register using the SWAPF nibble instruction. The SWAPF instruction must be used because it does not affect the flags in the status register. Microchip has application notes and code examples on how to do this. ------------- You should not need to switch off the GIE from within an ISR as the interrupt system is disabled until the RETFIE instruction is executed. You need to know about this when doing nested interrupts. When using nested interrupts you really need to understand the PIC very thoroughly. ------------- But the single most important thing about ISR code: NEVER USE ALL OF THE AVAILABLE REAL TIME IN THE INTERRUPT SERVICE ROUTINES! In fact using more than 20% of the processor bandwidth in the ISRs can make debug quite a challenge. Plus the interrupt response could be quite bad.
To Keyser and Julian.

>.. some fullquote deleted > > This means that when an ISR needs to save the context it must: > > Save the W register to a file register location that is allocated at the > same offset in all banks. > > Save the status register into the W register using the SWAPF nibble > instruction. The SWAPF instruction must be used because it does not affect > the flags in the status register. > > Microchip has application notes and code examples on how to do this.
In fact, it's even described in the manual, how to save the context during interrupt (chapter 14.7 in the PIC16F62x manual).
> You should not need to switch off the GIE from within an ISR as the > interrupt system is disabled until the RETFIE instruction is executed. > > You need to know about this when doing nested interrupts. When using nested > interrupts you really need to understand the PIC very thoroughly.
Nested interrupts on PIC are a very bad sugestion on a newbe.
> But the single most important thing about ISR code: > > NEVER USE ALL OF THE AVAILABLE REAL TIME IN THE INTERRUPT SERVICE ROUTINES! > > In fact using more than 20% of the processor bandwidth in the ISRs can make > debug quite a challenge. Plus the interrupt response could be quite bad.
This applies not only to PICs, but for most other micros. At least: It is always a more helpful, to read also about related things (here the basics about interrupt on PIC) in the manual. HTH Michael

Memfault Beyond the Launch