// 事件处理函数 //注意:该函数调用Read_Event_Status查询某个事件状态时,是该事件发生前的状态 //例如 某事件发生,调用该函数处理,则该函数内调用Read_Event_Status时返回0 // 相反,某事件结束,调用该函数处理,则该函数内调用Read_Event_Status时返回1 void Event_Data_Proc(INT8U Event_ID,INT8U Occur_Or_End) { INT8U Total_Event_ID; INT8U Clr_Demand_Man_Flag; INT8U Op_ID[4],Op_ID1[4]; _Debug_Print("\r\n++++++++++Event Data Proc,ID:%d,%s++++++++++",Event_ID,(Occur_Or_End EQ EVENT_OCCUR)?"Occur":"End"); Clr_Demand_Man_Flag = 0; if(Event_ID EQ ID_EVENT_CLR_DEMAND_MAN)//手动清需量转为通信清需量,同一事件ID处理,但是手动清需量的操作者ID为全FF { Clr_Demand_Man_Flag = 1; Event_ID = ID_EVENT_CLR_DEMAND_COM; //当前操作者id先备份 mem_set(Op_ID1, 0xFF, sizeof(Op_ID1), Op_ID1, sizeof(Op_ID1)); Store_Op_ID(Op_ID1, Op_ID, Op_ID, sizeof(Op_ID)); } else if(Event_ID EQ ID_EVENT_RELAY_ON || Event_ID EQ ID_EVENT_RELAY_OFF) //拉合闸,本地拉合闸记录操作者代码为FF { if(Relay_Status.Switch_Cause EQ S_OFF_PREPAID) //本地拉闸需要置操作者代码为全FF { mem_set(Op_ID1, 0xFF, sizeof(Op_ID1), Op_ID1, sizeof(Op_ID1)); Store_Op_ID(Op_ID1, Op_ID, Op_ID, sizeof(Op_ID)); } else //远程拉闸需要采用其操作者代码 { Store_Op_ID((INT8U *)Event_Data.Relay_Status.Op_ID, Op_ID, Op_ID, sizeof(Op_ID)); } } Event_Cumu_Proc(Event_ID,Occur_Or_End,EVENT_REAL); Total_Event_ID = Get_Total_Event_ID(Event_ID);//本事件对应的总计数也要处理 if(Total_Event_ID != NULL_EVENT_ID) { Debug_Print("Total Event Proc"); Event_Cumu_Proc(Total_Event_ID,Occur_Or_End,EVENT_REAL); } Event_Separate_Proc(Event_ID,Occur_Or_End,EVENT_REAL); //恢复操作者ID if(Clr_Demand_Man_Flag EQ 1) { Restore_Op_ID(Op_ID); } else if(Event_ID EQ ID_EVENT_RELAY_ON || Event_ID EQ ID_EVENT_RELAY_OFF) { Restore_Op_ID(Op_ID); } Debug_Print("++++++++++Event Data Proc:End++++++++++\r\n"); OS_TimeDly_Ms(10); //延迟10ms }
// Read the dial commands and send them to the modem. Wait for the expected response then move on to the next command. // Returns true if the last dial command has been processed. static bool LinkManagement_DialConnection(const char** DialCommands) { static char* ResponsePtr = NULL; char* CommandPtr = NULL; static uint8_t CharsMatched = 0; char c; if (USB_HostState != HOST_STATE_Configured) return false; while (!RingBuffer_IsEmpty(&Modem_ReceiveBuffer)) // Read back the response { c = RingBuffer_Remove(&Modem_ReceiveBuffer); Debug_PrintChar(c); if (c == *(ResponsePtr + CharsMatched)) // Match the response character by character with the expected response CharsMatched++; else CharsMatched = 0; if (CharsMatched != 0 && CharsMatched == strlen(ResponsePtr)) // Look for the expected response { DialSteps += 2; // Move on to the next dial command CharsMatched = 0; } } if (SystemTicks > 100) // Space each command by 1 second { CommandPtr = (char*)DialCommands[DialSteps]; ResponsePtr = (char*)DialCommands[DialSteps + 1]; if (CommandPtr == NULL || ResponsePtr == NULL) // No more dial commands { DialSteps = 0; return true; // Finished dialling } SystemTicks = 0; Debug_Print("Send: "); Debug_Print(CommandPtr); Debug_Print("(Expect: "); Debug_Print(ResponsePtr); Debug_Print(")\r\n"); while (*CommandPtr) RingBuffer_Insert(&Modem_SendBuffer, *(CommandPtr++)); // Send the command to the modem } return false; // Haven't finished dialling }
void ui_display_network_diagnostics(llabs_network_info_t* net_info, uint32_t ll_state) { char temp_string[LCD_COLUMNS+1]; if(NETWORK_DIAG_MENU != active_menu) { // nothing to do return; } if(1 == ll_state) //connected { sprintf(temp_string,"GW RSSI: %4ddBm ", net_info->rssi); strncpy(screen[MENU_LINE_1], temp_string, LCD_COLUMNS); sprintf(temp_string,"GW ID: %08X ", (unsigned int) net_info->gateway_id); strncpy(screen[MENU_LINE_2], temp_string, LCD_COLUMNS); sprintf(temp_string,"Ch/Frq: %02d/%u", net_info->gateway_channel, (unsigned int) net_info->gateway_frequency); strncpy(screen[MENU_LINE_3], temp_string, LCD_COLUMNS); } else if(3 == ll_state) //initializing { if(net_info->is_scanning_gateways) { Debug_Print("Scanning...\n"); sprintf(temp_string," Scanning ... "); } else { Debug_Print("Initializing #2\n"); sprintf(temp_string," Initializing ... "); } strncpy(screen[MENU_LINE_1], temp_string, LCD_COLUMNS); sprintf(temp_string," "); strncpy(screen[MENU_LINE_2], temp_string, LCD_COLUMNS); strncpy(screen[MENU_LINE_3], temp_string, LCD_COLUMNS); } else { sprintf(temp_string," Disconnected "); strncpy(screen[MENU_LINE_1], temp_string, LCD_COLUMNS); sprintf(temp_string," "); strncpy(screen[MENU_LINE_2], temp_string, LCD_COLUMNS); strncpy(screen[MENU_LINE_3], temp_string, LCD_COLUMNS); } // finish xTaskNotifyGive(s_screen_task_handle); }
//获得当前表示版本运行信息的办公室 void Debug_Print_Debug_Run_Info() { static S_Int8U Min = {CHK_BYTE, 0, CHK_BYTE}; static S_Int8U Counts ={CHK_BYTE, 0, CHK_BYTE}; INT8U Re; INT32U Mins; if(Check_Debug_En() EQ 0)//非工厂状态不打印 return; if(Cur_Time0.Time[T_MIN] EQ Min.Var)//每分钟执行一次该函数 return; Re = 1; Re &= CHECK_STRUCT_VAR(Min); Re &= CHECK_STRUCT_VAR(Counts); ASSERT(1 EQ Re); Min.Var = Cur_Time0.Time[T_MIN]; Counts.Var++; if(Counts.Var >= 5)//每隔5分钟打印一次当前调试运行时间 { Counts.Var = 0; if(OS_Get_Code_License_Flag() EQ CODE_LICENSE_ERR) { Mins = OS_Get_Debug_Run_Times(); Debug_Print("This is a Debug Version, Run Mins: %ld", Mins); } } }
//掉电保存事件数据 void Save_Event_PD_Data() { TRACE(); PwrOff_Proc_PUCK(); if(CHECK_STRUCT_SUM(Event_Data)) { mem_cpy((void *)&Event_Data.Meter_Instant_Status, (void *)&Meter_Instant_Status, sizeof(Meter_Instant_Status),\ (void *)&Event_Data.Meter_Instant_Status, sizeof(Event_Data.Meter_Instant_Status)); mem_cpy((void *)&Event_Data.Bat_Work_Status, (void *)&Bat_Work_Status, sizeof(Bat_Work_Status),\ (void *)&Event_Data.Bat_Work_Status, sizeof(Event_Data.Bat_Work_Status)); mem_cpy((void *)&Event_Data.Not_Even_Data, (void *)&Not_Even_Data_PUCK, sizeof(Not_Even_Data_PUCK),\ (void *)&Event_Data.Not_Even_Data, sizeof(Event_Data.Not_Even_Data)); mem_cpy((void *)&Event_Data.Prg_Key_Status, (void *)&Prg_Key_Status, sizeof(Prg_Key_Status),\ (void *)&Event_Data.Prg_Key_Status, sizeof(Event_Data.Prg_Key_Status)); // if(Get_Meter_Hard_Mode()==MODE_TEST) //自检模式掉电合闸 // Event_Data.Relay_Status = SWITCH_ON; //else //保存继电器状态和拉合闸原因 Event_Data.Relay_Status.Switch_Status = Relay_Status.Switch_Status; Event_Data.Relay_Status.Switch_Cause = Relay_Status.Switch_Cause; Event_Data.PD_Flag = 1; SET_STRUCT_SUM(Event_Data); Write_Storage_Data(_SDI_EVENT_DATA_PD, (void *)&Event_Data, sizeof(Event_Data)); } else Debug_Print("Save Event_PD_Data CS Error!!!"); }
//清除事件 void Clear_Event_Data(PROTO_DI Clr_PDI) { INT8U Re; Set_Clear_Data_Result(0); if(Check_Clear_Data_Authority() EQ 0) return; if(CLEAR_EVENT_FLAG!=Check_Clear_Data_Flag() && CLEAR_ALL_FLAG!=Check_Clear_Data_Flag()) return; Debug_Print("Clear_Event_Data, Clr_PDI = 0x%lx", Clr_PDI); if(Clr_PDI EQ 0xFFFFFFFF) { DISP_CLR_DATA_INFO; Clear_Event_Cumu_Data(); Clear_Event_Separate_Data(); Clear_VolStat_Data(); Clr_All_Event_Sram(); //清除内存中的事件数据,重新开始判定事件 Set_Clear_Data_Result(1); } else { Re = Clear_One_Event_Data((Clr_PDI & 0xFFFFFF00) | 0x01); if(Re EQ 0) //没有清除成功则将Clear_Event_PDI清零 { SET_STRUCT_SUM(Event_Data); Set_Clear_Data_Result(0); } else Set_Clear_Data_Result(1); } }
//写一条默认参数,参数标识为DI void Write_One_Def_Para(STORA_DI SDI) { INT16U i; INT16U Len; TRACE(); if(Check_Meter_Factory_Status() EQ 0)//当前不是工厂状态则推出 { Debug_Print("Write Def Para failed! not in factory status!"); return; } for(i = 0; i < S_NUM(Def_Para); i++) { if(SDI >= Def_Para[i].SDI && SDI < Def_Para[i].SDI + Def_Para[i].Num) { if(Check_Meter_Factory_Status() EQ 0)//当前不是工厂状态则推出 return; Len = Get_Storage_Data_Len(Def_Para[i].SDI); Write_Storage_Data(SDI, (void *) (Def_Para[i].pPara + (SDI - Def_Para[i].SDI) * Len), Len); return; } } }
bool TCPIP_Connect(void) { // Connect to the remote machine (www.example.com) uip_ipaddr(&RemoteIPAddress, 192, 0, 32, 10); TCPConnection = uip_connect(&RemoteIPAddress, UIP_HTONS(80)); if (TCPConnection != NULL) { Debug_Print("Connecting to host\r\n"); return true; } else { Debug_Print("Failed to Connect\r\n"); return false; } }
//清除掉电数据,数据全部置0 void Clr_Event_PD_Data() { TRACE(); Debug_Print("Clr_Event_PD_Data"); Clr_Event_PD_Ram_Data(); Write_Storage_Data(_SDI_EVENT_DATA_PD, (void *)&Event_Data, sizeof(Event_Data)); }
static void TCPIP_QueueData(const char* Data, const uint16_t Length) { if (Length > 0) WatchdogTicks = 0; // Reset the timeout counter for (uint16_t i = 0; i < Length; i++) putchar(Data[i]); Debug_Print("\r\n"); }
//检查是否需要设置默认参数 void Check_Boot_On_Flag() { INT32U Boot_Flag; INT32U Chk_Flag; INT8U i, Set_Def_Para_Flag = 0; TRACE(); //检查存储系统映射是否发生修改,如果发生了修改,则需要在工厂状态下重置默认参数!!! Chk_Flag = Get_Storage_Info_CS(); //获取整个存储系统的校验信息,如果发生修改则整个校验信息会发生改变 if(Read_Storage_Data(_SDI_BOOT_FLAG, &Boot_Flag, &Boot_Flag, sizeof(Boot_Flag)) != sizeof(Boot_Flag) || \ Chk_Flag != Boot_Flag) { Debug_Print("Sys Storage Map Modified or first time boot!!! Flag0 = %lx, Flag1 = %lx", Chk_Flag, Boot_Flag); //没有设置默认参数则显示No Para if(Check_Meter_Factory_Status() EQ 0)//非工厂状态下,在工厂状态下面会直接设参数 { for(i = 0; i < 10; i ++) { Clear_All_Dog(); Beep_For_Para(); Main_Dis_Info("NO PArA"); OS_TimeDly_Ms(300); } } Set_Def_Para_Flag = 1; //需要重置默认参数 } if(Check_Meter_Factory_Status() EQ 1)//只有在工厂状态才能设置默认参数 { if(Check_Sys_Status() EQ SYS_NORMAL)//系统电源正常的情况下才进行数据冻结和需量处理 { //Check_Sys_Storage();//存储器自检 if(Set_Def_Para_Flag EQ 1) { Read_Ext_RTC_Status();//第一次上电读取一下外部时钟!震荡器停止状态位清除,避免报警 Write_Def_Para(); if(Check_Meter_Factory_Status() EQ 1) { Boot_Flag = Chk_Flag; Write_Storage_Data(_SDI_BOOT_FLAG, &Boot_Flag, sizeof(Boot_Flag)); } Init_All_Channel();//重新初始化各通道 } } } }
//初始化过程中检测代码校验是否正确 void Init_Check_Code_License(void) { INT8U i; INT32U Code_ID; INT8U Mode; OS_Debug_Print_Version_Date(); //打印操作系统的时间和版本号 OS_Get_Code_ID((INT8U *)&Code_ID, (INT8U *)&Code_ID, sizeof(Code_ID)); Debug_Print("Code_ID: %lx", Code_ID); if(OS_Get_Code_License_Flag() EQ CODE_LICENSE_ERR) { Debug_Print("License_Key Error, System run in debug mode!!!"); for(i = 0; i < 4; i ++) { Code_License_Err_Proc("DEBUG"); Clear_All_Dog(); OS_TimeDly_Ms(200); } } else { Debug_Print("License_Key correct!!!"); } #if METER_DEBUG_EN > 0 Mode = Get_Meter_Hard_Mode(); if(Mode EQ MODE_FAC || Mode EQ MODE_DEBUG) //工厂或者调试模式 { for(i = 0; i < 4; i ++) { Code_License_Err_Proc("DEBUG-1"); Clear_All_Dog(); OS_TimeDly_Ms(200); } } #endif }
static void ui_display_gw_info_dl_strength(llabs_network_info_t* net_info, uint32_t ll_state) { char gw_strength_string[13]; uint32_t i; int16_t rssi_tmp; char temp_char; if(1 == ll_state) //connected { // construct strength meter, each square represents 10dB rssi_tmp = net_info->rssi + RSSI_METER_MIN; for(i=0; i<sizeof(gw_strength_string)-1; i++) { if(rssi_tmp > 0) { gw_strength_string[i] = 0xFF; // black square } else { gw_strength_string[i] = ' '; // blank square } rssi_tmp -= RSSI_METER_STEP; } gw_strength_string[sizeof(gw_strength_string)-1] = 0; temp_char = screen[MENU_LINE_1][0]; // have to save the first character of next line, since sprintf will put a null there sprintf(screen[MENU_TITLE_LINE],"GW:%s %+4d", gw_strength_string, net_info->rssi); screen[MENU_LINE_1][0] = temp_char; } else if(3 == ll_state) //initializing { if(net_info->is_scanning_gateways) { temp_char = screen[MENU_LINE_1][0]; // have to save the first character of next line, since sprintf will put a null there sprintf(screen[MENU_TITLE_LINE],"%s", "Scanning for GW... "); screen[MENU_LINE_1][0] = temp_char; } else { temp_char = screen[MENU_LINE_1][0]; // have to save the first character of next line, since sprintf will put a null there Debug_Print("Initializing #1\n"); sprintf(screen[MENU_TITLE_LINE],"%s", "Initializing... "); screen[MENU_LINE_1][0] = temp_char; } } else { temp_char = screen[MENU_LINE_1][0]; // have to save the first character of next line, since sprintf will put a null there sprintf(screen[MENU_TITLE_LINE],"%s", "Disconnected. "); screen[MENU_LINE_1][0] = temp_char; } }
void LinkManagement_ManageConnectionState(void) { switch (ConnectedState) { case LINKMANAGEMENT_STATE_Idle: SystemTicks = 0; DialSteps = 0; PPP_InitPPP(); ConnectedState = LINKMANAGEMENT_STATE_SendModemDialCommands; break; case LINKMANAGEMENT_STATE_SendModemDialCommands: if (LinkManagement_DialConnection(ModemDialCommands)) ConnectedState = LINKMANAGEMENT_STATE_SendNetworkDialCommands; break; case LINKMANAGEMENT_STATE_SendNetworkDialCommands: if (LinkManagement_DialConnection(NetworkDialCommands)) { Debug_Print("Starting PPP\r\n"); PPP_StartLink(); ConnectedState = LINKMANAGEMENT_STATE_WaitForLink; } break; case LINKMANAGEMENT_STATE_WaitForLink: PPP_ManageLink(); break; case LINKMANAGEMENT_STATE_InitializeTCPStack: PPP_ManageLink(); TCPIP_InitializeTCPStack(); break; case LINKMANAGEMENT_STATE_ConnectToRemoteHost: PPP_ManageLink(); TCPIP_ConnectToRemoteHost(); break; case LINKMANAGEMENT_STATE_ManageTCPConnection: PPP_ManageLink(); TCPIP_TCPIPTask(); break; } }
void I2cSoft_Reset(INT8U Id) { INT8U i; Debug_Print("IIC_Error----->Reset I2c_Soft Device,Id=%d!",Id); ASSERT_FAILED(); I2cSoft_Start(Id); CONST_I2C_PORT[Id].Set_Sclk_Pin(0); CONST_I2C_PORT[Id].Set_Sda_Pin(1); //SDA置1,SCL脉冲,释放总线 for(i=0; i<=9; i++) { CONST_I2C_PORT[Id].Set_Sclk_Pin(1); //SCL变高,锁存数据 CONST_I2C_PORT[Id].Set_Sclk_Pin(0); } I2cSoft_Start(Id); I2cSoft_Stop(Id); I2cSoft_Open(Id); }
void TCPIP_InitializeTCPStack(void) { Debug_Print("Init TCP Stack\r\n"); // Periodic Connection Timer Initialization timer_set(&Periodic_Timer, CLOCK_SECOND / 2); // uIP Initialization network_init(); clock_init(); uip_init(); // Set this machine's IP address uip_ipaddr_t LocalIPAddress; uip_ipaddr(&LocalIPAddress, IPAddr1, IPAddr2, IPAddr3, IPAddr4); uip_sethostaddr(&LocalIPAddress); ConnectedState = LINKMANAGEMENT_STATE_ConnectToRemoteHost; SystemTicks = 2000; // Make the first CONNECT happen straight away }
//写默认参数到存储器中,该函数必须在工厂状态下才能执行 void Write_Def_Para() { //INT8U Temp[10]; //INT16U Len; TRACE(); //判断是否需要重写校表参数,能够读出C相电流参数设置,说明已经置过默认参数了,就不置了 /* Len = Get_Storage_Data_Len(_SDI_ADJ_METER_C_CUR); if(Read_Storage_Data_Fix_Len(_SDI_ADJ_METER_C_CUR, 0, Len, Temp, Temp, sizeof(Temp)) EQ 0) //读不出来校表参数??重写之 { Debug_Print("Write Def Adj Para"); Set_Def_Adj_Para(); } */ Set_Def_Para_Except_Adj(); /* for(i = 0; i < S_NUM(Def_Para); i++) { if(Check_Meter_Factory_Status() EQ 0)//当前不是工厂状态则推出 return; Len = Get_Storage_Data_Len(Def_Para[i].SDI); for(j = 0; j < Def_Para[i].Num; j++) { if(Check_Meter_Factory_Status() EQ 0) return; //if(!(Def_Para[i].SDI+j>=0xCEE0 && Def_Para[i].SDI+j<=0xCEED))//test Write_Storage_Data(Def_Para[i].SDI + j, (void *) (Def_Para[i].pPara + j * Len), Len); } } */ Set_Def_Prepaid_Buy_Counts_Money(); //够电次数和金额需要单独设置 Set_All_Def_Data(); Set_Def_Prepaid_Money(); //置默认金额 Turn_Light_Off(); //关闭背光 Debug_Print("--------------Set Def Para End!------------"); }
//全失压数据累加处理 //Start_Time表示起始时间,Start_Time[0]->Start_Time[4]表示分、时、日、月、年,BCD码 //End_Time表示终止时间,End_Time[0]->End_Time[4]表示分、时、日、月、年,BCD码 //上电后,对上电前的前N(N<=10)次全失压,调用该函数N次 void All_Loss_Vol_Data_Proc(INT8U Start_Time[],INT8U End_Time[], INT32U Curr) { TRACE(); Debug_Print("All_Loss_Vol Start_Time:%x-%x-%x %x:%x, End_Time:%x-%x-%x %x:%x, Curr:%ld",\ Start_Time[4],Start_Time[3],Start_Time[2],Start_Time[1],Start_Time[0],\ End_Time[4],End_Time[3],End_Time[2],End_Time[1],End_Time[0], Curr); All_Loss_Vol_Time.Curr = Curr; //电流 //All_Loss_Vol_Time.Start_Time[0] = 0; //全失压发生的s //All_Loss_Vol_Time.End_Time[0] = 0; mem_cpy((INT8U *)All_Loss_Vol_Time.Start_Time, Start_Time, 6, (void *)All_Loss_Vol_Time.Start_Time,sizeof(All_Loss_Vol_Time.Start_Time)); mem_cpy((INT8U *)All_Loss_Vol_Time.End_Time, End_Time, 6, (void *)All_Loss_Vol_Time.End_Time,sizeof(All_Loss_Vol_Time.End_Time)); SET_STRUCT_SUM(All_Loss_Vol_Time); Event_Separate_Proc(ID_EVENT_ALL_LOSS_VOLT, EVENT_OCCUR, EVENT_REAL); Event_Separate_Proc(ID_EVENT_ALL_LOSS_VOLT, EVENT_END, EVENT_REAL); Write_Storage_Data(SDI_LAST_LOSS_VOL_OCCUR_TIME, (void *)All_Loss_Vol_Time.Start_Time, 6);//最近一次全失压发生和结束时刻 Write_Storage_Data(SDI_LAST_LOSS_VOL_END_TIME, (void *)All_Loss_Vol_Time.End_Time, 6); }
void DumpPacket(void) { int i, j; if (!DebugModeEnabled) return; Debug_Print("(Protocol = 0x"); Debug_PrintHex(PacketProtocol / 256); Debug_PrintHex(PacketProtocol & 255); Debug_Print("):\r\n"); for (i = 0; i < uip_len; i += 16) { Debug_PrintHex(i / 256); Debug_PrintHex(i & 255); Debug_Print(": "); for (j = 0; j < 16; j++) { if ((i + j) >= uip_len) break; Debug_PrintHex(*(uip_buf + i + j)); Debug_PrintChar(' '); } Debug_Print("\r\n "); for (j = 0; j < 16; j++) { if ((i + j) >= uip_len) break; if (*(uip_buf + i + j) >= 0x20 && *(uip_buf + i + j) <= 0x7e) { Debug_PrintChar(' '); Debug_PrintChar(*(uip_buf + i + j)); Debug_PrintChar(' '); } else Debug_Print(" . "); } Debug_Print("\r\n"); } }
/********************************************************************************** 函数功能:检查配置表是否配置矛盾 入口: 无 出口: 无 **********************************************************************************/ void Chk_Table_Conflict(void) { #ifdef CONFLICT_TAB_CHKEN INT16U i; INT8U Flag,Result=1; Debug_Print("Check LCD Soft Table Conflict......................."); for(i=1;i<MAX_S_NUM;i++) { Flag=SetOrClrPixPiyDot(LCD_S_Const[i].Sign,1,Sx); if(!Flag) { Result=0; Debug_Print("LCD_TABLE Error---->Config Table Error,Sign=S%d\n",LCD_S_Const[i].Sign); } } for(i=1;i<MAX_D_NUM;i++) { Flag=SetOrClrPixPiyDot(LCD_D_Const[i].Sign,1,Dx); if(!Flag) { Result=0; Debug_Print("LCD_TABLE Error---->Config Table Error,Sign=D%d\n",LCD_D_Const[i].Sign); } } for(i=1;i<MAX_N_NUM;i+=7) //7个seg为一个单位 { Flag=SetOrClrPixPiyDot(LCD_N_Const[i].Sign,1,Nx); if(!Flag) { Result=0; Debug_Print("LCD_TABLE Error---->Config Table Error,Sign=N%d\n",LCD_N_Const[i].Sign); } } if(Result) Debug_Print("LCD Soft Table no Conflicet,Succeed!"); else Debug_Print("LCD Soft Table Conflicet,Failed!"); InitLcdAllRam(); #endif }
// USB Modems make use of a feature called USB mode switching. You can read about it at http://www.draisberghof.de/usb_modeswitch/ // Depending on the modem you will have to define different commands to switch the modem from storage mode to modem mode. // One way to determine the correct command is to run the modem under Windows and use USBMonitor // (http://www.hhdsoftware.com/Downloads/usb-monitor.html) to determine what commands are sent to the modem. // Another method is to look at the code at http://www.draisberghof.de/usb_modeswitch/ to see if the codes for your modem have already been determined. // // This function returns: // true if the modem has been enumerated correctly // false if there is an error, or if we must wait for the modem to disconnect bool ProcessModemUSBStates(void) { uint8_t ErrorCode; Debug_Print("Send configuration command\r\n"); if ((ErrorCode = USB_Host_SetDeviceConfiguration(1)) != HOST_SENDCONTROL_Successful) { Debug_Print("Control error (Set Config)\r\n"); Debug_PrintHex(ErrorCode); LEDs_SetAllLEDs(LEDMASK_USB_ERROR); // Indicate error via status LEDs return false; } Debug_Print("Looking for modem device..."); // Get and process the configuration descriptor data // First time through we expect a non-modem device. Once the device has disconnected and re-attached it should be OK if ((ErrorCode = ProcessConfigurationDescriptor()) != SuccessfulConfigRead) { if (ErrorCode == ControlError) { Debug_Print("Control error (Get Configuration)\r\n"); Debug_PrintHex(ErrorCode); LEDs_SetAllLEDs(LEDMASK_USB_ERROR); // Indicate error via status LEDs return false; } else { Debug_Print("Not a modem device - switching modes\r\n"); USB_Host_SuspendBus(); // This will cause the device to disconnect and reconnect in modem mode return false; // Wait until USB device disconnects } } Debug_Print("Modem device enumerated\r\n"); return true; }
//#undef Debug_Print //#define Debug_Print _Debug_Print //全失压次数和时间统计 //上电后调用该函数一次,Counts表示掉电期间失压总次数,Mins表示掉电期间失压总分钟数 void All_Loss_Vol_Counts_Time_Proc(INT32U Counts,INT32U Mins) { //INT16U Re; //INT8U Temp[20]; INT32U Counts0,Mins0; INT16U Len; TRACE(); Debug_Print("All_Loss_Vol Counts:%ld, Mins:%ld", Counts, Mins); OS_Mutex_Pend(PUB_BUF0_SEM_ID); Len = Read_Storage_Data(EC_DI(0x03050000), (void *)Pub_Buf0, (void *)Pub_Buf0, sizeof(Pub_Buf0)); if(Len EQ 0) { ASSERT_FAILED(); Len = Read_Storage_Data(EC_DI(0x03050001), (void *)Pub_Buf0, (void *)Pub_Buf0, sizeof(Pub_Buf0)); } if(Len > 0) { mem_cpy(&Counts0, (INT8U *)Pub_Buf0 + 5, 4, &Counts0, sizeof(Counts0)); mem_cpy(&Mins0, (INT8U *)Pub_Buf0 + 9, 4, &Mins0, sizeof(Mins0)); } else { Counts0 = 0; Mins0 = 0; } Counts0 += Counts; Mins0 += Mins; Debug_Print("Total_All_Loss_Vol Counts:%ld, Mins:%ld", Counts0, Mins0); mem_cpy((INT8U *)Pub_Buf0 + 5, &Counts0, 4, (INT8U *)Pub_Buf0, sizeof(Pub_Buf0)); mem_cpy((INT8U *)Pub_Buf0 + 9, &Mins0, 4, (INT8U *)Pub_Buf0, sizeof(Pub_Buf0)); Write_Storage_Data(EC_DI(0x03050000), (INT8U *)Pub_Buf0, 13); Write_Storage_Data(EC_DI(0x03050001), (INT8U *)Pub_Buf0, 13); OS_Mutex_Post(PUB_BUF0_SEM_ID); /* Re=Read_Storage_Data(0x03050000,Temp,Temp,sizeof(Temp)); if(0 EQ Re) { ASSERT(0); Counts0 = Counts; Mins0 = Mins; } else { Counts0 = Bcd2Hex(Temp, 3); Mins0 = Bcd2Hex(Temp + 3, 3); Counts0 += Counts;//Bcd2Hex(Temp + 5, 4); Mins0 += Mins;//Bcd2Hex(Temp + 9, 4); Hex2Bcd(Counts0, Temp, 3, Temp, sizeof(Temp)); Hex2Bcd(Mins0, Temp + 3, 3, Temp, sizeof(Temp)); } Re=Write_Storage_Data(0x03050000, (void *)&Temp, 6); ASSERT(1 EQ Re); */ //---------------------------------- //对总的失压次数和时间进行统计 if(Get_Total_Event_ID(ID_EVENT_ALL_LOSS_VOLT) EQ ID_EVENT_TOTAL_LOSS_VOL)//全失压的时间和次数是否进入总失压和次数? { OS_Mutex_Pend(PUB_BUF0_SEM_ID); Len = Read_Storage_Data(EC_DI(0x10000101), (void *)Pub_Buf0, (void *)Pub_Buf0, sizeof(Pub_Buf0)); if(Len > 0) { mem_cpy(&Counts0, (INT8U *)Pub_Buf0 + 5, 4, &Counts0, sizeof(Counts0)); mem_cpy(&Mins0, (INT8U *)Pub_Buf0 + 9, 4, &Mins0, sizeof(Mins0)); Counts0 += Counts; Mins0 += Mins; Debug_Print("Total_Loss_Vol Counts:%ld, Mins:%ld", Counts0, Mins0); mem_cpy((INT8U *)Pub_Buf0 + 5, &Counts0, 4, (INT8U *)Pub_Buf0, sizeof(Pub_Buf0)); mem_cpy((INT8U *)Pub_Buf0 + 9, &Mins0, 4, (INT8U *)Pub_Buf0, sizeof(Pub_Buf0)); Write_Storage_Data(EC_DI(0x10000101), (INT8U *)Pub_Buf0, Len); } OS_Mutex_Post(PUB_BUF0_SEM_ID); } }
uint16_t network_read(void) { uint8_t c; while (!RingBuffer_IsEmpty(&Modem_ReceiveBuffer)) { c = RingBuffer_Remove(&Modem_ReceiveBuffer); switch (PacketState) { case PACKET_STATE_NULL: if (c == 0x7e) // New Packet { PacketState = PACKET_STATE_INHEADER; // We're now in the header PacketLength = 0; CurrentChecksum = 0xffff; // Start new checksum } break; case PACKET_STATE_INHEADER: if (c == 0x7d) // Escaped character. Set flag and process next time around { Escape = true; continue; } else if (Escape) // Escaped character. Process now. { Escape = false; c = (c ^ 0x20); } if (PacketLength == 1 && c != 0xff) // Should be 0xff. If not then Address-and-Control-Field-Compression is switched on { PacketLength += 2; // Adjust the length as if the 0xff 0x03 was there } if (PacketLength == 3) { if (c & 1) // Should be even. If it's odd then Protocol-Field-Compression is switched on { PacketProtocol = 0x00; // Add in the initial 0x00 PacketLength++; // Adjust the length as if the 0x00 was there } else PacketProtocol = c * 256; // Store the MSB of the protocol } if (PacketLength == 4) // End of header { PacketProtocol |= c; // Store the LSB of the protocol PacketLength = -1; // This will be incremented to 0 at the end of this loop Escape = false; PacketState = PACKET_STATE_INBODY; // We're now in the body } CurrentChecksum = CALC_CRC16(CurrentChecksum, c); // Calculate checksum break; case PACKET_STATE_INBODY: if (c == 0x7e) // End of packet { uip_len = PacketLength - 2; // Strip off the checksum and framing Escape = false; PacketState = PACKET_STATE_NULL; // Back to waiting for a header Debug_Print("\r\nReceive "); DumpPacket(); if (~TwoBackChecksum == (*(uip_buf + PacketLength - 1) * 256 + *(uip_buf + PacketLength - 2))) return PacketProtocol; else Debug_Print("Bad CRC\r\n"); } else { if (c == 0x7d) // Escaped character. Set flag and process next time around { Escape = true; continue; } else if (Escape) // Escaped character. Process now. { Escape = false; c = (c ^ 0x20); } *(uip_buf + PacketLength) = c; // Store the character in the buffer TwoBackChecksum = OneBackChecksum; // Keep a rolling count of the last 3 checksums OneBackChecksum = CurrentChecksum; // Eventually we need to see if the checksum is valid CurrentChecksum = CALC_CRC16(CurrentChecksum, c); // and we need the one two back (as the current one includes the checksum itself) } break; } PacketLength++; // Increment the length of the received packet } return 0; // No data or packet not complete yet }
void network_send(uint16_t protocol) { unsigned int checksum = 0xffff; PacketProtocol = protocol; PacketState = PACKET_STATE_NULL; Debug_Print("\r\nSend "); DumpPacket(); // Send out the packet with HDLC-like framing - see http://tools.ietf.org/html/rfc1662 // Start with the framing flag RingBuffer_Insert(&Modem_SendBuffer, 0x7e); // Address RingBuffer_Insert(&Modem_SendBuffer, 0xff); checksum = CALC_CRC16(checksum, 0xff); // Control RingBuffer_Insert(&Modem_SendBuffer, 0x03); checksum = CALC_CRC16(checksum, 0x03); // Protocol RingBuffer_Insert(&Modem_SendBuffer, protocol / 256); checksum = CALC_CRC16(checksum, protocol / 256); RingBuffer_Insert(&Modem_SendBuffer, protocol & 255); checksum = CALC_CRC16(checksum, protocol & 255); // Add the information, escaping it as necessary for (uint16_t i = 0; i < uip_len; i++) { if (*(uip_buf + i) < 0x20 || *(uip_buf + i) == 0x7d || *(uip_buf + i) == 0x7e) { RingBuffer_Insert(&Modem_SendBuffer, 0x7d); RingBuffer_Insert(&Modem_SendBuffer, *(uip_buf + i) ^ 0x20); } else { RingBuffer_Insert(&Modem_SendBuffer, *(uip_buf + i)); } checksum = CALC_CRC16(checksum, *(uip_buf + i)); if (RingBuffer_GetCount(&Modem_SendBuffer) >= 64) // Periodically flush the buffer to the modem USBManagement_SendReceivePipes(); } // Add the checksum to the end of the packet, escaping it as necessary checksum = ~checksum; if ((checksum & 255) < 0x20 || (checksum & 255) == 0x7d || (checksum & 255) == 0x7e) { RingBuffer_Insert(&Modem_SendBuffer, 0x7d); RingBuffer_Insert(&Modem_SendBuffer, (checksum & 255) ^ 0x20); } else { RingBuffer_Insert(&Modem_SendBuffer, checksum & 255); // Insert checksum MSB } if ((checksum / 256) < 0x20 || (checksum / 256) == 0x7d || (checksum / 256) == 0x7e) { RingBuffer_Insert(&Modem_SendBuffer, 0x7d); RingBuffer_Insert(&Modem_SendBuffer, (checksum / 256) ^ 0x20); } else { RingBuffer_Insert(&Modem_SendBuffer, checksum / 256); // Insert checksum LSB } RingBuffer_Insert(&Modem_SendBuffer, 0x7e); // Framing uip_len = 0; USBManagement_SendReceivePipes(); // Flush the rest of the buffer }
//上电事件处理 //上电事件处理 void PowerOn_Event_Proc() { //上电初始化过程中不需要关掉电中断,因为在此过程中掉电不会存数 if(Get_Sys_Status() != SYS_NORMAL) return; Debug_Print("----------PowerOn Event Proc Start----------"); //读出的掉电数据正确且确实发生了掉电 if(Read_Storage_Data(_SDI_EVENT_DATA_PD,(void *)&Event_Data,(void *)&Event_Data,sizeof(Event_Data)) != sizeof(Event_Data)) { Clr_Event_PD_Data(); } else if(Event_Data.PD_Flag EQ 1) { mem_cpy((void *)&Meter_Instant_Status,(void *)&Event_Data.Meter_Instant_Status,sizeof(Event_Data.Meter_Instant_Status),\ (void *)&Meter_Instant_Status,sizeof(Meter_Instant_Status)); mem_cpy((void *)&Bat_Work_Status,(void *)&Event_Data.Bat_Work_Status,sizeof(Event_Data.Bat_Work_Status),\ (void *)&Bat_Work_Status,sizeof(Bat_Work_Status)); mem_cpy((void *)&Not_Even_Data_PUCK, (void *)&Event_Data.Not_Even_Data, sizeof(Event_Data.Not_Even_Data),\ (void *)&Not_Even_Data_PUCK, sizeof(Not_Even_Data_PUCK)); mem_cpy((void *)&Prg_Key_Status, (void *)&Event_Data.Prg_Key_Status, sizeof(Event_Data.Prg_Key_Status),\ (void *)&Prg_Key_Status, sizeof(Prg_Key_Status)); Relay_Status.Switch_Status = Event_Data.Relay_Status.Switch_Status; Relay_Status.Switch_Cause = Event_Data.Relay_Status.Switch_Cause; //设置掉电前时间为当前时间,用于处理掉电前事件 Set_BCD_Array_Time((S_BCD_Time *)&Event_Data.Time, (S_Event_Time *)&Cur_Time2, (S_Event_Time *)&Cur_Time2, sizeof(Cur_Time2)); Init_PD_PO_Time(); //初始化上电和掉电时间 Save_LastPwrOff_Data_PUCK();//上次掉电数据处理 //重新覆盖Cur_Time1时间 Set_BCD_Array_Time((S_BCD_Time *)&Cur_Time1, (S_Event_Time *)&Cur_Time2, (S_Event_Time *)&Cur_Time2, sizeof(Cur_Time2)); /* //密码锁 if(CHECK_STRUCT_SUM(Event_Data._PSW_Err_Info) EQ 0 || CHECK_STRUCT_VAR(Event_Data._PSW_Err_Info) EQ 0) { ASSERT_FAILED(); mem_set((void *)&PSW_Err_Info, 0, sizeof(PSW_Err_Info),(void *)&PSW_Err_Info, sizeof(PSW_Err_Info)); INIT_STRUCT_VAR(PSW_Err_Info); SET_STRUCT_SUM(PSW_Err_Info); SET_STRUCT_SUM(Event_Data); } PSW_Err_Info.Set_En_Mins = 0; //设置有效时间应该清除 SET_STRUCT_SUM(PSW_Err_Info); */ //前一次冻结时间 if(CHECK_STRUCT_SUM(Event_Data._Last_Freeze_Time) EQ 0) { ASSERT_FAILED(); mem_set((void *)&Last_Freeze_Time, 0, sizeof(Last_Freeze_Time), (void *)&Last_Freeze_Time, sizeof(Last_Freeze_Time)); SET_STRUCT_SUM(Last_Freeze_Time); SET_STRUCT_SUM(Event_Data); } //事件瞬态字 mem_set((void *)&Event_Data.Meter_Instant_Status,0,sizeof(Event_Data.Meter_Instant_Status),\ (void *)&Event_Data.Meter_Instant_Status,sizeof(Event_Data.Meter_Instant_Status)); SET_STRUCT_SUM(Event_Data.Meter_Instant_Status); //编程记录 if(CHECK_STRUCT_SUM(Prog_Record) EQ 0) Clr_Prog_Record_Ram(); //编程操作者代码 mem_set((void *)&Event_Data._Operator_ID,0,sizeof(Event_Data._Operator_ID),\ (void *)&Event_Data._Operator_ID,sizeof(Event_Data._Operator_ID)); SET_STRUCT_SUM(Event_Data._Operator_ID); //需量越限记录 mem_set((void *)&Event_Data._Demand_Exceed_Limit,0,sizeof(Event_Data._Demand_Exceed_Limit),\ (void *)&Event_Data._Demand_Exceed_Limit,sizeof(Event_Data._Demand_Exceed_Limit)); SET_STRUCT_SUM(Event_Data._Demand_Exceed_Limit); //前一次校时时间 /* mem_set((void *)&Event_Data._Last_Adj_Time,0,sizeof(Event_Data._Last_Adj_Time),\ (void *)&Event_Data._Last_Adj_Time,sizeof(Event_Data._Last_Adj_Time)); SET_STRUCT_SUM(Event_Data._Last_Adj_Time); */ //当前时间 mem_cpy((void *)&Event_Data.Time,(void *)&Cur_Time1,sizeof(Cur_Time1),(void *)&Event_Data.Time,sizeof(Event_Data.Time)); Event_Data.PD_Flag = 0; SET_STRUCT_SUM(Event_Data); Write_Storage_Data(_SDI_EVENT_DATA_PD,(void *)&Event_Data,sizeof(Event_Data)); } else { Debug_Print("PD_Flag != 1"); } Debug_Print("----------PowerOn Event Proc End----------"); }
void TestSIM908(void *p_arg) { enum TRANSPORT_Event event; OS_ERR error; uint32_t recv_length; (void)p_arg; // uint32_t temp; // temp = list_string("aaaaa", list, ','); // temp = list_string("bbbbb", list, ','); // temp = list_string("cccccd", list, ','); // temp = list_string("dddde", list, ','); // temp = list_string("fee", list, ','); // temp = list_string("gd", list, ','); // temp = list_string("0123as", list, ','); // temp = list_string("0000df", list, ','); // // (void)temp; // while(1); // SIM90x_WaitResponseList2(1000, "aaa", "bbb", "ccc", "ddd", 0); // SIM90x_WaitResponseList2(2000, "000", "111111", "2445", "7777", 0); // SIM90x_WaitResponseList2(3000, "aaa", "bbb", "ccc", "ddd", "7777", 0); // SIM90x_WaitResponseList2(4000, "aaa", "bbb", "ccc", "ddd", "7777", "7777", 0); Debug_Print("Debug Test: %4d, %s, %4x...\n", 57, "abcdef", 88); Debug_Print("GPRS Init...\n"); TP_USART2.init((void*)0); SIM90x_Init(&TP_USART2); // TP_GPRS.setEventHandler() TP_GPRS.init((struct GPRS_CONFIG*)&eeyyyee_xicp_net); while(1) { event = TP_GPRS.waitEventTrigger(TRANSPORT_Event_Disconnect, 1); if( event == TRANSPORT_Event_Disconnect ) { Debug_Print("GPRS Reconnecting...\n"); GPRS_SwitchTMode(false); TP_GPRS.init( (struct GPRS_CONFIG*)&eeyyyee_xicp_net ); } event = TP_GPRS.waitEventTrigger(TRANSPORT_Event_RecvDone, 5000); if( event == TRANSPORT_Event_RecvDone ) { Debug_Print("GPRS data Recved...\n"); recv_length = TP_GPRS.recv( GPRS_RecvBuffer, sizeof(GPRS_RecvBuffer) ); Debug_Print("Recv: %s\n", GPRS_RecvBuffer); memset( GPRS_RecvBuffer, 0x00, recv_length ); } else { Debug_Print("GPRS No data Recved ...\n"); TP_GPRS.send(test0, strlen((const char*)test0)); } } }
void TCPIP_TCPCallback(void) { if (uip_acked()) Debug_Print("[ACK] "); if (uip_newdata()) { Debug_Print("New Data:\r\n"); TCPIP_QueueData(uip_appdata, uip_datalen()); if (TCPIP_IsDataQueueFull()) uip_stop(); } if (uip_connected()) { Debug_Print("Connected - Maximum Segment Size: 0x"); Debug_PrintHex(uip_mss() / 256); Debug_PrintHex(uip_mss() & 255); Debug_Print("\r\n"); } if (uip_closed()) { Debug_Print("Closed - Reconnecting..."); _delay_ms(1000); ConnectedState = LINKMANAGEMENT_STATE_ConnectToRemoteHost; } if (uip_aborted()) { Debug_Print("Aborted - Reconnecting... "); _delay_ms(1000); ConnectedState = LINKMANAGEMENT_STATE_ConnectToRemoteHost; } if (uip_timedout()) { Debug_Print("Timeout - Reconnecting..."); uip_abort(); _delay_ms(1000); ConnectedState = LINKMANAGEMENT_STATE_ConnectToRemoteHost; } if (uip_poll() && (SystemTicks > 3000)) { SystemTicks = 0; Debug_Print("\r\nSending GET\r\n"); TCPIP_SendGET(); } if (uip_rexmit()) { Debug_Print("\r\nRetransmit GET\r\n"); TCPIP_SendGET(); } if (uip_poll() && uip_stopped(TCPConnection)) { if (!(TCPIP_IsDataQueueFull())) uip_restart(); } }
bool Builder::spawn_process(const char* exe_name, const StringList& args, const StringListKV& env, const ::helpers::path& logfile, const ::helpers::path& working_directory/*={}*/) const { #ifdef _WIN32 ::std::stringstream cmdline; cmdline << exe_name; for (const auto& arg : args.get_vec()) // TODO: Escaping cmdline << " " << arg; auto cmdline_str = cmdline.str(); if(true) { ::std::cout << "> " << cmdline_str << ::std::endl; } else { DEBUG("Calling " << cmdline_str); } #if 0 // TODO: Determine required minimal environment, to avoid importing the entire caller environment ::std::stringstream environ_str; environ_str << "TEMP=" << getenv("TEMP") << '\0'; environ_str << "TMP=" << getenv("TMP") << '\0'; for(auto kv : env) { environ_str << kv.first << "=" << kv.second << '\0'; } environ_str << '\0'; #else for(auto kv : env) { _putenv_s(kv.first, kv.second); } #endif CreateDirectory(static_cast<::std::string>(logfile.parent()).c_str(), NULL); STARTUPINFO si = { 0 }; si.cb = sizeof(si); si.dwFlags = STARTF_USESTDHANDLES; si.hStdInput = NULL; si.hStdError = GetStdHandle(STD_ERROR_HANDLE); { SECURITY_ATTRIBUTES sa = { 0 }; sa.nLength = sizeof(sa); sa.bInheritHandle = TRUE; si.hStdOutput = CreateFile( static_cast<::std::string>(logfile).c_str(), GENERIC_WRITE, FILE_SHARE_READ, &sa, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); DWORD tmp; WriteFile(si.hStdOutput, cmdline_str.data(), static_cast<DWORD>(cmdline_str.size()), &tmp, NULL); WriteFile(si.hStdOutput, "\n", 1, &tmp, NULL); } PROCESS_INFORMATION pi = { 0 }; CreateProcessA(exe_name, (LPSTR)cmdline_str.c_str(), NULL, NULL, TRUE, 0, NULL, (working_directory != ::helpers::path() ? working_directory.str().c_str() : NULL), &si, &pi); CloseHandle(si.hStdOutput); WaitForSingleObject(pi.hProcess, INFINITE); DWORD status = 1; GetExitCodeProcess(pi.hProcess, &status); if (status != 0) { DEBUG("Process exited with non-zero exit status " << status); return false; } #else // Create logfile output directory mkdir(static_cast<::std::string>(logfile.parent()).c_str(), 0755); // Create handles such that the log file is on stdout ::std::string logfile_str = logfile; pid_t pid; posix_spawn_file_actions_t fa; { posix_spawn_file_actions_init(&fa); posix_spawn_file_actions_addopen(&fa, 1, logfile_str.c_str(), O_CREAT|O_WRONLY|O_TRUNC, 0644); } // Generate `argv` auto argv = args.get_vec(); argv.insert(argv.begin(), exe_name); if(true) { ::std::cout << ">"; for(const auto& p : argv) ::std::cout << " " << p; ::std::cout << ::std::endl; } else { Debug_Print([&](auto& os){ os << "Calling"; for(const auto& p : argv) os << " " << p; }); } DEBUG("Environment " << env); argv.push_back(nullptr); // Generate `envp` StringList envp; extern char **environ; for(auto p = environ; *p; p++) { envp.push_back(*p); } for(auto kv : env) { envp.push_back(::format(kv.first, "=", kv.second)); } //Debug_Print([&](auto& os){ // os << "ENVP="; // for(const auto& p : envp.get_vec()) // os << "\n " << p; // }); envp.push_back(nullptr); // TODO: Acquire a lock { ::std::lock_guard<::std::mutex> lh { this->chdir_mutex }; auto fd_cwd = open(".", O_DIRECTORY); if( working_directory != ::helpers::path() ) { chdir(working_directory.str().c_str()); } if( posix_spawn(&pid, exe_name, &fa, /*attr=*/nullptr, (char* const*)argv.data(), (char* const*)envp.get_vec().data()) != 0 ) { ::std::cerr << "Unable to run process '" << exe_name << "' - " << strerror(errno) << ::std::endl; DEBUG("Unable to spawn executable"); posix_spawn_file_actions_destroy(&fa); return false; } if( working_directory != ::helpers::path() ) { fchdir(fd_cwd); } } posix_spawn_file_actions_destroy(&fa); int status = -1; waitpid(pid, &status, 0); if( status != 0 ) { if( WIFEXITED(status) ) DEBUG("Compiler exited with non-zero exit status " << WEXITSTATUS(status)); else if( WIFSIGNALED(status) ) DEBUG("Compiler was terminated with signal " << WTERMSIG(status)); else DEBUG("Compiler terminated for unknown reason, status=" << status); DEBUG("See " << logfile << " for the compiler output"); return false; } #endif return true; }