[PicForth] Large amounts of text seem to cause PicForth to
generate bad code
David McNab
david at rebirthing.co.nz
Thu Dec 2 15:13:31 CET 2004
Alex Holden wrote:
>> unless you can post some code.
> Unfortunately there's about 1200 lines of it and creating a minimal
> example which demonstrates this particular problem is easier said than
> done.
My heart does go out to you. I have the 'pleasure' of putting out
similar fires on occasion with my code - which is at 5000 lines of
source and growing.
> Note that it's not crashing when it tries to 'type' the help text; in
> fact it crashes even if the program doesn't call 'type' at all. And the
> crash symptoms are different every time I reset it, but always
> exceptionally weird.
Now, it's smelling like an electrical issue.
A couple of weeks ago, I was wondering why my proto board was giving
weird random results, particularly if I moved my hand to within a few cm
of the board. Turned out that I hadn't wired the pullup resistor to
MCLR, so it was a fluke the board worked at all.
> Sometimes (usually) it prints random jibberish to
> the serial port; sometimes it doesn't. Sometimes the ISR dies (as
> evidenced by the 'heartbeat' LED stopping); sometimes it doesn't.
> Sometimes it even starts printing the bootloader question mark prompt
> over and over again in an infinite loop.
Yep, you're definitely in the eye of a maelstrom.
> This time it's
> proving exceptionally difficult, largely due to the randomness of the
> symptoms (giving me no clue where to look) and the amount of code
> involved (over 2000 instructions).
>
> I think I'm going to have to try harder to come up with a minimal
> example, but I suspect 'minimal' will still require something that uses
> more than 2Kwords of program memory.
I've got my code broken up into driver modules plus main application
module. And for every driver, I've got a separate test program. This has
saved my sanity more times than I dare to count.
What you're seeing is that your program is going off into the boonies in
different ways.
Without seeing your code, I can only offer some general
philosophy/encouragement (and some diagnostic code - attached)
1) there is a clear and definite cause of the problems you're seeing,
and it's most likely very simple
2) sometimes it requires an altered state of consciousness (or at least
shifting your cognitive processes out of the regular groove) to see
what's going wrong
3) suspect everything - leave no stone unturned
4) hopefully, you've got your code structured so that you can disable
certain bits without significantly altering control/data flow in the
rest of your system. For instance:
- try disabling all interrupts
- try disabling all on-chip devices (eg, ADC, USART, etc
5) more specific - if you've got any code words, be sure that you're
setting bank bits and PCLATH correctly
6) In the disassembly output, inspect all boundaries - 256-byte
boundaries, and 2k boundaries - ensuring that you're not getting burned
by the PICs nefarious data and program memory discontiguities
7) rename some of your functions, and insert stub replacements which do
nothing but consume the right amount of stack and return something plausible
8) this one has saved my soul - I've got a routine called '.s' which
dumps out the stack to tty (modules attached). stack leakage has caused
probably 50% of the weird bugs I've seen
9) you /can/ fix it :)
Hope this helps
--
Cheers
David
-------------- next part --------------
\ @+leo-ver=4
\ @+node:@file libtty.fs
\ @@language forth
\ libtty.fs
\
\ driver for on-chip USART
\ @+others
\ @+node:includes
needs picflash.fs
needs libstrings.fs
needs libttycore.fs
\ @-node:includes
\ @+node:tty.poll
\ ( -- 1|0 ) depending on whether incoming char is available
: tty.poll
rcif bit-set?
;
\ @-node:tty.poll
\ @+node:tty.puts
\ puts a string to tty
\ (string via 'c"' literals)
: tty.puts ( -- )
begin
str-char dup
while
tty.putc
repeat
drop
;
\ @-node:tty.puts
\ @+node:tty.putsl
\ puts, followed by crlf
: tty.putsl
tty.puts
tty.crlf
;
\ @-node:tty.putsl
\ @+node:tty"
meta
: tty"
meta> c" tty.puts
;
: ttyl"
meta> c" tty.putsl
;
target
\ @-node:tty"
\ @-others
\ @-node:@file libtty.fs
\ @-leo
-------------- next part --------------
\ @+leo-ver=4
\ @+node:@file libttycore.fs
\ @@language forth
\ libttycore.fs
\
\ just the core tty routines - tty.init, tty.getc, tty.putc
\ @+others
\ @+node:pin assignments
6 pin-c tty.pin-TX
7 pin-c tty.pin-RX
\ @-node:pin assignments
\ @+node:constants
\ constants for various baudrates and clock frequencies
\ (refer datasheet, table 10-4)
$81 constant 9k6 at 20MHz
$40 constant 19k2 at 20MHz
$4a constant 28k8 at 20MHz
$24 constant 33k6 at 20MHz
$14 constant 57k6 at 20MHz
\ set your baudrate here by uncommenting ONE of the below
\ 9k6 at 20MHz constant tty.baudrate
\ 19k2 at 20MHz constant tty.baudrate
\ 28k8 at 20MHz constant tty.baudrate
\ 33k6 at 20MHz constant tty.baudrate
57k6 at 20MHz constant tty.baudrate
\ @-node:constants
\ @+node:variables
variable tty.char
\ @-node:variables
\ @+node:tty.init
\ code foo
\ porta adjust-bank clrf
\ eedata adjust-bank clrf
\ 0 adjust-bank drop
\ return
\ end-code
: tty.init
\ reg-rp0 bcf \ BCF STATUS,5
\ reg-rp1 bcf \ BCF STATUS,6
\ $40 movlw \ MOVLW .64
\ portc movwf \ MOVWF PORTC
$40 portc !
\ banksel TRISA ; bank1
\ reg-rp0 bsf \ BSF STATUS,5
\ reg-rp1 bcf \ BCF STATUS,6
\ set RC6 & RC7 as input
\ trisc 6 bsf \ BSF TRISC,6
\ trisc 7 bsf \ BSF TRISC,7
tty.pin-RX >input
tty.pin-TX >input
\ BAUD RATE SETTINGS - see BAUDRATE equates above
\ tty.baudrate movlw \ MOVLW BAUDRATE
\ spbrg movwf \ MOVWF SPBRG
tty.baudrate spbrg !
\ movlw b'00100100' ; brgh = 1
\ $24 movlw \ MOVLW .36
\ txsta movwf \ movwf TXSTA ; enable Async Transmission, set brgh
$24 txsta !
\ banksel RCSTA ; bank0
\ reg-rp0 bcf \ BCF STATUS,5
\ reg-rp1 bcf \ BCF STATUS,6
\ $90 movlw \ MOVLW .144
\ rcsta movwf \ MOVWF RCSTA
$90 rcsta !
\ a few reads to ensure buffer is empty
\ rcreg ,w movf \ MOVF RCREG,W
\ rcreg ,w movf \ MOVF RCREG,W
\ rcreg ,w movf \ MOVF RCREG,W
rcreg @ drop
rcreg @ drop
rcreg @ drop
\ PROVIDE A SETTLING TIME FOR START UP
\ tty.char clrf
\ label: tty.init-0
\ tty.char ,f decfsz \ DECFSZ tty_char,1
\ tty.init-0 goto \ GOTO tty_init_warmup
0
begin dup while 1+ repeat drop
\ return
;
\ @-node:tty.init
\ @+node:tty.putc
\ ( ch -- ) waits till line available, then transmits char
: tty.putc
begin
txif bit-set?
until
txreg !
;
\ @-node:tty.putc
\ @+node:tty.getc
\ ( -- ch ) waits for incoming char, returns it
: tty.getc
\ wait till char available
begin
rcif bit-set?
until
\ and fetch it
rcreg @
;
\ @-node:tty.getc
\ @+node:tty.crlf
: tty.crlf
$0d tty.putc
$0a tty.putc
;
\ @-node:tty.crlf
\ @-others
\ @-node:@file libttycore.fs
\ @-leo
-------------- next part --------------
\ @+leo-ver=4
\ @+node:@file libttyhex.fs
\ @@language forth
\ libttyhex.fs
\
\ Words for sending/receiving hex data over tty
\ @+others
\ @+node:includes
needs libttycore.fs
\ @-node:includes
\ @+node:tty.put4x
\ puts a hex nybble to tty
: tty.put4x ( nyb -- )
$f and
dup $a < if
$30
else
$37
then
+ tty.putc
;
\ @-node:tty.put4x
\ @+node:tty.put8x
\ puts an 8-bit number to tty as hex
: tty.put8x ( n -- )
dup swapf-tos tty.put4x
tty.put4x
;
\ @-node:tty.put8x
\ @+node:tty.get4x
\ fetches a hex nybble from tty, ignoring any non-hex chars
: tty.get4x
begin
\ optimisation attempt
tty.getc [char] 0 -
dup 9 <= if
true
else
$11 - $df and
dup 6 <= if
$a + true
else
drop false
then
then
until
;
\ @-node:tty.get4x
\ @+node:tty.get8x
\ retrieves a byte from tty as hex chars
: tty.get8x
tty.get4x swapf-tos tty.get4x +
;
\ @-node:tty.get8x
\ @-others
\ @-node:@file libttyhex.fs
\ @-leo
-------------- next part --------------
\ @+leo-ver=4
\ @+node:@file libstacktrace.fs
\ @@language forth
\ libstacktrace.fs
\
\ words for stack leak debugging
\ mainly .s, which dumps stack to tty
\ - invoke .s-init anytime after startup, to mark the bottom of stack
\ - invoke .s anytime thereafter to send a stack dump to tty
\ @+others
\ @+node:includes
[ifundef] any-@
needs libfetch.fs
[then]
[ifundef] tty.init
needs libtty.fs
needs libttyhex.fs
[then]
\ @-node:includes
\ @+node:variables
variable .s-base
\ @-node:variables
\ @+node:stack tracing
\ @+node:.s-init
code .s-init
fsr ,w movf
.s-base movwf
.s-base ,f decf
return
end-code
\ @-node:.s-init
\ @+node:.s
: .s \ stack dump via tty
\ stack-base tty.put8x tty.crlf
\ tty" Stk(toplast): "
$20 tty.putc
fsr @ .s-base @ ( top bottom )
swap ( bottom top )
begin
2dup ( bottom top bottom top )
>= ( bottom top f )
while ( bottom top )
over @ tty.put8x ( bottom top )
$20 tty.putc ( .. )
swap 1- swap ( bottom-1 top )
repeat
drop drop
\ tty" (more): " tty.getc drop
tty.crlf
;
\ @-node:.s
\ @-node:stack tracing
\ @-others
\ @-node:@file libstacktrace.fs
\ @-leo
More information about the PicForth
mailing list