Flash AND MicroSD in the same program - how to? / Flexprop
There is jm_p2_flash.spin2. It works. But it reprograms pins, it has to... so after using this object to access the flash, the SD card no more works.
There is another problem. A 'read_block' procedure selects and deselects the flash via drvh and drvl #SF_CS. Call read_block several times and the SD is no more responding until power off (P2 soft reset doesn't help). I think the SD got clocks and started to do something/wait for something...
There is even worse problem: after one of experiments with reading/writing the flash I managed to overwrite the SD sector 0...
Now, work around:
(1) use the flash before mount "/sd", _vfs_open_sdcard()
(2) comment out drvh at the end of the read_block (I tested only reading) method, so it doesn't toggle the pin until all reads are done.
How to access both devices - when needed - in the same program?
How to protect the SD from being disabled/damaged when accessing the flash?
How to restore the pins after accessing the flash to enable SD again?
Edit: with commented out drvh there are errors reading from the flash. With not commented out drvh I have not responding SD card. I will try adding big gaps between reading blocks to check if it helps.
Edit 2: I gave up for now. This thing is too random. After several access to the flash SD became non-responsible until power off.
Edit 3: the boot process from flash doesn't harm the SD... so there is a way to read the flash in the way that SD still works after that...
Edit 4: the boot code doesn't use smart pins to access the flash....
The best solution seems to be adding flash_erase, flash_read and flash_write somewhere to the SD related flexprop driver. If these things are placed in one library, the library can keep the integrity of smart pins states between SD and SPI Flash access
Comments
That can be improved for sure. I'll take the complete blame for not considering this scenario from the SD card side. Currently, the driver relies on exclusive smartpin use so it can leave them configured and come back on the assumption nothing else has changed that config.
EDIT: Although if you're first unmounting the SD, then read/wrire EPPROM, then remounting the SD, then this smartpin reuse thing shouldn't be a problem.
As for the EEPROM driver. It'll work best by also using SPI clock mode 3. Namely CPOL = 1. This prevents accidental mis-selecting of the SD card.
I ended up with a Basic/Spin procedure which simply bitbangs the SPI using pinhi and pinlo. This thing seems to work without disabling the SD if called before mount
Edit: it works also when calling after mount, and then I still can read the file from SD after reading the flash so there is a hope...
I used this "mode 3" with clock signal =1 at idle.
The crude method looks like this:
Now... go to pure asm for some more speed
How to unmount a SD?
just
umount( "/sd" );
PS: I use it in my speed tester to induce a recalibration of the timings upon change of sysclock frequency. So not dissimilar situation in that the timings are calculated at init/mount time and reused per on-going read/write of the SD card.
EDIT: Reading over the source again, the timings are embedded in the config of the smartpins themselves.
It has to be
_umount
Then before accessing the flash, I had to do pinclear. And now it all seems to work.
So the summary:
_umount
before accessing the flash_umount
the smart pins have to be cleared bypinclear
before using flash,_umount
doesn't clear pinsOdd, maybe that's changed at some point. My speed tester code doesn't use underscores.
As expected. Most existing code uses mode 0, so is therefore prone to mis-selecting the SD card when attempting to access the EEPROM.
It won't take much to alter Jon's EPPROM driver. Usually such code is agnostic to CPHA and will work as mode 3 simply by inverting the clock pin. Which can be done with a single WRPIN at the start.
Hmm, yeah, there isn't any existing callback in the
sdmm.cc
driver file for unmounting. Therefore there's no clearing of the smartpins during unmount.Good.
Asm version of read block.
I have several programs that needs only reading, so now I can remove the flash access full blown object and use this instead.
I've refined your code a little: Maximised the read lag compensation (14 sysclocks) for operating at highest sysclock frequencies, made the clock symmetrical, and optimised the inner loops to sysclock/8.
I forgot the
rep
instruction while writing this... 4 clocks and 2 local variables less in your version.Edit: it is possible to make the code faster using long write (if one doesn't need byte access). 833 instead of 970 microseconds for 4 kB read at 336 MHz
You could also use WRFAST/WFBYTE to be even faster.
WFBYTE would be ~5% faster than WRBYTE but slower than WRLONG.
WFLONG would be ~1% faster than WRLONG so hardly worth it.
wrbyte fa, ha
takes 6.25 cycles on average.wrlong fa, ha
takes 5 cycles, whether or not ha long-aligned.Update:
DO not ever use jm_p2_flash.spin2 with an SD card residing in the slot.
It can not only set the card in unusable state, it can unformat the card overwriting sector 0 on it.
So remove the card before programming the flash or you can get an unformatted SD
If this happens, the solution is to use a Linux machine with "testdisk" installed. Testdisk can find the partition and restore the partition table. After this, the card can be used again, it seems no other data was lost.
Thank you for letting people know about this. I would have never thought to co-mingle the flash and uSD connections like this, hence I never put an a card into that socket.
The problem seems to be Mode 0 used. It causes the SD to receive random signals because flash clock is SD chipselect. If it is set low for too much time, the SD can think it is selected and starts to receiving commands.
I don't know how it can be initialized and formatted this way, but this was the second time it has sector 0 erased by writing (too much) data to the flash.
Now I use this bitbanged Mode 3 procedures. So far no side SD card effects. Maybe Mode 3 can be also done using smart pins. In theory reverting the clock should be sufficient. I didn't try this yet.
I did a very quick test with some demo code that uses the jm_p2_flash.spin2 driver. Per your suggestion, I inverted the clock output signal and get the same results as before. Hopefully, this will be helpful. What I'd really like is to see a unified driver that allows one to write to and read from either flash memory (above 1M) and the SD socket.
Jon you are fast. - 9:07 - 9:09 - 2 min
Mike
I'm able to compile the littlefs flash file system code with the latest flexspin, so it's at the point where we could add flash file system support. What's the final verdict on mixing SD and flash? Can they both be used together if mode 3 is used for the flash? Or should mounting one be possible only if the other is not mounted?
As it stands, using SPI Clock Mode 3, they can cleanly share alternately (without corruption) but can't share concurrently. My SD smartpin code assumes exclusive control of those pins once mounted ... therefore has to be remounted after other software changes pin config.
Unmount the SD before accessing the flash, remount after.
For me, once the SD has been mounted the flash is forever inaccessible, even if I unmount the SD. I guess something in the flash smartpin configuration is incompatible with the SPI object I'm using (the SimpleSpiFlash.spin2 object from the objex). Going the other way (mount flash, do stuff, unmount, then mount SD) seems to work though.
Oh, SimpleSpiFlash was one of the first pieces of code I wrote for the P2. I never claimed it is compatible with anything else. I was happy that it worked at all.
Agreed, that is the best solution.
I tried a mixed flash/SD access in my test code that loads cog drivers from the flash instead of compiling them in the program and it works (at least it worked when I tried this), but to do this I used a bitbanged flash driver (without smart pins involved).
This is the object:
D'oh, the answer was up-thread: the SD card pins have to have _pinclear applied at unmount. I've added a hook to sdmm.cc to allow this, and now switching between file systems works great.
@ManAtWork : your SimpleSpiFlash works great, and is the only flash driver actually in the obex ( @JonnyMac did some flash drivers, I think, but they're in a QuickByte rather than the obex ).
What board do you use to test this? Is there a series resistor between SD-DO and P58?
The problem might be that the SD card is not released correctly at unmounting. Then the DO pin remains active high and disturbs communication with the Flash. This can be solved with such a resistor or with a good release procedure. Cluso99 claimed that his SD-boot code in ROM releases the card correctly.
I think you need to set CS high and give the SDcard a bunch of clocks to release it fully.
Here is another Flash access code from PIK33, that should work together with an SD card (first post):
https://forums.parallax.com/discussion/175063/a-resource-burner-for-not-only-standalone-system#latest
Andy
Thanks, Andy. I'm using a P2 Eval board, and the problem was that the FlexC SD code wasn't clearing the smart pins on unmount. That's fixed now.
Thanks for the tip. Here's the video I found to explain the process: