Any limit to 'res' statements?

I have a strange bug and I was wondering if some kind soul could please help out.
I am busy writing some cog code and I added some code and the program crashed. So I removed the code and narrowed it down and the error occurs when I declare one more variable in a section of uninitialised variables ie myvariable res 1
If I add the same variables in the initialised section (ie myvariable long 0) then it works fine.
I'm trying to narrow down the fault.
First, is the cog full? No, because I am padding with 07 and when I do an F8 I can see that this code is not even half filling the cog as there is plenty of spare space. To double check that, I added in a whole lot of extra dummy code and it works fine.
Am I using the variables somewhere else? No, the fault can be replicated with many different variable names.
Is the order of variables important? No, adding in these extra variables at the end, beginning or middle gives the same fault.
So I can narrow it down to this little bit of code
This is the working code, with t6 ant t7 declared in the initialised section.
Put them in the uninitialised section using 'res' and the program crashes.
The solution is to not use 'res' to declare variables, but I'd like to understand more about why this is happening.
Program listing below (and sorry this can't be tested on a prop by itself as it needs an external ram chip).
Any help would be most appreciated - thanks in advance
I am busy writing some cog code and I added some code and the program crashed. So I removed the code and narrowed it down and the error occurs when I declare one more variable in a section of uninitialised variables ie myvariable res 1
If I add the same variables in the initialised section (ie myvariable long 0) then it works fine.
I'm trying to narrow down the fault.
First, is the cog full? No, because I am padding with 07 and when I do an F8 I can see that this code is not even half filling the cog as there is plenty of spare space. To double check that, I added in a whole lot of extra dummy code and it works fine.
Am I using the variables somewhere else? No, the fault can be replicated with many different variable names.
Is the order of variables important? No, adding in these extra variables at the end, beginning or middle gives the same fault.
So I can narrow it down to this little bit of code
latchlow long %11111111_11101111_11111111_11111111 ' mask for P20 latch
topram long 28672
t6 long 0 ' add here because adding to uninitialised data crashes the program
t7 long 0
' Uninitialized data
status res 1 ' status location in hub ram
t1 res 1 ' local variable
t2 res 1 ' local variable
t3 res 1 ' local variable
t4 res 1 ' local variable
t5 res 1 ' local variable
't6 res 1 ' local variable ' adding these two crashes the whole program???!!!!!
't7 res 1 ' local variable
This is the working code, with t6 ant t7 declared in the initialised section.
Put them in the uninitialised section using 'res' and the program crashes.
The solution is to not use 'res' to declare variables, but I'd like to understand more about why this is happening.
Program listing below (and sorry this can't be tested on a prop by itself as it needs an external ram chip).
Any help would be most appreciated - thanks in advance

CON
_clkfreq = 80_000_000 ' 5 Mhz clock
_clkmode = xtal1 + pll16x
modepins = %011_0000 ' pins 23-25 = %011_0000
PAL = %0001
NTSC = %0000
mode = $c0 + NTSC ' NTSC video
x_tiles = 16 '16 try 21,3 08+mode, and in the tv driver, _vx=#1 instead of #2
y_tiles = 14 '6
my_hx = 10+((mode&1)*6) '11+((mode&1)*6)
OBJ
tv : "JB_TV_AMS_03"
'ram : "Video_Ram" ' moved to here and recycle the screen buffer. Hard to do this for other objects as many incorporate hub ram as part of their code (usually near the end of cog ram) and assume this stays forever.
'serial: "FullDuplexSerial" ' standard serial, max 38400 speed
serial: "FullDuplexSerial2FC" ' faster version than standard serial, modified version of the 4 port serial object
PUB Main | i,n
'Diagonal ' diagonal line to hub in both external ram and hub
'BlueBackground
{
pixel(0,0,$07) ' pixels in four corners
pixel(255,0,$07)
pixel(0,223,$07)
pixel(255,223,$07)
repeat i from 0 to 223 ' test vertical line
pixel(128,i,02)
'pixel(128,0,$02) ' pixel test vertical line
'pixel(128,1,$02) ' pixel
'pixel(128,2,$07) ' pixel
'pixel(128,3,$07) ' pixel
}
tv.start(@tvparams)
'serial.start(31,30,0,38400) ' start the serial port
serial.addport(0,31,30,-1,-1,0,0,115200)
serial.start
ramparam2 := @nextline ' pass location of nextline which the video buffer updates
ramparam3 := @screen ' pass location of the screen buffer
ramparam4 := 256 ' number of pixels in each line (256 to about 330)
ramparam5 := @serialbuffer ' pass location of the serial data buffer
'ram.start(@ramparam1)
ram_start(@ramparam1)
repeat ' packet is 02,ndatabytes,row#,256bytes,03. Row# =0-223 and if >223 then can do other things
i := serial.rx(0) 'hangs until a byte arrives
if (i == 02) and (n >257) ' 02 is start of text
n :=0 ' reset counter if a 02 but don't store
else
bytefill(@serialbuffer+n,i,1) ' store the byte (stores 256+1 = 257 bytes)
n += 1 ' add 1 to n
if n>257 ' if end of line
repeat while serialbuffer.byte[257] <> 0 ' wait till cleared by the cog code
serial.tx(0,6) ' send an ack
{
PUB WriteByte(address,value) | i,oewrrd,oewr ' writes to one of 4096 entries (2^12) use latch to select which block
oewrrd := %00000000_11110000_00000000_00000000 ' 23 = oe, 22=wr, 21=rd 20=latch
oewr := %00000000_00110000_00000000_00000000 ' oe and wr low, rd and latch high
address := address & %00000000_00000000_00001111_11111111 ' mask off 12 bits
address := address << 8 ' shift left 8 places
value := value & %00000000_00000000_00000000_11111111 ' mask off value
i := address | value | oewr ' combine
dira := %00000000_11111111_11111111_11111111 ' direction pins
outa := i ' output
i := i | oewrrd ' set oe and wr high
outa := i ' output
dira := %00000000_00000000_00000000_00000000 ' need pullups on /oe /wr and /rd and /latch, and don't put leds on these pins to ground, use buffers ' tristate the pins - need pullups on oe/wr/rd
}
{
PUB ReadByte(address) | i,oewrrd,oerd,n ' reads from one of 4096 entries (2^12) - use latch to select which block
oewrrd := %00000000_11110000_00000000_00000000 ' 23 = oe, 22=wr, 21=rd 20=latch
oerd := %00000000_01010000_00000000_00000000 ' oe and rd low, wr and latch high
address := address & %00000000_00000000_00001111_11111111 ' mask off 12 bits
address := address << 8 ' shift left 8 places
i := address | oerd ' combine
dira := %00000000_11111111_11111111_00000000 ' direction pins
outa := i ' output
n := ina ' get the value
n := n & %00000000_00000000_00000000_11111111 ' mask out all but lower byte
i := i | oewrrd ' set oe and wr high
outa := i ' output /oe and /wr high
result := n ' return this value
dira := 0 ' tristate the pins - need pullups on /oe/ /rd and /wr
}
{
PUB SelectBlock(block) | latch,mask ' select one of 128 blocks (2^7)
mask := %00000000_00010000_00000000_01111111 ' pins to enable
latch := %11111111_11101111_11111111_11111111 ' mask for P20 latch
dira := mask ' enable P20 and P0-P6
outa := block ' output the data to P0-6
outa := outa & latch ' set P20 low
dira := 0 ' tristate pins (10k pullup on P20-23 so latch pin then goes high again)
PUB BlueBackground | n,i ' sets ram to blue
repeat n from 0 to 7 ' 7 blocks of 16 lines each
selectblock(n) ' block n
repeat i from 0 to 4095
writebyte(i,$04) ' blue =2d, black =02 dark blue = 0A
PUB Pixel(x,y,color)
if (y and 1) == 0 ' an even number so put in hub ram
bytefill(@screen+y*128+x,color,1) ' put in hub ram line 0 =0, 2=1, 4=2 (y/2)*256 is the same as y*128
else
y := (y-1)/2 ' odd number so put in external ram 1=0,3=1,5=2 so formula is (y-1)/2
selectblock(y>>4)
writebyte((y*256+x) & 4095,color) ' write to ram - - if >4095 then subtract 4096
{
PUB Diagonal | c,a,n,m,i ' write different colored lines to the ram chip
' blue background to the whole of external ram (hub ram already initialised to blue in tvparams)
repeat n from 0 to 7 ' 7 blocks of 16 lines each
selectblock(n) ' block n
repeat i from 0 to 4095
writebyte(i,$02) ' blue =2d, black =02
c := $0e ' pale blue
a := 0 ' ram counter
selectblock(0)
repeat i from 0 to 15 ' 16 lines ' rainbow in first block of ram
repeat n from 0 to 15
repeat m from 0 to 15
WriteByte(a,c)
a += 1
c += $10
c := $0e ' pale blue
repeat i from 0 to 15 ' 16 lines ' rainbow in first lines of hub
repeat n from 0 to 15
repeat m from 0 to 15
bytefill(@screen+i*256+n*16+m,c,1)
c += $10
' put the diagonal white line in ram with a blue background
repeat n from 0 to 7 ' 7 blocks of 16 lines each
selectblock(n) ' block n
repeat i from 0 to 15
writebyte(256*i+i+n*16,$07) ' single white pixel in a diagonal line
writebyte(256*i+i+144+n*16,$07) ' another diagonal line
repeat n from 0 to 111 ' put the diagonal line in hub
bytefill(@screen+256*n+n,$07,1)
repeat n from 0 to 111 ' put the second diagonal line in hub
bytefill(@screen+256*n+n+144,$07,1)
' single pixels
bytefill(@screen+256*50+128,$07,1) ' single pixel in hub
' now single pixel in ext ram
selectblock(3)
writebyte(256*4+128,$07)
}
}
' ram driver moved into main so cog data can be recycled
VAR
long cog
PUB Ram_Start(ramptr) : okay
ram_stop
okay := cog := cognew(@ram_entry, ramptr) + 1
PUB Ram_stop
'' Stop ram driver - frees a cog
if cog
cogstop(cog~ - 1)
' ram cog parameters
DAT
ramparam1 long 0
ramparam2 long 0
ramparam3 long 0
ramparam4 long 0
ramparam5 long 0
' buffer for serial port
DAT
serialbuffer byte $00[258] ' first byte is number of pixel values(256), then the row number, then 256 pixel values then a 03 (changed to 00 when read)
DAT
tvparams long 0 'status
long 1 'enable
long modepins 'pins
long mode 'mode
long x_tiles 'hc
long y_tiles 'vc
long my_hx 'hx
VSyncFlag long 0
nextline long 0
tvbitmapptr long @screen+$10
bordercolour long $02 ' border color
'screen byte $04[256*113] ' fill screen with a value for startup 112 rows = half screen plus 1
screen byte 0 ' dummy location, see end for rest of the screen array
DAT
'*******************************
'* Assembly language Ram driver *
'*******************************
' check the line number. If it has changed, then start reading the next line in and put @ screen
' if it has not changed then repeat the loop
' if it is the last line then restart the ram counter variable
' currentline counts up from 0 to tiles*16
' the video driver recycles the same 8*256 bytes in the screen buffer
' first, wait for currentline to equal zero and when it does, start reading in ram to @screen
' check the currentline. Shift left by 2 and mask-and with 1. 0-3 is 0, 4-7 is 1, 8-11 is 0, 12-15 is 1 etc
' Ram format. Each line is up to 512 pixels long. 256 is the standard video driver but over 300 does work
' so each line is 9 bits
' Then there are 4 lines in a group. Read these all in from ram in one subroutine call
' So that is 11 bits.
' And then these are in two groups of 4. So that is 12 bits.
' So - once 8 lines have been read in (12 bits = 4096 bytes), then change the latch
' There are 256/8 = 32 groups of 8 lines so that is 5 bits of the latch that are used
' and the 512k ram chip can store 4 frames (if needed)
' P0-7 is the data
' P8-P19 is the address for 8 lines (12 bits)
' P20 controls the latch enable
' P21 is /rd, P22 is /wr and P23 is /oe (chip select)
' ** There are pullups on P20 to P23 as the ram chip needs to retain data when transferring from spin to cog **
org
ram_entry
mov t1,par
mov status,t1
add t1,#4
rdlong _nextline,t1 ' line number in hub (updated by graphics cog) use with rdlong t1,_nextline
add t1,#4
rdlong screen_buf,t1 ' screen buffer location
add t1,#4
rdlong pixels_x,t1 ' pixels per line
add t1,#4
rdlong serial_buffer,t1 ' serial buffer for data coming in
mov ramline,screen_buf
add ramline,topram ' location of the temp 256 byte buffer that is rewritten each alternate line
mov serial_buf_last,serial_buffer
add serial_buf_last,#257 ' last entry in the serial buffer
mov outa,oewrrd ' oe/wr/rd/latch all high %00000000_11110000_00000000_00000000
mov dira,dira_pins ' enable these pins for output %00000000_11111111_11111111_00000000
' in 'spaghetti' code with jumps all over the place - but in a way that maximises speed (this works better than djnz loops)
' reset everything
' wait for zero line
' label1
' read line of data
' add 2 to local line counter
' if locallinecounter>=224 then back to beginning
' add 1 to blockcounter
' if blockcounter=16 then reset blockcounter and increment latchcounter
' wait for current_line to equal localline (will be 2,4,6,8 etc)
' goto label1
' *** don't forget # after all jmp and call instructions!!! ****
main_loop_1 mov sram_address,#0 ' start reading ram at address #0
mov localcounter,#0 ' my local line counter
mov blockcounter,#0 ' block is 256 bytes, 16 blocks per latch
mov latchcounter,#0 ' block is 4096 bytes reset block counter
call #selectlatch ' latch to zero
main_loop_2 mov hubaddr,ramline ' setup for rdblock
mov len,pixels_x ' setup for rdblock
main_loop_3 rdlong current_line,_nextline ' read the line that is being displayed
cmp current_line,localcounter wz ' equal to localcounter?
if_nz jmp #main_loop_3 ' loop until it is
call #rdblock ' read in 256 bytes
add sram_address,#256 ' next 256 bytes
add localcounter,#2 ' add 2 get ready for next line
cmp localcounter,#224 wc ' end of the screen = 224
' if_nc jmp #main_loop_1 ' restart everything
if_nc jmp #process_serial ' any new pixels?
add blockcounter,#1 ' add 1 to block counter
cmp blockcounter,#16 wz ' time for new block?
if_nz jmp #main_loop_2 ' skip if still on current block
mov sram_address,#0 ' reset the ram address
mov blockcounter,#0 ' reset blockcounter
add latchcounter,#1 ' add 1 to latchcounter
call #selectlatch ' latch to latchcounter
jmp #main_loop_2
' 10k pullups on /oe, /rd and /wr and latch and don't put leds on these three pins
'Read a "len" byte block given by "sram_address" into hub at "hubaddr" - Cluso99's ram driver
' preserves sram_address
rdblock
mov t1,sram_address ' store sram address
shl t1,#8 ' shift left so in the right position
or t1,oerd ' %00000000_01010000_00000000_00000000 ' /oe and /rd low
' outa pre-filled with the address shifted over by 8 and the /oe and /rd low
mov outa,t1 ' send it out
'nop ' cluso's driver has a nop but it seems ok without one
rdloop mov t2, ina ' read byte from SRAM \ ignores upper bits
wrbyte t2, hubaddr ' copy byte to hub /
add hubaddr, #1 ' inc hub pointer
add outa, #(1 << 8) ' inc sram address
djnz len, #rdloop ' loop for xxx bytes
mov outa,oewrrd ' oe,wr and rd and latch all high
rdblock_ret ret
' pass latchcounter
selectlatch mov dira,blockmask ' enable different pins to reading, ie P0-7 are outputs now
mov t1,latchcounter ' get the latch counter
and t1,#%01111111 'mask off high bit as 512k/4096/16 is 128
mov outa,t1 ' output blockcount byte
and outa,latchlow ' set latch low
'nop ' delay not needed
'nop
mov dira,dira_pins ' enable these pins for output %00000000_11111111_11111111_00000000
mov outa,oewrrd ' set oe,wr,rd and latch high
selectlatch_ret ret
' Write a "len" byte block given by t3 in external ram from hub at t4 - Cluso99's ram driver
wrblock
mov dira,pin0to23 ' dira pins %00000000_11111111_11111111_11111111
wrloop mov t1,t3 ' store sram address in t1
shl t1,#8 ' shift left so in the right position
rdbyte t2,t4 ' get the byte
or t1,oewr ' or with %00000000_00110000_00000000_00000000
or t1,t2 ' or with the hub address
mov outa,t1 ' send it out
nop ' wait a little
nop
or outa,oewrrd ' oe,wr and rd all high
add t4,#1 ' add 1 to hub address
add t3,#1 ' add 1 to sram address
djnz len, #wrloop ' loop for xxx bytes
mov dira,dira_pins ' enable these pins for output %00000000_11111111_11111111_00000000
mov outa,oewrrd ' oe,wr and rd and latch all high
wrblock_ret ret
' read serial data. The first byte is the row number, then 256 bytes
' if the last byte is zero then has been read, if not zero then read
' if the last byte is not zero, then process the data and then write a zero to the last byte
' if processing and the row is even then store to hub ram
' if the row is odd then store to external ram
' if the row number is 255 then this is an instruction packet so jump to processing instruction packets
process_serial rdbyte t1,serial_buf_last ' value in the last byte of the buffer
cmp t1,#0 wz
if_z jmp #main_loop_1 ' do nothing if zero
' if_z jmp #delaystart ' test shows 51000 instructions possible here
mov t2,serial_buffer ' t2 is a counter
mov t3,screen_buf ' t3 is the screen buffer
rdbyte t1,t2 ' t1 is row number
' cmp t1,#255 wz ' row = 0 to 223 = display, 255=instruction packet
' if_z jmp #instruction ' exit this
mov t5,t1 ' t5 also contains the row number
add t2,#1 ' increment - 1st byte is row number, data starts at 1
mov t4,#256 ' count timer
and t1,#1 ' mask out all but LSB
cmp t1,#1 wz ' test if odd or even
if_z jmp #serial_external ' odd so write to external ram
'put in hub ram line 0 =0, 2=1, 4=2 (y/2)*256 is the same as y*128
shl t5,#7 ' multiply by 128
add t3,t5 ' get hub location to store
serial_hub
rdbyte t1,t2 'get the first byte t1 = row number, multiply by 256 and add to t3
wrbyte t1,t3 ' store to hub ram
add t2,#1 ' increment source
add t3,#1 ' increment destination
djnz t4,#serial_hub ' do 256 times
jmp #serial_finish ' set last byte to zero to say finished
serial_external ' move data to external ram t5 contains row number - see pixels routine for the maths
rdbyte t1,serial_buffer ' t1 is the row number 0-31 = block 0, 32-63=block1
shr t1,#5 ' divide by 32
mov latchcounter,t1 ' set up latchcounter
call #selectlatch ' select the correct latch
rdbyte t3,serial_buffer ' get the row number again
and t3,#%11111 ' mask off so max is 31 as sram resets each block
sub t3,#1 ' subtract 1
shl t3,#7 ' multiply by 128 ie 256*(y-1)/2
mov len,#256 ' 256 bytes to write
mov t4,serial_buffer ' serial buffer location
add t4,#1 ' add 1 so points to correct place (the 02 begin block is discarded in spin, and the first number is the row number so ignore that too)
call #wrblock ' write len bytes to sram t3 from hub t4
jmp #serial_finish ' set last byte to zero to say finished reading
serial_finish mov t1,#0 ' set value to non zero to say this has been read
wrbyte t1,serial_buf_last ' store to the serial buffer
jmp #main_loop_1
'rwo 1 =sram0,row 3=sram256, row 5=sram512, row33=sram0, block1
'delaystart mov t1,delay ' for testing how much time is available after displaying frame
'delay1 djnz t1,#delay1 ' value of 51000 works, 52000 does not work
' jmp #main_loop_1 ' so this is the max number of instructions
'finish jmp #finish
' video block to sram (overwrites the block on the screen (would need some hub space OR a direct ram to ram routine)
' get line number, detect if even or odd and set a flag.
' get x and y longs and sram address (4 longs, 1 is command, 2 is x, 3 is y, 4 is sram address)
' move alternate (hub) lines to sram load x and djnz
' move lines from sram video buffer to the hub lines above
' move alternate (hub) lines to sram - until y all done
' instruction packet - 0=255,then 256 bytes starting at t2+1
' 8 bytes per packet
' byte 1 = 1 or 2 where 1 = screen to ram, 2=ram to screen
' byte 2 = x origin where 0,0 is top left corner
' byte 3 = y origin
' byte 4 is size_x number of x pixels
' byte 5 is size_y number of y pixels
' byte 6 = which 4k block
' byte 7 = high ram byte (value is 0 to 4095 so needs two bytes)
' byte 8 = low ram byte
instruction add t2,#1 ' now start of the packet. (skip the 255). t2 is the counter
rdbyte t3,t2 ' t3 = 1 or 2, screen to ram or ram to screen
add t2,#1
rdbyte t4,t2 ' t3 = org_x
add t2,#1
rdbyte t5,t2 ' t4 = org_y
add t2,#1
rdbyte t6,t2 ' t5 = sizex
add t2,#1
rdbyte latchcounter,t2 ' block to read
add t2,#1
rdword t7,t2 ' read two bytes = ram value
'call #selectlatch ' (alters t1)
' jump based on value in t3
'
jmp #serial_finish ' write a zero to say finished with the packet
' Initialised data
'address_mask long %00000000_00000000_00011111_11111111 ' 13 bits max 32 lines otherwise need to latch
oewrrd long %00000000_11110000_00000000_00000000 ' 23 = oe, 22=wr, 21=rd, latch high
oerd long %00000000_01010000_00000000_00000000 ' oe and rd low
oewr long %00000000_00110000_00000000_00000000 ' oe and wr low
dira_pins long %00000000_11111111_11111111_00000000 ' direction pins to be enabled
pin0to23 long %00000000_11111111_11111111_11111111 ' for testing
zero long %00000000_00000000_00000000_00000000 ' for testing
'smallblock long 1024
fivetwelve long %00000000_00000000_00000010_00000000 ' 512 for sram increment
blockmask long %00000000_00010000_00000000_11111111 ' mask for block select
latchlow long %11111111_11101111_11111111_11111111 ' mask for P20 latch
topram long 28672
t6 long 0 ' add here because adding to uninitialised data crashes the program
t7 long 0
' Uninitialized data
status res 1 ' status location in hub ram
t1 res 1 ' local variable
t2 res 1 ' local variable
t3 res 1 ' local variable
t4 res 1 ' local variable
t5 res 1 ' local variable
't6 res 1 ' local variable ' adding one more variable in res crashes the whole program???!!!!!
't7 res 1 ' local variable
screen_buf res 1 ' location of the screen buffer
_nextline res 1 ' currrent line - updated by the video driver
sram_address res 1 ' ram address value
hubaddr res 1
len res 1
current_line res 1
pixels_x res 1
localcounter res 1
blockcounter res 1
latchcounter res 1
serial_buffer res 1
serial_buf_last res 1
ramline res 1 ' location of a single line in the top part of the screen memory that can be rewritten
long $07070707[496-$] ' pad with white to 2k
fit 496 ' subtract this value (in longs) off the screen buffer
screen2 byte $04[256*113-490*4] ' fill screen with a value for startup 112 rows = half screen plus 1
Comments
So which isn't right, the long $07070707[496-$]
or the
screen2 byte $04[256*113-490*4]
(the aim is to have a screen buffer that uses almost all the hub ram, and to put cog code into this at startup and then recycle the memory. I have it working for one cog object and ultimately would like to do the same for the serial driver and video driver and get another 4k)
t6 long 0 ' add here because adding to uninitialised data crashes the program t7 long 0 pad long $07070707[496-$] ' pad with white to 2k ' Uninitialized data [COLOR="orange"]org pad[/COLOR] status res 1 ' status location in hub ram
The pad properly fills 2K or rather $1F0 longs and then we relocate the res section by preceding it with an org (overlayed on the padding). After applying this change (for me) the label ram_entry ends up at $158 in hub and screen2 at $918 which gives you $7C0 bytes or $1F0 longs.