Using SD card when booting from flash on P2 edge
Hey all,
Has anyone successfully used the SD card on an P2 Edge when booting an am from SPI Flash? I'm finding that any time I place an app in flash via the loadp2 flash bootloader and boot it, I can no longer mount the SD card, unless I disable flash booting (via the dipswitch). After which, I can reload the program via serial and things start working again, I can even re-enable the dip switch and it will mount again, until a I power cycle and everything loads from flash fresh. I think the bootloader is messing up the SD card after a power cycle and kicking out of SPI mode or something, but maybe I'm messing things up in a different way. And the fact that disabling the dipswitch and reloading the same program (without a power cycle) fixes things is interesting.
I'm using P2LLVM with iseries's SD card driver and the standard SPI flash bootloader from loadp2. Any directions or ideas to debug would be great! otherwise, I'll just store the data I need to save to flash and write a program to pull it manually.
Comments
I am using SD card with flash boot on P2-EC32 without any problems - there is a Basic interpreter in the flash. Then I can run any program from the SD usding the Basic interpreter commands. No problems with SD and flash coexisting.
The Basic interpreter is written with FlexBasic (Flexprop) and uses its built-in SD card driver.
The proper flash driver should run at SPI Mode 3. If not, SD card may be non-responsive or even unformatted (sector 0 overwritten) after accessing the flash.
Older drivers tend to all use SPI clock mode 0. That is known to be problematic when sharing the boot pins.
The Flexspin compiler provides standard C library from Spin2 programs using "libc.spin2" as an object. This gives Spin2 access to regular C API for files and streams.
Here's an example I use:
thanks all--will take a look. it does indeed look like the old SD driver I'm using uses mode 0. I guess I have some driver writing in my future! I'm assuming this still uses the same loadp2 bootloader that talks to flash in mode 0, but the newer SD driver is in mode 3, and that lets everything be happy?
The C library in spin2 is new to me since I work exclusively in C++ with p2llvm. might need to look into porting that over to be consistent with the rest of the P2 world.
Edit: where can I find the source for the libc.spin2 and the blkdrvr/sdsd.cc you use in that example?
Ah, LLVM meant nothing to me so I just assumed you were doing something with Spin.
libc.spin2 is in the Flexspin includes directory - https://forums.parallax.com/discussion/170730/flexprop-a-complete-programming-system-for-p2-and-p1/p1
sdsd.cc is my plug-in SD driver for Flexspin - https://obex.parallax.com/obex/sdsd-cc/
latest edition - https://forums.parallax.com/discussion/comment/1567225/#Comment_1567225
PS: You won't have the hardware for that driver. Sorry, I didn't think to select something else before posting it ...
Here it is again configured for Flexspin's built-in SD driver with the boot pins.
Obviously, you can look at the C sources instead of via Spin. Here's my C version of the same tester.
This is an old problem. My workaround was to do one of two things:
1) Set the dipswitches so that you only boot from serial when in development mode. That allows for rapid development time.
2) When flashing it, be sure to remove and reinsert the SD card before flashing it.
Power to the SD card should have been on a switched FET connected to the reset line.
I'm having a similar issue with P2 Stamp where the FlexProp uSD driver won't work after the flash is programmed.
But, this is when starting a new program over serial. So, guess this is different.
Haven't figure out what is going on there yet, but it might be because the program that is flashed toggles P58 and P59. But, maybe that's a red herring, not sure yet.
Anyway, what works is to first load the attached which uses FSRW to display the uSD contents using the prop tool debug window.
Then, can load a FlexProp program and have uSD work.
Sorry if this isn't relevant, maybe just adjacent...
This might be related, or not,
Back in 2019 we did some detailed testing on how many additional clocks various SDXC cards needed, beyond what the bootloader provides, in order to release the DO line back to floating state. Not releasing DO causes the subsequent boot to fail, but i imagine it also may cause mount issues.
The short answer was to use particular cards, eg SanDisk 64 GB SDXC Extreme or SanDisk 16 GB Ultra SDHC. These are able to boot multiple times in a row, despite not releasing the MISO line. Details in this thread, https://forums.parallax.com/discussion/comment/1465337/#Comment_1465337
The other potential solution might be to add some extra SPI clock cycles early in your program, before you do attempt to mount the SD card. Most SD cards required 1 or 2 extra clocks in order to free their DO pin. We found at least 1 Samsung that never released. We found the Sandisk 16GB Ultra (red and grey 2 tone) the least trouble overall
Thanks for all the input!
I'm using a SanDisk Ultra right now and I've dug in and found some really wacky things. For example, I can power cycle the card by removing it from the slot, putting back in, and then attempting to mount, and it still won't mount whenever I booted from flash. Something about the SPI_CS or SPI_CLK affecting the CS/CLK pins on the SD card must be putting into a bad state. However, the fact that I can remove the dipswitch, restart a program, then put it back and then the SD card mounts means that there is some sequence of pin toggles that should recover the card, I just have no idea what. I've tried adding extra clock pulses with CS high at the start of my program to clear it to no avail. I think for now, I'm going to write my log data to the the flash and use a separate program to read it off. Not as convenient as an SD card but it'll work for now, until I have time to dig into getting a more modern driver up to date.
It would be nice to have FETs that power off the flash or the SD card on the P2 edge module and allow for selection, but that's 2 more pins that get used up which is not ideal either. And it sounds like this generally works for most people, so likely a me problem with my drivers. I'll also read more about SD initialization and see what it might be doing if it's clk or cs pin is toggle too many times (as might be the case is happening whenever I load a full program from flash vs a clean boot)
Would using separate pins for the SD card be an option? It's easy to specify alternative pins when the card is wired elsewhere.
PS: And, yes, an electronic power switch is also supported in one driver.
Uses 7 or 8 pins though - https://forums.parallax.com/discussion/174988/new-sd-mode-p2-accessory-board/p1
@n_ermosh there is also something about some boot modes setting up the pins in smartpin mode. Sometimes one has to turn off their smartpin mode for other uses…
@evanh it would but the PCB I designed for this was relying on using the on board SD slot, otherwise I'll need to rework the it to use a different set of pins. I'm building 25 of these so that's an annoying amount of rework.
@Rayman I checked the bootloader code and it does reset the smartpins before launching the app, so I don't think that's the problem. I've tried all sorts of ways to reset the pins into their default config.
On the Parallax boards, there's a 10k pull-up resistor attached to pin P61 when the EEPROM is enabled.
I have had this problem with some SD cards. I have not had problems with 32GB Sandisk cards, but have with other. Most work, some do not.
I ported over evanh's sdmm driver and everything seems to work now! thanks for the help
Good to hear.
The logic of that driver wasn't me, BTW. I only hacked in the smartpins speed up. I learnt a lot from the original along the way, and it helped as a starting point for the SD mode driver. The placement of card busy check logic being a pretty key aspect. Eric fished up all the original SPI mode code.
@n_ermosh this is for LLVM? Still working on that? Might have to try that again…
So many projects on the go ... How many Rayman's are you?
@Rayman yeah, I use LLVM exclusively for my projects, slowly expanding the core LLVM libraries/backend as necessary.
So I've been experimenting with the new driver and I'm finding that writing it will freeze randomly. I'm not sure how often it happens, but I can't isolate to a single function--sometimes it's during write, sometimes it's during sync, and at varying points within those functions, but it seems to be something in the ff.c library. I'm not super familiar with FAT file systems, do ya'll have any ideas for how to debug?
Is that the same ff.c from FlexC, as in you've ported the whole FAT FS support from there?
PS: I've not struck lock-ups at that level. It's always been at the driver level, not following the card state correctly. It happened quite a lot early on in the SD mode driver with the use of WAITSE1 instructions expecting the clock gen to complete a specific number of pulses but the smartpin instruction for clocks hadn't been issued so there was nothing to complete. This was often due to the semi-pipelining arrangement of checking for completion of the prior transaction only upon driver resumption at beginning of a subsequent transaction.
Yeah it’s the same ff.c from flex C. And you’re probably right that it’s at the SD driver (I’m using SPI mode), so will see if I can isolate where in the driver it’s getting stuck. Will work on trying to hunt that down today and see where I need more help
If you get frustrated with smartpin intricacies and would rather just bit-bash everything you could port the sdmm_bashed.cc driver and see if that works better for you.
EDIT: Actually, maybe a better first option is to not set the driver's
#define _prop2_mode_eh
and just compile with the original bit-bashing code instead. It's very slow but might help with proving things for a start. EDIT2: That's assuming you didn't just strip that code during the porting of course.You were right in that it's something at the lowest level of the driver. I've narrowed it down to the actual asm TX loops:
it gets hung up waiting on the tx buffer to be ready for another byte. I need to comb through the smart pin configs, cause somewhere the propeller2.h for flexC diverged from mine, and where I have
wrpin(value, pin)
, flexC haswrpin(pin, value)
, so I'd put money on it being a simple issue like that.EDIT: Looks like both the TX and RX functions will hang up when waiting on the smart pin to pull IN high. Any ideas why that might happen? The lock-up doesn't seem to happen at any predictable point in time, but it does seem to be specific to the smart pins.
EDIT 2: replacing the testp loop with waitse seems to be more reliable--but I still had it happen once so far, so clearly that's still not a reliable way to wait for the pin, but the failure time is much much larger so I'm going to do some stress testing on it now.
EDIT 3: turns out a completely unrelated piece of code was messing with smartpin settings that happened to intersect with the SD pins. the fact that anything on this board worked at all is surprising given the bug I found in my app... but I think I fixed it all. waitse vs testp and jmp makes no difference (as it shouldn't). Will continue with stress testing everything.