Adaptation/GUID-80E0DB93-A96A-54A8-A201-E11935418BE7.dita
changeset 15 307f4279f433
equal deleted inserted replaced
14:578be2adaf3e 15:307f4279f433
       
     1 <?xml version="1.0" encoding="utf-8"?>
       
     2 <!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
       
     3 <!-- This component and the accompanying materials are made available under the terms of the License 
       
     4 "Eclipse Public License v1.0" which accompanies this distribution, 
       
     5 and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
       
     6 <!-- Initial Contributors:
       
     7     Nokia Corporation - initial contribution.
       
     8 Contributors: 
       
     9 -->
       
    10 <!DOCTYPE concept
       
    11   PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
       
    12 <concept id="GUID-80E0DB93-A96A-54A8-A201-E11935418BE7" xml:lang="en"><title>State
       
    13 Machines</title><shortdesc>Description of the structure and operation of state machines.</shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
       
    14 <p>The MultiMediaCard Controller uses state machines to manage the interactions
       
    15 with the MultiMediaCard hardware. </p>
       
    16 <p>State machines allows the controller to maintain the state of each submitted
       
    17 session – allowing it to schedule a second session when the first becomes
       
    18 blocked, for example. </p>
       
    19 <p>To handle the complex sequence of bus operations involved, the controller
       
    20 implements a state machine stack, allowing a parent state machine function
       
    21 to invoke a child state machine function. The state machine stack allows nesting
       
    22 of children down to a depth of 10 levels. </p>
       
    23 <p>Each session object has its own individual state machine stack because
       
    24 each session runs its own sequence of bus operations, with the controller
       
    25 managing these multiple sequences. This means that each session object has
       
    26 a state machine object, an instance of the <xref href="GUID-022AC0FE-86EE-3908-A9F8-4A33D04A68A5.dita"><apiname>TMMCStateMachine</apiname></xref> class. </p>
       
    27 <fig id="GUID-3CD3F1EF-FB6A-5D5D-B806-75536F8DF533">
       
    28 <image href="GUID-4592D493-A47C-5622-8C03-F24FABB4381C_d0e19271_href.png" placement="inline"/>
       
    29 </fig>
       
    30 <p>The state machine remembers the next state and child function name, and
       
    31 moves to that state as soon as control returns to the session. </p>
       
    32 <p>The stack chooses the next session to be handled and manages the state
       
    33 machine through the state machine dispatcher. </p>
       
    34 <ul>
       
    35 <li id="GUID-76BEBC23-FC9D-5244-A3EA-2A5424FC02D7"><p> <xref href="GUID-80E0DB93-A96A-54A8-A201-E11935418BE7.dita#GUID-80E0DB93-A96A-54A8-A201-E11935418BE7/GUID-44473E52-82B4-55E7-AE85-15AC88CE5BEB">Structure of the state machine stack</xref> </p> </li>
       
    36 <li id="GUID-0A56A8B9-65D7-54CB-A584-8C3C9AEFE339"><p> <xref href="GUID-80E0DB93-A96A-54A8-A201-E11935418BE7.dita#GUID-80E0DB93-A96A-54A8-A201-E11935418BE7/GUID-E8FCFD65-4664-52EE-B658-FCABF50D501D">Structure of a state machine function</xref> </p> </li>
       
    37 <li id="GUID-85E36E04-60CD-5560-93DE-5C15E8DBDD45"><p> <xref href="GUID-80E0DB93-A96A-54A8-A201-E11935418BE7.dita#GUID-80E0DB93-A96A-54A8-A201-E11935418BE7/GUID-667C5A70-0ABB-525F-A309-58102E380400">Example of a state machine calling sequence</xref> </p> </li>
       
    38 </ul>
       
    39 <section id="GUID-44473E52-82B4-55E7-AE85-15AC88CE5BEB"><title>Structure of
       
    40 the state machine stack</title> <p>The stack itself is represented as an array
       
    41 of <xref href="GUID-DDCE8054-1656-34EF-9CBC-53C796BFD5A6.dita"><apiname>TMMCMachineStackEntry</apiname></xref> objects contained within the state
       
    42 machine object <xref href="GUID-022AC0FE-86EE-3908-A9F8-4A33D04A68A5.dita"><apiname>TMMCStateMachine</apiname></xref>. </p> <p>The state machine
       
    43 maintains a "pointer", <xref href="GUID-022AC0FE-86EE-3908-A9F8-4A33D04A68A5.dita#GUID-022AC0FE-86EE-3908-A9F8-4A33D04A68A5/GUID-5EC9B7D0-A3A9-35DF-A91D-65920372C9A4"><apiname>TMMCStateMachine::iSP</apiname></xref>, to the current
       
    44 state entry. This is not a true pointer, but just a value that indexes into
       
    45 the array. However, for all practical purposes it has the effect of a pointer.
       
    46 Each state entry in the stack is thought of as having a parent-child relationship
       
    47 with the other. </p> <p>Each state entry maintains three pieces of information: </p> <ul>
       
    48 <li id="GUID-81454E68-4603-5211-8F9F-70F0F2F4B95D"><p>A pointer to the state
       
    49 machine function. </p> </li>
       
    50 <li id="GUID-B20834EB-3EAE-5D79-8564-8B2A5490A057"><p>A variable containing
       
    51 the current state; the value and meaning of the state is defined by the state
       
    52 machine function. </p> </li>
       
    53 <li id="GUID-32AFB296-0D5F-5FF7-9ECD-C9F798E04542"><p>A bitmask of <xref href="GUID-FF4AB1CF-7A2C-3FC6-B123-D6819E1BCDCA.dita"><apiname>TMMCErr</apiname></xref> defined
       
    54 error conditions; these are set by the parent state machine function so that
       
    55 it gets the chance to trap those errors if the child state machine function
       
    56 returns those errors. Errors are propagated up the stack, and any error conditions
       
    57 not trapped at any level in the state machine hierarchy leads to the state
       
    58 machine terminating with that error value. </p> </li>
       
    59 </ul> <fig id="GUID-064C53DB-6A96-5C6D-B3CD-B40A0251EF66">
       
    60 <image href="GUID-D8911BE6-100D-588A-8E5C-A429A72AFCDA_d0e19356_href.png" placement="inline"/>
       
    61 </fig> <p>In general, the overall state of the state machine reflects the
       
    62 state of the current state entry; for example, <xref href="GUID-E32D6BC3-F8D9-3F7E-94F6-56633B645D6A.dita#GUID-E32D6BC3-F8D9-3F7E-94F6-56633B645D6A/GUID-48F37107-2D11-3550-890B-D79844A97DBF"><apiname>TMMCStatemachine::State()</apiname></xref> returns
       
    63 the state held in the current state entry. </p> <p>While the flow of control
       
    64 through a stack can be complex, the following diagram shows a short example
       
    65 snapshot. Here, the current state in the current stack entry is <codeph>Sn</codeph> and
       
    66 is handled by the function <codeph>PF()</codeph>. The code decides to pass
       
    67 control to the child function <codeph>CF()</codeph>, but ensures that, on
       
    68 completion, the next state in the current stack entry will be <codeph>Sn+1</codeph>. </p> <fig id="GUID-6ACBC49E-14EE-526B-A1A3-426B64BF8476">
       
    69 <image href="GUID-D2D41326-BA88-5A02-805B-5EAEC29ADB5D_d0e19383_href.png" placement="inline"/>
       
    70 </fig> <p>For example, the <xref href="GUID-B5193656-9819-3E00-A335-EEF1726115A5.dita#GUID-B5193656-9819-3E00-A335-EEF1726115A5/GUID-F71A4421-2F9E-39FD-A352-97ECAAFE822D"><apiname>DMMCStack::CIMUpdateAcqSM()</apiname></xref> function
       
    71 implements the CIM_UPDATE_ACQ macro as defined by the <i>MultiMediaCard System
       
    72 Specification</i>, and is a typical state machine function. </p> <p>Most commands
       
    73 and macros involve one or more asynchronous operations and while such operations
       
    74 are outstanding, a session is blocked. While a session is blocked, its state
       
    75 machine dispatch function is not called. As soon an asynchronous event removes
       
    76 the blocking condition, control returns to the state machine. </p> </section>
       
    77 <section id="GUID-E8FCFD65-4664-52EE-B658-FCABF50D501D"><title>Structure of
       
    78 a state machine function</title> <p>State machine functions are defined and
       
    79 implemented in the <xref href="GUID-B5193656-9819-3E00-A335-EEF1726115A5.dita"><apiname>DMMCStack</apiname></xref> class in pairs: one as a static
       
    80 function, and the other as a member function. The static variant takes a <codeph>TAny*</codeph> pointer
       
    81 that is cast to a <xref href="GUID-B5193656-9819-3E00-A335-EEF1726115A5.dita"><apiname>DMMCStack</apiname></xref> pointer, and the <codeph>DMMCStack</codeph> member
       
    82 function is then called: </p> <codeblock id="GUID-F5EEA20F-2312-5394-84C4-5E568995291A" xml:space="preserve">TMMCErr DMMCStack::FunctionNameSMST( TAny* aPtr )
       
    83     {
       
    84     return( STATIC_CAST(DMMCStack*,aPtr)-&gt;FunctionNameSM() );
       
    85     }
       
    86 </codeblock> <codeblock id="GUID-3C01127E-4EBA-59AC-91F8-1F004A74E45B" xml:space="preserve">TMMCErr DMMCStack::FunctionNameSM()
       
    87     {
       
    88     enum states {EStBegin=0, EStNext,…, EStEnd };    // Enumeration of states for this state machine
       
    89     DMMCSession&amp; s = Session();
       
    90 
       
    91     SMF_BEGIN
       
    92     // State EStBegin
       
    93     // Actions for state EStBegin
       
    94 
       
    95     SMF_STATE( EStNext )
       
    96     // State EStNext
       
    97     // Actions for state EStNext
       
    98 
       
    99     SMF_END
       
   100     }
       
   101 </codeblock> <p>A state machine function can release control and wait to be
       
   102 re-entered by returning zero. If its session is not blocked then that will
       
   103 happen immediately. If the state machine function returns non-zero, the session
       
   104 will be completed with that error code unless the parent state machine function
       
   105 has explicitly intercepted such an error by setting the trap mask. </p> <ul>
       
   106 <li id="GUID-BEE3954A-733D-55CE-B09C-4B49304B44E1"><p> <xref href="GUID-80E0DB93-A96A-54A8-A201-E11935418BE7.dita#GUID-80E0DB93-A96A-54A8-A201-E11935418BE7/GUID-901D8456-F8D3-5E92-B3DA-EFE556D8C48B">Important points to note</xref> </p> </li>
       
   107 <li id="GUID-DA29FD1E-93EF-56C1-9650-8CE22B655897"><p> <xref href="GUID-80E0DB93-A96A-54A8-A201-E11935418BE7.dita#GUID-80E0DB93-A96A-54A8-A201-E11935418BE7/GUID-DBBA1450-AE5A-50E5-9B8C-F697CEFAD590">Blocking on an asynchronous request</xref> </p> </li>
       
   108 </ul> <p id="GUID-901D8456-F8D3-5E92-B3DA-EFE556D8C48B"><b>Important points to note</b> </p> <p>Each
       
   109 state machine function must define a list of states that can exist. States
       
   110 are defined as an enumeration whose first and last values <i>must</i> be labelled <codeph>EStBegin</codeph> and <codeph>EStEnd</codeph>,
       
   111 respectively. <codeph>EStBegin</codeph> must have the value zero. Any other
       
   112 intermediate states are program defined. </p> <p>To make the state machine
       
   113 functions more readable, a number of macros exist to help with the layout
       
   114 of the function code, and to control program flow. The most basic macros are <xref href="GUID-C095E583-3E71-31F3-B092-627357D72958.dita"><apiname>SMF_BEGIN</apiname></xref>, <xref href="GUID-38811BD9-F27C-3408-A04F-053314A2CF84.dita"><apiname>SMF_STATE</apiname></xref> and <xref href="GUID-C1089896-DD68-399C-BF34-2495C51A0CA1.dita"><apiname>SMF_END</apiname></xref> that expand into a switch statement. The above code expands
       
   115 to: </p> <codeblock id="GUID-16AE9141-5BE1-5B54-B083-7F60133DD018" xml:space="preserve">TMMCErr DMMCStack::FunctionNameSM()
       
   116 {
       
   117 enum states {EStBegin=0, EStNext,…, EStEnd };    // Enumeration of states for this state machine
       
   118 DMMCSession&amp; s = Session();
       
   119 
       
   120 TMMCStateMachine&amp; m = Machine();            //SMF_BEGIN
       
   121 const TMMCErr err = m.SetExitCode( 0 );        //SMF_BEGIN
       
   122 for(;;)                                        //SMF_BEGIN
       
   123     {                                        //SMF_BEGIN
       
   124     switch(m.State())                        //SMF_BEGIN
       
   125         {                                    //SMF_BEGIN
       
   126         case EStBegin:                        //SMF_BEGIN
       
   127             {                                //SMF_BEGIN
       
   128             if(err) (void)0;                //SMF_BEGIN 
       
   129             // State EStBegin
       
   130             // Actions for state EStBegin
       
   131 
       
   132             }                                //SMF_STATE
       
   133         case EStNext:                        //SMF_STATE
       
   134             {                                //SMF_STATE
       
   135             // State EStNext
       
   136             // Actions for state EStNext
       
   137 
       
   138         case EStEnd:                                                //SMF_END
       
   139             break;                                                    //SMF_END
       
   140             default:                                                //SMF_END
       
   141             DMMCController::Panic(DMMCController::EMMCMachineState);//SMF_END
       
   142         }                                                            //SMF_END
       
   143         break;                                                        //SMF_END
       
   144     }                                                                //SMF_END
       
   145 return(m.Pop());                                                    //SMF_END
       
   146 }</codeblock> <p>Notes: </p> <ul>
       
   147 <li id="GUID-7542D030-2641-5A15-A5AF-A02C491B24BB"><p>be aware that SMF_BEGIN
       
   148 generates an open curly bracket while SMF_STATE generates a corresponding
       
   149 close bracket, and SMF_END closes the switch statement. </p> </li>
       
   150 </ul> <p>You need to be aware of the code that is generated by these macros.
       
   151 In particular, some such as SMF_BEGIN generate an opening curly brace, while
       
   152 others such as SMF_STATE generate a corresponding close curly brace. Also,
       
   153 you need to know whether a macro generates a <codeph>break;</codeph> or a <codeph>return;</codeph> statement.
       
   154 Lack of awareness here may cause code to be generated that flows from one
       
   155 case statement to another, which may not be your intent. </p> <ul>
       
   156 <li id="GUID-7C57CF3E-0EB9-56A4-A07A-86027F5B42BA"><p> <xref href="GUID-C095E583-3E71-31F3-B092-627357D72958.dita"><apiname>SMF_BEGIN</apiname></xref> </p> </li>
       
   157 <li id="GUID-9A87EEA6-6D40-53E1-BCEE-F9A20C22D51D"><p> <xref href="GUID-C1089896-DD68-399C-BF34-2495C51A0CA1.dita"><apiname>SMF_END</apiname></xref> </p> </li>
       
   158 <li id="GUID-3ADD2CCB-4C83-54EC-80DB-3C8CFDDDCB7A"><p> <xref href="GUID-2BA7F4A7-ECB0-3839-809B-4C32D4F451BA.dita"><apiname>SMF_NEXTS</apiname></xref> </p> </li>
       
   159 <li id="GUID-41D972A7-18DE-5CE5-B0D6-039B0126199C"><p> <xref href="GUID-ACD776A5-5439-3BE9-8DD8-B537D8C2C637.dita"><apiname>SMF_CALL</apiname></xref> </p> </li>
       
   160 <li id="GUID-87C8FC8C-F810-5B3F-A7CC-99D6515F8F04"><p> <xref href="GUID-3802119E-0FC0-3B7C-9582-21563EC9AF61.dita"><apiname>SMF_CALLWAIT</apiname></xref> </p> </li>
       
   161 <li id="GUID-89669A58-5168-508A-AF9F-34C3347F0A69"><p> <xref href="GUID-2B6FA032-F8F9-3205-9CBB-EFB96691ACC9.dita"><apiname>SMF_CALLMYS</apiname></xref> </p> </li>
       
   162 <li id="GUID-A6C9952A-223E-5687-B67C-D89D50070BDB"><p> <xref href="GUID-C1D65C79-F781-3E22-AA73-F75BA2516F6F.dita"><apiname>SMF_CALLMEWR</apiname></xref> </p> </li>
       
   163 <li id="GUID-7FF0DFC9-D9DC-5E08-B668-4BC62B6E50EC"><p> <xref href="GUID-A143CA61-AA6B-3C5F-9E58-50BAF3786262.dita"><apiname>SMF_INVOKES</apiname></xref> </p> </li>
       
   164 <li id="GUID-F02BE381-0BA2-5E9D-AFB7-9064FBADC64C"><p> <xref href="GUID-A73CAEB2-2413-371E-A56F-2757C0723514.dita"><apiname>SMF_INVOKEWAITS</apiname></xref> </p> </li>
       
   165 <li id="GUID-A39E56F8-DE55-5EDE-A955-24E198026F39"><p> <xref href="GUID-94214574-2CCD-3BE4-ABD4-6A58328B29A2.dita"><apiname>SMF_WAIT</apiname></xref> </p> </li>
       
   166 <li id="GUID-1CB69F09-3BAC-5C41-B20E-5A2896C0E18E"><p> <xref href="GUID-33FBF199-09B8-32C3-BAD6-92D277722DB3.dita"><apiname>SMF_WAITS</apiname></xref> </p> </li>
       
   167 <li id="GUID-46D7BB96-3EC7-5207-BEE4-1E3ABB145D6B"><p> <xref href="GUID-B13D0665-AD49-348F-8795-67E8761B0BC8.dita"><apiname>SMF_RETURN</apiname></xref> </p> </li>
       
   168 <li id="GUID-A9A4DB91-2648-534D-BEA3-57A23147D750"><p> <xref href="GUID-2BA73A03-7379-394C-B9E8-4525316AF91F.dita"><apiname>SMF_EXIT</apiname></xref> </p> </li>
       
   169 <li id="GUID-E75E1BF0-CD8B-5EEA-98EA-13176AE0A308"><p> <xref href="GUID-57CF6330-1EA6-36A9-B2A1-2BB360B1E7FD.dita"><apiname>SMF_EXITWAIT</apiname></xref> </p> </li>
       
   170 <li id="GUID-D0617F39-4CF6-5FA7-995C-50688A82E703"><p> <xref href="GUID-6E9EF7EB-A9A2-3FA1-902D-188B4930927F.dita"><apiname>SMF_JUMP</apiname></xref> </p> </li>
       
   171 <li id="GUID-83791CBF-298A-5B5F-A9A0-8FB902AE81EB"><p> <xref href="GUID-85E63D6B-521B-309A-A1B1-18FDFCF626A0.dita"><apiname>SMF_JUMPWAIT</apiname></xref> </p> </li>
       
   172 <li id="GUID-F657F501-47AE-57D0-BEB6-A051176FC279"><p> <xref href="GUID-BF735A08-6E69-374F-8052-EF6CA101A3C3.dita"><apiname>SMF_GOTONEXTS</apiname></xref> </p> </li>
       
   173 <li id="GUID-F7D1B6D8-51A2-5C73-A709-1BB10CD27620"><p> <xref href="GUID-AA215584-34D9-36DA-A05A-8A4DF4636D5E.dita"><apiname>SMF_GOTOS</apiname></xref> </p> </li>
       
   174 <li id="GUID-042539CB-3019-57A2-B0AD-F1417756F842"><p> <xref href="GUID-38811BD9-F27C-3408-A04F-053314A2CF84.dita"><apiname>SMF_STATE</apiname></xref> </p> </li>
       
   175 <li id="GUID-ADD382E6-32C0-5773-8958-057F440C3FEC"><p> <xref href="GUID-11B9D102-4548-3321-8318-26E940273880.dita"><apiname>SMF_BPOINT</apiname></xref> </p> </li>
       
   176 </ul> <p id="GUID-DBBA1450-AE5A-50E5-9B8C-F697CEFAD590"><b> Blocking on an asynchronous
       
   177 request</b> </p> <p>The state machine can be made to block. This is done so
       
   178 that you can wait for an asynchronous operation to complete. When the operation
       
   179 completes, it unblocks the state machine. There are two stages to blocking
       
   180 a state machine: </p> <ul>
       
   181 <li id="GUID-544A1BE8-2896-5CEB-ADEB-4F63E26389C4"><p>Call <xref href="GUID-B5193656-9819-3E00-A335-EEF1726115A5.dita#GUID-B5193656-9819-3E00-A335-EEF1726115A5/GUID-E7B38752-F9AB-3A66-8FB6-E321717A63B5"><apiname>DMMCStack::BlockCurrentSession()</apiname></xref> to
       
   182 indicate that the state machine associated with the current session is to
       
   183 be blocked </p> </li>
       
   184 <li id="GUID-BDB03808-C220-5518-B0E7-232845FD0AD6"><p>Execute one of the SMF_xxxWAIT
       
   185 macros to return from the current state machine function and wait. </p> </li>
       
   186 </ul> <p>Note that the state machine function <i>must</i> return by calling
       
   187 one of the SMF_xxxWAIT macros. It must not poll or sit in a loop! The state
       
   188 machines are not threaded, and this means that CPU time can only be given
       
   189 to other tasks if the function returns. </p> <p> <xref href="GUID-B5193656-9819-3E00-A335-EEF1726115A5.dita#GUID-B5193656-9819-3E00-A335-EEF1726115A5/GUID-E7B38752-F9AB-3A66-8FB6-E321717A63B5"><apiname>DMMCStack::BlockCurrentSession()</apiname></xref> takes
       
   190 an argument describing the type of block. The state machine will only unblock
       
   191 when an unblock request with the matching argument is called. In the platform
       
   192 specific layer of the MultiMediaCard controller, you should always set the <xref href="GUID-8A9A2DD2-C630-3651-8374-17BCF2A09AC4.dita"><apiname>KMMCBlockOnASSPFunction</apiname></xref> bit
       
   193 in the argument passed to <codeph>BlockCurrentSession()</codeph>. </p> <p>To
       
   194 unblock the state machine, call <xref href="GUID-B5193656-9819-3E00-A335-EEF1726115A5.dita#GUID-B5193656-9819-3E00-A335-EEF1726115A5/GUID-E1FEFAD3-CD02-38AF-8E45-41099192D583"><apiname>DMMCStack::UnBlockCurrentSession()</apiname></xref> setting
       
   195 the <xref href="GUID-8A9A2DD2-C630-3651-8374-17BCF2A09AC4.dita"><apiname>KMMCBlockOnASSPFunction</apiname></xref> bit in the flags argument passed
       
   196 to the function, and also an error code. This will invoke the state machine
       
   197 scheduler, which will re-start the state machine. </p> <p>Note that further
       
   198 state machine processing must take place in a DFC rather than within the interrupt
       
   199 service routine (ISR), and this can be forced by ORing the session status, <xref href="GUID-0186BEDE-8E28-3F8C-8CAE-A8B92F41F47A.dita#GUID-0186BEDE-8E28-3F8C-8CAE-A8B92F41F47A/GUID-252B39FE-C203-37AD-82A4-63E9BFFD3473"><apiname>DMMCSession::iState</apiname></xref>,
       
   200 with the <xref href="GUID-5CF9ED11-2F3A-3E9B-9BFF-87DBE261F097.dita"><apiname>KMMCSessStateDoDFC</apiname></xref> bit <i>before</i> unblocking
       
   201 the session. The bit has the effect of queueing a DFC to resume the state
       
   202 machine at some later stage, before returning to the ISR. </p> <p>The following
       
   203 code shows the idea: </p> <codeblock id="GUID-C4C8C8EA-4A16-5E9C-A64D-194D7D17403C" xml:space="preserve">TMMCErr DMMCStackAssp::DoSomethingSM()
       
   204     {
       
   205     enum states {EStBegin=0, EStDone,EStEnd };    // enumeration of states for this state machine
       
   206 
       
   207     SMF_BEGIN
       
   208     // start the asynchronous operation
       
   209     BlockCurrentSession( KMMCBlockOnASSPFunction );
       
   210     StartAsynchronousOp();
       
   211 
       
   212     // block and wait. Go to state EStDone when the asynchronous op is complete
       
   213     SMF_WAITS( EStDone );
       
   214     
       
   215     SMF_STATE( EStDone )
       
   216     // operation is complete, check for errors and return from state machine
       
   217     TInt errors = CheckForHardwareErrors();
       
   218     SMF_RETURN( errors );
       
   219 
       
   220     SMF_END
       
   221     }
       
   222 </codeblock> <codeblock id="GUID-5CE18C2D-2780-5966-BC26-DD33D31BB5B3" xml:space="preserve">void TMMCInterrupt::Service( TAny* aParam )
       
   223     {
       
   224     Session().iState |= KMMCSessStateDoDFC;
       
   225     UnBlockCurrentSession(KMMCBlockOnASSPFunction, KMMCErrNone);
       
   226     }
       
   227 </codeblock> </section>
       
   228 <section id="GUID-667C5A70-0ABB-525F-A309-58102E380400"><title>Example of
       
   229 a state machine calling sequence</title> <p>This shows the state machine calling
       
   230 sequence that implements the reading of a single block on a MultiMediaCard,
       
   231 where the card is not yet selected. Note that the lowest level state machine
       
   232 function called is <codeph>IssueMMCCommandSM()</codeph>, which is implemented
       
   233 by the base port. </p> <fig id="GUID-A67E1B8E-322A-5AC8-9EEA-AC24C8868E81">
       
   234 <image href="GUID-A51C3E48-3ED0-519B-A128-C5175D7E175B_d0e19782_href.png" placement="inline"/>
       
   235 </fig> </section>
       
   236 </conbody></concept>