I see what you mean about FSRW port... Dug it up yesterday while resurrecting some hyperram code (in hopes of converting to 8-bit PSRAM).
It doesn't work with Prop Tool at all. Seems we were using an old version of PNut, last time used it.
This code here looks like a port of Kye's P1 sd code for the top level with an assembly low level code from FSRW with some audio stuff mixed in.
This is all good.
Think I'll try to fix FSRW though. A quick archeological look seems to point to the new Spin2 dialect being the problem.
Might just be that things like sign extension need fixing. Hope it's easy, or I'll be coming back here for this code. Would be nice to have version that didn't need a cog...
FSRW, when it worked, had two low level options, one that used a cog and one that didn't.
Could the code here work with the FSRW low level driver that didn't need a cog?
I think it just calls into the block driver to read/write blocks. So I guess yea.
FSRW is just bad IMO (the FAT layer, as it were). No directory support and consequently lets you do stupid things like creating a file with slashes in the name.
Trying to figure out Kye's code (never used it before), noticed something:
If you do FATEngineStart() with readOnly==false and then try to create a new file, it goes off the rails.
Not sure exactly what it does, but it's bad...
Spin2, like Spin, is a little strange with True/False...
I think in C, zero is false and anything else is true.
In Spin, zero is also false, but true is -1 only.
This function returns true (-1) if it fails, which is the opposite of what it says.
Also, doesn't return the Spin true if it succeeds ...
Doesn't really matter, except for figuring out how to use the code.
In Spin1 and Spin2, the system constant true is defined as -1, but as Ada points out, any non-zero value will evaluate as true in an expression. This is why you see the start() method of most objects add one to the cog number returned by the system; if there's no cog (-1) available, this will get changed to 0 which always evaluates as false. If successful, the cog id returned to the caller will be promoted to 1..8 which will evaluate as true in expressions.
The pitfall with Spin (and I guess C too) is that if you do something like:
If (Something == true)
DoThis()
It won't work as expected unless "Something" has the actual value for true.
All that aside, I was just commenting that the text notes at the start of the FATEngineStart() are just plain wrong.
Also, in my opinion, if documentation for a Spin function says it will return "true", it should return -1.
I agree with Ada on that implementation, but understand that everybody has their preferred style. You could do this because false only has one value in Spin.
if (something <> false)
do_this()
Also, in my opinion, if documentation for a Spin function says it will return "true", it should return -1.
I try to do this with my own code -- but what you're going through suggests we need to be careful. Treating true as not false tends to keep things in line.
@Wuerfel_21 said:
Yeah, the other SD driver options basically are
buggy FSRW port. buggy and jank.
Cluso's KyeFAT port, though when I posted this I think the block driver wasn't published or something. Still doesn't support SDSC cards, I think.
Flexspin's thingie. Good features, but slow. Doesn't use a cog.
ROM SD thing. Read-only.
That's why I threw together this one, because I needed something to put in Spin Hexagon that, well, actually worked. Hence why the block driver has audio streaming features (BTW, there's 2K of RAM being wasted if you don't use the audio. You can just set their sizes to zero near the bottom of the block driver file and it shouldn't explode)
Does your driver support the under 2GB cards that have byte addressing instead of block addressing? How much extra space does that part take up? What is needed is an interface that uses all of the pins for much higher speeds.
Hinv,
That quote is dated. Flexspin ain't slow any longer. I revamped the block transfer routines, for Prop2, a few months back - As of version 5.9.10.
@evanh said:
Hinv,
That quote is dated. Flexspin ain't slow any longer. I revamped the block transfer routines, for Prop2, a few months back - As of version 5.9.10.
Sorry about that. It's hard to keep up with all you guys are developing. Keep up the good work.
I always had trouble wrapping my mind around the return values for FATEngineStart() and harmonizing them with the code comments. I figured that it was just me.
Also, last fall when I was working on a project and wanted to test if an SD card was inserted in the SD slot, my test kept hanging, though I don't recall the exact details. But as a kludge, what I ended up doing was automatically showing an error screen first thing that instructed the user to insert an SD card (even if one was already inserted). Then I'd try to read a card (you know, if present), and if I could read the card okay, I'd quickly overwrite that error screen with the next desired screen. This all happened so fast that, if a card was properly inserted and readable, the user would never see the error screen, despite the fact that it was always automatically shown first thing upon turning on the system. I don't recall for sure if things were hung if no card was inserted (though probably), but it didn't matter because the system couldn't really work without an SD card, so just showing the error screen was enough (then the user could power down and insert a card and try again).
Again, it was a kludge or a work around (to prevent the driver from hanging), but it worked. But other than needing to do that, I had no problems reading hundreds and hundreds of pages of text over and over again using the Kye-Wuerfel_21 driver. It seemed to be quite reliable. However, I didn't need to write to the card, just read from it. So I don't know about the write reliability. Update: And no, trying to trap the error didn't avoid the problem, at least from what I recall.
Yea, mount failure might actually just hang. don't remember where you'd fix that off the top of my head. Writes in P2 Spin Hexagon are reliable, but it only writes 512 bytes of highscore data so idk. Very rarely it fails to start playing music for some reason, but that may be specific to Spin Hexagon and/or the audio component in general.
Think I have a version of the assembly driver that now works with both FSRW and @Wuerfel_21's Kye code.
Only real difference is the way they start. FSRW combines starting and mounting in one operation whereas split in two parts in Kye code.
Have to make two small changes to FSRW's mount_explicit() to support combined low level assembly driver:
comment out "unmount()" as that sends a command to driver that hasn't started yet and so hangs. Not clear what side effects that may have.
Call new "sdspi.mountCard()" after "sdspi.start_explicit".
In this way, old code that used FSRW still works.
Going to see if can do the same with the cogless version.
Figured out the cogless version didn't work at 297 MHz, needed an extra wait.
Think its good now, and there 3 versions of low level driver that work with this test code:
sdspi_with_audio --> @Wuerfel_21 version with audio functions added
sdspi_asm_mb2 --> Version I just made using ideas from the above
sdspi_bashed2 --> cogless version
Now, need to circle back to FSRW to make sure they all work there too...
Note: Uploaded new version after realizing prop tool did not archive some files properly because weren't saved first...
So I am starting to look at this fat32/sdspi combo due to the reset issue with my project. This is the only version of that combination that I have found works 100% reliably from an operational standpoint. Thank you @Wuerfel_21
(And boy would I like a cogless version that works!)
When you reset the P2 however, it will stop when you attempt to startup/mount the sd card. (I haven't debugged enough to know exactly where it stops) So far, I haven't figured out where the initialization sequence is, but I expect to see it start with a CMD52 followed by CMD0. I suspect the problem is both the I/O and Memory Controller on the card need to be reset, since it is not powercycled by a reset of the P2, and that isn't happening.
3.4.1 Re-initialize Both I/O and Memory
When the host re-initializes both the I/O and Memory controllers, it is strongly recommended that the host
either execute a power reset (power off then on) or issues reset commands to both controllers prior to any
other operation. If the host chooses to use the reset commands, it shall issue CMD52 (I/O Reset) first,
because it cannot issue CMD52 after CMD0 (Refer to Section 4.4). After the reset, the host shall re-initialize
both the I/O and Memory controller as defined in Figure 3-2.
3.4.2 Using a Combo Card as SDIO only or SD Memory only after Combo Initialization
If a host intends to use only the SDIO or the Memory portion of a Combo Card, it is strongly recommended
that the host power reset (power off then on) or issues reset commands to both controllers prior to any other
operation. If the host chooses to use the reset commands, it shall issue CMD52 (I/O Reset) first, because it
cannot issue CMD52 after CMD0 (Refer to Section 4.4). After the resets, the host re-initializes either the I/O
and Memory controller as defined in Figure 3-2.
Hey @Rayman the cogless version nukes my sd card. I can't remember what the exact symptoms were, but I can take a look again. A cogless driver means I can keep the HDMI output for viewing http requests.
Unfortunately, due to the memory requirements of my project flexprop won't compile it. The driver I am using has been 100% solid, except the reset issue. That's really a hardware problem as the power should be cycled with a reset on the Edge. It's part of the SD spec.
OK, so adding some debug info I have found that the P2 does not boot at all on reset. That means that most likely the SD card has a pin active that is preventing the P2 from reading the SPI flash. I don't think there is a way to undo this, unless we can pull the card out of that state when not in use.
Parallax peeps, If there is a new rev of the Edge in the works, please investigate having VCC for the SD card attached to either a pin or wired into the brownout and or reset circuit.
I went looking to see if there was a way to allow the P2 Edge to reset if the SD card is dismounted and the FAT engine stopped. Normally it will not.
I modified Ada's ( @Wuerfel_21 ) sdspi_with_audio to re-initialize the SD card just before stopping the SDSPI cog. This was accomplished, ironically, by calling mountCard(), which sends command "C", which calls init_card. Once the card is reinitialized, the P2 reboots properly when reset is pressed or a software reset is performed.
Modification is attached.
I wonder if there is a way to have the card placed in this state when it is idle?
I want to beg and plead that the next iteration of the Edge please have a transistor that power cycles the SD card upon reset being pressed.
Comments
I see what you mean about FSRW port... Dug it up yesterday while resurrecting some hyperram code (in hopes of converting to 8-bit PSRAM).
It doesn't work with Prop Tool at all. Seems we were using an old version of PNut, last time used it.
This code here looks like a port of Kye's P1 sd code for the top level with an assembly low level code from FSRW with some audio stuff mixed in.
This is all good.
Think I'll try to fix FSRW though. A quick archeological look seems to point to the new Spin2 dialect being the problem.
Might just be that things like sign extension need fixing. Hope it's easy, or I'll be coming back here for this code. Would be nice to have version that didn't need a cog...
FSRW, when it worked, had two low level options, one that used a cog and one that didn't.
Could the code here work with the FSRW low level driver that didn't need a cog?
I think it just calls into the block driver to read/write blocks. So I guess yea.
FSRW is just bad IMO (the FAT layer, as it were). No directory support and consequently lets you do stupid things like creating a file with slashes in the name.
Trying to figure out Kye's code (never used it before), noticed something:
If you do FATEngineStart() with readOnly==false and then try to create a new file, it goes off the rails.
Not sure exactly what it does, but it's bad...
Obviously, that's user error, but still...
Playing around some more, noticed some things...
FATEngineStart() claims to return false if it fails, but if I test with no SD installed at first and then install SD, it just hangs.
Also claims "Returns true on success or false. ", but actually returns some kind of cogid if it works, not "true".
Any non-zero value is truthy, so that holds. I think.
Spin2, like Spin, is a little strange with True/False...
I think in C, zero is false and anything else is true.
In Spin, zero is also false, but true is -1 only.
This function returns true (-1) if it fails, which is the opposite of what it says.
Also, doesn't return the Spin true if it succeeds ...
Doesn't really matter, except for figuring out how to use the code.
In C (stdbool.h),
true
actually means 1.But in both, any non-zero value is truthy, i.e. satisfies an IF condition
In Spin1 and Spin2, the system constant true is defined as -1, but as Ada points out, any non-zero value will evaluate as true in an expression. This is why you see the start() method of most objects add one to the cog number returned by the system; if there's no cog (-1) available, this will get changed to 0 which always evaluates as false. If successful, the cog id returned to the caller will be promoted to 1..8 which will evaluate as true in expressions.
The pitfall with Spin (and I guess C too) is that if you do something like:
It won't work as expected unless "Something" has the actual value for true.
All that aside, I was just commenting that the text notes at the start of the FATEngineStart() are just plain wrong.
Also, in my opinion, if documentation for a Spin function says it will return "true", it should return -1.
This is something you should never do to begin with
I agree with Ada on that implementation, but understand that everybody has their preferred style. You could do this because false only has one value in Spin.
I try to do this with my own code -- but what you're going through suggests we need to be careful. Treating true as not false tends to keep things in line.
Assuming one is using the PNut/Proptool compiler, extraneous operators in a condition will generate worse code.
Flexspin doesn't mind it.
Here's a program to do basic tests of the driver posted in top post.
Tested with latest Prop Tool.
Does your driver support the under 2GB cards that have byte addressing instead of block addressing? How much extra space does that part take up? What is needed is an interface that uses all of the pins for much higher speeds.
It should work with small cards, but I don't think I have any 2GB microSD cards laying around.
The overhead from supporting them is less than 100 bytes of code overall and one instruction to leftshift the block number in every issued command.
Hinv,
That quote is dated. Flexspin ain't slow any longer. I revamped the block transfer routines, for Prop2, a few months back - As of version 5.9.10.
Sorry about that. It's hard to keep up with all you guys are developing. Keep up the good work.
I always had trouble wrapping my mind around the return values for FATEngineStart() and harmonizing them with the code comments. I figured that it was just me.
Also, last fall when I was working on a project and wanted to test if an SD card was inserted in the SD slot, my test kept hanging, though I don't recall the exact details. But as a kludge, what I ended up doing was automatically showing an error screen first thing that instructed the user to insert an SD card (even if one was already inserted). Then I'd try to read a card (you know, if present), and if I could read the card okay, I'd quickly overwrite that error screen with the next desired screen. This all happened so fast that, if a card was properly inserted and readable, the user would never see the error screen, despite the fact that it was always automatically shown first thing upon turning on the system. I don't recall for sure if things were hung if no card was inserted (though probably), but it didn't matter because the system couldn't really work without an SD card, so just showing the error screen was enough (then the user could power down and insert a card and try again).
Again, it was a kludge or a work around (to prevent the driver from hanging), but it worked. But other than needing to do that, I had no problems reading hundreds and hundreds of pages of text over and over again using the Kye-Wuerfel_21 driver. It seemed to be quite reliable. However, I didn't need to write to the card, just read from it. So I don't know about the write reliability. Update: And no, trying to trap the error didn't avoid the problem, at least from what I recall.
Yea, mount failure might actually just hang. don't remember where you'd fix that off the top of my head. Writes in P2 Spin Hexagon are reliable, but it only writes 512 bytes of highscore data so idk. Very rarely it fails to start playing music for some reason, but that may be specific to Spin Hexagon and/or the audio component in general.
Does your version of the driver work with drives <= 2 GB?
Seems the one I have has provisions for shifting sectors, but it's not implemented.
The cogless version I have does work though on small cards...
IIRC i never actually tried it.
Think I have a version of the assembly driver that now works with both FSRW and @Wuerfel_21's Kye code.
Only real difference is the way they start. FSRW combines starting and mounting in one operation whereas split in two parts in Kye code.
Have to make two small changes to FSRW's mount_explicit() to support combined low level assembly driver:
comment out "unmount()" as that sends a command to driver that hasn't started yet and so hangs. Not clear what side effects that may have.
Call new "sdspi.mountCard()" after "sdspi.start_explicit".
In this way, old code that used FSRW still works.
Going to see if can do the same with the cogless version.
Figured out the cogless version didn't work at 297 MHz, needed an extra wait.
Think its good now, and there 3 versions of low level driver that work with this test code:
sdspi_with_audio --> @Wuerfel_21 version with audio functions added
sdspi_asm_mb2 --> Version I just made using ideas from the above
sdspi_bashed2 --> cogless version
Now, need to circle back to FSRW to make sure they all work there too...
Note: Uploaded new version after realizing prop tool did not archive some files properly because weren't saved first...
All three versions of low level driver appear to be working now with this slightly modified version of FSRW.
So I am starting to look at this fat32/sdspi combo due to the reset issue with my project. This is the only version of that combination that I have found works 100% reliably from an operational standpoint. Thank you @Wuerfel_21
(And boy would I like a cogless version that works!)
When you reset the P2 however, it will stop when you attempt to startup/mount the sd card. (I haven't debugged enough to know exactly where it stops) So far, I haven't figured out where the initialization sequence is, but I expect to see it start with a CMD52 followed by CMD0. I suspect the problem is both the I/O and Memory Controller on the card need to be reset, since it is not powercycled by a reset of the P2, and that isn't happening.
From the SDIO Simplified Specification:
More to come...........
@ke4pjw Cogless version from previous post doesn't work? Did you try the test program in the zip?
It's really nice to have FatFs working in FlexProp. That is pretty rock solid, tested across many platforms by, presumably, thousands of users.
But, I think I heard Chip is working on an SD driver. Hopefully, that will be better than what we have now for Spin2.
Hey @Rayman the cogless version nukes my sd card. I can't remember what the exact symptoms were, but I can take a look again. A cogless driver means I can keep the HDMI output for viewing http requests.
Unfortunately, due to the memory requirements of my project flexprop won't compile it. The driver I am using has been 100% solid, except the reset issue. That's really a hardware problem as the power should be cycled with a reset on the Edge. It's part of the SD spec.
OK, so adding some debug info I have found that the P2 does not boot at all on reset. That means that most likely the SD card has a pin active that is preventing the P2 from reading the SPI flash. I don't think there is a way to undo this, unless we can pull the card out of that state when not in use.
Parallax peeps, If there is a new rev of the Edge in the works, please investigate having VCC for the SD card attached to either a pin or wired into the brownout and or reset circuit.
Best Regards on this cold winter's night!
--Terry
I went looking to see if there was a way to allow the P2 Edge to reset if the SD card is dismounted and the FAT engine stopped. Normally it will not.
I modified Ada's ( @Wuerfel_21 ) sdspi_with_audio to re-initialize the SD card just before stopping the SDSPI cog. This was accomplished, ironically, by calling mountCard(), which sends command "C", which calls init_card. Once the card is reinitialized, the P2 reboots properly when reset is pressed or a software reset is performed.
Modification is attached.
I wonder if there is a way to have the card placed in this state when it is idle?
I want to beg and plead that the next iteration of the Edge please have a transistor that power cycles the SD card upon reset being pressed.
Thanks!
--Terry
+1 for the power switch for SD
Mike