/* * Copyright (C) ST-Ericsson SA 2010 * Author: Jean-Philippe FASSINO for ST-Ericsson. * License terms: GNU General Public License (GPL) version 2. */ #include #include #include #include #include #include #include #include /* * Panic */ const struct { char* name; unsigned int info1:1; unsigned int PC:1; unsigned int SP:1; unsigned int interface:1; } reason_descrs[] = { {"NONE_PANIC", 0, 0, 0, 0}, {"INTERNAL_PANIC", 1, 0, 0, 0}, {"MPC_NOT_RESPONDING_PANIC", 0, 0, 0, 0}, /* Should not be useful since in that case CM_getServiceDescription() not call */ {"USER_STACK_OVERFLOW", 0, 1, 1, 0}, {"SYSTEM_STACK_OVERFLOW", 0, 1, 1, 0}, {"UNALIGNED_LONG_ACCESS", 0, 1, 0, 0}, {"EVENT_FIFO_OVERFLOW", 0, 0, 0, 1}, {"PARAM_FIFO_OVERFLOW", 0, 0, 0, 1}, {"INTERFACE_NOT_BINDED", 0, 0, 0, 0}, {"USER_PANIC", 1, 0, 0, 0} }; static t_component_instance* getCorrespondingInstance( t_panic_reason panicReason, t_uint32 panicThis, t_dup_char *itfName, t_cm_instance_handle *instHandle) { t_component_instance *instance; t_uint32 k; for (k=0; kthisAddress == panicThis && panicThis == 0) { *itfName = "Internal NMF service"; *instHandle = ENTRY2HANDLE(instance, k); return instance; } for(i = 0; i < instance->Template->requireNumber; i++) { int nb = instance->Template->requires[i].collectionSize, j; for(j = 0; j < nb; j++) { if(instance->interfaceReferences[i][j].instance != NULL && instance->interfaceReferences[i][j].instance != (t_component_instance *)NMF_HOST_COMPONENT && instance->interfaceReferences[i][j].instance != (t_component_instance *)NMF_VOID_COMPONENT && instance->interfaceReferences[i][j].instance->thisAddress == panicThis) { *itfName = instance->Template->requires[i].name; *instHandle = ENTRY2HANDLE(instance, k); return instance; } } } } else { // The component which has generated the panic is the good one. if(instance->thisAddress == panicThis) { *itfName = "?"; *instHandle = ENTRY2HANDLE(instance, k); return instance; } } } *itfName = "?"; *instHandle = 0; return 0; } PUBLIC EXPORT_SHARED t_cm_error CM_ReadMPCString( t_nmf_core_id coreId, t_uint32 dspAddress, char * buffer, t_uint32 bufferSize) { while(--bufferSize > 0) { char ch = cm_DSP_ReadXRamWord(coreId, dspAddress++); if(ch == 0) break; *buffer++ = ch; }; *buffer = 0; // Reset panicReason cm_writeAttribute(cm_EEM_getExecutiveEngine(coreId)->instance, "rtos/commonpart/serviceReason", MPC_SERVICE_NONE); return CM_OK; } /****************/ /* Generic part */ /****************/ PUBLIC EXPORT_SHARED t_cm_error CM_getServiceDescription( t_nmf_core_id coreId, t_cm_service_type *srcType, t_cm_service_description *srcDescr) { t_uint32 serviceReason; t_component_instance *ee; // Acknowledge interrupt (do it before resetting panicReason) cm_DSP_AcknowledgeDspIrq(coreId, DSP2ARM_IRQ_1); ee = cm_EEM_getExecutiveEngine(coreId)->instance; // Read panicReason serviceReason = cm_readAttributeNoError(ee, "rtos/commonpart/serviceReason"); if(serviceReason == MPC_SERVICE_PRINT) { *srcType = CM_MPC_SERVICE_PRINT; srcDescr->u.print.dspAddress = cm_readAttributeNoError(ee, "rtos/commonpart/serviceInfo0"); srcDescr->u.print.value1 = cm_readAttributeNoError(ee, "rtos/commonpart/serviceInfo1"); srcDescr->u.print.value2 = cm_readAttributeNoError(ee, "rtos/commonpart/serviceInfo2"); } else if(serviceReason != MPC_SERVICE_NONE) { t_uint32 panicThis; t_dup_char itfName; t_component_instance *instance; *srcType = CM_MPC_SERVICE_PANIC; srcDescr->u.panic.panicReason = (t_panic_reason)serviceReason; srcDescr->u.panic.panicSource = MPC_EE; srcDescr->u.panic.info.mpc.coreid = coreId; // Read panicThis panicThis = cm_readAttributeNoError(ee, "rtos/commonpart/serviceInfo0"); instance = getCorrespondingInstance(srcDescr->u.panic.panicReason, panicThis, &itfName, &srcDescr->u.panic.info.mpc.faultingComponent); LOG_INTERNAL(0, "Error: Panic(%s, %s), This=%x", cm_getDspName(coreId), reason_descrs[srcDescr->u.panic.panicReason].name, (void*)panicThis, 0, 0, 0); if(reason_descrs[srcDescr->u.panic.panicReason].interface != 0) { LOG_INTERNAL(0, ", interface=%s", itfName, 0, 0, 0, 0, 0); } if(reason_descrs[srcDescr->u.panic.panicReason].info1 != 0) { // Info 1 srcDescr->u.panic.info.mpc.panicInfo1 = cm_readAttributeNoError(ee, "rtos/commonpart/serviceInfo1"); LOG_INTERNAL(0, ", Info=%x", srcDescr->u.panic.info.mpc.panicInfo1, 0, 0, 0, 0, 0); } if(reason_descrs[srcDescr->u.panic.panicReason].PC != 0) { t_uint32 DspAddress = 0xFFFFFFFF; t_uint32 DspSize = 0x0; // PC need to be read in rtos/commonpart/serviceInfo1 srcDescr->u.panic.info.mpc.panicInfo1 = cm_readAttributeNoError(ee, "rtos/commonpart/serviceInfo1"); if(instance != 0) { cm_DSP_GetDspAddress(instance->memories[instance->Template->codeMemory->id], &DspAddress); cm_DSP_GetDspMemoryHandleSize(instance->memories[instance->Template->codeMemory->id], &DspSize); } if(DspAddress <= srcDescr->u.panic.info.mpc.panicInfo1 && srcDescr->u.panic.info.mpc.panicInfo1 < (DspAddress + DspSize)) LOG_INTERNAL(0, ", PC:off=%x ", srcDescr->u.panic.info.mpc.panicInfo1 - DspAddress, srcDescr->u.panic.info.mpc.panicInfo1, 0, 0, 0, 0); else LOG_INTERNAL(0, ", PC:", srcDescr->u.panic.info.mpc.panicInfo1, 0, 0, 0, 0, 0); } if(reason_descrs[srcDescr->u.panic.panicReason].SP != 0) { srcDescr->u.panic.info.mpc.panicInfo2 = cm_readAttributeNoError(ee, "rtos/commonpart/serviceInfo2"); LOG_INTERNAL(0, ", SP=%x", srcDescr->u.panic.info.mpc.panicInfo2, 0, 0, 0, 0, 0); } LOG_INTERNAL(0, "\n", 0, 0, 0, 0, 0, 0); if(instance != 0) { LOG_INTERNAL(0, "Error: Component=%s<%s>\n", instance->pathname, instance->Template->name, 0, 0, 0, 0); } // We don't set rtos/commonpart/serviceReason = MPC_SERVICE_NONE, since we don't want the // MMDSP to continue execution, and we put in in Panic state cm_DSP_SetStatePanic(coreId); } else { *srcType = CM_MPC_SERVICE_NONE; } return CM_OK; }