![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
breakLIN_RacEI
Dependencies: mbed mbed-rtos Watchdog MODSERIAL ConfigFile
main.cpp
- Committer:
- JavierGC
- Date:
- 2021-02-22
- Revision:
- 0:939d1f478fb5
File content as of revision 0:939d1f478fb5:
#include "mbed.h" #include "rtos.h" #include "MODSERIAL.h" #include "Watchdog.h" #include "ConfigFile.h" /***** DEFINITIONS *****/ #define TxBuffer_NumMess 16 #define RxBuffer_NumMess 16 #define MessSizePC 128 #define MessSizeLIN 128 #define TxBuffer TxBuffer_NumMess*MessSizePC #define RxBuffer RxBuffer_NumMess*MessSizePC #define PC_MaxMailElements 16 #define LIN_MaxMailElements 16 #define PCMessWait MessSizePC*10/9.6 //ms #define LINMessWait 1//ms /***** STRUCTURES *****/ typedef struct { char command; /* command to execute */ char message[MessSizePC]; /* arguments */ } PC_mail_t; typedef struct LINMessage_t // Lin Message Structure { char IDfield; char Data[8]; // Maximum Number of Data char Checksum; } LINMessage; typedef struct { char command; /* command to execute */ LINMessage mess; } LIN_mail_t; /***** FUNCTIONS *******/ void read_Full_Message(char Port_); // Reading Buffer from LIN Line [LIN Line Depends on the Port] void send_Full_Message(char ID_Field, char Data[8], char Checksum, char Port); // Sending a Full Message to the LIN Line void send_Header_Message(char ID_Field,int Port); // Sending a Header Message to the LIN Line void send_Break(int Port); // Sending a Break Command to the LIN Line void LoadPCMail(char comm, char *mess); // Puts a mail in the stuck void messageFromPC(MODSERIAL_IRQ_INFO *q); // Gets a Message from the PC and Calls the Load Mail [0] int ComPC_Write(char *mess); // Send a Message Back to the PC void TLogSTR(char *Tstr); // Get the Time signature void GetConfig(void); // Read Configuration Data void Initialize(void); // Initialize MBED after Reboot void Read_Diagnostics(char *mess); // Return a Message with Diagnostics void Flash_Messages(int Port); // Discards all messages in LIN Port void Reset_UUT(void); // Reset The UUT /**** Watchdog ****/ Watchdog wd; extern "C" void mbed_reset(); /**** End of Watchdog ****/ /**** Serial Communication PC ****/ DigitalOut ledPC(LED1); DigitalOut Reboot_Pin(p29); MODSERIAL pc(USBTX, USBRX, TxBuffer,RxBuffer); // The USB as pc char InitialMessage[50]; // The initial Message when the MBED turns on bool LOGPC; // Logging information from the PC int PC_Baudrate=115200; // The Baudrate of the PC double TxBufferWait; // The Time to Wait char ChEnd; // The termination character of the PC Serial Communication Mail<PC_mail_t, PC_MaxMailElements> PC_mail; // The PC_mail int PCMailNum = 0; // Initialize to zero time_t ctTime; struct tm * timeinfo; int LIN_Wait_Echo = 0; int LIN_Wait_Response = 0; bool Wait_Echo_Response = false; /**** LIN 1 ****/ DigitalOut ledUART1(LED2); MODSERIAL LIN1(p13, p14, TxBuffer,RxBuffer); // The UART1 as LIN1 int LIN1Baud = 19200; /**** LIN 2 ****/ MODSERIAL LIN2(p28, p27, TxBuffer,RxBuffer); // The UART2 as LIN2 DigitalOut ledUART2(LED3); int LIN2Baud = 19200; void ComPC_thread_proc(void const *args) //proceso paralelo de gestión PC: tareas solicitadas y envío a PC { while(true) { osEvent evt = PC_mail.get(osWaitForever); if (evt.status == osEventMail) { PC_mail_t *mail = (PC_mail_t*)evt.value.p; char mess[MessSizePC]; char Tstr[20]; TLogSTR(Tstr); switch (mail->command) { case 0: //request from PC switch(mail->message[0]) { case 'R': // Reboot the Microcontroller/Updates the Firmware if(strcmp(mail->message,"REBOOT")==0) {mbed_reset();/*wd.Configure(2.0);*/} else { snprintf (mess,MessSizePC,"NAK(%s):%s\r\n",Tstr, mail->message); } break; case 'T': // Set the Current Time float seconds; sscanf(&mail->message[1],"%f",&seconds); set_time((double)seconds); time_t ctTime; ctTime = time(NULL); snprintf(mess,MessSizePC,"%s",ctime(&ctTime)); LoadPCMail(1,mess); break; case 'L': // LIN Line LINMessage LINMess; unsigned int temp_ID; unsigned int temp_Data[8]; unsigned int temp_Checksum; switch (mail->message[1]) { case '1': //LIN 1 ledUART1 = true; switch (mail->message[2]) { case 'W': //Write Full Message to LIN1 sscanf(&mail->message[3],"%u;%u;%u;%u;%u;%u;%u;%u;%u;%u;",&temp_ID,&temp_Data[0],&temp_Data[1],&temp_Data[2],&temp_Data[3],&temp_Data[4],&temp_Data[5],&temp_Data[6],&temp_Data[7],&temp_Checksum); LINMess.IDfield = temp_ID; LINMess.Checksum = temp_Checksum; for(int k=0; k<8; k++){ LINMess.Data[k] = temp_Data[k]; } send_Full_Message(LINMess.IDfield, LINMess.Data, LINMess.Checksum, 1); // Maybe Disable interrupts here if(Wait_Echo_Response) { wait_ms(LIN_Wait_Echo); read_Full_Message(1);} ledUART1 = false; break; case 'H': //Write Remote Header to LIN1 sscanf(&mail->message[3],"%u;",&temp_ID); LINMess.IDfield = temp_ID; send_Header_Message(LINMess.IDfield,1); if(Wait_Echo_Response) { wait_ms(LIN_Wait_Echo); wait_ms(LIN_Wait_Response); read_Full_Message(1); } ledUART1 = false; break; case 'R': //Read Data from LIN1 read_Full_Message(1); ledUART1 = false; break; case 'T': //Reset Reset_UUT(); ledUART1 = false; LoadPCMail(99,"Reset_OK"); break; default: ledUART1 = false; break; } break; case '2': //LIN 2 ledUART2 = true; switch (mail->message[2]) { case 'W': //Write Full Message to LIN2 sscanf(&mail->message[3],"%u;%u;%u;%u;%u;%u;%u;%u;%u;%u;",&temp_ID,&temp_Data[0],&temp_Data[1],&temp_Data[2],&temp_Data[3],&temp_Data[4],&temp_Data[5],&temp_Data[6],&temp_Data[7],&temp_Checksum); LINMess.IDfield = temp_ID; LINMess.Checksum = temp_Checksum; for(int k=0; k<8; k++){ LINMess.Data[k] = temp_Data[k]; } send_Full_Message(LINMess.IDfield, LINMess.Data, LINMess.Checksum, 2); // Maybe Disable interrupts here if(Wait_Echo_Response) { wait_ms(LIN_Wait_Echo); read_Full_Message(2); } ledUART2 = false; break; case 'H': //Write Remote Header to LIN2 sscanf(&mail->message[3],"%u;",&temp_ID); LINMess.IDfield = temp_ID; send_Header_Message(LINMess.IDfield,2); if(Wait_Echo_Response) { wait_ms(LIN_Wait_Echo); wait_ms(LIN_Wait_Response); read_Full_Message(2); } ledUART2 = false; break; case 'R': //Read Data from LIN2 read_Full_Message(2); ledUART2 = false; break; default: ledUART2 = false; break; } break; case 'F': //Flash the Buffer of all the LINs { ledUART1 = true; ledUART2 = true; Flash_Messages(1); Flash_Messages(2); ledUART1 = false; ledUART2 = false; LoadPCMail(50,"Flash_OK"); break; } default: break; } break; } case 1: //Send LOG to PC if(LOGPC) { snprintf(mess,MessSizePC,"LOG(%s):%s\r\n",Tstr ,mail->message); } else { mess[0]=0; } break; case 50: //Send to PC a Message from LINs snprintf(mess,MessSizePC,"LINs:%s\r\n",mail->message); break; case 51: //Send to PC a Message from LIN1 snprintf(mess,MessSizePC,"LIN1:%s\r\n",mail->message); break; case 52: //Send to PC a Message from LIN2 snprintf(mess,MessSizePC,"LIN2:%s\r\n",mail->message); break; case 99: //Information from the Micro snprintf(mess,MessSizePC,"MBED:%s\r\n",mail->message); break; default: break; } PC_mail.free(mail); PCMailNum--; if(PCMailNum==0){ledPC=false;} else {ledPC=true;} ComPC_Write(mess); } } } /**** End of Serial Communication PC ****/ int main() { Initialize(); PCMailNum=0; Thread ComPC_thread (ComPC_thread_proc,NULL,osPriorityBelowNormal); // Start a ComPC Thread! pc.attach(&messageFromPC, MODSERIAL::RxAutoDetect); // Attach an Interrupt to the TX Line pc.autoDetectChar(ChEnd); // Autodetect the End Characted LoadPCMail(99,InitialMessage); // ************ WD ************* wd.WatchdogCausedReset(); wd.Configure(5.0); // ************ WD_end ********* while(true) { wd.Service(); Thread::wait(500); // what is this doing here? } } void GetConfig(void) { #define CfgNumParam 9 #define CfgSizeParam 50 pc.format(8,Serial::Even,1); // Configuration for the Format of the data for the PC pc.baud(115200); // Configuration for the Baudrate of the communication to the PC [default] ConfigFile cfg; LocalFileSystem local("local"); int i; char value[CfgNumParam][CfgSizeParam]; char CfgK[CfgNumParam][CfgSizeParam]= {"InitialMessage","BaudRate","ChEnd","LOGPC","LIN1Baud","LIN2Baud","LINWaitResp_ms","LINWaitProd_ms","Wait_Response"}; if (!cfg.read("/local/config.cfg")) { error("\r\nFailure to read a configuration file"); } char Tstr[10]; for (i=0; i<CfgNumParam; i++) { if (cfg.getValue(CfgK[i], &value[i][0], sizeof(value[i]))) { TLogSTR(Tstr); /*pc.printf("CFG_Param(%s): '%s'='%s'\r\n", Tstr,CfgK[i], value[i]);*/ } else { error("Failure Reading '%s'\r\n", CfgK[i]); } } strcpy(InitialMessage,value[0]); PC_Baudrate=atoi(value[1]); ChEnd=(char)atoi(value[2]); LOGPC=(bool)atoi(value[3]); LIN1Baud=atoi(value[4]); LIN2Baud=atoi(value[5]); LIN_Wait_Echo = atoi(value[6]); LIN_Wait_Response = atoi(value[7]); Wait_Echo_Response = (bool)atoi(value[8]); TxBufferWait= 10000*MessSizePC/PC_Baudrate; while(!pc.txBufferEmpty()) { Thread::wait(100); }; } void Initialize(void) { Reboot_Pin = false; GetConfig(); pc.baud(PC_Baudrate); pc.format(8,Serial::Even,1); // Configuration for PC LIN1.baud(LIN1Baud); LIN1.format(8,Serial::None,1); // Configuration for LIN1 LIN2.baud(LIN2Baud); LIN2.format(8,Serial::None,1); // Configuration for LIN2 } void TLogSTR(char *Tstr) // Put to Tstr the Time information as a character { ctTime = time(NULL); timeinfo = localtime ( &ctTime ); timeinfo->tm_hour=(timeinfo->tm_hour+1)%24; strftime (Tstr,MessSizePC,"%H:%M:%S",timeinfo); } void LoadPCMail(char comm, char *mess) //Working in Parallel to Load a message to the stack { while(PCMailNum>=PC_MaxMailElements) { Thread::wait(PCMessWait); } // Wait if there are many other things in Queue if(comm!=1 || LOGPC) { PC_mail_t *mail = PC_mail.alloc(); mail->command = comm; snprintf(mail->message,MessSizePC,"%s",mess); PC_mail.put(mail); PCMailNum++; } } void messageFromPC(MODSERIAL_IRQ_INFO *q) //Received Message from PC and Put it in stack with a Value of 0 { ledPC=true; MODSERIAL *sys = q->serial; char temp[MessSizePC]; int i=sys->move(temp,MessSizePC,ChEnd); if (temp[i-2]=='\r') { i-=2; } else { i-=1; } temp[i]=0; LoadPCMail(0,temp); } int ComPC_Write(char *mess) // Send a Message Back to the PC { int i=strlen(mess); if(i>0) { while((TxBuffer-pc.txBufferGetCount())<i) { Thread::wait(TxBufferWait); } // Wait until the Buffer is ready return pc.printf(mess); } return 0; // return code if i negative } void Convert_Character_to_Number_to_String(char* temp_string, char Character) { unsigned int Temp_Number = Character; sprintf (temp_string,"%u",Temp_Number); temp_string[3]=0; } void read_Full_Message(char Port_) // Maybe Disable Interrupts Here { char tmp[MessSizeLIN]; char digit[4]; char uniq_char; int index = 0; switch(Port_) // Read the Buffer from LIN Port AND Send a Message to the PC { case 1: // LIN1 index = 0; while(LIN1.readable()==1) { uniq_char = LIN1.getc(); Convert_Character_to_Number_to_String(digit,uniq_char); for(int j=0; j<strlen(digit);j++) { tmp[index++] = digit[j]; } tmp[index++]=';'; } tmp[index]=0; LoadPCMail(51,tmp); break; case 2: // LIN2 index = 0; while(LIN2.readable()==1) { uniq_char = LIN2.getc(); Convert_Character_to_Number_to_String(digit,uniq_char); for(int j=0; j<strlen(digit);j++) { tmp[index++] = digit[j]; } tmp[index++]=';'; } tmp[index]=0; LoadPCMail(52,tmp); break; default: break; } } void send_Full_Message(char ID_Field_, char Data_[8], char Checksum_, char Port_) // Maybe Disable interrupts here { switch(Port_) { case 1: // LIN1 send_Break(Port_); //send 15bit of Zero Break; LIN1.putc(0x55); //send 0x55 Synchronisation Character LIN1.putc(ID_Field_); //send ID field for(int k=0;k<8;k++) {LIN1.putc(Data_[k]);} //send Data LIN1.putc(Checksum_); //send Checksum break; case 2: // LIN2 send_Break(Port_); //send 15bit of Zero Break; LIN2.putc(0x55); //send 0x55 Synchronisation Character LIN2.putc(ID_Field_); //send ID field for(int k=0;k<8;k++) {LIN2.putc(Data_[k]);} //send Data LIN2.putc(Checksum_); //send Checksum break; default: break; } } void send_Header_Message(char ID_Field,int Port) // Maybe Disable interrupts here { switch(Port) { case 1: // LIN1 send_Break(Port); //send 15bit of Zero Break; LIN1.putc(0x55); //send 0x55 Synchronisation Character LIN1.putc(ID_Field); //send ID field break; case 2: // LIN2 send_Break(Port); //send 15bit of Zero Break; LIN2.putc(0x55); //send 0x55 Synchronisation Character LIN2.putc(ID_Field); //send ID field break; default: break; } } void send_Break(int Port) { int time_BREAK = 0; switch(Port) { case 1: // LIN1 time_BREAK = 1000000/LIN1Baud; // time in us LPC_UART1->LCR |= 0x40; wait_us(time_BREAK*15); LPC_UART1->LCR &= ~(0x40); break; case 2: // LIN2 time_BREAK = 1000000/LIN2Baud; // time in us LPC_UART2->LCR |= 0x40; wait_us(time_BREAK*15); LPC_UART2->LCR &= ~(0x40); break; default: break; } } void Flash_Messages(int Port_) // Flashes all the Messages from the Buffer on LINs { if(Port_==1) // Read the Buffer from LIN Port AND Send a Message to the PC { while(LIN1.readable()==1) { LIN1.getc();} } else if(Port_==2) { while(LIN2.readable()==1) { LIN2.getc();} } } void Reset_UUT(void) { Reboot_Pin = true; wait_ms(200); Reboot_Pin = false; }