/* * _system_assertions() - check memory integrity and other assertions */ uint8_t _system_assertions() { uint8_t value = 0; if (tg.magic_start != MAGICNUM) { value = 1; } // Note: reported VALue is offset by ALARM_MEMORY_OFFSET if (tg.magic_end != MAGICNUM) { value = 2; } if (cm.magic_start != MAGICNUM) { value = 3; } if (cm.magic_end != MAGICNUM) { value = 4; } if (gm.magic_start != MAGICNUM) { value = 5; } if (gm.magic_end != MAGICNUM) { value = 6; } if (cfg.magic_start != MAGICNUM) { value = 7; } if (cfg.magic_end != MAGICNUM) { value = 8; } if (cmdStr.magic_start != MAGICNUM) { value = 9; } if (cmdStr.magic_end != MAGICNUM) { value = 10; } if (mb.magic_start != MAGICNUM) { value = 11; } if (mb.magic_end != MAGICNUM) { value = 12; } if (mr.magic_start != MAGICNUM) { value = 13; } if (mr.magic_end != MAGICNUM) { value = 14; } if (ar.magic_start != MAGICNUM) { value = 15; } if (ar.magic_end != MAGICNUM) { value = 16; } if (st_get_st_magic() != MAGICNUM) { value = 17; } if (st_get_sps_magic() != MAGICNUM) { value = 18; } if (rtc.magic_end != MAGICNUM) { value = 19; } xio_assertions(&value); // run xio assertions if (value == 0) { return (STAT_OK);} rpt_exception(STAT_MEMORY_FAULT, value); cm_alarm(ALARM_MEMORY_OFFSET + value); return (STAT_EAGAIN); }
/* * _system_assertions() - check memory integrity and other assertions */ uint8_t _system_assertions() { uint8_t value = 0; if (tg.magic_start != MAGICNUM) { value = 1; } if (tg.magic_end != MAGICNUM) { value = 2; } if (cm.magic_start != MAGICNUM) { value = 3; } if (cm.magic_end != MAGICNUM) { value = 4; } if (gm.magic_start != MAGICNUM) { value = 5; } if (gm.magic_end != MAGICNUM) { value = 6; } if (cfg.magic_start != MAGICNUM) { value = 7; } if (cfg.magic_end != MAGICNUM) { value = 8; } if (cmdStr.magic_start != MAGICNUM) { value = 9; } if (cmdStr.magic_end != MAGICNUM) { value = 10; } if (mb.magic_start != MAGICNUM) { value = 11; } if (mb.magic_end != MAGICNUM) { value = 12; } if (mr.magic_start != MAGICNUM) { value = 13; } if (mr.magic_end != MAGICNUM) { value = 14; } if (st_get_st_magic() != MAGICNUM) { value = 15; } if (st_get_sps_magic() != MAGICNUM) { value = 16; } if (rtc.magic_end != MAGICNUM) { value = 17; } xio_assertions(&value); // run xio assertions if (value == 0) { return (TG_OK);} rpt_exception(TG_MEMORY_CORRUPTION, value); cm_shutdown(); return (TG_EAGAIN); }
stat_t write_persistent_value(nvObj_t *nv) { if (cm.cycle_state != CYCLE_OFF) return(rpt_exception(STAT_FILE_NOT_OPEN)); // can't write when machine is moving /* not needed if (nv->valuetype == TYPE_FLOAT) { if (isnan((double)nv->value)) return(rpt_exception(STAT_FLOAT_IS_NAN)); // bad floating point value if (isinf((double)nv->value)) return(rpt_exception(STAT_FLOAT_IS_INFINITE));// bad floating point value } */ return (STAT_OK); }
mpBuf_t * mp_get_write_buffer() // get & clear a buffer { if (mb.w->buffer_state == MP_BUFFER_EMPTY) { mpBuf_t *w = mb.w; mpBuf_t *nx = mb.w->nx; // save linked list pointers mpBuf_t *pv = mb.w->pv; memset(mb.w, 0, sizeof(mpBuf_t)); // clear all values w->nx = nx; // restore pointers w->pv = pv; w->buffer_state = MP_BUFFER_LOADING; mb.buffers_available--; mb.w = w->nx; return (w); } rpt_exception(STAT_FAILED_TO_GET_PLANNER_BUFFER); return (NULL); }
stat_t write_persistent_value(nvObj_t *nv) { if (cm.cycle_state != CYCLE_OFF) return(rpt_exception(STAT_FILE_NOT_OPEN)); // can't write when machine is moving /* not needed if (nv->valuetype == TYPE_FLOAT) { if (isnan((double)nv->value)) return(rpt_exception(STAT_FLOAT_IS_NAN)); // bad floating point value if (isinf((double)nv->value)) return(rpt_exception(STAT_FLOAT_IS_INFINITE));// bad floating point value } */ nvm.tmp_value = nv->value; ritorno(read_persistent_value(nv)); if ((isnan((double)nv->value)) || (isinf((double)nv->value)) || (fp_NE(nv->value, nvm.tmp_value))) { memcpy(&nvm.byte_array, &nvm.tmp_value, NVM_VALUE_LEN); nvm.address = nvm.profile_base + (nv->index * NVM_VALUE_LEN); (void)EEPROM_WriteBytes(nvm.address, nvm.byte_array, NVM_VALUE_LEN); } nv->value =nvm.tmp_value; // always restore value return (STAT_OK); }
void json_print_response(uint8_t status) { #ifdef __SILENCE_JSON_RESPONSES return; #endif if (js.json_verbosity == JV_SILENT) { // silent means no responses return; } if (js.json_verbosity == JV_EXCEPTIONS) { // cutout for JV_EXCEPTIONS mode if (status == STAT_OK) { if (cm.machine_state != MACHINE_INITIALIZING) { // always do full echo during startup return; } } } // Body processing nvObj_t *nv = nv_body; if (status == STAT_JSON_SYNTAX_ERROR) { nv_reset_nv_list(); nv_add_string((const char *)"err", escape_string(cs.bufp, cs.saved_buf)); } else if (cm.machine_state != MACHINE_INITIALIZING) { // always do full echo during startup uint8_t nv_type; do { if ((nv_type = nv_get_type(nv)) == NV_TYPE_NULL) break; if (nv_type == NV_TYPE_GCODE) { if (js.echo_json_gcode_block == false) { // kill command echo if not enabled nv->valuetype = TYPE_EMPTY; } //++++ } else if (nv_type == NV_TYPE_CONFIG) { // kill config echo if not enabled //fix me if (js.echo_json_configs == false) { // nv->valuetype = TYPE_EMPTY; // } } else if (nv_type == NV_TYPE_MESSAGE) { // kill message echo if not enabled if (js.echo_json_messages == false) { nv->valuetype = TYPE_EMPTY; } } else if (nv_type == NV_TYPE_LINENUM) { // kill line number echo if not enabled if ((js.echo_json_linenum == false) || (fp_ZERO(nv->value))) { // do not report line# 0 nv->valuetype = TYPE_EMPTY; } } } while ((nv = nv->nx) != NULL); } // Footer processing while(nv->valuetype != TYPE_EMPTY) { // find a free nvObj at end of the list... if ((nv = nv->nx) == NULL) { // oops! No free nvObj! rpt_exception(STAT_JSON_TOO_LONG, "json_print"); // report this as an exception return; } } char footer_string[NV_FOOTER_LEN]; // in xio.cpp:xio.readline the CR||LF read from the host is not appended to the string. // to ensure that the correct number of bytes are reported back to the host we add a +1 to // cs.linelen so that the number of bytes received matches the number of bytes reported sprintf((char *)footer_string, "%d,%d,%d", 1, status, cs.linelen + 1); cs.linelen = 0; // reset linelen so it's only reported once // if (xio.enable_window_mode) { // 2 footer styles are supported... // sprintf((char *)footer_string, "%d,%d,%d", 2, status, xio_get_window_slots()); //...windowing // } else { // sprintf((char *)footer_string, "%d,%d,%d", 1, status, cs.linelen); //...streaming // cs.linelen = 0; // reset linelen so it's only reported once // } nv_copy_string(nv, footer_string); // link string to nv object nv->depth = 0; // footer 'f' is a peer to response 'r' (hard wired to 0) nv->valuetype = TYPE_ARRAY; // declare it as an array strcpy(nv->token, "f"); // set it to Footer nv->nx = NULL; // terminate the list // serialize the JSON response and print it if there were no errors if (json_serialize(nv_header, cs.out_buf, sizeof(cs.out_buf)) >= 0) { fprintf(stderr, "%s", cs.out_buf); } }
static stat_t _dispatch() { uint8_t status; // read input line or return if not a completed line // xio_gets() is a non-blocking workalike of fgets() while (true) { if ((status = xio_gets(tg.primary_src, tg.in_buf, sizeof(tg.in_buf))) == STAT_OK) { tg.bufp = tg.in_buf; break; } // handle end-of-file from file devices if (status == STAT_EOF) { // EOF can come from file devices only if (cfg.comm_mode == TEXT_MODE) { fprintf_P(stderr, PSTR("End of command file\n")); } else { rpt_exception(STAT_EOF, 0); // not really an exception } tg_reset_source(); // reset to default source } return (status); // Note: STAT_EAGAIN, errors, etc. will drop through } tg.linelen = strlen(tg.in_buf)+1; // linelen only tracks primary input strncpy(tg.saved_buf, tg.bufp, SAVED_BUFFER_LEN-1); // save input buffer for reporting // dispatch the new text line switch (toupper(*tg.bufp)) { // first char // case '!': { cm_request_feedhold(); break; } // include for diagnostics // case '@': { cm_request_queue_flush(); break; } // case '~': { cm_request_cycle_start(); break; } case NUL: { // blank line (just a CR) if (cfg.comm_mode != JSON_MODE) { tg_text_response(STAT_OK, tg.saved_buf); } break; } case 'H': { // intercept help screens cfg.comm_mode = TEXT_MODE; print_general_help(); tg_text_response(STAT_OK, tg.bufp); break; } case '$': case '?':{ // text-mode configs cfg.comm_mode = TEXT_MODE; tg_text_response(cfg_text_parser(tg.bufp), tg.saved_buf); break; } case '{': { // JSON input cfg.comm_mode = JSON_MODE; js_json_parser(tg.bufp); break; } default: { // anything else must be Gcode if (cfg.comm_mode == JSON_MODE) { strncpy(tg.out_buf, tg.bufp, INPUT_BUFFER_LEN -8); // use out_buf as temp sprintf(tg.bufp,"{\"gc\":\"%s\"}\n", tg.out_buf); js_json_parser(tg.bufp); } else { tg_text_response(gc_gcode_parser(tg.bufp), tg.saved_buf); } } } return (STAT_OK); }
stat_t _command_dispatch() { #ifdef __AVR stat_t status; // read input line or return if not a completed line // xio_gets() is a non-blocking workalike of fgets() while (true) { if ((status = xio_gets(cs.primary_src, cs.in_buf, sizeof(cs.in_buf))) == STAT_OK) { cs.bufp = cs.in_buf; break; } // handle end-of-file from file devices if (status == STAT_EOF) { // EOF can come from file devices only if (cfg.comm_mode == TEXT_MODE) { fprintf_P(stderr, PSTR("End of command file\n")); } else { rpt_exception(STAT_EOF); // not really an exception } tg_reset_source(); // reset to default source } return (status); // Note: STAT_EAGAIN, errors, etc. will drop through } #endif // __AVR #ifdef __ARM // detect USB connection and transition to disconnected state if it disconnected if (SerialUSB.isConnected() == false) cs.state = CONTROLLER_NOT_CONNECTED; // read input line and return if not a completed line if (cs.state == CONTROLLER_READY) { if (read_line(cs.in_buf, &cs.read_index, sizeof(cs.in_buf)) != STAT_OK) { cs.bufp = cs.in_buf; return (STAT_OK); // This is an exception: returns OK for anything NOT OK, so the idler always runs } } else if (cs.state == CONTROLLER_NOT_CONNECTED) { if (SerialUSB.isConnected() == false) return (STAT_OK); cm_request_queue_flush(); rpt_print_system_ready_message(); cs.state = CONTROLLER_STARTUP; } else if (cs.state == CONTROLLER_STARTUP) { // run startup code cs.state = CONTROLLER_READY; } else { return (STAT_OK); } cs.read_index = 0; #endif // __ARM #ifdef __RX stat_t status; parse_gcode_func_selection(CODE_PARSER); // read input line or return if not a completed line // xio_gets() is a non-blocking workalike of fgets() while (true) { if ((status = xio_gets(cs.primary_src, cs.in_buf, sizeof(cs.in_buf))) == STAT_OK) { cs.bufp = cs.in_buf; break; } // handle end-of-file from file devices if (status == STAT_EOF) { // EOF can come from file devices only //gfilerunning = false; xio_close(cs.primary_src); // macro_func_ptr = command_idle; if (cfg.comm_mode == TEXT_MODE) { fprintf_P(stderr, PSTR("End of command file\n")); } else { rpt_exception(STAT_EOF); // not really an exception } tg_reset_source(); // reset to default source } return (status); // Note: STAT_EAGAIN, errors, etc. will drop through } #endif // __AVR // set up the buffers cs.linelen = strlen(cs.in_buf)+1; // linelen only tracks primary input strncpy(cs.saved_buf, cs.bufp, SAVED_BUFFER_LEN-1); // save input buffer for reporting // dispatch the new text line switch (toupper(*cs.bufp)) { // first char case '!': { cm_request_feedhold(); break; } // include for AVR diagnostics and ARM serial case '%': { cm_request_queue_flush(); break; } case '~': { cm_request_cycle_start(); break; } case NUL: { // blank line (just a CR) if (cfg.comm_mode != JSON_MODE) { text_response(STAT_OK, cs.saved_buf); } break; } case '$': case '?': case 'H': { // text mode input cfg.comm_mode = TEXT_MODE; text_response(text_parser(cs.bufp), cs.saved_buf); break; } case '{': { // JSON input cfg.comm_mode = JSON_MODE; json_parser(cs.bufp); break; } default: { // anything else must be Gcode if (cfg.comm_mode == JSON_MODE) { // run it as JSON... strncpy(cs.out_buf, cs.bufp, INPUT_BUFFER_LEN -8); // use out_buf as temp sprintf((char *)cs.bufp,"{\"gc\":\"%s\"}\n", (char *)cs.out_buf); // '-8' is used for JSON chars json_parser(cs.bufp); } else { //...or run it as text text_response(gc_gcode_parser(cs.bufp), cs.saved_buf); } } } return (STAT_OK); }