Shop OBEX P1 Docs P2 Docs Learn Events
Google Code repository for open-source Spinneret Web Server firmware — Parallax Forums

Google Code repository for open-source Spinneret Web Server firmware

David CarrierDavid Carrier Posts: 294
edited 2013-04-18 13:04 in Accessories
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.
«1

Comments

  • kuismakuisma Posts: 134
    edited 2011-01-07 02:03
    Download last driver version here
    - 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.
  • Roy ElthamRoy Eltham Posts: 2,996
    edited 2011-01-07 09:03
    I added DHCP.spin, s-35390A.spin, and Basic_I2C_Driver.spin (dependency of s-35390A.spin) to the repository.

    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?
  • Timothy D. SwieterTimothy D. Swieter Posts: 1,613
    edited 2011-01-22 01:08
    Hi guys!

    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.
  • kuismakuisma Posts: 134
    edited 2011-01-22 01:15
    Tim, I got this excellent tutorial from David Carrier;
    Mikael,
    Thanks for your work; I have added you as a contributor. If you are familiar with Subversion, then use the information here to check out the repository: http://code.google.com/p/spinneret-w...ource/checkout. If you are using TortoiseSVN, just right click in an explorer window and click "SVN Checkout...", then enter https://spinneret-web-server.googlecode.com/svn/trunk/ as the URL. You don't need a password to check out, but you will need the password from https://code.google.com/hosting/settings to commit. To commit, right click on a file or folder that you have changed and click "SVN Commit...", make sure any new files are checked, and press "OK".
  • Timothy D. SwieterTimothy D. Swieter Posts: 1,613
    edited 2011-01-22 01:21
    Thanks kuisma. I'll read through the links and see if I can get something going. I am guessing I may need to be added as a contributor. I'll PM David.
  • Timothy D. SwieterTimothy D. Swieter Posts: 1,613
    edited 2011-01-24 16:27
    OK - I am able to checkout and commit now. (thank you David)

    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.
  • David CarrierDavid Carrier Posts: 294
    edited 2011-01-24 17:37
    Timothy,
    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.
  • Timothy D. SwieterTimothy D. Swieter Posts: 1,613
    edited 2011-01-24 17:39
    Thanks David - I overlooked the message field. Everything else for checking out and committing seems to be working.
  • Timothy D. SwieterTimothy D. Swieter Posts: 1,613
    edited 2011-01-24 17:50
    Team -

    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?
  • kuismakuisma Posts: 134
    edited 2011-02-10 08:49
    Tim,

    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.
  • Timothy D. SwieterTimothy D. Swieter Posts: 1,613
    edited 2011-02-11 18:35
    Kuisma -

    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?
  • kuismakuisma Posts: 134
    edited 2011-02-11 22:57
    Tim,

    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.
  • kuismakuisma Posts: 134
    edited 2011-02-12 00:09
    New versions of the drivers uploaded.
    * Made the drive singelton by moving VAR variables to a DAT secion, making multiple object multiple cog usage possible.
    * Bugfix: txUDP failed silently if W5100 socket in ARP state. Will now wait for ARP to finnish.
    * txUDP now verifies that the socket is in UDP mode, otherwise returns false. /kuisma

    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.
  • Timothy D. SwieterTimothy D. Swieter Posts: 1,613
    edited 2011-02-12 16:35
    Kuisma -

    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.
  • kuismakuisma Posts: 134
    edited 2011-02-12 23:38
    Tim,

    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).
    OBJ
      net  : "W5100_Indirect_Driver.spin"
    
      [...]
    
        net.mutexLock
        rv := net.txUDP(SOCKET_UDP, @syslog_packet)
        net.mutexRelease
    

    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;

    OBJ
      net  : "W5100_Indirect_Driver.spin"
    
      [...]
    
      repeat
        repeat
          net.mutexLock
          i := net.rxUDP(SOCKET_UDP, @buffer)
          net.mutexRelease
          ifnot i
            PauseMSec(100)
        until i
    
        sport := buffer.byte[4]<<8 + buffer.byte[5]
        log.syslog(string("Got packet of length %d "), i, true)
        log.syslog(string("from port %d"), sport, false)
    
        case sport
          123:
            sntp.gettransmittimestamp(+1, @buffer, @longhigh, @longlow)
      [...]
    

    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.
  • kuismakuisma Posts: 134
    edited 2011-02-13 02:12
    Drivers in the Google repository now updated with primitives for mutual exclusive lock handling (mutexInit, mutexLock, mutexRelease and mutexReturn).
  • kuismakuisma Posts: 134
    edited 2011-02-13 03:00
    I found a bug in my ARP handling routines in txUDP. It actually assumes you'll *get* an ARP reply sooner or later. If not, e.g. the target host is down, txUDP will never return.

    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.
  • kuismakuisma Posts: 134
    edited 2011-02-14 02:45
    kuisma wrote: »
    I found a bug in my ARP handling routines in txUDP. It actually assumes you'll *get* an ARP reply sooner or later. If not, e.g. the target host is down, txUDP will never return.

    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".
  • jstjohnzjstjohnz Posts: 91
    edited 2011-02-21 20:24
    kuisma wrote: »
    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-
  • jstjohnzjstjohnz Posts: 91
    edited 2011-02-21 21:36
    Would it make more sense to have the same method names in both the spi and indirect drivers?
  • kuismakuisma Posts: 134
    edited 2011-02-21 23:11
    jstjohnz wrote: »
    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.

    Oh dear, how very embarrassing. I have just uploaded a (hopefully) fixed version. Please verify.
    jstjohnz wrote: »
    Would it make more sense to have the same method names in both the spi and indirect drivers?

    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?
  • Stephen MoracoStephen Moraco Posts: 303
    edited 2011-02-22 01:00
    Kuisma,

    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
  • kuismakuisma Posts: 134
    edited 2011-02-22 02:12
    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.

    First, re-read #18 above why there is a good reason doing this.
    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?

    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.
  • jstjohnzjstjohnz Posts: 91
    edited 2011-02-22 14:34
    kuisma wrote: »
    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 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.
  • kuismakuisma Posts: 134
    edited 2011-02-22 22:45
    jstjohnz wrote: »
    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.

    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.
    jstjohnz wrote: »
    I would vote to replace INDIRECT and SPI with WIZ.

    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.
  • jstjohnzjstjohnz Posts: 91
    edited 2011-02-23 17:56
    Might as well just drop the suffix altogether. I like the idea of a new start method that would be universal while keeping the original startXXX methods for compatibility.
  • kuismakuisma Posts: 134
    edited 2011-02-27 23:45
    Do we need higher level network interface methods in the driver? From time to time people seems to be confused about the low level of rxTCP(), and one idea is to implement a more easy-to-use interface. E.g. reading a complete line (guaranteed), reading until (a specified) terminator, reading until timeout etc?

    Or is this best kept in a separate wrapper object?
  • ChrisCantrellChrisCantrell Posts: 25
    edited 2011-07-10 18:15
    I *think* I submitted a bug on the current version of the demo code (rev 2 in SVN). In case it didn't get through: The rxTCP function occasionally reads a zero-byte-length packet when I refresh my browser. There is no pattern, but it happens with continued refreshes. I'm not sure if it is the browser (windows 7, Chrome) or the driver code or my busy home network while the kids play XBOX.

    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
  • Mike GMike G Posts: 2,702
    edited 2011-07-10 18:33
    The rxRCP can very well read 0 bytes if the data has not reached the buffer. It's good to check the status register of socket 0, in your case, to see what's going on. Otherwise, you could lock up waiting for data while the socket is in a close wait state
  • ChrisCantrellChrisCantrell Posts: 25
    edited 2011-07-10 18:48
    I added code to print the status register after every request packet. The result is the same for 0-length and non-0-length packets:

    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.
Sign In or Register to comment.