Em 10/4/2011 02:13, Justin Richards escreveu: > I often look at other peoples code and admire what appears to me to be > an elegant solution for various tasks. > > I then try to incorporate some of these ideas. Ideas such as tight or > cohesive functions, avoiding global variables, employing state > machines, structured programing etc. So I try to keep these goals in > mind, that is create efficient code that can be easily maintained by > others. > > However, I do struggle and spend a lot of time deciding what is the > best approach and suspect these are some of the things that separates > a good programmer from the not so good. Take a look at this: It is for PIC16 and doesn't use state machines, but can be converted to the state machine model (co-routines) easily. > I am trying to implement a State Machine for sending UDP packets. What type of state machine do you use? Do you use an explicit 'switch'? Or do you use macros to abstract the state machine? > I started with hastily thrown together example to use as a starting point= .. > > I tidied it up, added additional states, modified to support a > passed-to-function (using ROM char) message to send rather than a hard > coded message and added some debug. (A previous thread relates to > debug). You could use my implementation of 'generic' pointers, to abstract to 'RAM' versus 'ROM' issue: > So now I have a state machine where I need to call the function 5 > times with the same message to be sent to ensure the correct message > is sent. Called at least 5 times in the hope that it transition thru > all states to at least send msg. Organize your main loop to call all your state machines in sequence, and if some state machine doesn't have something to do it returns immediately. > This is not elegant. So I question what is a good way to signal the > UDP state machine that a message needs to be sent. > > Possible solution is to use a global variable that the state machine > examines in the Nothing-to-do-State and then take a snap shot of the > message to send once one appears in the buffer. But this means the > message is no longer passed by ref to ROM but a reference to a global > (RAM) string. Using generic pointers you don't need to worry anymore where the message is= .. > I then must create a lock indicating to other > processing that you can not change the message to send until the > previous one has been sent, but I still need the state machine to > execute periodically to ensure that it is services. I could use a > return value from the UDP process that is true only when there UDP > state machine idle, this seems elegant as it makes it easy to have the > state machine execute periodically but creates an additional overhead. > > So I get bogged down step back and think ... > > What is required > > A mechanism to signal the UDP state machine that something is to be sent Create a small 'proxy' function that all other functions call to send a packet. This 'proxy' function is the only function besides the state machine itself that knows the state machine internals and always do the correct procedure to send a message (setting a flag, reading a lock or mutex, etc.) > A mechanism to signal the caller that it is ok to send The 'proxy' function could return a 'busy' status. > A mechanism to pass the message to send. Pass as a pointer, and if needed copy it to a buffer private to the state machine. > A mechanism to ensure the state machine is called periodically. Call it from the main loop every iteration. If it doesn't have anything to do it just returns and takes very little CPU time. > My best solution is to use a single global string that can provide for > all the above mechanisms. > > But this results in a function the requires the use of a global > variable, lacks cohesion, adds complexity to the caller as the caller > must now copy the text to a global string before calling the function. > > To improve the code, I think to pass the string by reference but this > seems to just add overhead as the same pointer will always be passed. > i.e the location of memory used for all the mechanisms is fixed. > > So my final solution will be to use a single global string for > everything and pass nothing and return nothing and include some macros > to add another level of abstraction to make the code more readable. That's really bad practice... > Is this the way you would do it. > > Any thoughts warmly welcome. > > Cheers justin Best regards, Isaac --=20 http://www.piclist.com PIC/SX FAQ & list archive View/change your membership options at http://mailman.mit.edu/mailman/listinfo/piclist .