PDA

View Full Version : Solved CLKFREQ mysteriously jumps from 80mhz to 824,195,128



R Pankau
03-23-2012, 04:52 AM
I could not figure out what was going on with my interrupts, all of a sudden the interrupts were taking roughly 10x longer between executions.
this is my clock setup
_clkmode = XTAL1 + PLL16x
_xinfreq = 5_000_000

at boot up CLKFREQ returns 80,000,000 as expected, then after writing to the SD card once it returns 824,195,128 instead. (using fsrw.spin) then it appears to stay put. essentially making all of the waitcnt instructions take a little over 10 times longer.

I've had other strange things with this board as well, for instance if I use SD-MMC_FATEngine instead, then the SD driver will not operate if GPS_IO_mini.spin is used in the same project. I suspect that some resource is being shared not so well but I cannot figure out which one.

MagIO2
03-23-2012, 05:05 AM
I bet there is a bug in your code. FSRW is very well testes like all objects in the object exchange.

By the way ... what do you mean with interrupts? There is no such concept for propellers.

Waitcnt needing longer than expected you have when you just missed the cnt!

You should post your code!

Mark_T
03-23-2012, 10:33 AM
Suspiciously 824195128 is $31203838, valid ASCII, which is the string fragment "88 1" - so a memory overwrite is most likely.

Dave Hein
03-23-2012, 12:24 PM
The CLKFREQ value is located at location 0. It appears that you are writing to location 0. You may be using a NULL pointer somewhere. This kind of error could happen if you did something like BYTEMOVE(buffer, string("88 1"), 4) instead of BYTEMOVE(@buffer, string("88 1"), 4), and buffer is an uninitialized VAR variable that would contain a zero.

R Pankau
03-23-2012, 01:52 PM
Very insightful, I think the offending piece of code lies in this that I used from OBEX


PUB readNEMA
Null[0] := 0
repeat
longfill(gps_buff,20,0)
repeat while Rx <>= "$" ' wait for the $ to insure we are starting with
Rx := uart.rx ' a complete NMEA sentence
cptr := 0

repeat while Rx <>= CR ' continue to collect data until the end of the NMEA sentence
Rx := uart.rx ' get character from Rx Buffer
if Rx == ","
gps_buff[cptr++] := 0 ' If "," replace the character with 0
else
gps_buff[cptr++] := Rx ' else save the character

if gps_buff[2] == "G"
if gps_buff[3] == "G"
if gps_buff[4] == "A"
copy_buffer(@GPGGAb, @GPGGAa)

if gps_buff[2] == "R"
if gps_buff[3] == "M"
if gps_buff[4] == "C"
copy_buffer(@GPRMCb, @GPRMCa)

if gps_buff[0] == "P"
if gps_buff[1] == "G"
if gps_buff[2] == "R"
if gps_buff[3] == "M"
if gps_buff[4] == "Z"
copy_buffer(@PGRMZb, @PGRMZa)


if gps_buff[0] == "G"
if gps_buff[1] == "P"
if gps_buff[2] == "G"
if gps_buff[3] == "S"
if gps_buff[4] == "A"
copy_buffer(@GPGSAb, @GPGSAa)

The ascii 88 1 is the first four chars of Longitude.
the "Null[0] right off the bat has me thinking that it's writing to location zero.

the "interrupt" I refer to is just this, running it a separate cog.


PUB interrupt
repeat
waitcnt(80_000_000 + cnt)
cntr++

and I use cntr a global var to trigger subs then clear cntr,then wait again. I had CLKFREQ in the waitcnt instruction at first then switched it to 80Mhz and noticed that things began working better.

I also use byte addressing in this, which is where all the writing to the sd card happens. but I believe it should never affect location zero....requires a closer look though.




pub write_sd(landmark) |address, i

ret_val := \sd.popen(string("Log01.txt"),"a")
if landmark == 2
\sd.SDstr(gps.GPSaltitude)
\sd.SDstr(string(", "))

'bytefill(@lat_and_long,0,15) 'Clear Buffer
address := gps.latitude 'Get address of latitude
byte[lat_and_long][0] := byte[address][0]
byte[lat_and_long][1] := byte[address][1]
byte[lat_and_long][2] := " "
i := 3
repeat 7
byte[lat_and_long][i] := byte[address][i-1]
i++
byte[lat_and_long][i] := 0
\sd.SDstr(lat_and_long)
\sd.SDstr(string("N, "))

'bytefill(@lat_and_long,0,15) 'Clear Buffer
address := gps.longitude 'Get address of longitude
byte[lat_and_long][0] := byte[address][1]
byte[lat_and_long][1] := byte[address][2]
byte[lat_and_long][2] := " "
i := 3
repeat 7
byte[lat_and_long][i] := byte[address][i]
i++
byte[lat_and_long][i] := 0
\sd.SDstr(lat_and_long)

\sd.SDstr(string("W, "))
\sd.SDstr(gps.satellites)
\sd.SDstr(string(", "))
\sd.SDstr(gps.valid)
\sd.SDstr(string(", "))
\sd.SDstr(gps.time)
\sd.SDstr(string(", "))
\sd.SDstr(gps.heading)
\sd.SDstr(string(", "))
\sd.SDstr(gps.speed)
\sd.SDstr(string(", "))
\sd.SDstr(gps.date)
\sd.SDstr(string(" ",13,10))
'debug.str(string("test"))
'debug.dec(ret_val)
'debug.tx(13)
\sd.pflush
\sd.pclose
'debug.str(string("after file close",13,10))


if landmark == 1
\sd.SDstr(gps.GPSaltitude)
\sd.SDstr(string(", "))
\sd.SDstr(gps.latitude)
\sd.SDstr(string(", -"))
\sd.SDstr(gps.longitude)


\sd.SDstr(string(", "))
\sd.SDstr(gps.satellites)
\sd.SDstr(string(", "))
\sd.SDstr(gps.valid)
\sd.SDstr(string(", "))
\sd.SDstr(gps.time)
\sd.SDstr(string(", "))
\sd.SDstr(gps.heading)
\sd.SDstr(string(", "))
\sd.SDstr(gps.speed)
\sd.SDstr(string(", "))
\sd.SDstr(gps.date)
\sd.SDstr(string(", Landmark"))
\sd.SDstr(string(" ",13,10))
'debug.str(string("test"))
'debug.dec(ret_val)
'debug.tx(13)
\sd.pflush
\sd.pclose

if ret_val == 0
outa[Green_LED] := 1 'Blink LED for success.
waitcnt(clkfreq/100 + cnt)
outa[Green_LED] := 0

if ret_val <> 0
outa[Blue_LED] := 1 'Blink LED for NOT success.
waitcnt(clkfreq/2 + cnt)
outa[Blue_LED] := 0


maybe I should have used byte[@lat_and_long][0], I assumed that referencing a var array would return the address of the first byte, but.... now I see that by clearing the array to zero, or if it starts out that way, the byte[effectively zero][0] then writes to location zero.

R Pankau
03-23-2012, 02:04 PM
This should work a little better
Now if I could find the switch to turn off "unsolved" on the forum heading.



pub write_sd(landmark) |address, i

ret_val := \sd.popen(string("Log01.txt"),"a")
if landmark == 2
\sd.SDstr(gps.GPSaltitude)
\sd.SDstr(string(", "))

'bytefill(@lat_and_long,0,15) 'Clear Buffer
address := gps.latitude 'Get address of latitude
byte[@lat_and_long][0] := byte[address][0]
byte[@lat_and_long][1] := byte[address][1]
byte[@lat_and_long][2] := " "
i := 3
repeat 7
byte[@lat_and_long][i] := byte[address][i-1]
i++
byte[@lat_and_long][i] := 0
\sd.SDstr(lat_and_long)
\sd.SDstr(string("N, "))

'bytefill(@lat_and_long,0,15) 'Clear Buffer
address := gps.longitude 'Get address of longitude
byte[@lat_and_long][0] := byte[address][1]
byte[@lat_and_long][1] := byte[address][2]
byte[@lat_and_long][2] := " "
i := 3
repeat 7
byte[@lat_and_long][i] := byte[address][i]
i++
byte[@lat_and_long][i] := 0
\sd.SDstr(lat_and_long)

\sd.SDstr(string("W, "))
\sd.SDstr(gps.satellites)
\sd.SDstr(string(", "))
\sd.SDstr(gps.valid)
\sd.SDstr(string(", "))
\sd.SDstr(gps.time)
\sd.SDstr(string(", "))
\sd.SDstr(gps.heading)
\sd.SDstr(string(", "))
\sd.SDstr(gps.speed)
\sd.SDstr(string(", "))
\sd.SDstr(gps.date)
\sd.SDstr(string(" ",13,10))
'debug.str(string("test"))
'debug.dec(ret_val)
'debug.tx(13)
\sd.pflush
\sd.pclose
'debug.str(string("after file close",13,10))


if landmark == 1
\sd.SDstr(gps.GPSaltitude)
\sd.SDstr(string(", "))
\sd.SDstr(gps.latitude)
\sd.SDstr(string(", -"))
\sd.SDstr(gps.longitude)


\sd.SDstr(string(", "))
\sd.SDstr(gps.satellites)
\sd.SDstr(string(", "))
\sd.SDstr(gps.valid)
\sd.SDstr(string(", "))
\sd.SDstr(gps.time)
\sd.SDstr(string(", "))
\sd.SDstr(gps.heading)
\sd.SDstr(string(", "))
\sd.SDstr(gps.speed)
\sd.SDstr(string(", "))
\sd.SDstr(gps.date)
\sd.SDstr(string(", Landmark"))
\sd.SDstr(string(" ",13,10))
'debug.str(string("test"))
'debug.dec(ret_val)
'debug.tx(13)
\sd.pflush
\sd.pclose

if ret_val == 0
outa[Green_LED] := 1 'Blink LED for success.
waitcnt(clkfreq/100 + cnt)
outa[Green_LED] := 0

if ret_val <> 0
outa[Blue_LED] := 1 'Blink LED for NOT success.
waitcnt(clkfreq/2 + cnt)
outa[Blue_LED] := 0

Sapieha
03-23-2012, 02:14 PM
To that You need reedit first post of thread in advanced mode



This should work a little better
Now if I could find the switch to turn off "unsolved" on the forum heading.



pub write_sd(landmark) |address, i

ret_val := \sd.popen(string("Log01.txt"),"a")
if landmark == 2
\sd.SDstr(gps.GPSaltitude)
\sd.SDstr(string(", "))

'bytefill(@lat_and_long,0,15) 'Clear Buffer
address := gps.latitude 'Get address of latitude
byte[@lat_and_long][0] := byte[address][0]
byte[@lat_and_long][1] := byte[address][1]
byte[@lat_and_long][2] := " "
i := 3
repeat 7
byte[@lat_and_long][i] := byte[address][i-1]
i++
byte[@lat_and_long][i] := 0
\sd.SDstr(lat_and_long)
\sd.SDstr(string("N, "))

'bytefill(@lat_and_long,0,15) 'Clear Buffer
address := gps.longitude 'Get address of longitude
byte[@lat_and_long][0] := byte[address][1]
byte[@lat_and_long][1] := byte[address][2]
byte[@lat_and_long][2] := " "
i := 3
repeat 7
byte[@lat_and_long][i] := byte[address][i]
i++
byte[@lat_and_long][i] := 0
\sd.SDstr(lat_and_long)

\sd.SDstr(string("W, "))
\sd.SDstr(gps.satellites)
\sd.SDstr(string(", "))
\sd.SDstr(gps.valid)
\sd.SDstr(string(", "))
\sd.SDstr(gps.time)
\sd.SDstr(string(", "))
\sd.SDstr(gps.heading)
\sd.SDstr(string(", "))
\sd.SDstr(gps.speed)
\sd.SDstr(string(", "))
\sd.SDstr(gps.date)
\sd.SDstr(string(" ",13,10))
'debug.str(string("test"))
'debug.dec(ret_val)
'debug.tx(13)
\sd.pflush
\sd.pclose
'debug.str(string("after file close",13,10))


if landmark == 1
\sd.SDstr(gps.GPSaltitude)
\sd.SDstr(string(", "))
\sd.SDstr(gps.latitude)
\sd.SDstr(string(", -"))
\sd.SDstr(gps.longitude)


\sd.SDstr(string(", "))
\sd.SDstr(gps.satellites)
\sd.SDstr(string(", "))
\sd.SDstr(gps.valid)
\sd.SDstr(string(", "))
\sd.SDstr(gps.time)
\sd.SDstr(string(", "))
\sd.SDstr(gps.heading)
\sd.SDstr(string(", "))
\sd.SDstr(gps.speed)
\sd.SDstr(string(", "))
\sd.SDstr(gps.date)
\sd.SDstr(string(", Landmark"))
\sd.SDstr(string(" ",13,10))
'debug.str(string("test"))
'debug.dec(ret_val)
'debug.tx(13)
\sd.pflush
\sd.pclose

if ret_val == 0
outa[Green_LED] := 1 'Blink LED for success.
waitcnt(clkfreq/100 + cnt)
outa[Green_LED] := 0

if ret_val <> 0
outa[Blue_LED] := 1 'Blink LED for NOT success.
waitcnt(clkfreq/2 + cnt)
outa[Blue_LED] := 0

R Pankau
03-23-2012, 04:41 PM
Thanks for the help.

MagIO2
03-23-2012, 06:35 PM
You should go back to waitcnt( CLKFREQ+cnt ) as it usually works correctly. It does not work in your case because CLKFREQ is actually a value stored somewhere in the first 16 bytes of HUB-RAM. If your code somehow overwrites it, you get trouble in code that uses CLKFREQ.

So, if you still have the problem after changing back you did not fix the original bug yet and this means it can also overwrite other parts which cause more harm!

It's better to post the whole truth, because the bug might be at a place you'd never expect it to be! The propeller tool has a niche archive function which zips all needed files from actual file point of view. So, select your top-file and do an archive and post it here.

R Pankau
03-23-2012, 08:56 PM
Here's the entire thing. pretty messy.

MagIO2
03-23-2012, 09:52 PM
You should only use COGINIT for a very good reason - but there is only a limited number of those, so you should rather use COGNEW.

I think your code is fine, but the GPS code seems to be buggy, starting wit this:
byte gps_buff[80],Rx',cksum
....
longfill(gps_buff,20,0)

This overwrites the whole begin of HUB-RAM propably destroying something in your code which makes it write to wrong memory locations as well.

kuroneko
03-24-2012, 12:01 AM
longfill(gps_buff,20,0)

This overwrites the whole begin of HUB-RAM propably destroying something in your code which makes it write to wrong memory locations as well.
FWIW, it doesn't.

MagIO2
03-24-2012, 09:45 AM
Maybe I'm wrong?!
My expectation was that longfill works the same way as bytemove, which needs a pointer to the memory. If my expectation is wrong I'd say that SPIN has an inconsistency in the syntax.
If my expectation is correct, gps_buff is an array to store the incoming string. Using it without @ means that
gps_buff[0] is read and used as address which is 0.

kuroneko
03-24-2012, 10:16 AM
Maybe I'm wrong?!
My expectation was that longfill works the same way as bytemove, which needs a pointer to the memory ...
Relax, look at the parameters. Requirements are longfill(ptr, value, count), so with count being 0 it's not doing anything useful. That said, the object is a can of worms. Given its functionality it's easier to rewrite this bit.

@R Pankau: would it be possible to get a data dump of the stuff coming from the GPS unit for one of the failure cases? I don't have any GPS h/w so that would kind of help figuring out where it goes wrong.

R Pankau
03-25-2012, 03:07 AM
are you just looking for the string that comes from the gps unit in its raw form?
the incompatibility that I spoke of in my first post I believe is happening before any reading of gps data takes place.
for instance the SD_MMC fat engine has written for it a SD card profiler demo program, if I run that demo everything is great, if I load the gps object in the same project even without calling it the demo crashes with no apparent cause, nothing is written to the sd card, i believe usually the error string is written to the card if it was successfully mounted with a file open.

I used coginit once as a troubleshooting method, thinking I had a faulty cog possibly, also rearranged the order of starting the objects. it just needs to be switched back to cognew.

kuroneko
03-25-2012, 03:14 AM
are you just looking for the string that comes from the gps unit in its raw form?
Exactly. I just need something to replay and feed the GPS object with.

R Pankau
03-25-2012, 03:26 AM
just grabbed this...now you know the location of my living room.

$GPRMC,032531,A,3016.3376,N,08811.8669,W,000.0,000 .0,250312,,,A*61

$GPGGA,032532,3016.3377,N,08811.8667,W,1,03,02.4,0 0237.5,M,-033.9,M,,*7A

$GPGSA,A,2,08,11,19,,,,,,,,,,02.6,02.4,01.0*00

$GPGSV,3,1,11,01,28,140,26,03,13,050,00,06,02,047, 00,07,76,142,33*73

$GPGSV,3,2,11,08,62,317,34,11,46,124,41,13,18,192, 26,17,13,220,00*77

$GPGSV,3,3,11,19,48,051,41,26,19,315,30,28,34,283, 00,,,,*40

$GPRMC,032532,A,3016.3377,N,08811.8667,W,000.0,000 .0,250312,,,A*6D

$GPGGA,032533,3016.3376,N,08811.8669,W,1,03,02.4,0 0237.5,M,-033.9,M,,*74

$GPGSA,A,2,08,11,19,,,,,,,,,,02.6,02.4,00.9*08

$GPGSV,3,1,11,01,28,140,00,03,13,050,27,06,02,047, 00,07,76,142,33*72

$GPGSV,3,2,11,08,62,317,34,11,46,124,41,13,18,192, 00,17,13,220,26*77

$GPGSV,3,3,11,19,48,051,41,26,19,315,29,28,34,283, 00,,,,*48

$GPRMC,032533,A,3016.3376,N,08811.8669,W,000.0,000 .0,250312,,,A*63

$GPGGA,032534,3016.3375,N,08811.8671,W,1,03,02.4,0 0237.5,M,-033.9,M,,*79

$GPGSA,A,2,08,11,19,,,,,,,,,,02.6,02.4,00.9*08

$GPGSV,3,1,11,01,28,140,00,03,13,050,00,06,02,047, 00,07,76,142,34*70

$GPGSV,3,2,11,08,62,317,33,11,46,124,41,13,18,192, 00,17,13,2

R Pankau
03-25-2012, 03:27 AM
out of sheer laziness I used a prebuilt gps parser. this would not be rocket science to get what I need from this. maybe I should just roll my own.

kuroneko
03-25-2012, 03:32 AM
Thanks.


... if I load the gps object in the same project even without calling it the demo crashes with no apparent cause ...
I assume you at least started it?

R Pankau
03-25-2012, 03:35 AM
correct, started, not called.

R Pankau
03-25-2012, 03:51 AM
One thing I have not done is see how big the buffer in my gps object gets.

R Pankau
03-25-2012, 04:07 AM
90975

here is the sd card test. it fails with either gps parser.

kuroneko
03-25-2012, 04:46 AM
here is the sd card test. it fails with either gps parser.
That's serious! Can you try the attached parser object? All it does is place the incoming string in a buffer without actually parsing it. I also adjusted its stack (was too short).

Also, the object uses a cut down version of FDS but sets the transmit pin to 0 which I believe is used by the SD card interface. So if you could move that out of the way and see if it resolves the issue (serXmit). That said, the other parser object (Lite) doesn't have the pin conflict so something else is going on here.

Note that the attached object also uses 0 for tx. Just set it to something unused.

Edit: Just in case, there should be a buffer length check (while Rx <> CR and cptr < 80).

R Pankau
03-25-2012, 04:24 PM
I think you are on to something here. I forced the xmit pin to 16 for the gps module, and the sd profiler works then.
The SD-MMC_FATEngine.spin object is a pretty nice SD object, so I may try to redo this now that it works.