Netduino home hardware projects downloads community

Jump to content


The Netduino forums have been replaced by new forums at community.wildernesslabs.co. This site has been preserved for archival purposes only and the ability to make new accounts or posts has been turned off.

ziggurat29

Member Since 24 Nov 2012
Offline Last Active Mar 07 2014 04:38 PM
-----

#51205 Proper way to multithread on Netduino

Posted by ziggurat29 on 08 July 2013 - 01:15 PM

I'd like to add to hanzibal's suggestion that also, the interrupts are delivered on an internal worker thread that runs at Highest priority.  You don't really want to do much significant work there beyond hanzi's suggestion of queueing it for further processing on other threads (I'm speaking form personal experience on that; it's confusing, then amusing, to see the rest of the system running in slo-mo just because you're doing work in a button event handler rather than handing it off).

 

Lastly, as you've observed, the first 'main' thread seems internally to have some other duties.  It also has some scheduling oddities, e.g. as reported in this thread (no pun intended):

http://forums.netdui...ngs/#entry50924

I think most folks mask that effect because they sleep, but still it's interesting to be aware of it.




#51017 Spark Core (TI CC3000) Porting for Super WiFI Mini?

Posted by ziggurat29 on 02 July 2013 - 01:24 PM

Ziggurat29, You have to let me help you.  I was just gearing up to do a .NET MF port myself.  I have an CC3000EM and I was about to setup an Arduino and ...

 

Sure, why not?

My plans (up to this point) were:

*  prove hardware interface (done)

*  prove SPI communications (done, I believe)

*  first make a managed code 'driver'

*  then make a native code integration with the firmware

So, two 'products' come out, one managed, and one native.  I want to do the managed version first because I believe it will be easier to experiment and debug in that context, and should cement my understanding of the part (the documentation is stunningly poor), and because I think it is a useful end in it's own right.  Once I have a thorough understanding of the device, then for the firmware it's a separate exercise to plan the integration, ostensibly replacing lwip (or maybe they can coexist, but I need to get into netmf's networking code to see what that means, since you'd effectively be making a multihomed system).

 

...  Can you post a zip of what you have so far?  Being able to start with (at least) the basic SPI stuff working would be very helpful.  

 

What I have right now, such as it is, is really exploratory code with no design to speak of, so it would be an embarrassment for me to post it.  If you really need it, I can douche out my more spirited comments and send it to you PM or something, but really I can sum it up this way:

 

Electrical:

using NP2

D13 - sck

D12 - miso

D11 - mosi

D6 - /IRQ

D5 - PWREN

D4 - /CS

3.3v  - pwr *

GND - no 'earth'ly idea

 

*  this will have to change soon as I start doing radio stuff; too much load

 

I am manually managing /CS and monitoring /IRQ for now -- maybe forever.  The SPI transactions often have to be done in two parts, and /IRQ is irksome in that it has mixed duty and doesn't seem useful to use it as an interrupt source, at least not so far, and anyway it gives me the feel of being level-sensitive and that's not supported on the NP2, but I'm not sure.

 

Software:

 

things:

SPI cc3000;   //I spi something that begins with the letter 'cc'    OutputPort cs;    //active low    OutputPort pwren;  //active high    //InterruptPort irq;  //interrupt; active low    InputPort irq;    //YYY I'm going to poll this for now until I understand this device better  

config:

  //make our spi (mode 1)      cc3000 = new SPI(new SPI.Configuration(        Pins.GPIO_NONE,    // SS-pin (we will manually do it)        false,        // SS-pin active state (low)        0,          // The setup time for the SS port YYY 50 uSec        0,          // The hold time for the SS port        false,        // The idle state of the clock (low)        false,        // The sampling clock edge (trailing)        1000,        // The SPI clock rate in KHz        SPI_Devices.SPI1));  // The used SPI bus (refers to a MOSI MISO and SCLK pinset)      //make our (manually controlled) cs (active low)      cs = new OutputPort(Pins.GPIO_PIN_D4, true);      //make our power control (active high)      pwren = new OutputPort(Pins.GPIO_PIN_D5, false);      //make our interrupt input (active low)  //XXX holding off on this until I understand the device better      //irq = new InterruptPort(Pins.GPIO_PIN_D6, false, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeLow);      irq = new InputPort(Pins.GPIO_PIN_D6, false, Port.ResistorMode.Disabled);  

  //power up      pwren.Write(true);  

 

the spi clock speed was chosen semi arbitrarily, to make debugging with the scope easier.  Side note:  specifying 1000 KHz actually gave me a clock of 640 KHz.  I measured.  Maybe a Gates reference joke -- 'who will ever need more than 640K'?  anyway....

 

action:

 

The SPI transactions are mostly normal.  'Mostly', because:

*  the first one only after powerup requires a 50usec pause after the 4th byte before continuing.  seems like a workaround for device bug.  I do this by two sequential WriteRead operations.  netmf is slow enough that you don't have to use any delay code, and you get about 84 us delay.  happily there doesn't appear to be a max delay.

*  the reads involve retrieving a length of the variably sized payload that follows, so you need to do those transactions in two phases also.

 

goofy first write (also this required to be a 'link start' command):

 

  //wait for the signal that its ready      //XXX III support a timeout      while (irq.Read()){}      begin();  //assert cs and (redundantly) wait for irq      //delay(50usec);      //goofy first write has a little pause after the first busy bit before moving on with the rest      cc3000.WriteRead(pktLinkStart, 0, 4, null, 0, 0, 0);      //delay(50usec);        //and then the rest of it      cc3000.WriteRead(pktLinkStart, 4, 6, null, 0, 0, 0);      end();  //negate cs  

reading is a little interesting in that you must retrieve the length, and then complete the reading:

 

  //wait for the signal that its ready      //XXX III support a timeout      while (irq.Read()) { }      begin();  //assert cs and (redundantly) wait for irq      //write header and read the length bytes      cc3000.WriteRead(pktReadHeader, 0, 5, pktReadPayloadLen, 0, 2, 3);      //make length into a number; header is big endian.  other things are little.      int nPayloadLen = ( pktReadPayloadLen[0] << 8 ) | pktReadPayloadLen[1];      if (0 != nPayloadLen)      {        byte[] pktBogoWrite = new byte[1];  //dummy        //read payload        //XXX sanity check on length        byte[] pktReadPayload = new byte[nPayloadLen];        cc3000.WriteRead(pktBogoWrite, 0, 1, pktReadPayload, 0, nPayloadLen, 0);        //XXX III 'spatchy      }      end();  //negate cs  

OK looks like I did wind up posting most of what I did so far, haha!

 

Some things:

 

*  a healthy level of distrust of the documentation is worthwhile.  For instance, they contradict themselves in what is the spi mode to use.  It is spi mode 1.

*  you can tell that different engineering teams worked on this, not necessarily in concert for whatever reason.  For instance, some values are big endian, and others are little endian, so watch for that.

*  the 5 byte header I would probably re-phrase as:

  *  unsigned char byDir;  //1 = write, 3 = read;  from the spi master perspective

  *  unsigned short sWriteLen;  //little-endian;  when op=1, master indicates payload length; otherwise zero

  *  unsigned short wReadLen;  //little-endian;  when op=3, slave indicates payload length; otherwise zero

 

I think this covers most of the SPI; I still need to get a handle on whether there is more /IRQ consideration since the doc claims it serves some double duty, and that there is collision resolution to be performed.

 

Beyond that, I planned to do some reading in the light of my newfound knowledge, before I do much more coding.  There's something called 'patches' which are not really clear to me if I care about, and they use the term 'event' which I think really means 'return value' and 'asynchronous notification'.

 

On the plus side, it looks like the part is what I would describe as:

*  SPI-based RPC mechanism to Berkeley sockets, with some added stuff as needed (e.g. setting mac, wifi keys, etc).

 

So I think it should be straightforward to implement an API even on the managed side that very closely resembles the existing network api, and possibly on the native side to mesh with what exists there as well.  Hope springs eternal!




#50715 SerialPort / Itead Studio Bluetooth Shield V2.2

Posted by ziggurat29 on 22 June 2013 - 01:48 PM

you're not doomed, you can make it work, though it will have to be on COM1 since for some reason they didn't bring out D2/D3, and as you observed only the one D0-7 header (and so don't have a complete COM3).

 

First, I have not used this shield.  But, I have used the underlying BT module, the HC-05, and with it connected to the netduino.  So it is doable.

 

NB datasheet:

ftp://imall.iteadstudio.com/IM120417010_BT_Shield_v2.2/DS_BluetoothHC05.pdf

p2 indicates:  "Default Baud rate: 38400, Data bits:8, Stop bit:1,Parity:No parity"

 

your code shows 9600.

 

However the various ITead docs are inconsistent, so take them with appropriate salt.  For example one says the PIN code is 0000, and another says it is 1234.  They also state that Vih is 4.5v, which you will not get out of a 3.3v board, but I suspect that rating is actual Vimax instead of Vih.

 

You netduino code at first glance looks like an OK 'loopback' test.  But I havent' run it so thats just a desk check.  I can say that I have had problems with SerialDataReceivedEventHandler, but those are sporadic, so let's not worry about that now.

 

You are wise to do a loopback test as a sanity check.  If you like, you can loopback even closer by connecting the TX to the RX of the radio, bypassing the netduino.  You can do that either by removing all the jumpers, and connecting the TX to the RX with a jumper wire; or by temporarily removing all your code in main (thereby leaving the netduino pins in high-impedance) and jumpering at the header.  You should be able to connect to the radio as you have been, and see data sent comes right back.  This will verfify from the radio to your windows phone code, and take com configuration out of the equation.

 

Next I suspect you just have to configure your jumpers correctly.  I love the ascii art but I confess I got confused by the [] and the colors, so let me just say that the way it is shown in your datasheet's 'figure 3', is probably the way you want.  I.e. the TX of the board to D0 (rx of netduino) and the RX of the board to D1 (tx of netduino).  Depending on their sense of RX and TX you might reverse that, but I think that is it.

 

Keep at it, it will (probably!) work.




#50625 Security for remote commands over the network

Posted by ziggurat29 on 18 June 2013 - 08:58 PM

yes.  you have a lot of options, and as always with security, you can make something that looks like it works (e.g. stuff is encrypted, and your commands execute) but is alas, ultimately, is insecure.  Here is a paraphrased version of my work on a recent project regarding similar concerns:

 

all things considered, I would prefer to do it this way:

*  public key in your netduino app

*  private key on your systems that generate the command that needs to be authenticated

*  your command-issuing system signs the command, ideally with a nonce or sequence number to prevent replay attacks

 

this should be secure so long as your command-issuing systems protect their private key correctly (and so long as their aren't bugs in your impl to exploit!), and disregarding DOS attacks (which are a separate class of threat anyway).  end of story.

 

fly in that ointment is that netduino doesn't have any crypto in the firmware, so you have to add crypto in managed code.  OK, not the end of the world, and I personally recommend the BouncyCastle crypto lib -- it's reputable, the license is good, and you can pluck out the modules you want with a few hours effort.

 

fly in that ointment is that the netmf will go TU on large constant data arrays (like s-boxes for symmetric algos), and it's just too much stuff for all the bignum calcs that you need for the asymmetric crypto.  this last part is a pretty big deal because it means you are going to have to use symmetric encryption methods, and that means key management -- yuck.

 

so, what I did was use a HMAC-SHA1 with a random per-device shared-secret key that I put on SD.  This functions as a signature algorithm, but using symmetric methods.  I stock pregenerated SD cards containing profiles, and just get the rest of the hardware as-needed.  When deploying, the key is loaded into my (trusted) backend systems that generate the commands, and the SD is stuck into the unit.  I have online and offline systems; the online systems use timestamps to avoid replay attacks (they are constantly synchronized with the backend), and the offline systems use a sequence number scheme to do similar.  Using the SD card isn't that big of a deal for me since I have plenty of other non-secure config and log storage needs anyway.

 

I really do not like this arrangement at all, but that's as good as it gets without assymmetric crypto.  Also, don't be tempted to use any onboard device info for your shared secret key (like mac, or even chip serial number).  The key must be random (or at least not not derivable solely from device data.  an acid test is:  if the netduino can generate the secret key without some additional data somehow injected onto it, then so can anyone else, and you are insecure).

 

Also, because the shared secret is on the SD, which is removable, this is a significant weakness.  But my units are in a locked enclosure, and I mostly mitigate that with some revocation capability and logging to detect fraud.  But that stuff all depends on the design of the rest of the system, and you may or may not have those luxuries.  But as they say, there is no security without physical security.  If someone can diddle with the wires going to your unit then all the crypto in the world doesn't matter.

 

But to truly be good, you really need assymmetric crypto.  Then almost all of this goes away, and you are just left with securing trust.  But we don't have it right now, alas...

 

-dave

 

p.s. and of course security is a continuum.  if you just want to exclude silliness, but not a motivated adversary, then even non-secure things help.  For instance, I got tired of dictionary attacks on my servers.  Just moving my SSH port off the default took the attack level to narily zero.  Secure approach?  Not at all. Quieted attack rate?  Oh, youbetcha.  So a valuable action nonetheless....




#50172 is it possible to use existing c code with NETMF ?

Posted by ziggurat29 on 01 June 2013 - 02:47 PM

Well, I never could get into the wiki to post my article "Building an Interop Assembly for Netduinio Plus 2", so I'm going to attach it here.

 

There are two files,

1)  BuildingInteropAssemblyForNetduinoPlus2.zip

  contains the article and all the source, projects, etc.

2)  demopeekpokefirmware.dfu

  optional, contains a pre-built firmware image with the sample interop in case you want to play a bit without going through the trouble to build.

 

The sample project is simple, but a bit useful since it lets you read and write to arbitrary memory locations.  Since the hardware is memory mapped, you can play with features not normally accessible; for instance, in the demo, I use the on-chip hardware random number generator, and also read the chip's unique serial number.

 

Anyway, hopefully its useful to someone, and I'll move it to the wiki if that ever gets fixed.

Attached Files




#50167 Weird problem powering up GSM shield

Posted by ziggurat29 on 01 June 2013 - 10:23 AM

my experience is not comprehensive, so I can only speak to the module that I have been using, which is vended by SeeedStudios,

 

The v1.2 of this board had several problems (including power and i2c), but they have greatly improved that in the current v 2.0, and the older ones are out-of-market now.  But some folks knocked-off that design (or they all used the same reference design, I don't know), so I would avoid any ones that looks like it in the picture.

 

I do miss the SMA connector on the older board, though.  Also, these use the older arduino pinout, so you loose the R3 pins.  And still, you'll want to power it from an adapter with some heft to it's current capacity -- the voltage can be lower since the regulators are going to drop that way down anyway.  I use a 7.5v switcher, but 9v work fine and are much more common (7.5 is important for me for a different circuit I have attached to the system).

 

The SIM900 module on which the board is based, quirky though it is, does work -- it's the board designs around the modules which had the problems I experienced.  I have not used a board based on the Spectrum part, but I had looked at it's data sheet a while back, and it seemed to be functionally much the same as the SIM900, so I'd probably select a product based upon board's design more than the module its using.  Plus if you've already coded to the SIM900's AT commands, maybe you don't want to rework that stuff.




#50145 Weird problem powering up GSM shield

Posted by ziggurat29 on 31 May 2013 - 12:41 PM

...I did try USB power without debugger. It still fails. Which confuses me even more  :)

 

I also saw the power requirements (2A) and also said to myself "No way will a netduino supply that power". However I have encountered zero issues running ..

yeah and Im surprised your computer's usb would supply that much power, either.  oh well, there it is!  I suppose it's also possible the schematic is inaccurate -- it shows D9 going through a voltage divider of 0 ohms and 10k ohms.




#49915 Socket Exception 10050 after an hour

Posted by ziggurat29 on 24 May 2013 - 12:06 PM

I have used it long terms without problems if all systems are running correctly.

 

By that bold statement (haha, bold font that is) I mean that I have run a netduino connected to, and communicating with, a server on the Internet, for over a week time, without apparent errors.

 

However, I have personally has this bad experience (which is different from yours, but nonetheless here it is):

*  if my daemon, running on the server on the Internet, is taken down.  E.g. to update the binary, whatever

*  then the netduino will properly detect that it has disconnected

*  my code will loop around in a retry loop to re-establish connection (after a brief sleep)

*  and at the 'connect' call, the thread will hang.  forever.  even if the daemon is brought up later.  so I wind up having to implement a watchdog also, but at least only the one thread is hanged.

 

Things that do work correctly for me are:

*  netduino ethernet cable unplugged, connection lost, retry connection repeatedly, plug back in, recovers connectivity to server

*  take down whole server on Internet, netduino detects lost connection, retries, recovers

 

So from my viewpoint, in my case, it seems that somewhere deep in the firmware the 'connection refused' state (when the port is not listening) is causing woes, but the various other problems related to 'host not reachable' are OK.  Moreover, the problems seems to manifest itself when it has once successfully connected, rather than when it has never successfully connected at all.

 

Anyway, I know my problem is different than yours -- yours is interesting -- but I wanted to let you know what did and did not work for me since thats what you last asked.




#49880 How to deploy without the need of Visual Studio

Posted by ziggurat29 on 23 May 2013 - 11:58 PM

Well I may have to join you in that effort; I need to do the same thing as my project goes beyond the lovingly-hand-deployed-by-the-author pilot phase.

 

I did a little work on an STDFU-based deployment, this work was really for flashing the netduino firmware, but as I mentioned that approach can also deploy the app.  Details here, as well as functioning source:

 

http://forums.netdui...ributors/page-3

 

this is an incomplete project from UI and usability, but the important bits of flashing firmware work correctly.

I also did a mostly unrelated thing -- it had to do with assigning the MAC address to a board as a manufacturing step -- but I mention it because it is a desktop app that uses the same assemblies the MFDeploy does.  It might give you some ideas on the firmware deployment.  Then again, quite possibly not, but you can decide if its of any use:

 

http://forums.netdui...el-and-barcode/

 

Personally, as I mentioned, I find it handy to deploy both the (netduino) firmware version with which QA tested my application, along with my applicationitself, but I can appreciate the MFDeploy approach.  Plus, there's always the network settings which are easier to do via MFDeploy.  Oh, and plus you don't have to hold down the button.  Which may not be so accessible when its in a box.

 

Lastly, another of my long pending mini-projects is to replace tiny booter with a mechanism to permit over-the-air updates.  I did a little work testing dynamically loading netmf assemblies.  The technique works, but it is a bust for me as a methodology because all the code is then in RAM.  If curious, it's described here:

 

http://forums.netdui...pdate-possible/

 

However, I am pretty sure I can make a tinybooter replacement to do it.  Tinybooter is meaningful on other netmf things, but it doesn't do much on netduino.  I built a firmware image with no tinybooter and it ran just fine.  The only thing I know of that the tinyclr does do is allow setting of stuff in the config sector.  And it can, it just doesn't.  So there's 48k of code space available for something fun, like checking SD for an update image, flashing it, and rebooting.

 

Anyway, this is one of my ponderously long posts, and I apologize for that, but as Blaise Pascal once wrote 'I apologize that this is long, but I lacked the time to make it short'.  Ha!




#49865 How to deploy without the need of Visual Studio

Posted by ziggurat29 on 23 May 2013 - 09:33 PM

MFDeploy is supposed to be able to.  I personally have yet to get it to really work, though.  Rather than re-typing, deets here:

 

http://forums.netdui...oading-my-code/

 

On the other hand, all the mfdeploy stuff you can write your own app around, so maybe you get get it to work programatically.  I've been meaning to try, but I am swamped.

 

Lastly, you can make a DFU for your app and do it like a firmware update.  I do do this.  Moreover, I combine the firmware image with my app image into one DFU, and that serves as the master copy.  Side benefit being that I am deploying with a known version of the firmware with which we have tested.  You'd think newer versions would have less bugs but not always!




#49696 N+2 didn't fry with 16V input

Posted by ziggurat29 on 21 May 2013 - 05:14 PM

spec headroom.

the regulator has an absolute maximum of 20v.  you wouldn't want to take it to that max.

http://www.onsemi.co...l/MC33269-D.PDF

 

those linear regulators drop the voltage by dissipating the energy as heat.  so depending on how much current you are drawing (rated max 800ma), you will reach a different max, max power dissipation.

 

9v will keep you safe and have a reasonable bit of load capability for your stuff in addition to the board.  7.5 will do you even better.

 

and as you observed, unregulated transformer are a nominal voltage under load.  under reduced load they go up quite a lot.  I did fry a part (a max1771) a while back because of that -- 12v xfrmer, part max rating 16v, but xfrmer out under low load was 19v.  the max1771 is very unforgiving!  (and costly, but wasn't my design).




#48354 Need for a good GSM/SMS/GPRS Library

Posted by ziggurat29 on 13 April 2013 - 03:51 PM

Curious, what module/shield are you using?

 

I did a SIM900 interface recently, but it was contract work, so I can't post source right now without explicit permission from my client (I did talk to them already about posting non-core-ip source, and they were receptive, but I haven't made actually doing it a priority yet since I'm still pretty busy in pilot).  If you want to forge ahead in advance of the coming of that day, here at least are my experiences with it.  Shortest story:  SIM900 works, but is quite quirky!

 

OK, first, let me say that I was focused on the TCP client feature, and I did not do SMS.  My application supports wired ethernet (on the NP2), and also TCP/IP connectivity over the SIM900 module, (and some other communications channels I won't mention since they are off topic).  Truthfully, I think SMS is easier than TCPIP since it's oriented towards short, atomic, messages, rather than a stream, but much of what follows will still be relevant.

 

The SIM900 has an /embedded/ TCP/IP stack that exposes connection functionality via ancient-style Hayes modem-y AT commands.  You don't get to do tcpip proper, but rather you squirt chunklets of data back and forth via AT commands.  This has some challenges:

  • since you are mixing channel data with control data (e.g. the AT commands themselves, and error responses), you've got to demultiplex that.  There is a 'transparent mode' that works a little like an old-school modem, switching inline between control and data, but you still have to look out for and use the +++ escape to get into and out of command mode.  Blick!  I chose to use 'non-transparent' mode, where the delineation is unambiguous, but you've got more parsing to do.  Also, if you are going to support multiple client connetions, or a single server connection, you will need this mode.  I would suggest coding against non-transparent unless you are really sure you will never need anything else, or if you are supporting a dialup modem as your fallback where this mode would be a natural analog.
  • there is a single-connect and multi-connect mode.  I implemented multi-connect because, why not?  Single connect only gets you limitations as far as I can tell, and it doesn't really simplify coding.  And you have to use multi-connect if you ever want to do 'server'.
  • it's not really documented, but the SIM900 is an idle-request design; i.e., you must wait until you have received some acknowledgement to an issued command before issuing another one.  Don't pour out a sequence of commands then eat the various responses.  Wait for each and every command to complete with a response; and, if you time out getting a positive/negative acknowledgement, you might be best off just throwing and letting some recovery logic get things back into a know state.  Oh!...
  • the responses to all the standard GSM AT commands are minimal, clear, and parseable with a handcoded parser.  The reponses to all the simcom extensions, and certainly to all the TCPIP stuff, are not so much so.  Horror!  However I had an early epiphany in that the Netduino supports regular expressions.  You'll take a 30k or so hit on your app's image size, but parsing will actually become the pleasant part.  I was concerned about RAM usage, and so I did not pre-compile the regexes, and rather did that each time needed.  I was concerned about speed, but this is actually quite quick relative to the 19.2 data rate.
  • there are so many error codes/scenarios that you will be happiest if you define an exception that you can throw for undefined/unknown/unhandled scenarios.  That way the calling module can catch it and at least recycle to recover.  My servicing thread looks like vaguely this:
while ( keepOnKeepinOn ){    try    {         initModemStuff();  //setting all the registers/options/whatnot         doAllModemyStuffs(); //actually pumping data        teardownModemStuff();	//down, you go!     }     catch ( ModemBooBoo e )     {         log ( e );         //Maybe Sleep() a bit before recycling around    }}

?

(^^ sorry, can't make this look right.  looks correct while editing; at least its super short)

 

In this way you can have something functional, yet robust against errors, right away, and then you refine the error handling as a separate task (e.g. maybe you don't need to throw, but can adapt to the condition).

  • the AT interface to TCPIP is so peculiar that I created an abstraction that mostly looks like a socket.  This way I was able to strap on my protocol handler code on top of a real socket, or on top of a connection provided by the SIM900 with minimal effort.  You'll need to implement internal buffers for each channel (the module supports up to 8 client connections, or 7 client + 1 server).
  • you send channel data by telling the modem that you want to do so, and it will present you with a prompt (which they call a 'promoting mark' haha).  Then you emit your data.  Then the modem returns automatically to command mode and you carry on.  This has some caveats:
    • they mention using Ctrl-Z to terminate the data.  There is no escaping mechanism, so if you happen to need to send an 0x26 yourself, you are hosed.  I designed my protocol to be textual (against my better wishes) because of this.  However, I made a booboo.  I failed to notice that the AT+CIPSEND= can take an optional 'length' parameter, in which case you /don't/ send the Ctrl-Z to terminate -- the modem will simply know you are done, and automatically return to command mode.  So now you actually can send binary with impunity!
    • the modem will asynchronously notify you of receive data.  Consequently, you must be prepared to receive it at all times and buffer it for your client's subsequent recv().  You must be prepared to throw away any overrun data.
    • the send channel has a limit on how much you can write at any given time.  This is like an MTU, and maybe it event is derived from the MTU because it is not fixed.  It depends on which network you connected to.  You must be prepared to take client send() calls and chunk the data up into multiple AT+CIPSEND= subject to this limit.  In my case, I keep an array of these per-channel limit values, which I query and setup as part of my connect() process.  That way they are always up-to-date when I need to do a send().
  • because of all these things, I structured my SIM900 interface module somewhat like this:
    • receive data event handler (more on this later)
    • incoming data buffer, used for building textual lines.  This is a fixed 128 bytes which is more than long enough for any text lines that the modem produces (channel data doesn't go through this)
    • an array of received text lines; an event is signaled when new ones are added.  I limit this to 20 max, which really is way more than enough for all the commands the modem supports.
    • an array of channel info, including:
      • an event for 'received'
      • a receive data buffer
      • a 'max send len' value
    • state machine with states of:
      • Normal  -- making text lines, for command mode
      • PromotingMarkWaitGreaterThan -- first waiting state for the signal to send channel data
      • PromotingMarkWaitSpace -- second waiting state for the signal to send channel data
      • PromotingMarkPendingNormal -- we were waiting for a promoting mark, but are receiving an asynchronous text line (like a status change) before the promoting mark came, and so need to switch back to PromotingMarkWaitGreaterThan when it is finished
      • NormalReceive -- receiving channel data; put in channel buffer instead of using to build text lines
    • the receive data event handler notionally drives the state machine, taking the raw data and either building text lines (which will be interpreted as responses or asynchronous notifications), or buffering into the relevant receive channel, or the special case of noticing that the promoting mark has been received.  It signals an event when these things happen, on which the client thread can synchronize to pace it's activities.  For what it's worth, my code has 10 events -- one for each of 8 possible data channels, 1 for 'text line received' and one for 'promoting mark found'.
  • I originally implemented using a dotNet SerialPort.DataReceived event for the COM port.  This works for a little while, then the event stops getting fired.  I don't know what this is, and others have complained about it.  I think it's a bug in the firmware.  I was distraught at the propect of redesigning until I hit upon this idea:
    • worker thread
    • while ! should end
    • if valid com and com is open and 0 != BytesToRead
      • read into buffer, signal 'come and get it' event
    • else sleep for a time guaranteed not to cause an overrun, which in my case for 19.2 and a 256 byte buffer in the firmware was 100ms

This scheme functionally resembles the DataReceived approach, so I was able to shim it in without disrupting the rest of the design.  In fact, since it is a fundamental problem with the com port, and because I use three com ports, I factored this out, and made a virtual method for the 'DataReceived'.  Then it really looked a lot like the dotnet mechanism.

  • The rest of the module consisted of methods that wrapped the AT command dialogs that I was interested in exposing.  They all followed a general form:
    • lock()  //the modem has an idle-request design, and an issued AT command should be fully processed before issuing another
    • generate the AT command text from parameters
    • send the command, collect received text lines subject to various conditions such as count, timeout, and where the response is expected to be found in the sequence
    • inspect the result; perhaps parsing out return data.  As mentioned, I use regex's for the non-trivial ones, but you can certainly hand parse if you can't or don't want to use the regex assembly
  • OK fun stuff, the SIM900 is not consistent across commands as to where things like 'OK' are emitted.  Most commands response by sending info, and then finish with an 'OK'.  So you can pull text lines until you hit 'OK' or an error indicator for most things.  But not all!  Some (particularly the SimCom extensions) return 'OK' and /then/ return the requested data, so you have to just know how many lines that will be on a command-by-command basis.  Because of this, I have a couple helper methods like 'sendATCommandGetResponse' and 'sendATCommandGetNLines' so I can tweak those particulars as needed.

So, once you have all that framework in place, you can just crank out all the AT commands you want with relative ease, since you're now working at a higher level of abstraction (completed text lines and chunks of channel data).  This is also why I said that adding SMS will be easy; it's just another AT command.

 

OK, hardware quirks.  The particulars will depend on the module/shield you are using, but in my case:

  • Power.  There is no pin you can read to know if the modem is on!  WTF?  So, the way I do it is:
    • send empty 'AT' command.  This will alway return 'OK' if it is in command mode and your serial port is set up.  It has a secondary benefit in that this is what you must do to trigger autobaudding.  Note, for autobauding, the AT is case-sensitive.  Anyway, I interpret a failure of this command to mean 'power is off' which is not strictly true but is good enough for my purposes.
  • Power.  To turn on the power, you simulate a button push by pulsing D9.  Haha, yes.  OK, that's how it's done.  Be sure to hold it long enough and wait after releasing it for the modem to 'boot' before sending the intial blank 'AT' command for autobauding (and sanity check that it is indeed on).
  • There is no handshaking.  The SIM900 module has RTC/CTS lines, but on my module they are not brought out.  This normally gives me the heebiejeebies, but since the modem has an idle-request design, and because there are well-defined maximal sized data chunklets involved in the various interactions, you can robustly get away without the handshaking so long as you are punctual about consuming the receive dataas it comes.
  • Some of the early boards out there will suck the living daylights out of your Vcc when powering the radio up, causing a spurious reset, so you really need to power the board from the jack.  Later rev boards are more gentle.

OK, GPRS quirks:

  • you need to get a SIM card.  I used EmbeddedWorks.
  • the GPRS acts a bit like a dialup mode, and uses a thing called an 'Access Point Name', which looks like a DNS name, but don't get too hung up on that.  Its a magic text string that you must provide at certain times to make your board able to get to the Internet.  You do this by 'activating a PDP context', which requires the APN to do so.

Your wireless provider will tell you what it is.  I don't know why they don't just put it on their web site -- its not a security issue because its not actually a DNS name and you have to have a valid SIM card to use it, but there it is.  Save yourself hours of trouble and just ask support immediately what the APN you need is.

  • the SIM900 needs the APN at various times.  Moreover, sometimes it needs the APN indirectly, by referencing an 'index' to some stored APNs, and at other times it needs it explicitly in the AT command.  Sheesh.  Anyway, when it is 'indexed', the index is into some NVRAM, which you only need to set once.  In fact, you want to avoid writing to it too much for wear reasons, so what I do is:
  • query what's there
  • see if it's already set to what I want
  • if so carry on
  • if not set it

that way the board is self-initializing.

  • be prepared for the mobile provider to terminate your PDP context out of the blue.  If you implemented the exception mechanism I described, you will be robust against this automatically, but you can also handle the asynchronous notification from the modem and try to restablish connection more 'surgically' if you want.
  • be aware that the mobile provider will consider hammering out reconnect attempts as abusive, and will make it so you cannot reconnect!  I did this several times while in my code/test/debug process.  You just have to wait a while (hours) and then you can resume.  I put a Sleep in my recovery loop to avoid hammering their system.
  • I do not know why, but I seem to pay for about 4 times as much actual channel data that I send.  I think they charge even for IP headers, but even that seems like way too much.  I need to follow up with my mobile provider about that, but I'm still within my monthly limit so it's not a crisis for me to understand.  I do mention this so you can take it into consideration for planning.
  • little secret:  these devices operate on some different 'part' of the cellular network, and the connection is stony-solid even when festivals are in town, which normally result in a no-talk/no-text zone for consumer's handsets.  Hmm!

So my modem init sequence looks like this:

  • setup COM port
  • send empty AT command to test for power on
  • flick power switch if needed, and retest power on
  • reset modem with ATZ
  • turn off echo mode with ATE0
  • query stored APN, set if needed.  There are two slots (indices) you can store it in, and I arbitrarily store mine in slot 1.
  • query SIM card ICCID.  I do this to detect if there is a SIM installed.  You won't get far without it, but you will get far enough that you will not know you are without it.
  • give the modem a chance to get on the network, which can be slow the very first time; presumably because there is first-time activation stuff going on in the mobile provider's system.
  • activate the PDP context (this will refer to the APN by index) with an AT+CGACT.  This can be very very slow the first time; I use a timeout of 60 sec
  • set the TCP to the 'multiconnect' option with an AT+CIPMUX.  This will imply 'non-transparent'; don't issue a 'set non-transparent' command, because that will now return an error (even though the option value is correct, hmm!).
  • start the 'TCP task' wtih an AT+CSTT.  Here you will need the APN again, but this time not by index; rather it's part of the AT command itself.  Hmm!  Whatever.  I am guessing that this is some sort of separate program running in the SIM900 module that you have to crank up.
  • 'bring up the wireless' for the TCP 'task' with an AT+CIICR.  You just have to do it, and it can take a while; I use a timeout of 30 sec.
  • 'get local IP address' with an AT+CIFSR.  This is more than a gratuitous query, it is required to make you actually have an IP address assigned.  You can throw it away or just log it for fun as I do.

Now you're ready to make connections!  You make a connection by supplying host and port number, and a connection slot number.  As mentioned, the SIM900 will support 8 connections 0-7, but since the first connection is special, I use connection 1-7.  The first is special in that it is the only one that can support server functionality.  So if you make a client connection on 0, you can forget about server.  You establish the connection with AT+CIPSTART.  Internally, if successful, I immediately also issue a AT+CIPSEND? to update the connection max length values.

 

Now you can finally do useful things with your emulated socket Send() and Recv() (and Poll(), isConnected(), etc).

 

My teardown does:

  • shutdown the TCP task
  • detach from network
  • pulse power to turn off (there is an AT command for this as well, but I don't use it)

Oh, one last thing worth mentioning.  Your connected modem will probably NOT be internet reachable.  You get a non-routeable address like 10.x.x.x.  If you need your units to take inbound requests, you will need to either:


a)  work with your mobile provider, who will probably set up a VPN into your device's subnet.  This will be thousands of dollars up front with also some monthly costs.


b)  set up a 'relay agent' that your devices connect out to, which will forward inbound requests (and responses) through that single device connection.


I did 'b' since I've done this many times before to achieve firewall/NAT traversal.

 

Oh, one last last thing:

  • avoid some self-inflicted baldness by investing in one of those FTDI modules.  You can develop all your code on the desktop, which is way way easier (I find) to develop and debug than on the device.
  • you can also use this same module to 'monitor' the communications to the modem using something like putty, etc.  I only found it necessary to monitor the modem data back, so I only needed one, but if you want to monitor both sides, you can use a pair of them.
  • If you do develop on the desktop, remember that not everything there is available on dotNetMF.  I routinely did trial compiles to validate that as I went; especially when developing fancy stuff to avoid coding myself into a porting corner.
  • Also be aware that some of those platform differences will be visible only at runtime.  E.g. the regex impl on dotNetMF actually derives from a Java project, and not all the features are there.  In my case, I had designed my regexs with 'named capture groups', which aren't supported on netmf, so I had some boring porting work to do.  You only find out that at runtime, however, with a rather uninformative error message in the exception thrown.

 

Hope that is of some use!

 

-dave




#47681 Modem does not respond to AT command

Posted by ziggurat29 on 28 March 2013 - 02:19 PM

guessing, but

*  power modem

*  connect port (I use putty but your hyperterminal should be fine so long as you're just opening the com port and not sending any config)

*  send AT

  send it upper case, and press return after.  Most modems will autobaud, and lock onto the AT, but they are often case-sensitive and 'at' wont do.

*  send ATZ

  to reset settings to the default.

beyond that check your connections of course and if possible monitor the lines with a scope




#47598 'over the air' update; possible?

Posted by ziggurat29 on 26 March 2013 - 04:14 PM

OK, I performed some tests.  Here's a brief(?) summary of the tests, the results, etc.  I have attached my test projects, which also has more detailed run captures, on the off chance anyone might want to fiddle with it some more without redoing the test code from scratch.

 

This was run on NP2 firmware 4.2.2.1, and compiled with DevStudio 2010 Ultimate.

Four tests ('static' means 'not dynamicallly loaded'):

1)  baseline static, trivial operation, get final approximate free memory with GC(true)

2)  baseline dynamic, same trivial operation, but in a separate assembly loaded from SD card

3)  nontrivial static, has reference to hefty module, use it minimally

4)  nontrivial dynamic, same thing from SD card.  This has three flavors; more on that later.

 

OK, right as I started out constructing test 2 it becme obvious that I personally was not going to be able to use this technique for my application because this does indeed load the assembly into RAM, and currently my assembly is 58k in release build (with deps it gets to 90k deployed), but my app currently quiesces with about 50k bytes free, so in my case I have a RAM shortage.  So much for me and my application.

Still the technique seems interesting so I pressed on with the tests.  Here is a summary of the final free memory as reported by GC(true), which is fairly approximate as it turns out; more on that later.

 

Test01 -- 105012 Test02 --  87708 Test03 --  99468

Test04 wontwork -- n/a Test04 explicit   --  59172 Test04 implicit   --  82080  

(the doc in the project has more detailed sampling points throughout the execution if you're at all curious)

 

Test 4 has three flavors because it has a reference to another assembly.  There is a 'wontwork' project that, well, wont work, because it does not satisfy that dependency.  It just there to prove the point, and if you want to see how the system behaves in that case.  The other two satisfy that dependency by either having the host (loading) module reference the dependent assembly itself (implicit), or having that modules load the dependency from the SD card (explicit).

 

Some Observations:

*  you need the 'le' version of your built module.  Assembly.Load() will fail if you pick the wrong one.  Not lots of helpful debug messages, though.

*  scary debugger message when doing Assembly.Load()

  "Invalid address 0 and range 40 Ram Start 20000000, Ram end 20020000"

I grepped in the firmware source and found it as part of Debugger.cpp  Interestingly, this same line is commented out in 4.2.1 stuff.  So you may or may not get it depending on your firmware version.

I think it is confined to the debugger and benign in the real world.  To be sure I would have to attach the jtag and analyze the call stack and I was not in the mood for that mishegas so I skipped looking into it further.

*  GC(true) is pretty approximate.  In one run I had memory increasing with each alloc!  I put in a 10 second sleep and the numbers made more sense, so I guess that there some internal framework-allocated resources that get released in a manner outside of your control.  I mention this so that in general folks don't get too caught up in GC(true) numbers or attribute more vercity to them than they are worth.  They're useful but can be misleading if you don't double check sanity.

*  When explicitly loading SystemTextRegularExpression in test 4 'explicit' the app would hang at the Assembly.Load().  However, it would immediately unhang if I set a breakpoint while it was hung!  I don't know if the hang is debugger related (and not happen with no debugger attached).  To find out I one would need to change all the Debug.Prints() to spew to a file or something else and run it without the debugger to see what happens.  But this doesn't inspire confidence in stability.  Note, no hangs of this sort were experienced with the 'implicit' load test.

 

What can you do with it?

 

*  Well, in my case I can't use it as-is just because my project is too big.  But if your particular application isn't strapped for RAM, then this may be a viable approach.

*  Also, maybe with planning you can use it more effectively.  For instance, my project has three different communications mechanisms, but really in practice only one of them will be used depending on the site requirements.  So maybe I could break up my project so that it only loads the one it needs, like an old-school 'overlay'.

*  It could be very useful in certain niche cases, loading some sort of 'personality' from the SD card.  For instance, I have a site specific config file on the SD card, and I have code I wrote to parse it.  But alternatively I could have an assembly that consists of the string values and dynamically load that instead of parsing the config file.  Those values would have wound up in RAM anyway, and I save all the parsing code, so it could be a memory saver in the end.

*  a writeable byte array with an executable assembly in it?  hmm, all sorts of self-modifying code shenanigans come to mind!

 

Hope this is of interest to someone!

 

-dave

 

p.s. Fabien Royer did all the work to figure out how to load the assemblies, as per the link Dave VanderWekke provided above -- I just made these tests.  There's a bunch of other interesting things on that site, so it's worth a visit irrespective of this dynamically loading thing.

 

Attached File  NP2DynLoadTest.zip   36.25KB   17 downloads




#47556 'over the air' update; possible?

Posted by ziggurat29 on 25 March 2013 - 01:21 PM

thanks so much for doing the research!  I'll devise an A/B test on memory impact and report back the results.






home    hardware    projects    downloads    community    where to buy    contact Copyright © 2016 Wilderness Labs Inc.  |  Legal   |   CC BY-SA
This webpage is licensed under a Creative Commons Attribution-ShareAlike License.