This may be a bit off topic, but I started this thread, so what the heck: The SD card that I tested with was just a 2GB card that, according to Win 10, was formatted as FAT, not FAT32. Offhand, I assume that means FAT16 in the case of that card, but I'm not positive (though surely it's not FAT12). But wuerfel_21's version of Kye's driver worked with this 2GB FAT card just fine (perhaps there's some backwards compatibility going on, but I'm not sure).
Anyway, the card was full and I wanted to try things with a card formatted as FAT32 (as I figure that I should move away from FAT). So I went to the store about two hours ago and picked up a new card. I had a choice between SDHC and SDXC. I figured that SDHC would be the "safer" choice, but I wanted to learn if SDXC would work. So I crossed my fingers and bought an SDXC card.
On putting it into the PC (Win 10), I saw that the card was preformatted as exFAT, and when I went to reformat it, Win 10 only gave me the options of exFAT and NTSF, no FAT32 option. You see, the card that I bought was a 64GB card. I guess I should have stuck with 32GB (or less), though I don't know if SDXC cards come in capacities below 64GB. So anyway, I googled the matter and ended up downloading a program called AOMEI Partition Assistant Standard. And it was able to format the card as FAT32 (with a cluster/allocation size of 32KB, the default). Afterwards, I tried file booting a program off of the SD card as described above and it worked. And I can also read a big text file off of it just fine.
I can see the responses in my head now: "Windoze 10? There's your problem!" But have fun. Anyway, just thought I'd pass this experience along. Now that I think about it, I seem to recall someone recommending sticking to 32 GB cards and below for an easier time of it. But I didn't think about that at the store. That probably makes sense, though, as I doubt I'll ever come close to using up this card in my P2 experiments (though who knows, as pics, audio and video take up a lot of space, but those media aren't on my radar just now (I'm just using text for now)). Nevertheless, I learned a little something from this experience.
By the way, in working through this, I read that the FAT32 file system can go well beyond 32GB's of capacity, but the individual file size is limited to 4GB, which I can live with.
Thanks. That's a nice summary of SDXC. You call 'em like you see 'em. And thanks for the A1 rating tip.
Update: Yes, it says "A1, Random: R1500, W:500 IOPS." It also says "V10, UHS-I, Class 10." It was a cheap card (uSD actually, with an SD adapter, though I'd prefer just an SD card for this usage (fewer contacts to worry about)). It's an Adata brand. I know that you folks recommend Sandisk (and maybe Transcend), but it's what they had and it was cheap. I wanted something right away for testing and got it at a nearby store.
@evanh said:
RCFAST handover solves the reliability issue right now without needing mailboxes.
I don't see an OS ever taking hold to be honest. The propeller architecture is intended to be used low level. Taking that away is a negative.
PS; The idea of self-hosting also clashes with this IMHO.
It is not always about self -hosting. The OP @JRetSapDoog is working on a P2 version of his Game-Cube and needs the ability to load different Games out of a list in a menu.
The same might go for a P2 Bench Tool where you might need to run different programs on the same Hardware.
Quite agree- not being able to run p2 programs loaded from an SD card attached to that P2 is a real show stopper- it limits its use in so many ways- in my humble opinion.
@msrobots said:
It is not always about self -hosting. The OP @JRetSapDoog is working on a P2 version of his Game-Cube and needs the ability to load different Games out of a list in a menu.
Hey! Stop peeping in my window. I thought I saw someone looking in today. But you're right. I got the new PCB a few weeks back, and, so far, it seems to be working. And I'll need to begin work on a menu program soon. In the early stage, I'd probably be satisfied if all the files being file booted off of the SD card were Spin2 files. But longer term, it'd be nice if they could be anything. I hope that the files on SD card won't have to "announce" what kind of programs they are in an about file or something, (that is, whether they are Spin2 or non-Spin2 programs), as I don't know if there would be a straightforward way for the menu program to figure that out on its own by inspecting the program data after loading it.
About this clock stuff, I've only just started to read up about it. But so far, I'm still pretty confused. However, I appreciate your comments and evanh's comments.
So in that I'm muddled about that, I was just thinking about what you said about a "sets all pins to input" step. That seems prudent to me, so I'll do that. I wonder if dira~ does the same thing as pinfloat(0 addpins 31). But even if it does, what about the the pins being used as video DAC's? Perhaps they would still be active (I'm guessing so). So I was just checking and I see that there is a pinclear instruction (with a pinfield), and apparently it does a DIR=0 followed by a WRPIN=0. So I guess that I can just use that. I wonder if any other settings from the currently running program might "hang around" somehow. Or maybe stopping the cogs helps with that.
@msrobots said:
It is not always about self -hosting. The OP @JRetSapDoog is working on a P2 version of his Game-Cube and needs the ability to load different Games out of a list in a menu.
The same might go for a P2 Bench Tool where you might need to run different programs on the same Hardware.
RCFAST handover works while it's a single application at a time. And that's it really. The application has a designed frequency in mind, and that can be set at hand over.
EDIT: And some applications want to vary the sysclock frequency. No problem, they do that under their own management, after the RCFAST handover.
An FYI: FlexBasic already has the CHAIN command for loading binaries (arbitrary binaries) from fat32 or from the PC host. It does have a significant restriction, namely that both the original program and the new program have to fit into RAM at the same time, but for games (which presumably reserve a big chunk of RAM for a screen buffer) this probably should work fine. Similar functionality is provided by the C execve() function, and this could be called from a FlexSpin program.
Thanks, ersmith. Perhaps that indicates that my "half-n-half" method for loading a program from the SD card isn't so weird after all (first to upper half of hub, then to the lower half). And the game console I'm working on has four screens, so it potentially uses a lot of buffer space, so limiting code to half the hub may be an acceptable limitation, as you said. In fact, I just wrote the pasm portion to copy the program from upper hub to lower hub and it seems to be working after a quick test.
As for using FlexBasic on the game console, I'll bet that many would prefer to program games in Basic, and I think that Basic makes string handling easier. Currently, I'm using Spin2 (in bytecode form) because it's what I'm more familiar with, and it is kind of (though not really) a native high-level language for the P2. But hopefully programs for the console can be written in various languages. I can see writing a program in Spin2 with the Prop Tool and then moving it to FlexSpin to compile to pasm for more speed, for example.
Of course, I still need to figure out the clock stuff and possibly how to differentiate a Spin2 from a non-Spin2 program, but one step at a time. Thanks for your very pertinent comment.
I updated the post with my earlier experimental method to file boot, as I needed to do the final move of the program from the upper half of the hub to the lower half in pasm2 to once again avoid the bytecodes getting clobbered during the transfer. Anyway, here's the code for the pasm2. I hardly have any experience in pasm programming, so please let me know how it can be improved.
Prior to launching this code, the Spin2 code (in cog 0) has already copied the program off of the SD card to the upper half of the hub.
dat
moveProgram
org
'copy upper half of hub to lower half of hub
'note: hub is addressed in bytes, not longs
mov ltm, ##65536 'load number of longs to transfer
mov ptra, ##262_144 'load beginning address of second half of hub into ptra
mov ptrb, #0 'load beginning address of first half of hub into ptrb
copy
rdlong tmp, ptra++ 'read four bytes from upper half of hub into tmp
wrlong tmp, ptrb++ 'copy four bytes from tmp into lower half of hub
djnz ltm, #copy 'when ltm goes to 0, transfer is complete
'clear the upper half of hub (now that it has been copied to lower half)
mov ltm, ##65536 'load number of longs to transfer
mov ptra, ##262_144 'load beginning address of second half of hub into ptra
clear
wrlong #0, ptra++ 'clear four bytes of the upper hub
djnz ltm, #clear 'when ltm goes to 0, clear operation is complete
'TBDone: possibly stop other cogs here
'TBDone: read the clock settings (at $40 & $44) and safely set the clock
'load program from beginning of hub into cog 0 and start it
coginit #0, #0 'start new program in cog 0
'kill the current cog
cogid tmp 'get the current cog's ID
cogstop tmp 'stop the current cog
ltm long 0 'number of longs-to-move = 65,536
tmp long 0 'temporary to hold four bytes to transfer
fit 496
Thanks for all the comments (including the ones that I haven't yet gotten around to responding to).
@JRetSapDoog said:
I hardly have any experience in pasm programming, so please let me know how it can be improved.
mov ltm, ##65536 'load number of longs to transfer
mov ptra, ##262_144 'load beginning address of second half of hub into ptra
mov ptrb, #0 'load beginning address of first half of hub into ptrb
copy
rdlong tmp, ptra++ 'read four bytes from upper half of hub into tmp
wrlong tmp, ptrb++ 'copy four bytes from tmp into lower half of hub
djnz ltm, #copy 'when ltm goes to 0, transfer is complete
You could make it faster by copying larger blocks at a time, but I assume that's not important here. But what you should always do is use REP instead of DJNZ where possible.
mov ptra, ##262_144 'load beginning address of second half of hub into ptra
mov ptrb, #0 'load beginning address of first half of hub into ptrb
rep @.copy,##65536
rdlong tmp, ptra++ 'read four bytes from upper half of hub into tmp
wrlong tmp, ptrb++ 'copy four bytes from tmp into lower half of hub
.copy
'clear the upper half of hub (now that it has been copied to lower half)
mov ltm, ##65536 'load number of longs to transfer
mov ptra, ##262_144 'load beginning address of second half of hub into ptra
clear
wrlong #0, ptra++ 'clear four bytes of the upper hub
djnz ltm, #clear 'when ltm goes to 0, clear operation is complete
Clearing RAM can be done a lot cleaner and much faster like this
setq ##(65536/4)-1
wrlong #0,##262_144
And stopping the other cogs can be done like this:
Though relatedly, assuming any game someone might write uses large framebuffers seems like a bad idea, since real-time scanline rendering is the better choice in a lot of cases (though not sure how well it scales to multiple displays) and that only needs a few K of buffer space.
@ersmith said:
An FYI: FlexBasic already has the CHAIN command for loading binaries (arbitrary binaries) from fat32 or from the PC host. It does have a significant restriction, namely that both the original program and the new program have to fit into RAM at the same time, but for games (which presumably reserve a big chunk of RAM for a screen buffer) this probably should work fine. Similar functionality is provided by the C execve() function, and this could be called from a FlexSpin program.
There is also a dodge to this that can be used where both programs are very large and attempting to move both into memory at once would exceed the P2's memory. Write a "one-liner" program consisting of just the "chain" command. The "old" main program calls the one-liner and terminates. The one-liner (with a very small footprint) runs and calls the "new" program and then terminates itself. This way neither of the "big" programs reside in memory at once.
@JRetSapDoog said:
Of course, I still need to figure out the clock stuff and possibly how to differentiate a Spin2 from a non-Spin2 program, but one step at a time. Thanks for your very pertinent comment.
You can relax, it's taken care of for you. The exception being if you are coding a purely Pasm program with no HLL assistance. Only then do you have to know the details.
PS: I chimed in on this topic to correct the incorrect thinking that mailboxes were involved in the taking care of it.
@Wuerfel_21: Hey, great suggestions! Thanks for the guidance. I implemented all of them as best I could (hope that the clear part is right, though it seems to work):
dat
moveProgram
org
'copy upper half of hub (262,144 bytes = 65536 longs) to lower half of hub
mov ptra, ##262_144 'load beginning address of second half of hub into ptra
mov ptrb, #0 'load beginning address of first half of hub into ptrb
rep #2, ##65536 'execture the read-and-write instruction pair 65536 times
rdlong tmp, ptra++ 'read four bytes from upper half of hub into tmp
wrlong tmp, ptrb++ 'copy four bytes from tmp into lower half of hub
'clear the upper half of hub (now that it has been copied to lower half)
setq ##65_536-1 'use setq to do a "fast block" clear for 65536 longs
wrlong #0, ##262_144 'zero out the upper half of the hub a long at a time
'Stop all other cogs (whether extant and active or not)
cogid kid 'get cog (kog) id
mov tmp, #15 'highest possible cog number (on a future 16-cog P2 variant)
.kill cmp tmp, kid wz 'don't stop the current cog
if_nz cogstop tmp 'stop all but the current cog
djnf tmp, #.kill
'To be done: Possibly place clock code below
'hubset #$F0 'set 20 MHz+ (RCFAST) mode (glitches about half the time)
'waitx ##200_000_000/100 'wait ~10ms (possibly omit/change)
'load program from beginning of hub into cog 0 and start it
coginit #0, #0 'start new program in cog 0
'kill the current cog
cogid tmp 'get the current cog's ID
cogstop tmp 'stop the current cog
kid res 1 'current cog's (kog's) id
tmp res 1 'temporary, mainly to hold four bytes to transfer at a time
fit 496
I knew about (and had played with) rep before, but I neglected to use it to avoid the branch penalty. Thanks for the reminder. And I don't think I had done a fast block move with setq, so thanks so much for that. Oh, and about loading up a bunch of cog registers to do things faster, yes, I figured that was a possibility, but I didn't think it would be as readable, and the time savings in this menu case would likely be swamped by the other processing time involved, as you suggested.
That pure Pasm example right there is a good one to comment on ... Since the clock frequency is not being set at all, it means the default of RCFAST will be in use. What's more, even setting a frequency there, with the crystal+PLL, won't need any special precautions. The glitchy step is the transition out of a particlular PLL mode, normally back to RCFAST. Most applications just set it once and don't change the frequency again.
So, even a pure Pasm program has to be coded to deal with the clock setting glitch only if it's wanting to re-adjust the sysclock frequency.
PS: This assumes RCFAST handover is always applied.
@evanh said:
You can relax, it's taken care of for you. The exception being if you are coding a purely Pasm program with no HLL assistance. Only then do you have to know the details.
Thanks, evanh. For a Spin2 program, the interpreter will always be loaded (by me/the menu program) into cog 0 and launched. Then the Spin2 interpreter will take care of setting the clock (from hub $40 & $44) as specified, such that the clock settings in the new program can potentially be different than those in the old program. <--Does all of that comport with what you're saying? If so, that's good. And you're saying that other HLL's would work similarly.
So what about the case of a Spin2 program being compiled to pasm in Flexspin to pasm, would things get taken care of in that case? I believe that it's "pure" pasm (at least there's no interpreter), but I suppose that Flexspin must generate the code to set the clock (through hubset instructions) one way or another, so maybe that scenario is okay, too.
BTW, when I tried doing a hubset #$F0 for the RCFAST mode just before the call to coginit, the code failed to run the new program (at a clock that gave me video, anyway) about half the time (almost every other time). That was without a delay after it. But even with a delay, that was generally the case. Anyway, it sounds like you're saying that I don't even need to switch to RCFAST because the interpreter (running at whatever frequency the old program was running at) should be able to switch over without glitching, if I understand you correctly.
Update: Whoops! You just added "PS: This assumes RCFAST handover is always applied." So I need to think about this and experiment some more.
@JRetSapDoog said:
So what about the case of a Spin2 program being compiled to pasm in Flexspin to pasm, would things get taken care of in that case? I believe that it's "pure" pasm (at least there's no interpreter), but I suppose that Flexspin must generate the code to set the clock (through hubset instructions) one way or another, so maybe that scenario is okay, too.
Taken care of. When I say "pure Pasm" I'm talking about you the coder writing the program.
@evanh said:
All the high-level languages are built using RCFAST handover routines on the Prop2. Mailboxing is not used for this purpose.
The reason I added that caveat is for any pure pasm programs, ie: hand crafted loaders, to follow suit when doing handovers.
Hmm, in the case of the Spin2 language from the Prop Tool, are the "mailboxes" that you are referring to the hub locations $40 & $44 or something else? And when the Spin2 interpreter runs, does it pick up the clock settings from these two locations or just post them there for the user? And in the latter case, then it must use separate instructions to set the clock, I presume.
Update: Well, the "post' part isn't right, as they are already there, I presume, in the loaded bytecodes in the hub.
@JRetSapDoog said:
BTW, when I tried doing a hubset #$F0 for the RCFAST mode just before the call to coginit, the code failed to run the new program (at a clock that gave me video, anyway) about half the time (almost every other time). That was without a delay after it. But even with a delay, that was generally the case. Anyway, it sounds like you're saying that I don't even need to switch to RCFAST because the interpreter (running at whatever frequency the old program was running at) should be able to switch over without glitching, if I understand you correctly.
Well, umm, you probably can't use HUBSET() as a function/instruction for adjusting the clock frequency in any language without knowing the correct non-glitching steps. I haven't looked into what library options for frequency adjust there is yet ...
@JRetSapDoog said:
So what about the case of a Spin2 program being compiled to pasm in Flexspin to pasm, would things get taken care of in that case? I believe that it's "pure" pasm (at least there's no interpreter), but I suppose that Flexspin must generate the code to set the clock (through hubset instructions) one way or another, so maybe that scenario is okay, too.
Taken care of. When I say "pure Pasm" I'm talking about you the coder writing the program.
@JRetSapDoog said:
BTW, when I tried doing a hubset #$F0 for the RCFAST mode just before the call to coginit, the code failed to run the new program (at a clock that gave me video, anyway) about half the time (almost every other time). That was without a delay after it. But even with a delay, that was generally the case. Anyway, it sounds like you're saying that I don't even need to switch to RCFAST because the interpreter (running at whatever frequency the old program was running at) should be able to switch over without glitching, if I understand you correctly.
Well, umm, you probably can't use HUBSET() as a function/instruction for adjusting the clock frequency in any language without knowing the correct non-glitching steps. I haven't looked into what library options for frequency adjust there is yet ...
Okay, for Spin2 it's CLKSET(NewCLKMODE, NewCLKFREQ) Safely establish new clock settings, updates CLKMODE and CLKFREQ
Only use HUBSET() for non-clock ops. The docs should have this stated me thinks.
@evanh said:
FLexBASIC has same: clkset(mode, freq) There is no hubset() function in FlexBASIC so can't mess that one up without using assembly.
FlexC has: _clkset(mode, freq)
Today, I read about Spin2's clkset() method for safely setting the clock (glitch free), but I've used pasm to do the final handover (and I'm not sure if I can use in-line assembly in Spin2 to do that because I don't know if the pasm loads up in cog registers or still gets pulled in instruction-by-instruction from the hub (which could get clobbered)). Need to look into that, but, for now, I just launched a pasm cog to finish the handover.
@Wuerfel_21 said:
Though relatedly, assuming any game someone might write uses large framebuffers seems like a bad idea, since real-time scanline rendering is the better choice in a lot of cases (though not sure how well it scales to multiple displays) and that only needs a few K of buffer space.
That's true. And such a small footprint is also true of the tile mapped video driver (from Eric Smith) that I'm testing with right now. But if I'm using the Prop Tool, does it matter that the program and data are much smaller than half the hub? It does occur to me that I'm not clearing out any space that is unused in the lower half of the hub. But I haven't decided if any residual garbage there would matter.
In an earlier post, you mentioned something about Spin2 not having a free memory instruction of some kind. However, when I use the Prop Tool, it seems to show all the remaining space above the program and data as being free, so maybe it's okay to use it (though who knows about some possible future change).
But in the case of C and Basic, perhaps it's possible that they put something important up there in the images that they produce. So that could be a problem, I guess. Maybe that's part of what you're saying.
Anyway, about using this half-n-half method, partly, it's allowing me to learn. I'll gladly switch to a better way when such a way is available. I may try to think about that (I did look at the cluster chain code you provided, but not in the context of the overall driver). But first, I think it would be good for me to start working on a menu program, such that I could do experiments more conveniently. Later, if another file booter is avaiable, I could switch to it. I thank you for all of the guidance, and frankly, without your version of Kye's FAT32 driver (or perhaps Cluso99's), I'd be dead in the water.
@JRetSapDoog said:
Hmm, in the case of the Spin2 language from the Prop Tool, are the "mailboxes" that you are referring to the hub locations $40 & $44 or something else? And when the Spin2 interpreter runs, does it pick up the clock settings from these two locations or just post them there for the user? And in the latter case, then it must use separate instructions to set the clock, I presume.
Yes, it posts them for modular user code to use for internal calculations, ie: multiple objects in one application. Using the CLKFREQ variable is the correct solution. Different compilers use different addresses.
PS: CLKSET() will use CLKFREQ's partner variable, CLKMODE, as part of the reliable steps to prevent glitching/lockups/crashes.
My own pure pasm wrapper routines has its own way that doesn't touch hubRAM. I developed it long ago for stepping through many sysclock frequencies. Some of my test code blitzes hubRAM, it's nice knowing everything is contained in the one cog when doing that.
@JRetSapDoog said:
Hmm, in the case of the Spin2 language from the Prop Tool, are the "mailboxes" that you are referring to the hub locations $40 & $44 or something else? And when the Spin2 interpreter runs, does it pick up the clock settings from these two locations or just post them there for the user? And in the latter case, then it must use separate instructions to set the clock, I presume.
Yes, it posts them for modular user code to use for internal calculations, ie: multiple objects in one application. Using the CLKFREQ variable is the correct solution. Different compilers use different addresses.
PS: CLKSET() will use CLKFREQ's partner variable, CLKMODE, as part of the reliable steps to prevent glitching/lockups/crashes.
Thanks, evanh. So, in my little pasm routine to finish the handover (particularly coping the upper hub to the lower hub and doing coginit), you don't think that I need to try to set the clock mode to RCFAST (and you think that doing so could cause glitches)? That is, the new program will just temporarily inherit the clock from the old program, whatever speed it is (likely 10x or so greater than RCFAST) and then it will adjust the clock to whatever speed it wants (perhaps by first going to RCFAST itself). Or am I wrong? Sorry, to keep circling around this.
Comments
Yep, you're right. That's what I tried to say/correct in my last post (before this one).
This may be a bit off topic, but I started this thread, so what the heck: The SD card that I tested with was just a 2GB card that, according to Win 10, was formatted as FAT, not FAT32. Offhand, I assume that means FAT16 in the case of that card, but I'm not positive (though surely it's not FAT12). But wuerfel_21's version of Kye's driver worked with this 2GB FAT card just fine (perhaps there's some backwards compatibility going on, but I'm not sure).
Anyway, the card was full and I wanted to try things with a card formatted as FAT32 (as I figure that I should move away from FAT). So I went to the store about two hours ago and picked up a new card. I had a choice between SDHC and SDXC. I figured that SDHC would be the "safer" choice, but I wanted to learn if SDXC would work. So I crossed my fingers and bought an SDXC card.
On putting it into the PC (Win 10), I saw that the card was preformatted as exFAT, and when I went to reformat it, Win 10 only gave me the options of exFAT and NTSF, no FAT32 option. You see, the card that I bought was a 64GB card. I guess I should have stuck with 32GB (or less), though I don't know if SDXC cards come in capacities below 64GB. So anyway, I googled the matter and ended up downloading a program called AOMEI Partition Assistant Standard. And it was able to format the card as FAT32 (with a cluster/allocation size of 32KB, the default). Afterwards, I tried file booting a program off of the SD card as described above and it worked. And I can also read a big text file off of it just fine.
I can see the responses in my head now: "Windoze 10? There's your problem!" But have fun. Anyway, just thought I'd pass this experience along. Now that I think about it, I seem to recall someone recommending sticking to 32 GB cards and below for an easier time of it. But I didn't think about that at the store. That probably makes sense, though, as I doubt I'll ever come close to using up this card in my P2 experiments (though who knows, as pics, audio and video take up a lot of space, but those media aren't on my radar just now (I'm just using text for now)). Nevertheless, I learned a little something from this experience.
By the way, in working through this, I read that the FAT32 file system can go well beyond 32GB's of capacity, but the individual file size is limited to 4GB, which I can live with.
Yes, SDXC is a basically a fake standard that means "large SDHC preformatted as exFAT".
The reason Windoze doesn't want to format large FAT32 volumes probably has something to do with Microsoft collecting royalties on exFAT...
Also, when choosing cards, look out for the A1 rating. It guarantees fast random access.
Thanks. That's a nice summary of SDXC. You call 'em like you see 'em. And thanks for the A1 rating tip.
Update: Yes, it says "A1, Random: R1500, W:500 IOPS." It also says "V10, UHS-I, Class 10." It was a cheap card (uSD actually, with an SD adapter, though I'd prefer just an SD card for this usage (fewer contacts to worry about)). It's an Adata brand. I know that you folks recommend Sandisk (and maybe Transcend), but it's what they had and it was cheap. I wanted something right away for testing and got it at a nearby store.
It is not always about self -hosting. The OP @JRetSapDoog is working on a P2 version of his Game-Cube and needs the ability to load different Games out of a list in a menu.
The same might go for a P2 Bench Tool where you might need to run different programs on the same Hardware.
Mike
Hi
Quite agree- not being able to run p2 programs loaded from an SD card attached to that P2 is a real show stopper- it limits its use in so many ways- in my humble opinion.
Dave
Hey! Stop peeping in my window. I thought I saw someone looking in today. But you're right. I got the new PCB a few weeks back, and, so far, it seems to be working. And I'll need to begin work on a menu program soon. In the early stage, I'd probably be satisfied if all the files being file booted off of the SD card were Spin2 files. But longer term, it'd be nice if they could be anything. I hope that the files on SD card won't have to "announce" what kind of programs they are in an about file or something, (that is, whether they are Spin2 or non-Spin2 programs), as I don't know if there would be a straightforward way for the menu program to figure that out on its own by inspecting the program data after loading it.
About this clock stuff, I've only just started to read up about it. But so far, I'm still pretty confused. However, I appreciate your comments and evanh's comments.
So in that I'm muddled about that, I was just thinking about what you said about a "sets all pins to input" step. That seems prudent to me, so I'll do that. I wonder if dira~ does the same thing as pinfloat(0 addpins 31). But even if it does, what about the the pins being used as video DAC's? Perhaps they would still be active (I'm guessing so). So I was just checking and I see that there is a pinclear instruction (with a pinfield), and apparently it does a DIR=0 followed by a WRPIN=0. So I guess that I can just use that. I wonder if any other settings from the currently running program might "hang around" somehow. Or maybe stopping the cogs helps with that.
You should take a look at my P2 OS here
https://forums.parallax.com/discussion/173395/clusos-propeller-os-v2-38-includes-sd-driver-and-fat32-object-plus-serial-driver
Currently I haven't progressed to the loading/running a program from SD yet.
For a comparison, look at my P1 OS which does load/run programs.
https://forums.parallax.com/discussion/138251/clusos-propeller-os-v1-14-now-with-spin-pasm-compiler-eeprom-read-write/p1
RCFAST handover works while it's a single application at a time. And that's it really. The application has a designed frequency in mind, and that can be set at hand over.
EDIT: And some applications want to vary the sysclock frequency. No problem, they do that under their own management, after the RCFAST handover.
An FYI: FlexBasic already has the CHAIN command for loading binaries (arbitrary binaries) from fat32 or from the PC host. It does have a significant restriction, namely that both the original program and the new program have to fit into RAM at the same time, but for games (which presumably reserve a big chunk of RAM for a screen buffer) this probably should work fine. Similar functionality is provided by the C execve() function, and this could be called from a FlexSpin program.
Thanks, ersmith. Perhaps that indicates that my "half-n-half" method for loading a program from the SD card isn't so weird after all (first to upper half of hub, then to the lower half). And the game console I'm working on has four screens, so it potentially uses a lot of buffer space, so limiting code to half the hub may be an acceptable limitation, as you said. In fact, I just wrote the pasm portion to copy the program from upper hub to lower hub and it seems to be working after a quick test.
As for using FlexBasic on the game console, I'll bet that many would prefer to program games in Basic, and I think that Basic makes string handling easier. Currently, I'm using Spin2 (in bytecode form) because it's what I'm more familiar with, and it is kind of (though not really) a native high-level language for the P2. But hopefully programs for the console can be written in various languages. I can see writing a program in Spin2 with the Prop Tool and then moving it to FlexSpin to compile to pasm for more speed, for example.
Of course, I still need to figure out the clock stuff and possibly how to differentiate a Spin2 from a non-Spin2 program, but one step at a time. Thanks for your very pertinent comment.
I updated the post with my earlier experimental method to file boot, as I needed to do the final move of the program from the upper half of the hub to the lower half in pasm2 to once again avoid the bytecodes getting clobbered during the transfer. Anyway, here's the code for the pasm2. I hardly have any experience in pasm programming, so please let me know how it can be improved.
Prior to launching this code, the Spin2 code (in cog 0) has already copied the program off of the SD card to the upper half of the hub.
Thanks for all the comments (including the ones that I haven't yet gotten around to responding to).
You could make it faster by copying larger blocks at a time, but I assume that's not important here. But what you should always do is use REP instead of DJNZ where possible.
Clearing RAM can be done a lot cleaner and much faster like this
And stopping the other cogs can be done like this:
Though relatedly, assuming any game someone might write uses large framebuffers seems like a bad idea, since real-time scanline rendering is the better choice in a lot of cases (though not sure how well it scales to multiple displays) and that only needs a few K of buffer space.
There is also a dodge to this that can be used where both programs are very large and attempting to move both into memory at once would exceed the P2's memory. Write a "one-liner" program consisting of just the "chain" command. The "old" main program calls the one-liner and terminates. The one-liner (with a very small footprint) runs and calls the "new" program and then terminates itself. This way neither of the "big" programs reside in memory at once.
You can relax, it's taken care of for you. The exception being if you are coding a purely Pasm program with no HLL assistance. Only then do you have to know the details.
PS: I chimed in on this topic to correct the incorrect thinking that mailboxes were involved in the taking care of it.
@Wuerfel_21: Hey, great suggestions! Thanks for the guidance. I implemented all of them as best I could (hope that the clear part is right, though it seems to work):
I knew about (and had played with) rep before, but I neglected to use it to avoid the branch penalty. Thanks for the reminder. And I don't think I had done a fast block move with setq, so thanks so much for that. Oh, and about loading up a bunch of cog registers to do things faster, yes, I figured that was a possibility, but I didn't think it would be as readable, and the time savings in this menu case would likely be swamped by the other processing time involved, as you suggested.
That pure Pasm example right there is a good one to comment on ... Since the clock frequency is not being set at all, it means the default of RCFAST will be in use. What's more, even setting a frequency there, with the crystal+PLL, won't need any special precautions. The glitchy step is the transition out of a particlular PLL mode, normally back to RCFAST. Most applications just set it once and don't change the frequency again.
So, even a pure Pasm program has to be coded to deal with the clock setting glitch only if it's wanting to re-adjust the sysclock frequency.
PS: This assumes RCFAST handover is always applied.
Thanks, evanh. For a Spin2 program, the interpreter will always be loaded (by me/the menu program) into cog 0 and launched. Then the Spin2 interpreter will take care of setting the clock (from hub $40 & $44) as specified, such that the clock settings in the new program can potentially be different than those in the old program. <--Does all of that comport with what you're saying? If so, that's good. And you're saying that other HLL's would work similarly.
So what about the case of a Spin2 program being compiled to pasm in Flexspin to pasm, would things get taken care of in that case? I believe that it's "pure" pasm (at least there's no interpreter), but I suppose that Flexspin must generate the code to set the clock (through hubset instructions) one way or another, so maybe that scenario is okay, too.
BTW, when I tried doing a hubset #$F0 for the RCFAST mode just before the call to coginit, the code failed to run the new program (at a clock that gave me video, anyway) about half the time (almost every other time). That was without a delay after it. But even with a delay, that was generally the case. Anyway, it sounds like you're saying that I don't even need to switch to RCFAST because the interpreter (running at whatever frequency the old program was running at) should be able to switch over without glitching, if I understand you correctly.
Update: Whoops! You just added "PS: This assumes RCFAST handover is always applied." So I need to think about this and experiment some more.
All the high-level languages are built using RCFAST handover routines on the Prop2. Mailboxing is not used for this purpose.
The reason I added that caveat is for any pure pasm programs, eg: hand crafted loaders, to follow suit when doing handovers.
Taken care of. When I say "pure Pasm" I'm talking about you the coder writing the program.
Hmm, in the case of the Spin2 language from the Prop Tool, are the "mailboxes" that you are referring to the hub locations $40 & $44 or something else? And when the Spin2 interpreter runs, does it pick up the clock settings from these two locations or just post them there for the user? And in the latter case, then it must use separate instructions to set the clock, I presume.
Update: Well, the "post' part isn't right, as they are already there, I presume, in the loaded bytecodes in the hub.
Well, umm, you probably can't use HUBSET() as a function/instruction for adjusting the clock frequency in any language without knowing the correct non-glitching steps. I haven't looked into what library options for frequency adjust there is yet ...
Okay, thanks so much!
Okay, for Spin2 it's
CLKSET(NewCLKMODE, NewCLKFREQ) Safely establish new clock settings, updates CLKMODE and CLKFREQ
Only use HUBSET() for non-clock ops. The docs should have this stated me thinks.
FLexBASIC has same:
clkset(mode, freq)
There is no hubset() function in FlexBASIC so can't mess that one up without using assembly.FlexC has:
_clkset(mode, freq)
Today, I read about Spin2's clkset() method for safely setting the clock (glitch free), but I've used pasm to do the final handover (and I'm not sure if I can use in-line assembly in Spin2 to do that because I don't know if the pasm loads up in cog registers or still gets pulled in instruction-by-instruction from the hub (which could get clobbered)). Need to look into that, but, for now, I just launched a pasm cog to finish the handover.
That's true. And such a small footprint is also true of the tile mapped video driver (from Eric Smith) that I'm testing with right now. But if I'm using the Prop Tool, does it matter that the program and data are much smaller than half the hub? It does occur to me that I'm not clearing out any space that is unused in the lower half of the hub. But I haven't decided if any residual garbage there would matter.
In an earlier post, you mentioned something about Spin2 not having a free memory instruction of some kind. However, when I use the Prop Tool, it seems to show all the remaining space above the program and data as being free, so maybe it's okay to use it (though who knows about some possible future change).
But in the case of C and Basic, perhaps it's possible that they put something important up there in the images that they produce. So that could be a problem, I guess. Maybe that's part of what you're saying.
Anyway, about using this half-n-half method, partly, it's allowing me to learn. I'll gladly switch to a better way when such a way is available. I may try to think about that (I did look at the cluster chain code you provided, but not in the context of the overall driver). But first, I think it would be good for me to start working on a menu program, such that I could do experiments more conveniently. Later, if another file booter is avaiable, I could switch to it. I thank you for all of the guidance, and frankly, without your version of Kye's FAT32 driver (or perhaps Cluso99's), I'd be dead in the water.
Yes, it posts them for modular user code to use for internal calculations, ie: multiple objects in one application. Using the CLKFREQ variable is the correct solution. Different compilers use different addresses.
PS: CLKSET() will use CLKFREQ's partner variable, CLKMODE, as part of the reliable steps to prevent glitching/lockups/crashes.
My own pure pasm wrapper routines has its own way that doesn't touch hubRAM. I developed it long ago for stepping through many sysclock frequencies. Some of my test code blitzes hubRAM, it's nice knowing everything is contained in the one cog when doing that.
Thanks, evanh. So, in my little pasm routine to finish the handover (particularly coping the upper hub to the lower hub and doing coginit), you don't think that I need to try to set the clock mode to RCFAST (and you think that doing so could cause glitches)? That is, the new program will just temporarily inherit the clock from the old program, whatever speed it is (likely 10x or so greater than RCFAST) and then it will adjust the clock to whatever speed it wants (perhaps by first going to RCFAST itself). Or am I wrong? Sorry, to keep circling around this.