PDA

View Full Version : Bytes disappearing into nowhere... [solved]



Patrick1ab
05-31-2010, 07:10 AM
Hi everyone!

I've got a strange little problem over here. While trying to read data from the buffer of my W5100 ethernet chip, I can see that some bytes (which should be there) are missing.
For example:
"icy-metaint: 16384" becomes "icy-metain: 16384"

I should mention, that it's always the same byte of the above example which is missing.
I tried to find the problem by comparing the "rxTCP" function of the driver with the pseudocode description in the W5100 datasheet, but everything looks fine to me. Am I missing something?

This is the code I'm using to read a line of up to 127 characters:




VAR
byte strTemp[*128]
...
PRI readLine | i, rx

i := 0
repeat
if net.rxTCP(0, @rx, 1) == 0 'Copy one byte to "rx"; If the number of received bytes is zero, terminate string and abort
strTemp[*i] := 0
abort -1
elseif rx == 13 'If the character is carriage return, check next byte
next
elseif rx == 10 or i => 127 'Check if the current character is line feed or if the string contains 127 characters
quit
strTemp[*i++] := rx

strTemp[*i] := 0 'Terminate string

return i






In the attachments, I added a copy of the W5100 driver I'm using and the datasheet of this chip.

Post Edited (Patrick1ab) : 5/31/2010 8:04:48 PM GMT

Phil Pilgrim (PhiPi)
05-31-2010, 08:19 AM
Patrick,

Try using my website, www.phipi.com/format (http://www.phipi.com/format), to format your code. You won't have the italics problem.

-Phil

wjsteele
05-31-2010, 09:03 AM
Just a sanity check... are you sure the byte is actually being transmitted?

Bill

pullmoll
05-31-2010, 10:21 AM
Patrick1ab said...
Shouldn't that be:




strTemp[ i] := 0 'Terminate string





Oh, it is. Just another case of forum software eating up indices :)

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Pullmoll's Propeller Projects (http://pmbits.ath.cx/prop/)

bill190
05-31-2010, 10:32 AM
Well I don't know a thing about that chip, but with other things I have worked on, when sending data, there are registers which will indicate a byte has been sent, when that clears, THEN you can insert the next byte into the register for transmission.

If you don't check, you can send things too quickly and overwrite something before it gets sent on its way.

And these things always turn out to be something simple. An array not large enough, maybe halting reading before the last byte is read, etc. Of course finding that "simple thing" can take days of hunting! http://forums.parallax.com/images/smilies/mad.gif

What about ethernet "collisions"? When traffic is busy and data gets lost? I have no idea how that gets handled, but I suppose something would need to retransmit?

Patrick1ab
05-31-2010, 04:57 PM
Hi!

Thanks for the replies everyone.


Phil Pilgrim (PhiPi) said...
Patrick,

Try using my website, www.phipi.com/format (http://www.phipi.com/format), to format your code. You won't have the italics problem.

-Phil


This is great! Thanks.




wjsteele said...

Just a sanity check... are you sure the byte is actually being transmitted?



Yes, it's definitely being transmitted. I checked with my computer and Wireshark:

0180 2e 66 6d 0d 0a 63 6f 6e 74 65 6e 74 2d 74 79 70 .fm..content-typ
0190 65 3a 20 61 75 64 69 6f 2f 6d 70 65 67 0d 0a 69 e: audio/mpeg..i
01a0 63 79 2d 70 75 62 3a 20 31 0d 0a 69 63 79 2d 6d cy-pub: 1..icy-m
01b0 65 74 61 69 6e 74 3a 20 31 36 33 38 34 0d 0a 69 etaint: 16384..i
01c0 63 79 2d 62 72 3a 20 39 36 0d 0a 0d 0a cy-br: 96....




bill190 said...
Well I don't know a thing about that chip, but with other things I have worked on, when sending data, there are registers which will indicate a byte has been sent, when that clears, THEN you can insert the next byte into the register for transmission.

If you don't check, you can send things too quickly and overwrite something before it gets sent on its way.


This chip has a similar mechanism for both sending and receiving data. This is a brief overview of how it works if you want to receive data:

- First you have to check if data has been received, reading the receive size register of a specified socket (in my case socket 0):

readSPI((_S0_RX_RSR0 + (_socket * $0100)), @temp0, 2)


- If this register isn't zero, then you need to read the "Socket 0 RX Read Pointer" and calculate the start address to read data from:



readSPI((_S0_RX_RD0 + (_socket * $0100)), @temp0, 2)
pcktptr.byte := temp0.byte[0]
pcktptr.byte[0] := temp0.byte
pcktoffset := pcktptr & _RX_expmask
pcktstart := (_RX_base + (_socket * $0800)) + pcktoffset



- Afterwards you can read the number of bytes according to the receive size register. Of course there is a special case if the buffer rolls over, but this is all handled by the "rxTCP" function.



bill190 said...
What about ethernet "collisions"? When traffic is busy and data gets lost? I have no idea how that gets handled, but I suppose something would need to retransmit?

The hardwired TCP stack of this chip should take care of this.

MagIO2
05-31-2010, 07:32 PM
Is this code running in the initial SPIN COG or did you start it in another COG? It could be that either the stack is to small or another piece of code is overwriting the stack. I've had a short look into the W5100-driver and it's passing the address to the variable on the stack.

If you don't have a copyright issue, you should always post the whole code and not an extract.

MagIO2
05-31-2010, 07:49 PM
By the way ... why do you read byte by byte? The size you pass to the rxTCP is only limiting the maximum number of bytes copied to the buffer. So, I'd read 128 bytes and then process the buffer. If you replace 13 by 0 you have a valid string in the buffer starting at the strTemp-address.

With the next call you'd skip the linefeed, copy all not processed data to the beginning of the buffer with a bytemove and fill the buffer up to the end by reading the next chunk of bytes via rxTCP.

You can repeat this until rxTCP returns 0 AND all characters in the buffer have been processed.

I don't know what you want to do, but maybe you can alos utilize the ConfigReader I put into the object exchange (Tools) to read the TCP-stream instead of a SD card-file.

Patrick1ab
05-31-2010, 08:25 PM
Hi MagIO2,

thanks for your reply.


MagIO2 said...
Is this code running in the initial SPIN COG or did you start it in another COG? It could be that either the stack is to small or another piece of code is overwriting the stack. I've had a short look into the W5100-driver and it's passing the address to the variable on the stack.


The code is running in the initial SPIN COG.



MagIO2 said...
By the way ... why do you read byte by byte? The size you pass to the rxTCP is only limiting the maximum number of bytes copied to the buffer. So, I'd read 128 bytes and then process the buffer. If you replace 13 by 0 you have a valid string in the buffer starting at the strTemp-address.

With the next call you'd skip the linefeed, copy all not processed data to the beginning of the buffer with a bytemove and fill the buffer up to the end by reading the next chunk of bytes via rxTCP.

You can repeat this until rxTCP returns 0 AND all characters in the buffer have been processed.


Sounds good. I will try to modify the code and see what happens.
However, the error must be somewhere else. I just made some tests and it looks like the bytes are also missing/skipped if I read 32 bytes at once.
I think that I have to check the driver again... Maybe it has something to do with the RX_mask or the start address calculation.


MagIO2 said...
I don't know what you want to do, but maybe you can alos utilize the ConfigReader I put into the object exchange (Tools) to read the TCP-stream instead of a SD card-file.


What I want to do is reading the header of a shoutcast stream. In particular the metaint information, which tells me how many bytes of music data are between the meta data.

Patrick1ab
06-01-2010, 01:54 AM
MagIO2 said...
If you replace 13 by 0 you have a valid string in the buffer starting at the strTemp-address.


Hmm, it turns out that there is one major disadvantage, reading these 128 bytes at once.
Either you have to go through the whole string again afterwards or you have to modify the rx function of the driver to be able to check if there is a value of 13.
This is already included in the current solution.

Ariba
06-01-2010, 03:30 AM
One possible problem:
You overwrite only the lowest byte of the rx variable with net.rxTCP(0, @rx, 1), but check then the whole 32 bit variable against 13, 10 and =>128.
The states of rx bits 8..31 are unknown because rx is never initalized to zero.
I don't know if that fixes your problem, but I would set rx := 0 before the loop.

Andy

Patrick1ab
06-01-2010, 04:02 AM
Great! Thanks Andy, that's it. http://forums.parallax.com/images/smilies/wink.gif

MagIO2
06-01-2010, 04:14 AM
Yep ... that's what I meant ... read 128 bytes and then loop to find the CR.

If you analyze the code you'll see that this will be much faster than the loop reading byte by byte. The copy-job which then copies the not processed bytes to the beginning of the buffer can be done by a bytemove, which is very fast as well.