breakLIN_RacEI

Dependencies:   mbed mbed-rtos Watchdog MODSERIAL ConfigFile

Revision:
0:939d1f478fb5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Mon Feb 22 17:12:27 2021 +0000
@@ -0,0 +1,469 @@
+#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;
+    }
\ No newline at end of file