REV A P2 Edge booting from flash possible?
rogloh
Posts: 6,399
Hi,
First time I've tried it on this board but am having problems booting an old REV-A P2-Edge board from flash. I can see the flash from my app when loaded and running from a RAM download and I can also write to it with loadp2 but it refuses to boot from flash for some reason.
I've got the pull up and down icon dip switches both set off, and flash enabled (serial + flash boot). Won't boot my app from flash. Also tried with the up dip switch disabled and down enabled (flash only boot), with the same result.
I measured P59 resistance to ground (out of circuit) being 10k when the down dip switch is enabled and 14Meg when disabled so I think the DIP switch is working. Measured P61 (flash CS) to be 300k to ground and 10k to the V56 IO pad.
I'm now wondering if there was some known issue in the early boards? Or perhaps there is a problem with my app - but it seems fine when loaded to RAM. I'll pare it down to just toggling a LED and try that too but I suspect it'll be the same. My current binary app image size is about 330kB so I know it fits.
I'm using loadp2 rev 0.77 to flash the P2-Edge with these settings.
loadp2 -t -flash xxx.binary
I know loadp can write to the flash as I also share the upper flash with data and I can see that data in flash if the app is run from RAM.
My RAM load works when I flashed the upper filesystem data at 1MB offset, but the boot from flash seems to fail. Also tried this out...
loadp2 -t -HIMEM=flash @0=z80.binary,@80000000=z80.binary,@80100000=/Users/roger/z80fs.bin
For testing I wrote a simple flash sector dump app which I loaded to RAM and can see my app in FLASH sitting at sector 2 onwards - sector 0 and 1 seem to have a small initial 1kB bootloader written to it which reads in the remaining app code starting from the 1kB offset in flash:
Sector 0 08 00 90 FD FC C2 47 EA 9C 43 05 00 3C 94 0C FC ......G..C..<... 50 78 64 FD 3C 02 1C FC 58 78 64 FD 1D 32 60 FD Pxd.<...Xxd..2`. 00 00 8C FC 0A 00 CC F9 02 00 20 F3 00 04 80 F1 ................ 05 00 64 F0 00 34 20 F9 01 00 64 F0 3C 00 24 FC ..d..4....d.<.$. 1F 06 64 FD 00 34 A4 FC 24 36 60 FD F5 05 9C FB ..d..4..$6`..... 50 F4 65 FD 3C 00 0C FC 42 0F 80 FF 1F 00 65 FD P.e.<...B.....e. 00 00 EC FC 00 00 00 40 00 00 F5 C0 00 00 00 00 .......@........ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ ... Sector 2 00 00 00 00 01 EC 63 FD 02 00 00 FF 04 EC E7 FC ......c......... 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
What am I missing? It has been a while since I tried flashing something on a P2 so perhaps I have forgotten something simple and I'm just doing something dumb, or maybe REV A flash booting is problematic...?
Could it be some initial clock setting that is normally patched by loadp2 or something like that? My flexspin based app does have _clkfreq set to 270000000, but no explicit CLKMODE setup otherwise. Although I didn't think it really patched the settings unless -PATCH option was applied anyway.

Comments
Ok, so it turns out that this LED test did boot from flash when I flashed it using this command:
loadp2 -FLASH ledflash.binaryso perhaps my 330kB is too big for reliable serial downloading, or perhaps there is a bad sector somewhere in the flash...hope not. I guess I'll try to add a CRC check or read back all the sectors and manually compare the source binary.
CON _clkfreq = 100000000 PUB main() repeat waitms(1000) pintoggle(56)I should also mention: I tried the app boot test after first removing the PropPlug (in case that was holding down reset) and then re-powering the P2-Edge, but always get the same problem with my main app not starting up.
I've never used the multipart bundling let alone also burning it to flash. EDIT: Oh, oops, that was an alternate.
Ah-ha! The -FLASH option has to be all caps! I guess all of Loadp2's options are case sensitive then.
Verbose without -FLASH option:
Verbose with -FLASH option:
I get this output with verbose enabled:
Just ran this simple total byte sum test on the binary stored in flash. Doesn't look like there is a problem with the flash contents itself unless the initial loader is getting rejected by the P2 boot process.
CON _clkfreq = 100000000 OBJ f:"ers_fmt" uart:"SmartSerial" flash:"SpiFlash" PUB main() uart.start(115200) send:=@uart.tx send("checksum=",f.dec(checksum()),13,10) repeat PUB checksum() :sum | i sum:=0 repeat i from 1024 to $54567+1024 if (i//512 == 0) flash.read(@buffer, i,512) sum+=buffer[(i & $1ff)] DAT buffer byte 0[512]Result was this:
❯ loadp2 -t reader.binary
( Entering terminal mode. Press Ctrl-] or Ctrl-Z to exit. )
checksum=40231575
Did the same computation over binary file with this same result
od -v -An -tu1 z80.binary | awk '{for(i=1;i<=NF;i++) sum+=$i} END {print sum}'40231575Doesn't the first 1kB loaded need to sum to the 32 bit value of "Prop" or something like that for the P2 to boot from flash? I guess I can check that too...
Something very weird about loadp2 and the -FLASH option. I see some of this code sitting in the first sector but it doesn't seem to contain the "app_longs" value which is meant to be set by the programmer. Why is this value missing? What am I doing wrong on the command line ? @ersmith do you know? None of the longs after the "wmode" value seem to be present there. Isn't loadp2 meant to fill this in for us? EDIT: Ok I found this sector code is actually from flash_stub.spin2 and not flash_loader.spin2.
Here's the loader code from what I can tell...EDIT: no this is the loader code from the programmer (see post below).
' On entry, both spi_cs and spi_ck are low outputs and the flash is outputting bit 7 of the ' byte at address $400 on spi_do. By cycling spi_ck, any additional application data can be ' received from spi_do. ' ' Once all application data is in the hub, an application checksum is verified, after which ' cog 0 is restarted by a 'COGINIT #0,#$00000' to execute the application. If that checksum ' fails, due to some data corruption, the SPI pins will be floated and the clock stopped ' until the next reset. As well, a checksum is verified upon initial download of all data, ' before programming the flash. This all ensures that no errant application code will boot. ' org ' ' ' First, move application data in cog app_start..$0FF into hub $00000+ ' loader setq #$100-app_start-1 'move code from cog app_start..$0FF to hub $00000+ wrlong app_start,#0 sub app_longs,#$100-app_start wcz 'if app longs met or exceeded, run application if_be coginit #0,#$00000 '(small applications verified by 'Prop' checksum) ' ' ' Read in remaining application longs ' wrpin #%01_00101_0,#spi_ck 'set spi_ck smart pin for transitions, drives low fltl #spi_ck 'reset smart pin wxpin #1,#spi_ck 'set transition timebase to clk/1 drvl #spi_ck 'enable smart pin setxfrq clk2 'set streamer rate to clk/2 wrfast #0,##$400-app_start*4 'ready to write to hub at application continuation .block bmask x,#10 'try max streamer block size for longs ($7FF) fle x,app_longs 'limit to number of longs left sub app_longs,x 'update number of longs left shl x,#5 'get number of bits setword wmode,x,#0 'insert into streamer command shl x,#1 'double for number of spi_ck transitions wypin x,#spi_ck '2 start spi_ck transitions waitx #3 '2+3 align spi_ck transitions with spi_do sampling xinit wmode,#0 '2 start inputting spi_do bits to hub, bytes-msb-first waitxfi '? wait for streamer to finish tjnz app_longs,#.block 'if more longs left, read another block wrpin #0,#spi_ck 'clear spi_ck smart pin mode ' ' ' Verify application checksum ' rdfast #0,#0 'sum all application longs rep #2,app_longs2 rflong x add app_sum,x wz 'z=1 if verified stop if_nz fltl #spi_di addpins 2 'if checksum failed, float spi_cs/spi_ck/spi_di pins if_nz hubset #%0010 '..and stop clock until next reset coginit #0,#$00000 'checksum verified, run application ' ' ' Data ' clk2 long $4000_0000 'clk/2 nco value for streamer wmode long $C081_0000 + spi_do<<17 'streamer mode, 1-pin input, bytes-msb-first, bytes to hub zeroa '(used by programmer as long 0) app_longs long 0 'number of longs in application (set by programmer) zerob '(used by programmer as long 0) app_longs2 long 0 'number of longs in application (set by programmer) zeroc '(used by programmer as long 0) app_sum long 0 '-sum of application longs (set by programmer) x '(used by loader as variable) loader_sum byte -"P",!"r",!"o",!"p" '"Prop" - sum of $100 loader longs (set by programmer) ' ' ' Application start ' app_start 'append application bytes after this label@evanh is your loadp2 flash_stub.h file in the loadp2 root folder area the same as this? I wonder if mine is somehow corrupted? This file is generated when I build loadp2 source.
unsigned char flash_stub_bin[] = {
0x08, 0x00, 0x90, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x3c, 0x94, 0x0c, 0xfc, 0x50, 0x78, 0x64, 0xfd, 0x3c, 0x02, 0x1c, 0xfc,
0x58, 0x78, 0x64, 0xfd, 0x1d, 0x32, 0x60, 0xfd, 0x00, 0x00, 0x8c, 0xfc,
0x0a, 0x00, 0xcc, 0xf9, 0x02, 0x00, 0x20, 0xf3, 0x00, 0x04, 0x80, 0xf1,
0x05, 0x00, 0x64, 0xf0, 0x00, 0x34, 0x20, 0xf9, 0x01, 0x00, 0x64, 0xf0,
0x3c, 0x00, 0x24, 0xfc, 0x1f, 0x06, 0x64, 0xfd, 0x00, 0x34, 0xa4, 0xfc,
0x24, 0x36, 0x60, 0xfd, 0xf5, 0x05, 0x9c, 0xfb, 0x50, 0xf4, 0x65, 0xfd,
0x3c, 0x00, 0x0c, 0xfc, 0x42, 0x0f, 0x80, 0xff, 0x1f, 0x00, 0x65, 0xfd,
0x00, 0x00, 0xec, 0xfc, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf5, 0xc0
};
unsigned int flash_stub_bin_len = 108;
Update:
Okay now I'm more confused than before. There seems to be two different flash loaders. One seems to be bundled with some programming code (flash_loader.spin2), and the other is standalone (flash_stub.spin2). The latter is what is in my flash by the looks of it.
Update2: I checked the total 32 bit sum of the first 1kB in flash. Results in
checksum=706F7250which is "Prop" so it look like the P2 should boot this. Starting to wonder if maybe my own app is somehow locking up if flash is already enabled after boot or something like that since it also uses flash. I'm going to try modifying it to not read flash and just blink a LED instead like that other short test app I wrote.Update3: Nope, disabling flash in my app doesn't help. Still no boot. I'm at a loss now. Power draw from flash boot perhaps...?
After it is built I manually copy the resulting binary "loadp2" into a stand-alone directory in my exec path. Nothing else is copied from the build and the build directory is ignored after. I only look at again when updating with
git pull. Last build was August 2025, v0.077.Content of flash_stub.h
unsigned char flash_stub_bin[] = { 0x08, 0x00, 0x90, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x94, 0x0c, 0xfc, 0x50, 0x78, 0x64, 0xfd, 0x3c, 0x02, 0x1c, 0xfc, 0x58, 0x78, 0x64, 0xfd, 0x1d, 0x32, 0x60, 0xfd, 0x00, 0x00, 0x8c, 0xfc, 0x0a, 0x00, 0xcc, 0xf9, 0x02, 0x00, 0x20, 0xf3, 0x00, 0x04, 0x80, 0xf1, 0x05, 0x00, 0x64, 0xf0, 0x00, 0x34, 0x20, 0xf9, 0x01, 0x00, 0x64, 0xf0, 0x3c, 0x00, 0x24, 0xfc, 0x1f, 0x06, 0x64, 0xfd, 0x00, 0x34, 0xa4, 0xfc, 0x24, 0x36, 0x60, 0xfd, 0xf5, 0x05, 0x9c, 0xfb, 0x50, 0xf4, 0x65, 0xfd, 0x3c, 0x00, 0x0c, 0xfc, 0x42, 0x0f, 0x80, 0xff, 0x1f, 0x00, 0x65, 0xfd, 0x00, 0x00, 0xec, 0xfc, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf5, 0xc0 }; unsigned int flash_stub_bin_len = 108;I think you've already figured this out, but for reference in case someone stumbles across this thread: the boot ROM will only boot the first $400 bytes of the flash, so in most cases that needs to contain a second stage boot loader. In loadp2 we have two variants of this second stage bootloader:
flash_loader.spin2is used to write the data if-FLASHand-SINGLEare both given, and it contains its own second stage boot stub confusingly also calledLoader(it's near the end offlash_loader.spin2). IIRC it's the old flash loader and was kept as a backup. For regular-FLASHwe prepend the stub inflash_stub.spin2to the binary and write it to flash usinghimem_flash.spin2, which is the new mechanism for writing stuff and is intended to be compatible with things like the hyperflash (although as yet there is nohimem_hyper.spin2). The himem mechanism is also used for loading ELF files to flash (or potentially to other kinds of external memory) for execute in place. At the moment AFAIK only the riscvp2 toolchain supports producing such ELF files.Thanks Eric. Good to know about -SINGLE selection.