Shop OBEX P1 Docs P2 Docs Learn Events
SD card objects, fsrw etc... — Parallax Forums

SD card objects, fsrw etc...

R PankauR Pankau Posts: 127
edited 2010-03-18 02:00 in Propeller 1
I'm trying my best to get the object fsrw to write to an SD card.
First thing I did was run test.spin and the results were good.
Here's the output:

Clock: 80000000 ClusterSize: 32768 ClusterCount: 60023
Raw write 3968 kB in 2197 ms at 1805 kB/s
Raw read 1920 kB in 2185 ms at 878 kB/s
fsrw pwrite 2016 kB in 2006 ms at 1005 kB/s
fsrw pread 2016 kB in 2299 ms at 876 kB/s
FSRW pputc 63 kB in 2111 ms at 29 kB/s
FSRW pgetc 63 kB in 1840 ms at 34 kB/s
All done!

So, when I try a little bit of this my results differ. Maybe I'm not calling the routines in the correct order to init the card?
Here is a snippet of my code. sd is fsrw.spin
BYTEFILL(@strng_buf, "b", 39)
strng_buf[noparse][[/noparse]39] := 0
success_mount := \sd.mount(0)
success_popen := \sd.popen(@FileName, "w" )
success_write := \sd.SDStr(@strng_buf)
\sd.pflush
\sd.pclose




the values that return in success_mount, success_popen, and success_write are -41, -2, 0

The -41 is quite confusing since it is not one of the abort values at all. the other two don't surprise me since the mount failed.

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔

Comments

  • MagIO2MagIO2 Posts: 2,243
    edited 2010-03-16 06:10
    You should always post the whole code - simply attach it to the message ... at least the whole code ... sometimes even the whole project is better.
    What version of FSRW do you use?

    Yes, in general your code-snipped does not look to bad. First you have to mount, then you open the file and then you can use the file.
  • R PankauR Pankau Posts: 127
    edited 2010-03-16 13:55
    I can post the entire thing when I get home.

    not much else going on.·· receiving signals from GPS, although it is disconnected for this test.··

    Thought maybe fsrw was only capable of 512 bytes per cluster.· my card is 2Gig so it is 32768 per cluster.· the paradox for me is that the test worked. so in theory (not too big of a stretch) it should work.··

    the Test, however, did use another object "safe_spi.spin" which could hold some clues.·· I'm not using that one, not sure if it is needed.· it appears more robust maybe, but also not as user firendly.··

    The version is 2.6 I'm almost sure.·· have to double check.·

    Can anyone give me a quick answer to why there are so many flavors of this object?· Do I need just one?· the right one?·

    Actually another test that I performed was the code straight out of the book,

    attachment.php?attachmentid=73963

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    441 x 69 - 3K
  • MagIO2MagIO2 Posts: 2,243
    edited 2010-03-16 18:39
    Did you try to read a file with the same driver?
    Do you have a capacitor in place close to the SD card? If writing is the problem the SD card might draw to much peak currency which can't be delivered by the power supply fast enough.

    I had such kind of problems with version 2.4. In the fastes driverthe timing is very tough and depending on capacities in the wiring , buffer capacitors used and even the signal length from COG to IO-pin it may work or not. I simply replaced the COGNEW (which takes the next free COG) with a COGINIT to start the SPI-driver in COG where it works.

    If this does not work, you should test the different SPI-drivers in the test.spin and take the fastes one which works.
  • R PankauR Pankau Posts: 127
    edited 2010-03-16 21:19
    Thus far I have not been able to get past the mount on my own but the test.spin seems to work and I'm calling the same object in my code that the test uses.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
  • MagIO2MagIO2 Posts: 2,243
    edited 2010-03-16 22:14
    Clock settings?
    The parameter in the mount is the pin, do you really use pins 0-4?

    If you are not willing to post your code there will be nothing more than guessing.
  • R PankauR Pankau Posts: 127
    edited 2010-03-17 01:54
    It's not that I'm not willing but since the last time we spoke I had a full time job to attend to, 3 kids to feed, bathe, play with and put to bed after 3 books each... whew! now I can relax with some code.

    I am using 0,1,2,3 for DO, SCLK, DI, and CS
    the hardware was the same during test.spin that came with the fsrw object (from object exchange)as it is now and it worked well with the test code. (no visible errors from fsrw or safe_spi) Also the test code declared both objects fsrw as well as safe_spi and it appears that both were called at will. no abort messages have ever appeared from running the test code. Looking at the SD card after running the test I found two files filled with "!" so there is no doubt in my mind that it was capable of dealing with 32k clusters. I have a feeling that my code however is tied down to 512 bytes per cluster by using fsrw exclusively. my SD card will not format at 512 since it is 2Gig.

    I'm reluctant to go chasing hardware issues if it has proven to work with other code. Seems like it must be my software that is the issue here.

    'GPS reading and displaying for debugging.
    
    
    CON
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
    
    REC_FROM_GPS_PIN = 17
    
    OBJ
    gps   : "GPS_IO_mini"
    debug : "FullDuplexSerial"
    sd : "fsrw"
    'block : "safe_spi"
    
    var
    long success_mount, success_popen, success_write
    byte strng_buf[noparse][[/noparse]40]
    byte tbuf[noparse][[/noparse]20], sdmounted
    
    DAT
    FileName  byte "Log01.txt",0
    pub main
    
    gps.start(17, 4800)       'start gps receive and parse
    debug.Start(31, 30, 0, 115200)
    
    
    waitcnt (clkfreq + cnt)   ' wait for 1sec to allow other cogs to init.
    
    BYTEFILL(@strng_buf, "b", 39)
    strng_buf[noparse][[/noparse]39] := 0
    success_mount := \sd.mount(0)
    success_popen := \sd.popen(@FileName, "w" )
    success_write := \sd.SDStr(@strng_buf)
    \sd.pflush
    \sd.pclose
           
      repeat
          debug.dec(success_mount)
          debug.str(string(", "))
          debug.dec(success_popen)
          debug.str(string(", "))
          debug.dec(success_write)
          debug.str(string(", "))
          debug.str(gps.GPSaltitude)
          debug.str(string(", "))
          debug.str(gps.latitude)
          debug.str(string(", "))
          debug.str(gps.longitude)
          debug.str(string(", "))
          debug.str(gps.satellites)
          debug.str(string(", "))
          debug.str(gps.valid)
          debug.str(string(", "))
          debug.str(gps.time)
          debug.str(string(", "))
          debug.str(gps.heading)
          debug.str(string(", "))
          debug.str(gps.speed)
          debug.str(string(", "))
          debug.str(gps.vdop)
          debug.tx(13) 
          waitcnt(clkfreq / 4 + cnt)
    
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
  • MagIO2MagIO2 Posts: 2,243
    edited 2010-03-17 07:50
    Good advice (not only for you [noparse]:o[/noparse]) : If you have questions like "why doesn't it work ..." ALWAYS·attach at least the SPIN-file or at best the whole archive to the INITIAL POST!
    You see what happens: It's like a ping pong game and you get valuable tips much later

    For example - in your first post you only gave the snippet:
    BYTEFILL(@strng_buf, "b", 39)
    strng_buf[noparse][[/noparse]39] := 0
    success_mount := \sd.mount(0)
    success_popen := \sd.popen(@FileName, "w" )
    success_write := \sd.SDStr(@strng_buf)
    \sd.pflush
    \sd.pclose
    
    

    As such this snippet is fine! The important thing - from my experience is:
    DAT
    FileName  byte "Log01.txt",0
    pub main
    
    [color=red]gps.start(17, 4800)[/color]       'start gps receive and parse
    [color=orange]debug.Start(31, 30, 0, 115200)[/color]
    
    
    waitcnt (clkfreq + cnt)   ' wait for 1sec to allow other cogs to init.
    
    BYTEFILL(@strng_buf, "b", 39)
    strng_buf[noparse][[/noparse]39] := 0
    .....
    
    

    It's already mentioned in one of my guessing posts:
    MagIO2 said...
    ·..... In the fastes driverthe timing is very tough and depending on capacities in the wiring , buffer capacitors used and even the signal length from COG to IO-pin it may work or not. I simply replaced the COGNEW (which takes the next free COG) with a COGINIT ....
    What you do is, you start two other COGs before doing the mount. Which means the SD driver most likely will run in COG 3 (COG 0 = Spin interpreter, COG 1 = gps, COG 2 = serial). This means you could have the same problems than me. So, simply try it again after moving the mount to the beginning of your main.

    You did not answer the question about the capacitor?! This is one of the advices I was given when I searched my problem.

    What are your requirements for the read/write speed? If you can live with ~800kB/sec reads, the slow driver is fine. And that's the reason why it's in the FSRW package - when the fast drivers fail (f.e. because of bad SD cards or bad PCB design ....) the slow driver still gives you a chance to use the SD interface.

    Post Edited (MagIO2) : 3/17/2010 7:57:48 AM GMT
  • R PankauR Pankau Posts: 127
    edited 2010-03-17 13:23
    I have not used any extra caps.·it's on a Prop proto board.· the lead lengths are 1 inch or less, and roughly equal.·

    Speed requirements are not fast.·· 40 bytes every 20 seconds or so.·

    So you think the mount is too soon in time before the other functions, popen for example?

    Does that answer this question though:· Why after running test.spin does mine work?· Could it be that my mount is not really working still but it does not matter because the card thinks the previous mount is in effect?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
  • MagIO2MagIO2 Posts: 2,243
    edited 2010-03-17 13:53
    Have a look at any mainboard .. or PCB holding digital circuits. You'll find a lot of capacitors there. Why? Because there is a lot of fast signal switching going on on those boards. Signal switching means that there is some currency involved and usually the power supply is to far away to deliver the currency in an appropriate time. That's why you have capacitors close to the chips. ... close to the Propeller ... and in your case you should have a cap close to the power-lines of the SD card as well.

    If the speed requirements are so low, use safe_spi. Why is it less user friendly? You should always call FSRW functions.

    No, I don't think the mount is to soon ... once again ...
    MagIO2 said...
    It's already mentioned in one of my guessing posts:
    MagIO2 said...
    ·..... In the fastes driverthe timing is very tough and depending on capacities in the wiring , buffer capacitors used and even the signal length from COG to IO-pin it may work or not. I simply replaced the COGNEW (which takes the next free COG) with a COGINIT ....
    What you do is, you start two other COGs before doing the mount. Which means the SD driver most likely will run in COG 3 (COG 0 = Spin interpreter, COG 1 = gps, COG 2 = serial). This means you could have the same problems than me. So, simply try it again after moving the mount to the beginning of your main.
    This means, that the fast version of SPI driver works when it is loaded into COG 1 and it does not work if it's loaded into COG 3 in your case. The COGs sit on different places of the propeller chips die, having different signal paths to the I/O ports. Shifting the mount to the beginning means that COG 1 is used for SPI, COG 2 for GPS and COG 3 for serial interface.
    R. Pankau said...
    Does that answer this question though:· Why after running test.spin does mine work?· Could it be that my mount is not really working still but it does not matter because the card thinks the previous mount is in effect?
    No, this is news ... you never mentioned it before. Did you maybe switch to safe_spi?
  • David BDavid B Posts: 592
    edited 2010-03-17 16:06
    I think it would be a good idea to use the return code values.

    If a mount fails, the code should not try to open a file.

    If a file open fails, the code should not try to write to the file.

    Once the first failure is detected, further results will be suspect, no matter what their values.

    What to do in case of failure can be a hard choice, and depends on what failed as well as what the overall project needs to do, whether to retry the same operation, or to continue other work, or to display an error message, or to completely halt.

    But in general, failure codes should be believed and listened to and acted upon.
  • R PankauR Pankau Posts: 127
    edited 2010-03-17 20:42
    Hmmm I'm searching for where I mentioned that I can get my code to mount, open and write immediately after running the test.spin file.· Maybe I never submitted after previewing last night.·

    Anyway this is a good point.·· my code in general fails, returns -1 on the mount I believe.· until...· I load test.spin.·· This always works.· it never shows any errors and I get the messages that I posted in my original thread.·
    then If I load my code without removing the SD card or cycling power it works as well, returns 0 for mount, open and writes, and the data is there to see on the SD card when I look with the pc.··


    When the card goes back into the prop board it will not work with my code again until test.spin is run first.·(going back to default mode not-spi I'm guessing)

    Looking through test.spin I did see that the first access to the SD card was accomplished not with fsrw but with safe_spi directly I believe using start instead of mount (it's not in front of me now)·· then later in the test it gets to mount with the fsrw object.· I have tried accessing through start and safe_spi as well but it returns an error.
    obviously something about test.spin is different enough to allow it to always work. But it's just the top level so I must be·missing something or my·timing·is off.·

    One other hint is that the return code from the mount abort was "SD card not reset" that might have been -1 but I'm not sure.··· Evidently test.spin was successful in resetting the card but this is the point at which my code gets stuck.·


    So as far as the caps and lead lengths, all of the real bit-banging and critical timing is still being accomplished by the same code regardless of what top level code is calling the shots, mine or test.spin.···· We're not talking about Gbits per second here are we?···the test results showed more like kbits per second.· ·I'll take a peek at the data lines tonight with a scope to see what the bit widths are.··
    ·

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
  • rokickirokicki Posts: 1,000
    edited 2010-03-17 21:29
    If you'll post the full minimal code that fails (remove any extraneous objects and try to get it
    as small as possible) I can try it here. Otherwise, we're just guessing.

    Note that "resetting" the SD card can be a bit tricky. Have you tried downloading your code
    to EEPROM, presumably seeing it fail, and then power cycling the board (ideally with the board
    *not* attached via USB)? A power cycle is guaranteed to reset an SD card (although a power
    cycle with USB attached might not).

    But *usually* things like this come down to something else; some other object writing over
    fsrw's vars, or somewhere someone using buf instead of @buf, or something like that.
    That's why we want to see the code.
  • R PankauR Pankau Posts: 127
    edited 2010-03-17 21:54
    I can try to squeeze out the fluff.··
    I'll have to work on the minimal code a little later.
    I have tried writing to EEProm and letting it come up after power on but the Prop Plug was still attached.· That's also how I debug so I guess I'd have to pull the card and look at the results on a pc.··· When the mount aborts and returns -1 indicating card not reset my assumption was that the card was not put into SPI mode.·· I'm wondering what reset really means in this context.··

    First thing I will remove all of·the gps code.· that will put the fsrw in cog1, that will test MAGIO2's·theory.···in that respect it·will match test.spin.·
    ·


    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
  • R PankauR Pankau Posts: 127
    edited 2010-03-18 02:00
    Attached is a file that works.
    some good advice thanks. I moved the mount prior to the 1 second wait before calling any other methods from fsrw. tried it without gps then added gps back in then switched the order around, Looks like it does not matter where the fsrw resides (cogwise) that's what I would expect.

    What did surprise me however is that it was not exactly consistent with being successful on the mount portion. so I added the loop so it would continue to try if the mount failed. Am I correct in believing that an object is not loaded into a cog until coginit or the like is invoked usually with start or in this case mount? I guess my point is that if I added a waitcnt before the mount method it should not matter because nothing is going on prior to the call in either case. It would be nice to know why the mount does not always take. By all accounts the writing and opening always works though. Log01.txt appears to have contiguous rows.

    To make things more robust I could watch for abort and return values from popen etc. like David B suggested and if anything fails then calling mount again should clean things up.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Sign In or Register to comment.