fsrw pread strange behavior
Hi there,
I am trying to read bytes from an SD card into a data block. It seems as though a fsrw.pread command is not correctly reading bytes and placing them into the desired array, whereas a fsrw.pgetc will read them correctly directly from the SD file. Just one more bit of background: the DAT block array I want to fill with the bytes from the SD card ("v4data.spin") is in a separate object than the code calling the fsrw.pread method ("MT_config.spin"). Here is a code example:
A user can change the values of the apnservVal to preset values via a pwrite command (not shown) in MT_Config.spin. Judging from the outcome of the pgetc command illustrated below, it appears the pwrite method is working correctly.
So, the bottom line is this: the pgetc code returns the expected, user-changed values from the MT_config file, even after resetting the Propeller. However, after resetting the propeller, the pread returns the pre-defined values set at compile time from the Propeller memory that should be updated with the new values.
Here is what is displayed in a terminal (via the uarts debug calls above):
-- output directly from pgetc method debug --
read config
ApnServ?:"WWW.CDEFG.COM"?????????? <---- New, user-changed value apparently correctly written and read out from the SD card file
read config
-- output from memory after pread debug --
numBytes 0 <--- note 0 bytes read
ApnServ:"WWW.XXXXX.COM" <---- Note that data block starting at v4data MTConfigFileStart has not been updated
Any insights are appreciated. Thank you.
I am trying to read bytes from an SD card into a data block. It seems as though a fsrw.pread command is not correctly reading bytes and placing them into the desired array, whereas a fsrw.pgetc will read them correctly directly from the SD file. Just one more bit of background: the DAT block array I want to fill with the bytes from the SD card ("v4data.spin") is in a separate object than the code calling the fsrw.pread method ("MT_config.spin"). Here is a code example:
' "v4data.spin" (Object with DAT block where I want to store data from SDcard): PUB GetMTConfigFileStart return @MTConfigFileStart DAT MTConfigFileStart 'store config data starting here apnServTitle byte "ApnServ",0 colon1 byte ":" apnservVal byte 34,"WWW.XXXXX.COM",34,0[10] cr1 byte 13 MTConfigFileEnd byte $3 'end of config data block
A user can change the values of the apnservVal to preset values via a pwrite command (not shown) in MT_Config.spin. Judging from the outcome of the pgetc command illustrated below, it appears the pwrite method is working correctly.
'"MT_config.spin" (Object I am calling to read data from SD card. The UARTS object has previously been initialized and started a port 0 to talk on pins p30 & p31 to the terminal): CON DEBUG = 0 OBJ SD : "fsrw" UARTS : "FullDuplexSerial4portPlus_0v3" v4data : "v4data" PUB Main: sd_err 'called from the main program startup object sd_err := \sd.mount(sd_do) ReadConfigFile PUB ReadConfigFile : sd_err | startPtr,fileSize,char,idx,numBytes uarts.str(debug,string("read config",13)) sd_err := \SD.popen(string("MT_config.txt"), "r") if sd_err == -1 uarts.str(debug,string("no MTconfig file",13)) WriteConfigFile '<---- go create a MT_config file if none exists return elseif sd_err < -1 uarts.str(debug,string("read error",13)) return fileSize := sd.get_filesize if fileSize > 500 'limit max size to prevent overrun filesize := 500 'try using pgetc to retrieve and print data from MT_config file repeat filesize char := sd.pgetc PrintChar(char) newline 'now close the file and reopen so we can try reading out of the file directly into the v4data DAT block using fsrw's pread method sd.pclose uarts.str(debug,string("read config",13)) sd_err := \SD.popen(string("MT_config.txt"), "r") startPtr := v4data.GetMTConfigFileStart 'set buffer pointer to the location where we want data to be placed from the fsrw pread method numBytes := doSDread(startPtr,fileSize) 'read fileSize number of bytes out of MT_config SD card file into bytes starting at location set by startPtr uarts.str(debug,string(13,"numBytes ")) 'print number of bytes read by doSDread method PrintDec(numBytes) newline sd.pclose repeat idx from 0 to fileSize 'Print all non-zero characters just transferred from SDcard to Prop memory char := byte[startPtr+idx] if char <> 0 uarts.tx(debug,char) PRI DoSDread(bufpnt,Nchars) : numBytes | sd_err 'reads N characters into the bufPoint buffer. ifnot SD_err numBytes := SD.pread(bufpnt, Nchars) 'Debugging routines PRI PrintChar(char) uarts.tx(debug,char) Pri NewLine uarts.tx(debug, 13) Pri PrintSpace uarts.tx(debug,32) PRI PrintDec(val) uarts.dec(debug,val) PRI PrintStr(strPtr) uarts.str(debug,strPtr) PRI delay(ms) waitcnt(clkfreq/1000*ms+cnt)
So, the bottom line is this: the pgetc code returns the expected, user-changed values from the MT_config file, even after resetting the Propeller. However, after resetting the propeller, the pread returns the pre-defined values set at compile time from the Propeller memory that should be updated with the new values.
Here is what is displayed in a terminal (via the uarts debug calls above):
-- output directly from pgetc method debug --
read config
ApnServ?:"WWW.CDEFG.COM"?????????? <---- New, user-changed value apparently correctly written and read out from the SD card file
read config
-- output from memory after pread debug --
numBytes 0 <--- note 0 bytes read
ApnServ:"WWW.XXXXX.COM" <---- Note that data block starting at v4data MTConfigFileStart has not been updated
Any insights are appreciated. Thank you.
Comments
Here you define SD_err as a local variable. Local variables are never initialized and ... they are local! So, it is actually another variable than the sd_err defined elsewhere in your code.
So, how does function-call works?
There is some place reserved on stack to store the return-address, the return-value and all the local variables. Reserve means that the stack pointer is moved behind the end of the needed memory.
There is no initialization which would set the values of local variables to 0! These local variables will have a value that is from the functions point of view unpredictable, as it depends on the code that ran before.
Anyway ... in your case I guess it is simply not zero and your ifnot will simply return false which skips the SD.pread!
This needs to be fixed.
I fixed the code by moving the ifnot sd_err call up into the calling method:
I use the sd_err variable a lot in the object, so I could also reasonably make it a global variable, I suppose. But, as it stands, "sd_err" is taking the place of the standard "result" variable for the (in this case) PUB ReadConfigFile method, so I figure that takes less program space than assigning a new, dedicated variable.