handle_error.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. #define SCPI_CORE_STATE__HANDLEERROR_GUARD
  2. #include "app/scpi/CommandParserStates/handle_error.h"
  3. #define SCPI_CORE_PRIVATE // access to 'scpi_core_private.h'
  4. #define SCPI_HANDLE_ERROR_C // access to some const variables in 'scpi_core_private.h'
  5. #include "app/scpi/scpi_core_private.h"
  6. #include "app/scpi/scpi_errq.h"
  7. //----------------------------------------------------------------
  8. // Refer to:
  9. // [1] SCPI Specification, revision 1999.0
  10. // "Standard Commands for Programmable Instruments (SCPI), VERSION 1999.0, May 1999"
  11. // [2] Gpib Programming Tutorial, (http://g2pc1.bu.edu/~qzpeng/gpib/manual/GpibProgTut.pdf)
  12. // Electronics Group (http://www.few.vu.nl/~elec), 11 January 2000 Electronics Group
  13. // [3] IEEE 488.2 Standard, revision IEEE Std 488.2-1987 (1992)
  14. // "IEEE Standard Codes, Formats, Protocols, and Common Commands for Use With IEEE Std 488.1-1987, IEEE
  15. //----------------------------------------------------------------
  16. // Refer "21.8.1 The Error/Event Queue", [1]
  17. // Refer "8.2.2 System sub-system", [2]
  18. // =================================================================================
  19. // @sHandleErrorContext_t
  20. // State's private context typedef
  21. typedef struct
  22. {
  23. uint8_t lastEventCode;
  24. }
  25. sHandleErrorContext_t;
  26. // =================================================================================
  27. // @ctx_HandleError
  28. // State's private context
  29. sHandleErrorContext_t ctx_HandleError;
  30. // =================================================================================
  31. // @fsqvbl_HandleError
  32. // State's virtual table
  33. static void fsqe_HandleError( const struct fFSeqEntry_t * this, tFSeqCtx_t ctx );
  34. static void fsql_HandleError( const struct fFSeqEntry_t * this, tFSeqCtx_t ctx );
  35. static const struct fFSeqEntry_t * fsqf_HandleError( const struct fFSeqEntry_t * this, tFSeqCtx_t ctx, const struct fFSeqEntry_t * * pnext );
  36. const fFSeqVTable_t fsqvbl_HandleError =
  37. {
  38. .f = fsqf_HandleError,
  39. .enter = fsqe_HandleError,
  40. .leave = fsql_HandleError
  41. };
  42. // =================================================================================
  43. // @fsqe_HandleError
  44. // State's enter routine
  45. static void fsqe_HandleError( const struct fFSeqEntry_t * this, tFSeqCtx_t ctx )
  46. {
  47. sScpiParserContext_t * global_ctx = ctx;
  48. sHandleErrorContext_t * private_ctx = fsq_GetPrivateCtxRef(this);
  49. (void)global_ctx, (void)private_ctx;
  50. private_ctx->lastEventCode = global_ctx->sEvent.eCode;
  51. if( SCPI_ERROR_STATE != global_ctx->sExecution.runtimeError )
  52. {
  53. if( ! errq_push( &global_ctx->sExecution.xScpiErrorQueue,
  54. global_ctx->sExecution.runtimeError,
  55. global_ctx->sExecution.xScpiErrorMessage ) )
  56. {
  57. // Error Queue Overflow
  58. global_ctx->sExecution.errorQueueOverflow = true;
  59. // "21.8.1 The Error/Event Queue", [1]
  60. // "21.8.11 Device-Specific Error", [1]
  61. // "11.5.1.1.6 Bit 3 N Device-Specific ERROR (DDE)", [3]
  62. GPIBMachine.fGPIB_set_event_status_register_device_specific_error_state(
  63. &global_ctx->sGPIB.registers, true );
  64. global_ctx->sExecution.runtimeError = SCPI_ERROR_SUCCESS; // clear error code
  65. global_ctx->sEvent.eStatus = eScpiStatus_success; // clear error status
  66. }
  67. else
  68. {
  69. // Notify GPIB: error available in the queue
  70. // "4 Instrument status", [2]
  71. // "4.1 Status Byte registers (STB and SRE)", [2]
  72. // "11.2.2.3 Master Summary Status", [4]
  73. // "11.3.2.4 Clearing the Service Request Enable Register", [3]
  74. GPIBMachine.fGPIB_set_error_available_bit( &global_ctx->sGPIB.registers, true );
  75. switch( SCPI_ERROR_CLASS(global_ctx->sExecution.runtimeError) )
  76. {
  77. // ------------ Reasons: --------------
  78. // "6.1.6.1.1 Parser Errors", [3]
  79. // "6.5.4 Command Error", [3]
  80. case SCPI_ERROR_CLASS_COMMAND:
  81. GPIBMachine.fGPIB_set_event_status_register_command_error_state(
  82. &global_ctx->sGPIB.registers, true );
  83. break;
  84. // ------------ Reasons: --------------
  85. // "6.5.5 Execution Error", [3]
  86. // "11.5.1.1.5 Bit 4 N Execution ERROR (E)", [3]
  87. // "<...> the device shall continue parsing the input stream. <...>", [3]
  88. case SCPI_ERROR_CLASS_EXECUTION:
  89. GPIBMachine.fGPIB_set_event_status_register_execution_error_state(
  90. &global_ctx->sGPIB.registers, true );
  91. // "11.5.1.1.5 Bit 4 N Execution ERROR (E)", [3]
  92. // "<...> the device shall continue parsing the input stream. <...>", [3]
  93. global_ctx->sEvent.eCode = eScpiEventContinue; // change event code to continue parsing
  94. break;
  95. // "11.5.1.1.6 Bit 3 N Device-Specific ERROR (DDE)", [3]
  96. case SCPI_ERROR_CLASS_DEVICE:
  97. GPIBMachine.fGPIB_set_event_status_register_device_specific_error_state(
  98. &global_ctx->sGPIB.registers, true );
  99. break;
  100. // ------------ Reasons: --------------
  101. // "6.3.1.3 QUERY State", [3]
  102. // "6.3.1.7 DEADLOCK State", [3]
  103. // "6.3.2.2 UNTERMINATED Action", [3]
  104. // "6.3.2.3 INTERRUPTED Action", [3]
  105. // "6.5.7 Query Error", [3]
  106. case SCPI_ERROR_CLASS_QUERY:
  107. GPIBMachine.fGPIB_set_event_status_register_query_error_state(
  108. &global_ctx->sGPIB.registers, true );
  109. break;
  110. }
  111. global_ctx->sExecution.runtimeError = SCPI_ERROR_SUCCESS; // clear error code
  112. global_ctx->sEvent.eStatus = eScpiStatus_success; // clear error status
  113. }
  114. }
  115. }
  116. // =================================================================================
  117. // @fsql_HandleError
  118. // State's leave routine
  119. static void fsql_HandleError( const struct fFSeqEntry_t * this, tFSeqCtx_t ctx )
  120. {
  121. sScpiParserContext_t * global_ctx = ctx;
  122. sHandleErrorContext_t * private_ctx = fsq_GetPrivateCtxRef(this);
  123. (void)ctx, (void)private_ctx, (void)global_ctx;
  124. }
  125. // =================================================================================
  126. // @fsqf_HandleError
  127. // State's body routine
  128. static const struct fFSeqEntry_t * fsqf_HandleError( const struct fFSeqEntry_t * this,
  129. tFSeqCtx_t ctx,
  130. const struct fFSeqEntry_t * * pDeferredNext )
  131. {
  132. // --------------------------------------------------------------------------
  133. const struct fFSeqEntry_t * nextstate = NULL; // do not change state, do not call next state
  134. sScpiParserContext_t * global_ctx = ctx;
  135. sHandleErrorContext_t * private_ctx = fsq_GetPrivateCtxRef(this);
  136. uint8_t nextEvent = eScpiEventEmpty;
  137. // --------------------------------------------------------------------------
  138. switch( global_ctx->sEvent.eCode )
  139. {
  140. case eScpiEventRestart:
  141. {
  142. // go to reset state
  143. nextstate = fsq_GetStateById(this,eParserResetState);
  144. }
  145. break;
  146. case eScpiEventContinue:
  147. {
  148. // Search for the following message unit separator
  149. // goto next state: eProcessEndOfProgramData
  150. nextstate = fsq_GetStateById(this,eProcessEndOfProgramData);
  151. nextEvent = private_ctx->lastEventCode;
  152. (void)global_ctx->sEvent.eStatus;; // already cleared
  153. }
  154. break;
  155. case eScpiEventError: // transport error
  156. {
  157. global_ctx->sEvent.eStatus = eScpiStatus_success;
  158. (void)nextstate; // keep this state
  159. }
  160. break;
  161. case eScpiEventRead: // read event during Error condition:
  162. case eScpiEventWrite: // command parse error -> error state
  163. {
  164. // Respond with empty string:
  165. if( global_ctx->sRead.nDataLength == 0 ) // no response in output buffer
  166. if( global_ctx->sRead.nBufferSize >= 1 ) // there is vacant room in output buffer
  167. {
  168. scpi_WriteCharOutput( ' ' );
  169. // "Query error", "11.5.1.1.7 Bit 2", [3]
  170. // "An attempt is being made to read data from the Output Queue when no output is either present or pending"
  171. GPIBMachine.fGPIB_set_event_status_register_query_error_state( &global_ctx->sGPIB.registers, true );
  172. }
  173. global_ctx->sEvent.eStatus = eScpiStatus_success;
  174. global_ctx->sMessage.r_bEndOfMessage = true;
  175. scpi_UpdateMessageAvailable();
  176. (void)nextstate; // keep this state
  177. }
  178. break;
  179. }
  180. global_ctx->sEvent.eCode = nextEvent;
  181. return nextstate;
  182. }