static void s_eoprot_print_mninfo_status(eOmn_info_basic_t* infobasic, uint8_t * extra, const EOnv* nv, const eOropdescriptor_t* rd) { #undef DROPCODES_FROM_LIST #define CAN_PRINT_FULL_PARSING static const eOerror_code_t codecanprint = EOERRORCODE(eoerror_category_System, eoerror_value_SYS_canservices_canprint); #if defined(DROPCODES_FROM_LIST) static const eOerror_code_t codes2drop_value[] = { EOERRORCODE(eoerror_category_System, eoerror_value_SYS_canservices_parsingfailure), EOERRORCODE(eoerror_category_System, eoerror_value_SYS_canservices_rxmaisbug), EOERRORCODE(eoerror_category_System, eoerror_value_SYS_canservices_rxfromwrongboard), EOERRORCODE(eoerror_category_System, eoerror_value_SYS_transceiver_rxseqnumber_error) }; static const int codes2drop_number = sizeof(codes2drop_value) / sizeof(eOerror_code_t); int i; for(i=0; i<codes2drop_number; i++) { if(codes2drop_value[i] == infobasic->properties.code) { return; } } #endif { char str[384] = {0}; static const char * sourcestrings[] = { "LOCAL", "CAN1", "CAN2", "UNKNOWN" }; static const char nullverbalextra[] = "no extra info despite we are in verbal mode"; static const char emptyextra[] = "NO MORE"; uint32_t sec = infobasic->timestamp / 1000000; uint32_t msec = (infobasic->timestamp % 1000000) / 1000; uint32_t usec = infobasic->timestamp % 1000; eOmn_info_type_t type = EOMN_INFO_PROPERTIES_FLAGS_get_type(infobasic->properties.flags); eOmn_info_source_t source = EOMN_INFO_PROPERTIES_FLAGS_get_source(infobasic->properties.flags); uint16_t address = EOMN_INFO_PROPERTIES_FLAGS_get_address(infobasic->properties.flags); eOmn_info_extraformat_t extraf = EOMN_INFO_PROPERTIES_FLAGS_get_extraformat(infobasic->properties.flags); uint16_t forfutureuse = EOMN_INFO_PROPERTIES_FLAGS_get_futureuse(infobasic->properties.flags); const char * str_source = NULL; const char * str_code = NULL; const char * str_extra = NULL; uint8_t *p64 = NULL; str_source = (source > eomn_info_source_can2) ? (sourcestrings[3]) : (sourcestrings[source]); str_code = eoerror_code2string(infobasic->properties.code); str_extra = NULL; if(eomn_info_extraformat_verbal == extraf) { str_extra = (NULL == extra) ? (nullverbalextra) : ((const char *)extra); } else { str_extra = emptyextra; } p64 = (uint8_t*)&(infobasic->properties.par64); if(codecanprint == infobasic->properties.code) { uint16_t len = 0; char canframestring[7] = {0}; #if defined(CAN_PRINT_FULL_PARSING) feat_embObjCANPrintHandler(eo_nv_GetBRD(nv), infobasic); return; #endif // it is a canprint: treat it in a particular way. // in first step: just print the 6 bytes (at most) of the payload: now on 03/03/15 we have implemented first step // in second step: do the same inside ethResources // in third step: inside ethResources it is called the proper class can_string_generic with one instance per can board. // maybe to save memory, we can instantiate the can_string_generic in runtime only when the can board sends a canprint. // this third step allows to concatenate the can print frames into a single message as robotInterface // does with can-based robots len = infobasic->properties.par16; if((len > 2) && (len <=8)) { // we have a valid canframe memcpy(canframestring, &p64[2], len-2); canframestring[len-2] = 0; // string terminator snprintf(str, sizeof(str), " from BOARD %d, src %s, adr %d, time %ds %dm %du: CANPRINT: %s [size = %d, D0 = 0x%.2x, D1 = 0x%.2x]", eo_nv_GetBRD(nv)+1, str_source, address, sec, msec, usec, canframestring, len, p64[0], p64[1] ); } else { snprintf(str, sizeof(str), " from BOARD %d, src %s, adr %d, time %ds %dm %du: CANPRINT is malformed (code 0x%.8x, par16 0x%.4x par64 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x) -> %s + INFO = %s", eo_nv_GetBRD(nv)+1, str_source, address, sec, msec, usec, infobasic->properties.code, infobasic->properties.par16, p64[7], p64[6], p64[5], p64[4], p64[3], p64[2], p64[1], p64[0], str_code, str_extra ); } } else { // treat it as the normal case if(EOERRORCODE(eoerror_category_System, eoerror_value_SYS_transceiver_rxseqnumber_error) == infobasic->properties.code) { // marco.accame on 14apr15: // the ems may issue such an error code at reception of first udp packet from a freshly launched robotInterface. // the reason is that robotinterface send a ropframe with sequencenumber = 1 and the EMS may expect a bigger number // because of a previous launch of robotinterface. // best solution is to change fw of ems so that it sends a info with a different code (eoerror_value_SYS_transceiver_rxseqnumber_restarted). // that will be from fw version 1.73. // in the meantime, i transform the first report of eoerror_value_SYS_transceiver_rxseqnumber_error into a info plus an explanation. // i will remove it later on. static uint8_t alreadyreceived[32] = {0}; static const char realigned[] = "BUT QUITE SURELY THAT IS DUE to ROBOTINTERFACE JUST RESTARTED THUS RESETTING ITS SEQNUM"; uint8_t brd = eo_nv_GetBRD(nv); if((brd < sizeof(alreadyreceived)) && (0 == alreadyreceived[eo_nv_GetBRD(nv)])) { alreadyreceived[eo_nv_GetBRD(nv)] = 1; type = eomn_info_type_info; str_extra = realigned; } } snprintf(str, sizeof(str), " from BOARD %d, src %s, adr %d, time %ds %dm %du: (code 0x%.8x, par16 0x%.4x par64 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x) -> %s + INFO = %s", eo_nv_GetBRD(nv)+1, str_source, address, sec, msec, usec, infobasic->properties.code, infobasic->properties.par16, p64[7], p64[6], p64[5], p64[4], p64[3], p64[2], p64[1], p64[0], str_code, str_extra ); } if(type == eomn_info_type_debug) { embObjPrintDebug(str); } if(type == eomn_info_type_info) { embObjPrintInfo(str); } if(type == eomn_info_type_warning) { embObjPrintWarning(str); } if(type == eomn_info_type_error) { embObjPrintError(str); } if(type == eomn_info_type_fatal) { embObjPrintFatal(str); } } }
extern void eom_emstransceiver_callback_incaseoferror_in_sequencenumberReceived(EOreceiver *receiver) { // the only reason of using the following two variables as static is: to reduce the use of stack. static int64_t delta = 0; static eOerrmanDescriptor_t errdes = { .code = EOERRORCODE(eoerror_category_System, eoerror_value_SYS_transceiver_rxseqnumber_error), .sourcedevice = eo_errman_sourcedevice_localboard, .sourceaddress = 0, .par16 = 0, .par64 = 0 }; const eOreceiver_seqnum_error_t *err = eo_receiver_GetSequenceNumberError(receiver); if(NULL == err) { errdes.code = EOERRORCODE(eoerror_category_System, eoerror_value_SYS_runtimeerror); errdes.par64 = 0x123467fabc222; errdes.par16 = 1; eo_errman_Error(eo_errman_GetHandle(), eo_errortype_warning, NULL, NULL, &errdes); return; } if(1 == err->rec_seqnum) { // it is the first packet received from a remote transmitter freshly initted (i.e., robotInterface has just re-started bu this board was alive well before) // thus, we dont issue an error but an info: errdes.code = EOERRORCODE(eoerror_category_System, eoerror_value_SYS_transceiver_rxseqnumber_restarted); errdes.par64 = err->exp_seqnum; errdes.par16 = 1; eo_errman_Error(eo_errman_GetHandle(), eo_errortype_info, NULL, NULL, &errdes); // ok, now we must set back the error code as it is normal. errdes.code = EOERRORCODE(eoerror_category_System, eoerror_value_SYS_transceiver_rxseqnumber_error); } else { delta = err->rec_seqnum - err->exp_seqnum; if(delta > INT16_MAX) delta = INT16_MAX; //32767 else if(delta < INT16_MIN) delta = INT16_MIN; //-32768; errdes.code = EOERRORCODE(eoerror_category_System, eoerror_value_SYS_transceiver_rxseqnumber_error); errdes.par16 = (int16_t)delta; errdes.par64 = err->exp_seqnum; eo_errman_Error(eo_errman_GetHandle(), eo_errortype_error, NULL, NULL, &errdes); } } extern void eom_emstransceiver_callback_incaseoferror_invalidframe(EOreceiver *receiver) { static eOerrmanDescriptor_t errdesinvframe = { .code = EOERRORCODE(eoerror_category_System, eoerror_value_SYS_transceiver_rxinvalidframe_error), .sourcedevice = eo_errman_sourcedevice_localboard, .sourceaddress = 0, .par16 = 0, .par64 = 0 }; eo_errman_Error(eo_errman_GetHandle(), eo_errortype_error, NULL, NULL, &errdesinvframe); } // -------------------------------------------------------------------------------------------------------------------- // - definition of extern hidden functions // -------------------------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------------------------- // - definition of static functions // -------------------------------------------------------------------------------------------------------------------- /** @fn static void s_eom_emsappl_main_init(void) @brief It initialises the emsappl @details bla bla bla. **/ static void s_eom_emsappl_main_init(void) { // init leds via the EOtheLEDpulser object eOledpulser_cfg_t ledpulsercfg = { .led_enable_mask = (1 << eo_ledpulser_led_zero | 1 << eo_ledpulser_led_one | 1 << eo_ledpulser_led_two | 1 << eo_ledpulser_led_three | 1 << eo_ledpulser_led_four | 1 << eo_ledpulser_led_five), .led_init = (eOint8_fp_uint8_cvoidp_t) hal_led_init, .led_on = (eOint8_fp_uint8_t) hal_led_on, .led_off = (eOint8_fp_uint8_t) hal_led_off, .led_toggle = (eOint8_fp_uint8_t) hal_led_toggle }; eo_ledpulser_Initialise(&ledpulsercfg); // init the ems application EOMtheEMSapplCfg* emscfg = eom_emsapplcfg_GetHandle(); eom_emsappl_Initialise(&emscfg->applcfg); // set the led reserved for link if(eores_OK == eom_ipnet_ResolveIP(eom_ipnet_GetHandle(), emscfg->applcfg.hostipv4addr, 5*EOK_reltime100ms)) { // set led0 to ON eo_ledpulser_On(eo_ledpulser_GetHandle(), eo_ledpulser_led_zero); } else { eo_ledpulser_Off(eo_ledpulser_GetHandle(), eo_ledpulser_led_zero); } }