Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed mbed-rtos Watchdog MODSERIAL ConfigFile
Diff: main.cpp
- 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