20d ago
GH

Chapter 4 Proper Firmware Development

Section I: Theory

  • A robust embedded system relies on thorough hardware and firmware/software design.

  • Effective embedded code development uses state machines (SM).

  • This section provides a brief overview of state machines and their application in EMK310 coding question papers.

  • A state machine implementation of MARV's code would be the next logical step.

4.1 State machines in assembly language

  • A typical code test template will be analyzed to explain state machine application in embedded firmware design.

  • The state machine (SM) implementation in this module uses a "fall-through" strategy.

  • The machine cycles through all states sequentially, executing the enabled state during each cycle.

  • Example:

    • Three states: 1-2-3-2-3

    • First cycle: STATE1, STATE2, STATE3

    • Next cycle: STATE2, STATE3

  • If the sequence were 3-2-1-3-2, the machine would fall through to STATE3 during the first cycle, then to STATE2 during the second cycle, then to STATE1 followed by STATE 3 in the third cycle and finally to STATE 2 in the fourth cycle.

4.1.1 Start-up code
  • Before executable code, several lines are needed for setup, such as the microcontroller type and memory allocations.

  • Lines 1 to 22: Provide test details and standard instructions.

  • Lines 24 to 31: Contain the first part of the start-up code.

  • ";WYCH" stands for "write your code here".

  • Line 31 includes a custom EMK310 include file for algorithmic grading using the Auto Grading Software (AGS).

EMK310 AGS Include file
  • The "emk310ags_p18f45k22.inc" file defines registers and bits necessary for automated grading.

  • Lines marked with an INCn line number are inside the "emk310ags_p18f45k22.inc" file and are not part of the code template that you will receive for tests and exams.

  • The file must be saved in the same folder as your assembler code file.

  • Lines INC1 to INC19 are standard for PIC-AS include files. Consult the MPLAB X help on PIC-AS for information on the LIST and NOLIST directives.

  • Lines INC20 to INC61 define a standard set of general purpose registers that you need to use in your code and that the AGS "knows" the purpose of.

  • These lines use the EQU directive to equate a number to a label. (You can look up the meaning and application of any directive in the MPLAB X help files as shown for EQN in Figure 4.2 below.)

  • Delay1Delay1$$Delay1$$, Delay2Delay2$$Delay2$$, and Delay3Delay3$$Delay3$$ must be used when setting up a delay. During the grading process, the AGS can access them for grading purposes.

  • AGS can manipulate these variables to save time by only grading the duration of your delay once.

  • The register pairs VARnH:VARnLVARnH:VARnL$$VARnH:VARnL$$ will be used to grade calculations that you had to make for implementing the code, e.g. the duration of your delay.

  • Make sure you understand how to represent numbers larger than 255 over two or more registers.

  • The use of the EMK1EMK1$$EMK1$$ to EMK11EMK11$$EMK11$$ registers (lines INC40 to INC50) will be defined in the question paper and also allows grading of specific functions of the code as the register locations where operands and other data may be stored are known if these registers are used.

  • The bits of the AGS_Delay register (line INC51) are used as flags to signal to the AGS when a delay routine starts executing (setting a specific bit to 1) and when its stops executing (clearing the same bit to 0).

  • This strategy allows students to implement a delay in any preferred way as the AGS only counts the number of instruction cycles from the time that a specific flag bit in the AGS_Delay register is set until the time that it is cleared.

  • The AGSStatesL and AGSStatesH registers contain the flag bits that control the state machine of the system. Set and clear these bits to create the transition conditions for your state machine.

  • The AGS_Function register contains two flag bits to allow grading.

    • Bit 7: AGS grades all initialization required up to that point.

    • Bit 6: AGS takes control of the state machine, grading each state independently and then the flow of execution.

  • Mistakes in the initialization state will propagate through to the other states.

  • The AGS grades functionality, not just the code itself. The "correct" line of code must function as required to be awarded a mark.

  • The two registers AGSFlagsL and AGSFlagsH (lines INC55 and INC56) are used to flag specific points in the state machine where the AGS should evaluate the functionality of the code.

  • The register AGSSub in line INC57 is equivalent to the AGSFunction register, but is used to enable and disable subroutines (e.g. a delay subroutine), which are called by the different states rather than being part of the state machine sequence.

  • Lines INC63 to INC125, The compiler will replace the name of a bit, e.g. D1D1$$D1$$ with the value following the EQU directive.

  • If we thus want to set a flag for signalling that the first delay started to execute, the instruction would be BSFAGSDelay,D1BSF AGS_Delay, D1$$BSF AGS_Delay, D1$$.

  • The Funcn bits have been used to control the state machine in earlier assessments, but in the present assessments only bits 6 and 7 are used to request grading of the initialization section of the assessment (bit 7) or to request that the AGS takes control of the state machine (bit 6).

  • The bits that you presently have to use to control the transitions of your test or exam state machines’ flow are the staten bits that are contained in the AGSStatesL and AGSStatesH registers.

  • The include file contains bit definitions for controlling subroutine execution.

  • SREnablenSREnablen$$SREnablen$$ bits are legacy bits used in older assessments.

  • Presently, the sub0sub0$$sub0$$ to sub7sub7$$sub7$$ bits are used for this purpose.

Back to the start-up code in the coding template
  • Configuration bit setup should be placed in this section.

Reset vectors
  • Lines 45 to 48

  • This part of the template may be provided as shown above, or you may be expected to write the code to set up the reset and interrupt vectors.

  • The interaction between the vectors and the lines of code following them will be covered in Code Example 7.

4.1.2 Initialization
  • Lines 49 to 75: Typical code assessment sections, adapted to the question paper's requirements.

  • Code example 2 in Chapter 2 introduced the initialization of subsystems or peripheral devices of the PIC18 where the initialization of Port A was shown for digital output.

  • The test template provides a place to set up the internal oscillator for a specific frequency and also a place to initialize peripheral devices and functions such as the port(s) and interrupts required to solve the test problem.

  • Note the label INIT (line 51) and refer to line 46 where execution branches to the program memory address indicated by INIT.

4.1.3 Activating the AGS
  • Lines 76 to 86

  • Following the initialization state, the state machine of the system must now transition to the next state.

  • The label MAIN in line 79 simply marks the location in the program memory where the main program loop starts.

  • Lines 80 and 81 clear all the state transition bits, which are the bits contained in the AGSStatesL and AGSStatesH registers.

  • The numbers 0 to 7 have also been equated to state0 to state7 and to state8 to state15 in the EMK310 include file, meaning that we can refer to the state transition bits contained in the AGS_State registers as state0 to state15.

  • These lines therefore ensure that the state machine is in its start-up state.

  • Line 82 clears all the subroutine enable bits (which are much the same as the state transition staten bits), which are the bits contained in the AGS_Sub register.

  • The numbers 0 to 7 have been equated to sub0 to sub7 in lines INC116 to INC123 in the EMK310 include file, meaning that we can refer to the subroutine enable bits contained in the AGS_Sub register as sub0 to sub7.

  • The subroutine enable bits are used to queue the subroutines after the states in the fall-through mechanism upon which the state machine operates so that the subroutines may be tested independently from the states in which they are called both by yourself and by the AGS.

  • Lines 83 and 84 clear all the AGS flag bits that are included in the template and are used to flag sections of code for grading.

  • You generally do not have to attend to lines of code in the template that manipulate these bits.

  • Line 85 causes the first transition to occur. However, this transition is not in your system's state machine, but rather in the AGS that runs on top of your code

  • Setting bit Func7 signals to the AGS that the initialization of the µC is complete and that it can access the SFRs and GPRs (up to address 0x2F if relevant), to grade their content.

4.1.3 Testing and debugging individual states using a switch block
  • Lines 87 to 121

  • A standard reminder of the use and functioning of the switch block, which is a state machine controller for testing and debugging purposes, is provided in lines 87 to 99.

  • Line 107 marks the beginning of the switch block.

  • Lines 108 to 115 allows execution of any one of the states or subroutines, irrespective of state transition rules or calls to subroutines, by simply commenting out the line if the state or subroutine should not be executed, or uncommenting the line if the state or subroutine should be executed.

  • An example is line 108 that sets the state transition bit for STATE0 (without considering any conditions that should trigger the state transfer).

  • The default template does not contain states 8 to 15, but if necessary, these will be included in the specific assessment's template.

  • Lines 117 to 120 provide state transition switches for the first four subroutines. More can also be included in a specific assessment's template if necessary.

  • Assume for the moment that sub0 will enable a delay subroutine.

  • The delay subroutine might be called a few times throughout the code, but for debugging (and grading) purposes it is not necessary to step through the entire system's code to test only the delay code.

  • By setting sub0 (i.e. uncommenting line 117) and commenting all other SM transition bits (state0 to state7 and sub1 to sub4), the machine can be manipulated to execute the delay code alone and independently of the rest of the system.

  • The different functions of the system can be contained in separate states which can be developed and tested independently.

  • Adding a function to a state machine is also much easier than adding functionality to a program that has no specific structure: one simply adds the additional functionality in an additional state without having to change anything in the original code except perhaps the state transition rules.

  • It may be prudent to include a switch block in your MARV's code to allow you to test its different states and subroutines independently.

4.1.4 Rendering control of the state machine to the AGS
  • Lines 122 to 129

  • These lines transfer control of the state machine to the AGS, i.e. when the AGS detects the Func6 flag, it sequentially sets the state transition bits (state0 to state2 in this example) to test and grade the various states' (and subroutines') functionality independently.

  • It is also possible to initialize a state with known parameters, e.g. if a specific calculation needs to be performed in your code, the AGS can inject known values into, for example, the EMKn or VARn registers to verify the correct functioning of the code.

  • Lines 122 to 128 are part of every test template and will not affect the functioning of your code as Func6 will never be used anywhere else.

  • When coding your MARV, you obviously do not need to include these lines as there will be no AGS required to control the MARV's code at any point.

  • The MAIN program loop starts directly after the AGS switch line in line 132.

4.1.5 The structure of a state
  • All sequential states have the same structure.

  • The states' names may not be changed and you need to use the default names, i.e. STATE0, STATE1 etc (note the capitalization) in your tests and exams.

  • After the label (STATE0 in line 136) follows a few lines of code that allows the state machine to function and the AGS to know where it is in the code.

  • Line 138 tests the state transition flag for the particular state, in this case state0.

  • If the bit is set, the GOTO STATE1 instruction will be skipped and STATE0 will execute.

  • Line 140 sets a flag to signal to the AGS that STATE0 has been entered.

  • After the AGS code lines, you need to provide the code solution for the state as indicated by the ;WYCH comment in line 143.

  • All the other lines of code will be provided as part of the template.

  • In line 146 the transition from STATE0 needs to be set up.

  • This transition may be to any other state as required by the operation of the SM.

  • Another staten bit typically needs to be set here while the state0 bit needs to be cleared.

  • Remember, only one transition should be enabled at any one time.

  • Line 151 signals to the AGS that execution of STATE0 concluded.

4.1.6 The structure of a subroutine
  • The structure of a subroutine is very similar to that of a common state.

  • The primary difference between a common sequential state and a subroutine is that the subroutine is called from somewhere in the code (from within a state) and that the SM bit for the subroutine needs to be set before it is called.

  • Failing to set sub0 before SUB0 is called, will cause the subroutine to be skipped and will cause the program to fail as it will never reach the RETURN statement that should form part of your code starting in line 194.

  • As before, you need not be concerned with the use of the AGS flag bits.

  • the abort functionality provided in lines 205 and 206 that allows the AGS to abort the Delay once its duration has been tested. This allows for faster grading.

  • setting and clearing the D1 bit in the AGS_Delay register. The number of instruction cycles is counted between setting the bit in line 207 and clearing the bit in line 214. The duration of the delay can be calculated from the TCY count and can thus be graded.

4.1.7 Interrupt service routines
  • It is not necessary to create AGS bits to signal the occurrence of interrupts as interrupts already have built-in flag bits.

  • These are, of course, the interrupt flag bits, e.g. INT0IF for external interrupt INT0.

  • Interrupt service routines follow the subroutines in the template and the template provides a structure for the different interrupt sources that should be serviced.

  • The ISR is executed when an interrupt occurs and the program subsequently branches to the interrupt vector, 0x08.

4.1.8 Tables
  • For coding assessments where tables need to be included, the code will be located after the interrupt service routine section.

4.1.9 The end of the code
  • The end directive may or may not be given in the code template.

4.1.10 A state machine in action
  • Once the different states have been tested individually using the switch block, the state machine has to be set up to operate in the correct sequence.

  • Note that the code below does not follow the default code template exactly, but will form the basis of an SM code example.

  • Lines 133 to 227: These lines constitute the state machine.

  • Line 135 marks the start of the main program loop with the label MAIN_LOOP.

  • The state machine above follows a fall-through approach, i.e. the program cycles sequentially through the states and subroutines and executes the first one for which the transition or enable bit is set.

  • Line 139 labels the first state, STATE0.

  • Assume that the function of STATE0 is to make your MARV drive straight forward.

  • Line 141 tests the status of the STATE0 transition bit, i.e. AGS_StatesL,state0.

  • The instruction BTFSS AGS_StatesL, state0 (bit test file skip if set) checks whether state0 is set and if it is, the next instruction, GOTO STATE1, is skipped so that execution proceeds to the STATE0 code, represented in the template by ;WYCH.

  • In the example, the ;WYCH was replaced by the code in lines 146 to 150.

  • This strategy is repeated at the start of all the states (lines 165 to 167 for STATE1 and lines 185 to 187 for STATE2) and also for the delay subroutine (lines 211 to 213 for DELAY), making the code execution "fall through" to the state or subroutine for which the appropriate transition bit is set.

  • If we assume that after the drive forward state completed, the machine must transition to a reverse state (STATE1 in this example), the ;WYCH in the template should be replaced by $$BCF AGSStatesL,state0 $$ $$BSF AGSStatesL,state1$$

  • The next instruction that will be executed, will be the BTFSS AGS_StatesL,state1 instruction in line 165.

  • Since state1 will be set, STATE1 will be executed.

  • If the machine should have transitioned to STATE2, the transition 0 code should have been $$BCF AGSStatesL,state0 $$ $$BSF AGSStatesL,state2$$

  • In this case the instruction BTFSS AGS_StatesL,state1 instruction in line 165 will cause the next line, GOTO STATE2 in line 166, to be executed as state1 would be 0.

  • Setting and clearing the correct state bits in the transition sections of each state, therefore determines the sequence in which the state machine executes its program.

The delay state
  • At the point where the delay must be called

    • the subroutine enable bit sub3 for DELAY must be set,

    • the subroutine must be called, and

    • the subroutine enable bit sub3 must be cleared when done.

  • Also note the use of the AGS flag AGS_Delay,D1 to mark the start of the delay (BSF in line 215) and the end of the delay (BCF in line 224) so that the AGS can count the number of instruction cycles between setting and clearing the flag.

  • Lines 213 and 214 are used by the AGS to skip execution of the delay to expedite the grading process.

  • The AGS will set the BTFSC AGS_FlagsH,0 flag when grading of a specific part of the code is not dependent on execution of the full delay and this will cause the µC to execute the RETURN instruction in the next line, skipping the rest of the delay subroutine.

Restarting the machine
  • Line 212, GOTO MAIN_LOOP, sends the state machine back to restart the fall-through process from STATE0.

  • This instruction is required in the last state in the sequence (whether it be STATE2 or one of the other states) otherwise the state machine will not be able to reach all the states again once it cycled through one complete sequence.

  • It is important to remember to reset the state transition bits, i.e. set state0 and clear the others to allow the machine to restart the sequence.

4.1.11 More state machine examples
Example 1
  • The state machine implements a MARV that, at the start of STATE0, calls an ADC subroutine (last branch) and then

    • drives straight for a small distance (still in State 0),

    • skips to State 1 to turn left if it is off the track to the right, or

    • skips to State 2 to turn right if it is off the track to the left.

  • In State 0, the ADC subroutine needs to be called by code along the line of BSFAGSSub,sub0BSF AGS_Sub, sub0$$BSF AGS_Sub, sub0$$; To enable the ADC subroutine called SUB0SUB0$$SUB0$$ to be executed, CALLSUB0CALL SUB0$$CALL SUB0$$; Now call the ADC subroutineNext if we assume the output from the ADC subroutine sets flags in, for example EMK11, that indicates straight (bit 0), left (bit 1) or right (bit 2) the distinction among states could be done by
    BTFSCEMK11,0BTFSC EMK11,0$$BTFSC EMK11,0$$ ;Test for straight
    GOTOStraightGOTO Straight$$GOTO Straight$$ BTFSCEMK11,1BTFSC EMK11,1$$BTFSC EMK11,1$$; Test for left
    GOTOLeftGOTO Left$$GOTO Left$$ GOTORightGOTO Right$$GOTO Right$$ ; Assuming that if it is not straight or right, it must be left.

  • The conditions may be implemented as follows (there are other ways too)

  • $$Left: BSF AGSStatesL, state1 $$ $$GOTO ExitState0 $$ $$Right: BSF AGSStatesL, state2 $$ $$GOTO ExitState0Straight:;Somecodetodrivestraight Straight: ; Some code to drive straight $$ Straight: ; Some code to drive straight $$BSF AGS_StatesL, state0$$ ExitState0: ; Any line of relevant code, even a NOP if nothing else This will make the code either fall through to

    • STATE1 to turn left,

    • STATE2 to turn right, or

    • to fall through all the states (without executing them) and return to STATE0 if the MARV was on track.

  • In STATE1 and STATE2, the transition needs to send the machine back to STATE0 to determine an action based on the ADC output, i.e. $$CLRF AGSStatesL $$ $$BSF AGSStatesL,state0$$

  • In the subroutine, there should not be a state transition, but a RETURN from the subroutine.

Example 2
  • The state machine implements a traffic light that cycles through

    • all red (STATE0),

    • to East-West green (STATE1), to

    • all red (STATE0), to

    • North-South green (STATE2), etc.

  • It uses a delay implemented as a subroutine to control the duration of the cycles.

  • In STATE0 a flag bit would be required, e.g. EMK11,0 that is toggled to determine whether the state machine needs to transition to STATE1 (East-West green) or STATE2 (North-South green).

  • BTFSSEMK11,0BTFSS EMK11,0$$BTFSS EMK11,0$$ $$BSF AGSStatesL, state1 ; EastWest $$ $$BSF AGSStatesL, state2 ; NorthSouth$$

  • STATE1 and STATE2 will both transition to STATE0 again in this example, i.e. $$CLRF AGSStatesL $$ $$BSF AGSStatesL,state0$$

  • Wherever the delay subroutine is called, one has to first set the bit that would allow the state machine to enter the subroutine…

  • BSFAGSSub,sub0BSF AGS_Sub, sub0$$BSF AGS_Sub, sub0$$; To enable the Delay subroutine called ; DELAYDELAY$$DELAY$$ to be executed and then call the delay subroutine… CALLDELAYCALL DELAY$$CALL DELAY$$ ; Now call the Delay subroutine And remember, don't create a transition at the end of the subroutine, but put a RETURN from the subroutine to make the code function as a subroutine.

4.2 NIBBLE on state machines

  • This NIBBLE will be performed in your practical teams.

4.2.1 The basics you should gain from this NIBBLE
  • This NIBBLE aims to assist you in developing MARV's code as a state machine.

  • State machines are good for expanding code without having to change sections of code that are functioning and have been tested.

  • The worksheet must be included in the labbook for Practical 2.

Section II: Application

4.3 Coding examples
4.3.1 Code example 13: Delay loop example implemented as a SM
  • This example demonstrates two principles:

    1. the way in which the AGS template functions for grading, and

    2. the way in which code can be developed as a finite state machine to adhere to good programming practices.

  • Lines 1 to 20 are general instructions that provide details about the code.

  • In this case, the assessment details were left in the example, but you could, for example give details about the general flow of the code or any other information that you think might be helpful for someone (or yourself) reading your code later on.

  • Lines 27, 31 to 32, 35 to 37, 43 and 47 to 48 have been added to the template to implement the code for Example 6.

  • Line 27 specifies the processor, lines 35 and 36 specify the header files for the compiler, line 37 specifies the EMK310 include file, lines 31 and 32 specify the configuration bits, and line 43 adds the additional self-defined variable Count.

  • Note that Delay1 and Delay2 (include file) have already been defined (lines INC26 and INC29), i.e. redefining them will cause an error.

  • Line 47 specifies the code sector and line 48 specifies the reset vector.

  • These lines need to be added if they are not given in the template.

  • Lines 64 to 116 contain the "controller" or the "heart" of the State Machine.

  • The first MAIN label in line 67 followed by clearing the AGS registers and setting bit Func7 is really used by the AGS.

  • If you do not have an AGS-type system running on your code (also called a test bench), you can omit lines 71 to 73.

  • Func7 is used in line 73 indicate to the AGS that the initialization for the project is complete (for this example initialization of Port A) and that the setup of the PIC's SFRs and configuration bits can be evaluated.

  • The AGS would grade the content of LATA, ANSELA and TRISA at this point by either a bit-wise comparison, or a register comparison as dictated by the function of each specific special function register.

  • However, if you want to implement your code as a state machine (without a test system on top of the code), lines 94 to 108 are an example of code that provides manual control over the state machine and are thus a necessary, or at least helpful section of code.

  • Each of the bits state0 to state7 and sub0 to sub3 is used to activate (bit = 1) or deactivate (bit = 0) one state in the state machine.

  • By manipulating these bits you can thus bypass the "normal" order of execution of your state machine and test one state at a time.

  • It is this feature of state machines that is exploited by the AGS to ensure that the functionality of your code can be broken down in independent units (the states) and graded as independent units.

  • If one state therefore does not function as it should, it should not affect grading of another state that does function according to specification.

  • Func6 in line 111 is used by the AGS to take control of the state machine, i.e. the AGS checks for the location in the code where Func6 is set before it takes control of the state machine.

  • This allows you to write any number of lines of functional code in, for example, the initialization section.

  • If you prefer to set one bit at a time in an SFR,
    e.g.
    BSFANSELA,0BSF ANSELA,0$$BSF ANSELA,0$$ BSFANSELA,1BSF ANSELA,1$$BSF ANSELA,1$$ BSFANSELA,2BSF ANSELA,2$$BSF ANSELA,2$$ BCFANSELA,3BCF ANSELA,3$$BCF ANSELA,3$$ BSFANSELA,4BSF ANSELA,4$$BSF ANSELA,4$$ BCFANSELA,5BCF ANSELA,5$$BCF ANSELA,5$$ BSFANSELA,6BSF ANSELA,6$$BSF ANSELA,6$$ BSFANSELA,7BSF ANSELA,7$$BSF ANSELA,7$$
    instead of MOVLWb11010111MOVLW b'11010111'$$MOVLW b'11010111'$$ MOVWFANSELAMOVWF ANSELA$$MOVWF ANSELA$$
    you can do so as the AGS grades functionality and not the exact implementation, and grading of the states only starts once the Func6 bit is set.

  • Func6 will be set in test and exam templates unless setting it is specified as part of the test.

  • To grade the different states of code in an assessment, the AGS loops between line 115 (MAIN_LOOP) and the end of the last state.

  • It clears the staten and subn flags when it returns to MAIN_LOOP and sets the flag for the individual state that needs to be graded next.

  • The normal execution of your code will also loop between MAIN_LOOP (which is actually exactly the same as STATE0 in line 119 below) and the last state in your system.

  • When the code is executing in "system mode" i.e. not in debugging mode where you want to evaluate the functionality of each state independently, the code must also return to MAIN_LOOP (or STATE0).

  • The transitions between states will execute as coded in the state transition sections at the end of each state.

  • In debugging mode, it usually does not make sense to make the code loop through the entire sequence of states as one tests one state at a time.

  • For debugging purposes, the correct staten or subn flag will be set in the switch block and the code will be stepped through probably only until the state being tested is done and the code that implements the transition to the next state was verified.

  • Debugging would then be stopped and a different staten or subn flag would be set to test a different state.

  • Lines 117 to 146 show how the main code of the Delay example is implemented as STATE0 of our state machine.

  • Line 121 tests whether the transition flag for STATE0 is set.

  • If it is, the fall-through instruction GOTO DELAY_ON (which is the next state in the code, but not necessarily the next state to be executed) is skipped and STATE0 is executed.

  • The flag that is set in line 123 is a flag that the AGS uses to confirm that the state machine entered STATE0.

  • If you code your own state machine for your MARV, you may omit line 123, but you should use code that tests for a "state enable flag" such as state0 in this example.

  • Lines 117 to 124 will usually be given as part of assessment templates.

  • The code that flashes the LEDs on Port A is shown in lines 126 to 137.

  • The important changes from the code that was presented in Example 6, are

    • setting the enable flag sub0 for the OnDelayLoop (line 129) which is now implemented as a state and calling the delay state by its correct label for this example DELAY_ON.

    • setting the enable flag sub1 for the OffDelayLoop (line 134) which is implemented as yet another state and calling this delay state by its label DELAY_OFF.

    • allowing the state machine to return through the state transition code in lines 140 to 145 instead of using the GOTO Main instruction in line 137.

  • In line 141 the state machine sets state0 again (in case it was cleared somewhere else for some reason), which means that, once it cycled through testing whether it should execute all the other states (the two delay loop states in this example) in the code, it will return to STATE0 and execute it.

  • This is exactly how the code executed before except that there are a few additional instructions overhead for controlling the state machine.

  • Also note that if you did not clear the enable flags for the two delay states that follow STATE0 in the code, these would execute one after the other as the machine cycles through the states.

  • Clearing of the subn flags may be done either in the code above right after the states (subroutines) have been called, or inside the delay states (subroutines) as will be done in this example.

  • Lines 147 to 179 show how a subroutine (function) is implemented in the state machine.

  • The main difference between the implementation of a subroutine and that of a sequential routine is that there is no state transition section (compare lines 139 to 146 with lines 173 to 179) as the subroutine needs to return to the instruction after its initial call (i.e. to the MOVLW 0x00 in line 132).

  • The AGS code in lines 153 to 157 does the following.

    • Line 153 tests the state machine flag that you need to manipulate to control the flow of the state machine. It had to be set (line 129) before the subroutine was called (line 131), otherwise the delay in DELAYON would not execute (the execution would simply continue to DELAYOFF).

    • Line 154 makes the state machine "fall through" to the next state if sub0 was not set.

    • Line 155 tests a flag that we use to cancel the delay when grading the tests. If we graded the functioning and duration of the delay once, it is not necessary to execute the delay every time that it is called in the system. This flag can be manipulated in the AGS to abort execution of the delay (by making the RETURN in line 156 execute) and thus make the code grade faster.

    • The D1 flag bit that is set in line 157 is used to indicate the start of the delay. Clearing it in line 175 signals the end of the delay. If you use the stopwatch to time a delay, you must measure the delay between setting the Dn bit at the start of the delay and clearing it at the end.

  • Lines 160 to 171 are exactly the same as those in Code example 6.

  • Returning from the subroutine requires that the enable flag for the state is disabled (BCF AGS_Sub, sub0 in line 177) and that you include a RETURN instruction (line 178).

  • DELAYOFF functions exactly the same as the OnDelayLoop implemented as DELAYON except that the location to which this state falls through is now the MAIN_LOOP since this is the last state in the sequence.

4.3.2 Code example 14: INT0 example implemented as a


knowt logo

Chapter 4 Proper Firmware Development

Section I: Theory

  • A robust embedded system relies on thorough hardware and firmware/software design.
  • Effective embedded code development uses state machines (SM).
  • This section provides a brief overview of state machines and their application in EMK310 coding question papers.
  • A state machine implementation of MARV's code would be the next logical step.

4.1 State machines in assembly language

  • A typical code test template will be analyzed to explain state machine application in embedded firmware design.
  • The state machine (SM) implementation in this module uses a "fall-through" strategy.
  • The machine cycles through all states sequentially, executing the enabled state during each cycle.
  • Example:
    • Three states: 1-2-3-2-3
    • First cycle: STATE1, STATE2, STATE3
    • Next cycle: STATE2, STATE3
  • If the sequence were 3-2-1-3-2, the machine would fall through to STATE3 during the first cycle, then to STATE2 during the second cycle, then to STATE1 followed by STATE 3 in the third cycle and finally to STATE 2 in the fourth cycle.

4.1.1 Start-up code

  • Before executable code, several lines are needed for setup, such as the microcontroller type and memory allocations.
  • Lines 1 to 22: Provide test details and standard instructions.
  • Lines 24 to 31: Contain the first part of the start-up code.
  • ";WYCH" stands for "write your code here".
  • Line 31 includes a custom EMK310 include file for algorithmic grading using the Auto Grading Software (AGS).

EMK310 AGS Include file

  • The "emk310ags_p18f45k22.inc" file defines registers and bits necessary for automated grading.
  • Lines marked with an INCn line number are inside the "emk310ags_p18f45k22.inc" file and are not part of the code template that you will receive for tests and exams.
  • The file must be saved in the same folder as your assembler code file.
  • Lines INC1 to INC19 are standard for PIC-AS include files. Consult the MPLAB X help on PIC-AS for information on the LIST and NOLIST directives.
  • Lines INC20 to INC61 define a standard set of general purpose registers that you need to use in your code and that the AGS "knows" the purpose of.
  • These lines use the EQU directive to equate a number to a label. (You can look up the meaning and application of any directive in the MPLAB X help files as shown for EQN in Figure 4.2 below.)
  • Delay1Delay1, Delay2Delay2, and Delay3Delay3 must be used when setting up a delay. During the grading process, the AGS can access them for grading purposes.
  • AGS can manipulate these variables to save time by only grading the duration of your delay once.
  • The register pairs VARnH:VARnLVARnH:VARnL will be used to grade calculations that you had to make for implementing the code, e.g. the duration of your delay.
  • Make sure you understand how to represent numbers larger than 255 over two or more registers.
  • The use of the EMK1EMK1 to EMK11EMK11 registers (lines INC40 to INC50) will be defined in the question paper and also allows grading of specific functions of the code as the register locations where operands and other data may be stored are known if these registers are used.
  • The bits of the AGS_Delay register (line INC51) are used as flags to signal to the AGS when a delay routine starts executing (setting a specific bit to 1) and when its stops executing (clearing the same bit to 0).
  • This strategy allows students to implement a delay in any preferred way as the AGS only counts the number of instruction cycles from the time that a specific flag bit in the AGS_Delay register is set until the time that it is cleared.
  • The AGSStatesL and AGSStatesH registers contain the flag bits that control the state machine of the system. Set and clear these bits to create the transition conditions for your state machine.
  • The AGS_Function register contains two flag bits to allow grading.
    • Bit 7: AGS grades all initialization required up to that point.
    • Bit 6: AGS takes control of the state machine, grading each state independently and then the flow of execution.
  • Mistakes in the initialization state will propagate through to the other states.
  • The AGS grades functionality, not just the code itself. The "correct" line of code must function as required to be awarded a mark.
  • The two registers AGSFlagsL and AGSFlagsH (lines INC55 and INC56) are used to flag specific points in the state machine where the AGS should evaluate the functionality of the code.
  • The register AGSSub in line INC57 is equivalent to the AGSFunction register, but is used to enable and disable subroutines (e.g. a delay subroutine), which are called by the different states rather than being part of the state machine sequence.
  • Lines INC63 to INC125, The compiler will replace the name of a bit, e.g. D1D1 with the value following the EQU directive.
  • If we thus want to set a flag for signalling that the first delay started to execute, the instruction would be BSFAGSDelay,D1BSF AGS_Delay, D1.
  • The Funcn bits have been used to control the state machine in earlier assessments, but in the present assessments only bits 6 and 7 are used to request grading of the initialization section of the assessment (bit 7) or to request that the AGS takes control of the state machine (bit 6).
  • The bits that you presently have to use to control the transitions of your test or exam state machines’ flow are the staten bits that are contained in the AGSStatesL and AGSStatesH registers.
  • The include file contains bit definitions for controlling subroutine execution.
  • SREnablenSREnablen bits are legacy bits used in older assessments.
  • Presently, the sub0sub0 to sub7sub7 bits are used for this purpose.

Back to the start-up code in the coding template

  • Configuration bit setup should be placed in this section.

Reset vectors

  • Lines 45 to 48

  • This part of the template may be provided as shown above, or you may be expected to write the code to set up the reset and interrupt vectors.

  • The interaction between the vectors and the lines of code following them will be covered in Code Example 7.

4.1.2 Initialization

  • Lines 49 to 75: Typical code assessment sections, adapted to the question paper's requirements.
  • Code example 2 in Chapter 2 introduced the initialization of subsystems or peripheral devices of the PIC18 where the initialization of Port A was shown for digital output.
  • The test template provides a place to set up the internal oscillator for a specific frequency and also a place to initialize peripheral devices and functions such as the port(s) and interrupts required to solve the test problem.
  • Note the label INIT (line 51) and refer to line 46 where execution branches to the program memory address indicated by INIT.

4.1.3 Activating the AGS

  • Lines 76 to 86
  • Following the initialization state, the state machine of the system must now transition to the next state.
  • The label MAIN in line 79 simply marks the location in the program memory where the main program loop starts.
  • Lines 80 and 81 clear all the state transition bits, which are the bits contained in the AGSStatesL and AGSStatesH registers.
  • The numbers 0 to 7 have also been equated to state0 to state7 and to state8 to state15 in the EMK310 include file, meaning that we can refer to the state transition bits contained in the AGS_State registers as state0 to state15.
  • These lines therefore ensure that the state machine is in its start-up state.
  • Line 82 clears all the subroutine enable bits (which are much the same as the state transition staten bits), which are the bits contained in the AGS_Sub register.
  • The numbers 0 to 7 have been equated to sub0 to sub7 in lines INC116 to INC123 in the EMK310 include file, meaning that we can refer to the subroutine enable bits contained in the AGS_Sub register as sub0 to sub7.
  • The subroutine enable bits are used to queue the subroutines after the states in the fall-through mechanism upon which the state machine operates so that the subroutines may be tested independently from the states in which they are called both by yourself and by the AGS.
  • Lines 83 and 84 clear all the AGS flag bits that are included in the template and are used to flag sections of code for grading.
  • You generally do not have to attend to lines of code in the template that manipulate these bits.
  • Line 85 causes the first transition to occur. However, this transition is not in your system's state machine, but rather in the AGS that runs on top of your code
  • Setting bit Func7 signals to the AGS that the initialization of the µC is complete and that it can access the SFRs and GPRs (up to address 0x2F if relevant), to grade their content.

4.1.3 Testing and debugging individual states using a switch block

  • Lines 87 to 121
  • A standard reminder of the use and functioning of the switch block, which is a state machine controller for testing and debugging purposes, is provided in lines 87 to 99.
  • Line 107 marks the beginning of the switch block.
  • Lines 108 to 115 allows execution of any one of the states or subroutines, irrespective of state transition rules or calls to subroutines, by simply commenting out the line if the state or subroutine should not be executed, or uncommenting the line if the state or subroutine should be executed.
  • An example is line 108 that sets the state transition bit for STATE0 (without considering any conditions that should trigger the state transfer).
  • The default template does not contain states 8 to 15, but if necessary, these will be included in the specific assessment's template.
  • Lines 117 to 120 provide state transition switches for the first four subroutines. More can also be included in a specific assessment's template if necessary.
  • Assume for the moment that sub0 will enable a delay subroutine.
  • The delay subroutine might be called a few times throughout the code, but for debugging (and grading) purposes it is not necessary to step through the entire system's code to test only the delay code.
  • By setting sub0 (i.e. uncommenting line 117) and commenting all other SM transition bits (state0 to state7 and sub1 to sub4), the machine can be manipulated to execute the delay code alone and independently of the rest of the system.
  • The different functions of the system can be contained in separate states which can be developed and tested independently.
  • Adding a function to a state machine is also much easier than adding functionality to a program that has no specific structure: one simply adds the additional functionality in an additional state without having to change anything in the original code except perhaps the state transition rules.
  • It may be prudent to include a switch block in your MARV's code to allow you to test its different states and subroutines independently.

4.1.4 Rendering control of the state machine to the AGS

  • Lines 122 to 129
  • These lines transfer control of the state machine to the AGS, i.e. when the AGS detects the Func6 flag, it sequentially sets the state transition bits (state0 to state2 in this example) to test and grade the various states' (and subroutines') functionality independently.
  • It is also possible to initialize a state with known parameters, e.g. if a specific calculation needs to be performed in your code, the AGS can inject known values into, for example, the EMKn or VARn registers to verify the correct functioning of the code.
  • Lines 122 to 128 are part of every test template and will not affect the functioning of your code as Func6 will never be used anywhere else.
  • When coding your MARV, you obviously do not need to include these lines as there will be no AGS required to control the MARV's code at any point.
  • The MAIN program loop starts directly after the AGS switch line in line 132.

4.1.5 The structure of a state

  • All sequential states have the same structure.
  • The states' names may not be changed and you need to use the default names, i.e. STATE0, STATE1 etc (note the capitalization) in your tests and exams.
  • After the label (STATE0 in line 136) follows a few lines of code that allows the state machine to function and the AGS to know where it is in the code.
  • Line 138 tests the state transition flag for the particular state, in this case state0.
  • If the bit is set, the GOTO STATE1 instruction will be skipped and STATE0 will execute.
  • Line 140 sets a flag to signal to the AGS that STATE0 has been entered.
  • After the AGS code lines, you need to provide the code solution for the state as indicated by the ;WYCH comment in line 143.
  • All the other lines of code will be provided as part of the template.
  • In line 146 the transition from STATE0 needs to be set up.
  • This transition may be to any other state as required by the operation of the SM.
  • Another staten bit typically needs to be set here while the state0 bit needs to be cleared.
  • Remember, only one transition should be enabled at any one time.
  • Line 151 signals to the AGS that execution of STATE0 concluded.

4.1.6 The structure of a subroutine

  • The structure of a subroutine is very similar to that of a common state.
  • The primary difference between a common sequential state and a subroutine is that the subroutine is called from somewhere in the code (from within a state) and that the SM bit for the subroutine needs to be set before it is called.
  • Failing to set sub0 before SUB0 is called, will cause the subroutine to be skipped and will cause the program to fail as it will never reach the RETURN statement that should form part of your code starting in line 194.
  • As before, you need not be concerned with the use of the AGS flag bits.
  • the abort functionality provided in lines 205 and 206 that allows the AGS to abort the Delay once its duration has been tested. This allows for faster grading.
  • setting and clearing the D1 bit in the AGS_Delay register. The number of instruction cycles is counted between setting the bit in line 207 and clearing the bit in line 214. The duration of the delay can be calculated from the TCY count and can thus be graded.

4.1.7 Interrupt service routines

  • It is not necessary to create AGS bits to signal the occurrence of interrupts as interrupts already have built-in flag bits.
  • These are, of course, the interrupt flag bits, e.g. INT0IF for external interrupt INT0.
  • Interrupt service routines follow the subroutines in the template and the template provides a structure for the different interrupt sources that should be serviced.
  • The ISR is executed when an interrupt occurs and the program subsequently branches to the interrupt vector, 0x08.

4.1.8 Tables

  • For coding assessments where tables need to be included, the code will be located after the interrupt service routine section.

4.1.9 The end of the code

  • The end directive may or may not be given in the code template.

4.1.10 A state machine in action

  • Once the different states have been tested individually using the switch block, the state machine has to be set up to operate in the correct sequence.
  • Note that the code below does not follow the default code template exactly, but will form the basis of an SM code example.
  • Lines 133 to 227: These lines constitute the state machine.
  • Line 135 marks the start of the main program loop with the label MAIN_LOOP.
  • The state machine above follows a fall-through approach, i.e. the program cycles sequentially through the states and subroutines and executes the first one for which the transition or enable bit is set.
  • Line 139 labels the first state, STATE0.
  • Assume that the function of STATE0 is to make your MARV drive straight forward.
  • Line 141 tests the status of the STATE0 transition bit, i.e. AGS_StatesL,state0.
  • The instruction BTFSS AGS_StatesL, state0 (bit test file skip if set) checks whether state0 is set and if it is, the next instruction, GOTO STATE1, is skipped so that execution proceeds to the STATE0 code, represented in the template by ;WYCH.
  • In the example, the ;WYCH was replaced by the code in lines 146 to 150.
  • This strategy is repeated at the start of all the states (lines 165 to 167 for STATE1 and lines 185 to 187 for STATE2) and also for the delay subroutine (lines 211 to 213 for DELAY), making the code execution "fall through" to the state or subroutine for which the appropriate transition bit is set.
  • If we assume that after the drive forward state completed, the machine must transition to a reverse state (STATE1 in this example), the ;WYCH in the template should be replaced by BCFAGSStatesL,state0BCF AGSStatesL,state0 BSFAGSStatesL,state1BSF AGSStatesL,state1
  • The next instruction that will be executed, will be the BTFSS AGS_StatesL,state1 instruction in line 165.
  • Since state1 will be set, STATE1 will be executed.
  • If the machine should have transitioned to STATE2, the transition 0 code should have been BCFAGSStatesL,state0BCF AGSStatesL,state0 BSFAGSStatesL,state2BSF AGSStatesL,state2
  • In this case the instruction BTFSS AGS_StatesL,state1 instruction in line 165 will cause the next line, GOTO STATE2 in line 166, to be executed as state1 would be 0.
  • Setting and clearing the correct state bits in the transition sections of each state, therefore determines the sequence in which the state machine executes its program.

The delay state

  • At the point where the delay must be called
    • the subroutine enable bit sub3 for DELAY must be set,
    • the subroutine must be called, and
    • the subroutine enable bit sub3 must be cleared when done.
  • Also note the use of the AGS flag AGS_Delay,D1 to mark the start of the delay (BSF in line 215) and the end of the delay (BCF in line 224) so that the AGS can count the number of instruction cycles between setting and clearing the flag.
  • Lines 213 and 214 are used by the AGS to skip execution of the delay to expedite the grading process.
  • The AGS will set the BTFSC AGS_FlagsH,0 flag when grading of a specific part of the code is not dependent on execution of the full delay and this will cause the µC to execute the RETURN instruction in the next line, skipping the rest of the delay subroutine.

Restarting the machine

  • Line 212, GOTO MAIN_LOOP, sends the state machine back to restart the fall-through process from STATE0.
  • This instruction is required in the last state in the sequence (whether it be STATE2 or one of the other states) otherwise the state machine will not be able to reach all the states again once it cycled through one complete sequence.
  • It is important to remember to reset the state transition bits, i.e. set state0 and clear the others to allow the machine to restart the sequence.

4.1.11 More state machine examples

Example 1
  • The state machine implements a MARV that, at the start of STATE0, calls an ADC subroutine (last branch) and then
    • drives straight for a small distance (still in State 0),
    • skips to State 1 to turn left if it is off the track to the right, or
    • skips to State 2 to turn right if it is off the track to the left.
  • In State 0, the ADC subroutine needs to be called by code along the line of BSFAGSSub,sub0BSF AGS_Sub, sub0; To enable the ADC subroutine called SUB0SUB0 to be executed, CALLSUB0CALL SUB0; Now call the ADC subroutineNext if we assume the output from the ADC subroutine sets flags in, for example EMK11, that indicates straight (bit 0), left (bit 1) or right (bit 2) the distinction among states could be done by
    BTFSCEMK11,0BTFSC EMK11,0 ;Test for straight
    GOTOStraightGOTO Straight BTFSCEMK11,1BTFSC EMK11,1; Test for left
    GOTOLeftGOTO Left GOTORightGOTO Right ; Assuming that if it is not straight or right, it must be left.
  • The conditions may be implemented as follows (there are other ways too)
  • Left:BSFAGSStatesL,state1Left: BSF AGSStatesL, state1 GOTOExitState0GOTO ExitState0 Right:BSFAGSStatesL,state2Right: BSF AGSStatesL, state2 GOTOExitState0GOTO ExitState0 Straight: ; Some code to drive straight BSFAGSStatesL,state0BSF AGS_StatesL, state0 ExitState0: ; Any line of relevant code, even a NOP if nothing else This will make the code either fall through to
    • STATE1 to turn left,
    • STATE2 to turn right, or
    • to fall through all the states (without executing them) and return to STATE0 if the MARV was on track.
  • In STATE1 and STATE2, the transition needs to send the machine back to STATE0 to determine an action based on the ADC output, i.e. CLRFAGSStatesLCLRF AGSStatesL BSFAGSStatesL,state0BSF AGSStatesL,state0
  • In the subroutine, there should not be a state transition, but a RETURN from the subroutine.
Example 2
  • The state machine implements a traffic light that cycles through
    • all red (STATE0),
    • to East-West green (STATE1), to
    • all red (STATE0), to
    • North-South green (STATE2), etc.
  • It uses a delay implemented as a subroutine to control the duration of the cycles.
  • In STATE0 a flag bit would be required, e.g. EMK11,0 that is toggled to determine whether the state machine needs to transition to STATE1 (East-West green) or STATE2 (North-South green).
  • BTFSSEMK11,0BTFSS EMK11,0 BSFAGSStatesL,state1;EastWestBSF AGSStatesL, state1 ; EastWest BSFAGSStatesL,state2;NorthSouthBSF AGSStatesL, state2 ; NorthSouth
  • STATE1 and STATE2 will both transition to STATE0 again in this example, i.e. CLRFAGSStatesLCLRF AGSStatesL BSFAGSStatesL,state0BSF AGSStatesL,state0
  • Wherever the delay subroutine is called, one has to first set the bit that would allow the state machine to enter the subroutine…
  • BSFAGSSub,sub0BSF AGS_Sub, sub0; To enable the Delay subroutine called ; DELAYDELAY to be executed and then call the delay subroutine… CALLDELAYCALL DELAY ; Now call the Delay subroutine And remember, don't create a transition at the end of the subroutine, but put a RETURN from the subroutine to make the code function as a subroutine.

4.2 NIBBLE on state machines

  • This NIBBLE will be performed in your practical teams.

4.2.1 The basics you should gain from this NIBBLE

  • This NIBBLE aims to assist you in developing MARV's code as a state machine.
  • State machines are good for expanding code without having to change sections of code that are functioning and have been tested.
  • The worksheet must be included in the labbook for Practical 2.

Section II: Application

4.3 Coding examples

4.3.1 Code example 13: Delay loop example implemented as a SM

  • This example demonstrates two principles:
    1. the way in which the AGS template functions for grading, and
    2. the way in which code can be developed as a finite state machine to adhere to good programming practices.
  • Lines 1 to 20 are general instructions that provide details about the code.
  • In this case, the assessment details were left in the example, but you could, for example give details about the general flow of the code or any other information that you think might be helpful for someone (or yourself) reading your code later on.
  • Lines 27, 31 to 32, 35 to 37, 43 and 47 to 48 have been added to the template to implement the code for Example 6.
  • Line 27 specifies the processor, lines 35 and 36 specify the header files for the compiler, line 37 specifies the EMK310 include file, lines 31 and 32 specify the configuration bits, and line 43 adds the additional self-defined variable Count.
  • Note that Delay1 and Delay2 (include file) have already been defined (lines INC26 and INC29), i.e. redefining them will cause an error.
  • Line 47 specifies the code sector and line 48 specifies the reset vector.
  • These lines need to be added if they are not given in the template.
  • Lines 64 to 116 contain the "controller" or the "heart" of the State Machine.
  • The first MAIN label in line 67 followed by clearing the AGS registers and setting bit Func7 is really used by the AGS.
  • If you do not have an AGS-type system running on your code (also called a test bench), you can omit lines 71 to 73.
  • Func7 is used in line 73 indicate to the AGS that the initialization for the project is complete (for this example initialization of Port A) and that the setup of the PIC's SFRs and configuration bits can be evaluated.
  • The AGS would grade the content of LATA, ANSELA and TRISA at this point by either a bit-wise comparison, or a register comparison as dictated by the function of each specific special function register.
  • However, if you want to implement your code as a state machine (without a test system on top of the code), lines 94 to 108 are an example of code that provides manual control over the state machine and are thus a necessary, or at least helpful section of code.
  • Each of the bits state0 to state7 and sub0 to sub3 is used to activate (bit = 1) or deactivate (bit = 0) one state in the state machine.
  • By manipulating these bits you can thus bypass the "normal" order of execution of your state machine and test one state at a time.
  • It is this feature of state machines that is exploited by the AGS to ensure that the functionality of your code can be broken down in independent units (the states) and graded as independent units.
  • If one state therefore does not function as it should, it should not affect grading of another state that does function according to specification.
  • Func6 in line 111 is used by the AGS to take control of the state machine, i.e. the AGS checks for the location in the code where Func6 is set before it takes control of the state machine.
  • This allows you to write any number of lines of functional code in, for example, the initialization section.
  • If you prefer to set one bit at a time in an SFR,
    e.g.
    BSFANSELA,0BSF ANSELA,0 BSFANSELA,1BSF ANSELA,1 BSFANSELA,2BSF ANSELA,2 BCFANSELA,3BCF ANSELA,3 BSFANSELA,4BSF ANSELA,4 BCFANSELA,5BCF ANSELA,5 BSFANSELA,6BSF ANSELA,6 BSFANSELA,7BSF ANSELA,7
    instead of MOVLWb11010111MOVLW b'11010111' MOVWFANSELAMOVWF ANSELA
    you can do so as the AGS grades functionality and not the exact implementation, and grading of the states only starts once the Func6 bit is set.
  • Func6 will be set in test and exam templates unless setting it is specified as part of the test.
  • To grade the different states of code in an assessment, the AGS loops between line 115 (MAIN_LOOP) and the end of the last state.
  • It clears the staten and subn flags when it returns to MAIN_LOOP and sets the flag for the individual state that needs to be graded next.
  • The normal execution of your code will also loop between MAIN_LOOP (which is actually exactly the same as STATE0 in line 119 below) and the last state in your system.
  • When the code is executing in "system mode" i.e. not in debugging mode where you want to evaluate the functionality of each state independently, the code must also return to MAIN_LOOP (or STATE0).
  • The transitions between states will execute as coded in the state transition sections at the end of each state.
  • In debugging mode, it usually does not make sense to make the code loop through the entire sequence of states as one tests one state at a time.
  • For debugging purposes, the correct staten or subn flag will be set in the switch block and the code will be stepped through probably only until the state being tested is done and the code that implements the transition to the next state was verified.
  • Debugging would then be stopped and a different staten or subn flag would be set to test a different state.
  • Lines 117 to 146 show how the main code of the Delay example is implemented as STATE0 of our state machine.
  • Line 121 tests whether the transition flag for STATE0 is set.
  • If it is, the fall-through instruction GOTO DELAY_ON (which is the next state in the code, but not necessarily the next state to be executed) is skipped and STATE0 is executed.
  • The flag that is set in line 123 is a flag that the AGS uses to confirm that the state machine entered STATE0.
  • If you code your own state machine for your MARV, you may omit line 123, but you should use code that tests for a "state enable flag" such as state0 in this example.
  • Lines 117 to 124 will usually be given as part of assessment templates.
  • The code that flashes the LEDs on Port A is shown in lines 126 to 137.
  • The important changes from the code that was presented in Example 6, are
    • setting the enable flag sub0 for the OnDelayLoop (line 129) which is now implemented as a state and calling the delay state by its correct label for this example DELAY_ON.
    • setting the enable flag sub1 for the OffDelayLoop (line 134) which is implemented as yet another state and calling this delay state by its label DELAY_OFF.
    • allowing the state machine to return through the state transition code in lines 140 to 145 instead of using the GOTO Main instruction in line 137.
  • In line 141 the state machine sets state0 again (in case it was cleared somewhere else for some reason), which means that, once it cycled through testing whether it should execute all the other states (the two delay loop states in this example) in the code, it will return to STATE0 and execute it.
  • This is exactly how the code executed before except that there are a few additional instructions overhead for controlling the state machine.
  • Also note that if you did not clear the enable flags for the two delay states that follow STATE0 in the code, these would execute one after the other as the machine cycles through the states.
  • Clearing of the subn flags may be done either in the code above right after the states (subroutines) have been called, or inside the delay states (subroutines) as will be done in this example.
  • Lines 147 to 179 show how a subroutine (function) is implemented in the state machine.
  • The main difference between the implementation of a subroutine and that of a sequential routine is that there is no state transition section (compare lines 139 to 146 with lines 173 to 179) as the subroutine needs to return to the instruction after its initial call (i.e. to the MOVLW 0x00 in line 132).
  • The AGS code in lines 153 to 157 does the following.
    • Line 153 tests the state machine flag that you need to manipulate to control the flow of the state machine. It had to be set (line 129) before the subroutine was called (line 131), otherwise the delay in DELAYON would not execute (the execution would simply continue to DELAYOFF).
    • Line 154 makes the state machine "fall through" to the next state if sub0 was not set.
    • Line 155 tests a flag that we use to cancel the delay when grading the tests. If we graded the functioning and duration of the delay once, it is not necessary to execute the delay every time that it is called in the system. This flag can be manipulated in the AGS to abort execution of the delay (by making the RETURN in line 156 execute) and thus make the code grade faster.
    • The D1 flag bit that is set in line 157 is used to indicate the start of the delay. Clearing it in line 175 signals the end of the delay. If you use the stopwatch to time a delay, you must measure the delay between setting the Dn bit at the start of the delay and clearing it at the end.
  • Lines 160 to 171 are exactly the same as those in Code example 6.
  • Returning from the subroutine requires that the enable flag for the state is disabled (BCF AGS_Sub, sub0 in line 177) and that you include a RETURN instruction (line 178).
  • DELAYOFF functions exactly the same as the OnDelayLoop implemented as DELAYON except that the location to which this state falls through is now the MAIN_LOOP since this is the last state in the sequence.

4.3.2 Code example 14: INT0 example implemented as a