Google Code repository for open-source Spinneret Web Server firmware
David Carrier
Posts: 294
I have created a Google Code repository for the Spinneret Web Server and uploaded all of Timothy's original files to it. The Google Code account is using Subversion for version control, so it will automatically keep track of all changes and versions. This way, the change log and version number do not need to be inside the file or part of the file name. I have shortened the file names as i uploaded them. You will need to update the "OBJ" blocks in any code to use the shorter file names, but future file versions will keep the same names, so you won't have to change your "OBJ" blocks again.
There is also a wiki at http://code.google.com/p/spinneret-web-server/w/list and an issue tracker at http://code.google.com/p/spinneret-web-server/issues/list. We can use the wiki to formalise standards, such as how to store settings in the EEPROM, and use the issue tracker to report bugs and request features. We will still use this forum to coordinate the standards discuss the bugs, but we will be able to keep track of everything on the wiki and issue tracker.
If anyone would like to be able to use the wiki, use the issue tracker or be able commit, send me a private message, or email me at dcarrier@parallax.com and I'll get you set up. You will need a Google account, and to commit you will need to be able to use Subversion. I highly recommend using TortoiseSVN as a Subversion client; it only takes a few clicks to check out or submit code.
Anyone can download files from the repository using this link: http://code.google.com/p/spinneret-web-server/source/browse/#svn%2Ftrunk.
There is also a wiki at http://code.google.com/p/spinneret-web-server/w/list and an issue tracker at http://code.google.com/p/spinneret-web-server/issues/list. We can use the wiki to formalise standards, such as how to store settings in the EEPROM, and use the issue tracker to report bugs and request features. We will still use this forum to coordinate the standards discuss the bugs, but we will be able to keep track of everything on the wiki and issue tracker.
If anyone would like to be able to use the wiki, use the issue tracker or be able commit, send me a private message, or email me at dcarrier@parallax.com and I'll get you set up. You will need a Google account, and to commit you will need to be able to use Subversion. I highly recommend using TortoiseSVN as a Subversion client; it only takes a few clicks to check out or submit code.
Anyone can download files from the repository using this link: http://code.google.com/p/spinneret-web-server/source/browse/#svn%2Ftrunk.
Comments
- W5100_Indirect_Driver.spin
- W5100_SPI_Driver.spin
Drivers updated to version 0.8 svc revision 3.
- Different patch branches (kuisma & jstjohnz) merged into one, added modifications to both the SPI and Indirect driver.
I changed DHCP.spin to use the new driver name.
Also, should I change s-35390A.spin to have the I2C stuff built in or leave it using Basic_I2C_Driver.spin?
I'm interested in reviewing the latest drivers and possible making some adjustments to them. I've never used SVN before. I can see how I can download the code for review, but I imagine I need a client for checking out and checking back in the code. Can someone write a quick tutorial on how to do this, what software to use, etc?
Thank you.
I got a question, how do I commit with a message in the log? I didn't see an obvious way to do this. Thus in my recent updates (r7) there is no log message. The message should be:
Reviewed both SPI and IND drivers and updated both drivers to ensure that the rxTCP, txTCP, rxUDP, txUDP routines are identical in both drivers. This change rolls up the bug fixes to date. IMPORTANT: Please update both SPI and IND driver with the bug fixes or enhancement to these four routines. I also added further comments to the rxTCP and txTCP section of the code.
I like to use TortoiseSVN to work off of an SVN repository. To download the repository, you right click on a folder, click on "SVN Checkout...", enter "https://spinneret-web-server.googlecode.com/svn/trunk/" into the "URL of repository:" field, and click "OK". This should download a local copy of the repository. When you want to commit a file or folder, right click on it and click on "SVN Commit...". It will bring up a window with a "Message:" field. This is where the "log message" in Google Code comes from. Type in a message describing the changes, make sure all of the files that you want committed are checked, then click on "OK". If it requests a password, log into Google code and get it from https://code.google.com/hosting/settings.
David Carrier
Parallax Inc.
What is the best method to post a "to do" list on the WIZnet W5100 drivers? In Google Code there is an "Issue List", but the to do list also contains new functionality. Should the issue list be used for this too?
What about doing the W5100 driver singelton by declaring W5100cog, W5100flags, rx_mask_S, tx_mask_S and command variables in a DAT section instead as now in a VAR section? Today, it is not possible to include/refer the driver from more then one single object, and this is a major limitation. Today we have no hardware platform with more then one W5100 chip so I can't see any harm in making it singelton.
In a future version maybe the driver also can keep track of resource locking, making life easier for the application level programmer.
I've been puzzling through the idea of having a W5100 COG driver and having it accessed through shared HUBRAM for multiple application level. I've got a thread asking for advice from the community somewhere around here. Once we have a plan on how best to do this, I imagine the W5100 code will split. One version will stay close to what we have now and most certainly your recommendation to move items from VAR to DAT can occur. The new version will probably need these in VAR, but that is yet to be determined.
I'm really wanting to find an effecient and easy way to have multiple apps running through some API to a W5100 COG so that more sockets can be used, etc. Got any good ideas?
I am today using multiple object, multiple cog access to the W5100 and network via my singelton version of the driver with flying colors. I only have use a socket access lock at the application level to keep everything consistent. I can't see any more efficient way of doing this, except maybe for moving the socket lock handling to the driver.
But I don't see how to increase the number of available sockets, since it is limited by the W5100 hardware. The only way around this would be using raw mode implementing your own tcp/ip stack, but this is really not a good approach on the propeller. Still, my way sharing one and the same socket among different objects and cogs, will make the four sockets last longer, but it is only possible to multiplex the sockets this way in the UDP case in client mode. E.g. using the same W5100 socket for both SNTP requests and sending syslog.
I hope nobody minds the change to singelton. I assume there are more of us using the driver from several objects and cogs, than use more than one W5100 chip. But keep in mind you still need to lock the socket resources yourself if using multiple access, this is not handled by the driver (today). This is most simply implemented by a global lock making all calls to the driver mutual exclusive.
I am missing something, hopefully you can fill me in. How are you having a single cog with W5100 running, and other multiple object accessing it? Say you have a web server in one COG and the SNTP server in another cog and the W5100 driver in a third cog. I'm not making the connection between a "singleton" driver as you called it and how this allows for multiple parent objects to use only a single W5100 driver in the system.
I'm eager to learn as it sounds like you have achieved something I've been puzzling and didn't understand how to do. Time for me to learn!!
Thanks for updating the drivers on Google Code.
By removing all instance variables from an object (i.e. removing the VAR sections), using DAT sections to store variables, the variables will be "class variables" instead of "instance variables" in Java speak. You can then include this object (via "OBJ net : W5100_driver.spin") from several different objects, but it will still only be one and the same static object, not instances of it. Both the code and data of this object will be shared (since it is actually the same).
Make sure only one of your own objects starts/initializes it, preferable your main initialization routine. Since it is the same, you must only start it once. After that, all other object may call the methods in the "net" object.
Lets take my syslog client as an example (also singelton, no instance variablers, so I include it in all my objects in need of logging).
This is the main part of the syslog method, and it may be called by several different other methods on different cog's simultaneously. This is very likely, since I got lots of logging in my code. I've included primitives for manually locking access to the W5100 driver via the mutex ("mutual exclusive") calls (not uploaded to the repository yet). This is to ensure only one at a time are executing the driver object, since it is not MT safe by itself today.
This above is an example of multiple access of the W5100 driver, but we can make it even more interesting. I also use SNTP and need to be able to take care of the reply from the time server. For this, I'm using one and the same socket, same W5100 driver, but from still another cog and program;
The "OBJ net : W5100..." here only acts as a reference - it will not make the binary larger, allocate more run time stack or so, since the driver is singelton (contain only class variablers, no instance variables).
This above is my network receiver process, using the same socket as the syslog sender. This implies the same local port used, but since those are all clients, it is perfectly ok. I demultiplex the different usages ("sessions") by looking at the peer's server port as seen in the case statement above. In another part of the code, I send the actual SNTP request, in the same manner (as the syslog sender code).
I think I'll upload the driver with the mutex primitives to the repository as well (done). It's quite convenient to let the driver keep track of the semaphore lock this way.
The way to fix this "by the book", is in txUDP wait and verify that the data is actually transmitted, and not as today simply return to do better things during the time the W5100 does all the dirty work sending the bits down the line. Hence, the wait/verify version would be quite expensive. I would prefer that the next call to txUDP verifies that the previous call was successful, and in the case you really must know the current txUDP status, you can always check it yourself via Sn_SR/Sn_CR manually.
I'll give this some thoughts about how to solve in the best possible way. If you others have some input, please let me know. Till then, you now know that sending UDP to a non-existent target will deadlock txUDP.
No, my code actually works just as intended. If no ARP reply, txUDP will return with "false" after 1.8s, after the next call alto due to the mechanism described above. I.e. the first call will always return true because it returns asynchronously before the actual transmit has taken place, and the "true" return value may be interpreted as "queued for transmission successfully".
Kuisma:
I just tried getting current wiz spi driver from google. It appears as though there is a readIND reference in the spi driver txudp routine that prevents it from compiling.
-jim-
Oh dear, how very embarrassing. I have just uploaded a (hopefully) fixed version. Please verify.
Yes, this is an issue I've been thinking about a long time now.
What about we make readIND and readSPI obsolete, replacing them with a general read function, independent of what hardware interface used?
Of course, we keep the readIND and readSPI interfaces for backward compatibility, but documents them as "obsolete, use the read function when writing new code". Today, the user level applications differs quite a lot depending on what driver (ind vs spi) used, and this is not good at all. Both testing and developing is more prone to errors when you need two different source trees for the different version.
To clarify: By making the interface consistent between the two different drivers, we would only need to change the driver used at application level, and no need for one "UDP_Echo_Demo_SPI" and another "UDP_Echo_Demo_indirect" etc.
Objections?
I now have two spinnerets linked back to back and am finishing the code for this. This is partially client TCP code. As such I found if I'm understanding the code correctly that there is no wait for transmit complete in our drivers. The transmit transaction can end with complete or timed out with either bit indicated in the Sn_IR register. Do we want a method for this in both drivers? Seems the right place to put it. Maybe single call with return of success or timed-out trying...?
What puzzles me is why am I the first to need to check for transmit complete.... what am I missing?
-Stephen
First, re-read #18 above why there is a good reason doing this.
a) It is up to the application level programmer to keep track of the state of the socket. The driver can never make any decisions about what to do when things goes wrong, nor decide what status indicates that things actually is in an undesired state. This it today easy to implement at application level by reading the W5100 registers.
b) It is quite rare to need to know when your hardware emptied its buffers to the closest switch, what parts of your data is acknowledged by the peer and so - all this constituting different interpretations of "transmit complete". This is most often preferable delegated to the driver and hardware. As application level programmers, we most often only cares about the reply we get, or not get, and take appropriate actions according to this.
I really can't think of a downside to this. It would certainly make it easier to test code performance using both interfaces. Perhaps the start method should still have a unique name because of the different syntax. I would vote to replace INDIRECT and SPI with WIZ.
My idea is a general start method with a superset of parameters, calling the back end startINDIRECT or startSPI depending of driver. This way we can change driver used at application level by simply changing the driver, no code change what so ever. If you're using SPI and never IND (or reverse), you just can supply dummy arguments for those not needed, since they will never be used. Or use the old start-method still left for backward compatibility.
You are talking about the name of the method? readWIZ? Isn't it quite redundant, since it is the WizNET object? wiz.read(...) can't be much else than reading from the W5100, I would say.
Or is this best kept in a separate wrapper object?
An early version of the demo code ignored zero-length packets. I had to add that check back to make the demo reliable:
' ETHERNET.rxTCP(0, @data)
repeat
packetSize := ETHERNET.rxTCP(0, @data)
while packetSize == 0
Socket 0 Status Register: $17 - socket established
This is what I expect. I need to load ethereal and see what is actually going out on the wire.