User Tools

Site Tools


coding_state_machines

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

coding_state_machines [2014/09/18 00:00]
hutch removed
coding_state_machines [2014/11/10 21:13] (current)
hutch created
Line 7: Line 7:
 In the text, the authors implement the ''​tick()''​ function with two switch statements. We will still follow this approach. However, whereas the text implements the ''​tick()''​ method so that the state update happens first, followed by the state action, we will reverse this. Our ''​tick()''​ functions will perform the state-action first, followed by the state-update. The only implementation difference is that we place the switch-statement that performs the state-action first followed by the switch-statement that performs the state-update. In the text, the authors implement the ''​tick()''​ function with two switch statements. We will still follow this approach. However, whereas the text implements the ''​tick()''​ method so that the state update happens first, followed by the state action, we will reverse this. Our ''​tick()''​ functions will perform the state-action first, followed by the state-update. The only implementation difference is that we place the switch-statement that performs the state-action first followed by the switch-statement that performs the state-update.
  
-Why do this? Because it allows you to have an "​init"​ state that can perform initializations. Say, for example, that you only stay in the "​init"​ state for a single tick (this is often the case). With the organization proposed in the text, you will never execute a state-action that is associated with the "​init"​ state because the first that happens in the tick() function is to update the state and then perform the state action. By switching the order that state-update and state-action are performed, the state-action associated with the "​init"​ state will be performed before the state is updated. This may seem confusing for a minute but if you think carefully about it, it should begin to make sense.+Why do this? Because it allows you to have an "​init"​ state that can perform initializations. Say, for example, that you only stay in the "​init"​ state for a single tick (this is often the case). With the organization proposed in the text, you will never execute a state-action that is associated with the "​init"​ state because the first thing that happens in the tick() function is to update the state and then perform the state action. By the time that you reach the switch for the state-action,​ you are no longer in the "​init"​ state. By switching the order that state-update and state-action are performed, the state-action associated with the "​init"​ state will be performed before the state is updated. This may seem confusing for a minute but if you think carefully about it, it should begin to make sense.
  
 ==== File Organization ==== ==== File Organization ====
Line 88: Line 88:
   - The state names used in the ''​enum''​ must be the same names as those used in your state diagrams.   - The state names used in the ''​enum''​ must be the same names as those used in your state diagrams.
   - Each state machine will be placed in its own file.   - Each state machine will be placed in its own file.
-  - Follow the ''​enum''​ approach shown above. Avoid the "​-1"​ nonsense in the text. It is not portable and won't even compile with some compilers. +  - Follow the ''​enum''​ approach shown above. Avoid the "​-1"​ nonsense ​used in the Zyante ​text. It is not portable and won't even compile with some compilers.
- +
-===== Debugging Software State Machines ===== +
-Debugging software-based state machines, especially those that are time based (referred to as synchronous in the text) can be difficult using a conventional debugger because stopping the program interferes with execution and can make it difficult to find the bug. Often it is helpful to have your state machines print out messages as they change state so you can watch state transitions occur in real-time. +
- +
-The snippet of code shown below would be placed in the same file as the clock state-machine shown above. Call this function at the top of the tick function. The function shown below will print out state changes as they occur. What makes this code particularly helpful is that it only prints out a message when currentState changes value. This eliminates a lot of extraneous printing that often hides what you are trying to see. It keeps track of the previous value of currentState by using a static variable. Try using this function, I suspect that you will find it to be quite useful. +
- +
-Place this function before the tick() function to keep the compiler happy. Also make sure to ''​include <​stdio.h>''​. +
-<​code>​ +
-// This is a debug state print routine. It will print the names of the states each +
-// time tick() is called. It only prints states if they are different than the +
-// previous state. +
-void debugStatePrint() { +
-  static clockControl_st_t previousState;​ +
-  static bool firstPass = true; +
-  // Only print the message if: +
-  // 1. This the first pass and the value for previousState is unknown. +
-  // 2. previousState != currentState - this prevents reprinting the same state name over and over. +
-  if (previousState != currentState || firstPass) { +
-    firstPass = false; ​               // previousState will be defined, firstPass is false. +
-    previousState = currentState; ​    // keep track of the last state that you were in. +
-    printf("​msCounter:​%d\n\r",​ msCounter);​ +
-    switch(currentState) {            // This prints messages based upon the state that you were in. +
-      case init_st: +
-        printf("​init_st\n\r"​);​ +
-        break; +
-      case never_touched_st:​ +
-        printf("​never_touched_st\n\r"​);​ +
-        break; +
-      case waiting_for_touch_st:​ +
-        printf("​waiting_for_touch_st\n\r"​);​ +
-        break; +
-      case ad_timer_running_st:​ +
-        printf("​ad_timer_running_st\n\r"​);​ +
-        break; +
-      case auto_timer_running_st:​ +
-        printf("​auto_timer_running_st\n\r"​);​ +
-        break; +
-      case rate_timer_running_st:​ +
-        printf("​rate_timer_running_st\n\r"​);​ +
-        break; +
-      case rate_timer_expired_st:​ +
-        printf("​rate_timer_expired_st\n\r"​);​ +
-        break; +
-     } +
-  } +
-+
-</​code>​+
  
coding_state_machines.txt · Last modified: 2014/11/10 21:13 by hutch