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)