JGCtoGdT
Dependencies: ConfigFile MODSERIAL_uVision Watchdog mbed-rtos mbed
Diff: main.cpp
- Revision:
- 0:2e1b2d9fa0de
diff -r 000000000000 -r 2e1b2d9fa0de main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Sun May 05 16:39:34 2013 +0000 @@ -0,0 +1,519 @@ +#include "mbed.h" +#include "MODSERIAL.h" +#include "rtos.h" +#include "Watchdog.h" +#include "ConfigFile.h" + +Watchdog wd; + +extern "C" void mbed_reset(); + +char InitialMessage[50]; + +DigitalOut ledCAN1(LED1); +DigitalOut ledCAN2(LED2); +DigitalOut led3(LED3); +DigitalOut ledPC(LED4); + + +time_t ctTime; +struct tm * timeinfo; + +Ticker SpkTick; +Timer myT; + + +void LoadPCMail(char comm, char *mess); + +/************* Frequency ****************/ +InterruptIn Freq1(p15); +InterruptIn Freq2(p16); +InterruptIn Freq3(p17); +Timer F1; +Timer F2; +Timer F3; + +int Period1,Period2,Period3; + +void Freq1_Meas(void) +{ + Period1=F1.read_us(); + F1.reset(); +} +void Freq2_Meas(void) +{ + Period2=F2.read_us(); + F2.reset(); +} +void Freq3_Meas(void) +{ + Period3=F3.read_us(); + F3.reset(); +} +/************* End Frequency ************/ + +/************* PWM ****************/ +PwmOut PwmO1(LED3); +/************* End PWM ************/ + +/************* CAN ***********************/ +#define CAN_MaxMailElements 16 +#define CANMessWait 1//ms +#define MessSizeCAN 128 + +typedef struct { + char command; /* command to execute */ + CANMessage mess; +} CAN_mail_t; +/************* CAN 1 *********************/ +CAN can1(p9,p10); +int CAN1Freq=1000000; + +Mail<CAN_mail_t, CAN_MaxMailElements> CAN1_mail; +int CAN1MailNum; + +void LoadCAN1Mail(char command, CANMessage mess) //para cargar mensajes de trabajo al proceso paralelo CAN1_thread_proc +{ + while(CAN1MailNum>=CAN_MaxMailElements) { + Thread::wait(CANMessWait); + } + CAN_mail_t *mail = CAN1_mail.alloc(); + mail->command = command; + mail->mess=mess; + CAN1_mail.put(mail); + CAN1MailNum++; +} + +void messageFromCAN1() +{ + ledCAN1=true; + CANMessage msg; + can1.read(msg); + LoadCAN1Mail(10,msg); +} + +void CAN1_thread_proc(void const *args) //proceso paralelo de gestión CAN1 +{ + char tmp[MessSizeCAN]; + while(true) { + osEvent evt = CAN1_mail.get(osWaitForever); + if (evt.status == osEventMail) { + CAN_mail_t *mail = (CAN_mail_t*)evt.value.p; + + switch (mail->command) { + case 0: //request Reset CAN + can1.reset(); + LoadPCMail(1,"Reset CAN1"); + break; + case 1: //set frequency + can1.frequency(mail->mess.id); + LoadPCMail(1,"Set Frequency CAN1"); + break; + case 10: //Read from CAN + snprintf(tmp,MessSizeCAN,"ID=%i;TYPE=%i;FORMAT=%i;LEN=%d;DATA[0]=%u;DATA[1]=%u;DATA[2]=%u;DATA[3]=%u;DATA[4]=%u;DATA[5]=%u;DATA[6]=%u;DATA[7]=%u",mail->mess.id,mail->mess.type,mail->mess.format,mail->mess.len,mail->mess.data[0],mail->mess.data[1],mail->mess.data[2],mail->mess.data[3],mail->mess.data[4],mail->mess.data[5],mail->mess.data[6],mail->mess.data[7]); + LoadPCMail(2,tmp); + break; + case 20: //Write to CAN + can1.write(mail->mess); + LoadPCMail(1,"Write to CAN1"); + break; + default: // request to send message from code + break; + } + CAN1_mail.free(mail); + CAN1MailNum--; + ledCAN1=false; + } + } +} +/************* END CAN 1 ****************/ +/************* CAN 2 ********************/ +CAN can2(p30,p29); +int CAN2Freq=1000000; + +Mail<CAN_mail_t, CAN_MaxMailElements> CAN2_mail; +int CAN2MailNum; + +void LoadCAN2Mail(char command, CANMessage mess) //para cargar mensajes de trabajo al proceso paralelo CAN1_thread_proc +{ + while(CAN2MailNum>=CAN_MaxMailElements) { + Thread::wait(CANMessWait); + } + CAN_mail_t *mail = CAN2_mail.alloc(); + mail->command = command; + mail->mess=mess; + CAN2_mail.put(mail); + CAN2MailNum++; +} +void messageFromCAN2() +{ + ledCAN2=true; + CANMessage msg; + can2.read(msg); + LoadCAN2Mail(10,msg); +} +void CAN2_thread_proc(void const *args) //proceso paralelo de gestión CAN1 +{ + char tmp[MessSizeCAN]; + while(true) { + osEvent evt = CAN2_mail.get(osWaitForever); + if (evt.status == osEventMail) { + CAN_mail_t *mail = (CAN_mail_t*)evt.value.p; + + switch (mail->command) { + case 0: //request Reset CAN + can2.reset(); + LoadPCMail(1,"Reset CAN2"); + break; + case 1: //set frequency + can2.frequency(mail->mess.id); + LoadPCMail(1,"Set Frequency CAN2"); + break; + case 10: //Read from CAN + snprintf(tmp,MessSizeCAN,"ID=%i;TYPE=%i;FORMAT=%i;LEN=%d;DATA[0]=%u;DATA[1]=%u;DATA[2]=%u;DATA[3]=%u;DATA[4]=%u;DATA[5]=%u;DATA[6]=%u;DATA[7]=%u",mail->mess.id,mail->mess.type,mail->mess.format,mail->mess.len,mail->mess.data[0],mail->mess.data[1],mail->mess.data[2],mail->mess.data[3],mail->mess.data[4],mail->mess.data[5],mail->mess.data[6],mail->mess.data[7]); + LoadPCMail(3,tmp); + break; + case 20: //Write to CAN + can2.write(mail->mess); + LoadPCMail(1,"Write to CAN2"); + break; + default: // request to send message from code + break; + } + CAN2_mail.free(mail); + CAN2MailNum--; + ledCAN2=false; + } + } +} +/************* END CAN 2 ****************/ +/************* END CAN ******************/ + +/************* RS232 PC ******************/ +#define TxBuffer_NumMess 16 +#define RxBuffer_NumMess 16 +#define MessSizePC 128 +#define TxBuffer TxBuffer_NumMess*MessSizePC +#define RxBuffer RxBuffer_NumMess*MessSizePC +#define PC_MaxMailElements 16 +#define PCMessWait MessSizePC*10/9.6 //ms + +MODSERIAL pc(USBTX, USBRX,TxBuffer,RxBuffer); +bool LOGPC; +int BaudRate; +double TxBufferWait; +char ChEnd; + +typedef struct { + char command; /* command to execute */ + char message[MessSizePC]; /* arguments */ +} PC_mail_t; + +Mail<PC_mail_t, PC_MaxMailElements> PC_mail; +int PCMailNum; + +void TLogSTR(char *Tstr) +{ + 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) //para cargar mensajes de trabajo al proceso paralelo ComPC_thread_proc +{ + while(PCMailNum>=PC_MaxMailElements) { + Thread::wait(PCMessWait); + } + 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) //trabajo solicitado desde PC +{ + 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) //sólo para usarse en ComPC_thread_proc +{ + int i=strlen(mess); + if(i>0) { + while((TxBuffer-pc.txBufferGetCount())<i) { + Thread::wait(TxBufferWait); + } + return pc.printf(mess); + } + return 0; +} + +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 + CANMessage CanMess; + switch (mail->message[0]) { + case 'T': + 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 'C': //CAN + switch (mail->message[1]) { + case '1': //CAN1, Send from PC a Message to CAN1 + switch (mail->message[2]) { + case 'R': //reset CAN + LoadCAN1Mail(0,CanMess); + snprintf (mess,MessSizePC,"ACK(%s):%s\r\n",Tstr, mail->message); + break; + case 'F': //set Frequency CAN + sscanf(&mail->message[3],"%i",&CanMess.id); + LoadCAN1Mail(1,CanMess); + snprintf (mess,MessSizePC,"ACK(%s):%s\r\n",Tstr, mail->message); + break; + case 'W': //Write CAN + sscanf(&mail->message[3],"%i;%i;%i;%u;%u;%u;%u;%u;%u;%u;%u;%u",&CanMess.id,&CanMess.type,&CanMess.format,&CanMess.len,&CanMess.data[0],&CanMess.data[1],&CanMess.data[2],&CanMess.data[3],&CanMess.data[4],&CanMess.data[5],&CanMess.data[6],&CanMess.data[7]); + LoadCAN1Mail(20,CanMess); + snprintf (mess,MessSizePC,"ACK(%s):%s\r\n",Tstr, mail->message); + break; + default: + snprintf (mess,MessSizePC,"NAK(%s):%s\r\n",Tstr, mail->message); + break; + } + break; + case '2': //CAN2, Send from PC a Message to CAN2 + switch (mail->message[2]) { + case 'R': //reset CAN + LoadCAN2Mail(0,CanMess); + snprintf (mess,MessSizePC,"ACK(%s):%s\r\n",Tstr, mail->message); + break; + case 'F': //set Frequency CAN + sscanf(&mail->message[3],"%i",&CanMess.id); + LoadCAN2Mail(1,CanMess); + snprintf (mess,MessSizePC,"ACK(%s):%s\r\n",Tstr, mail->message); + break; + case 'W': //Write CAN + sscanf(&mail->message[3],"%i;%i;%i;%u;%u;%u;%u;%u;%u;%u;%u;%u",&CanMess.id,&CanMess.type,&CanMess.format,&CanMess.len,&CanMess.data[0],&CanMess.data[1],&CanMess.data[2],&CanMess.data[3],&CanMess.data[4],&CanMess.data[5],&CanMess.data[6],&CanMess.data[7]); + LoadCAN2Mail(20,CanMess); + snprintf (mess,MessSizePC,"ACK(%s):%s\r\n",Tstr, mail->message); + break; + default: + snprintf (mess,MessSizePC,"NAK(%s):%s\r\n",Tstr, mail->message); + break; + } + break; + default: + snprintf (mess,MessSizePC,"NAK(%s):%s\r\n",Tstr, mail->message); + break; + } + break; + case 'F': //Frequencies + switch (mail->message[1]) { + case '1': //Freq1, Get Freq11 + snprintf(mess,MessSizePC,"F1= %i usec\r\n",Period1); + break; + case '2': //Freq2, Get Freq2 + snprintf(mess,MessSizePC,"F2= %i usec\r\n",Period2); + break; + case '3': //Freq3, Get Freq3 + snprintf(mess,MessSizePC,"F3= %i usec\r\n",Period3); + break; + default: + snprintf (mess,MessSizePC,"NAK(%s):%s\r\n",Tstr, mail->message); + break; + } + break; + case 'P': + float duty=0; + int periodus=0; + switch (mail->message[1]) { + case '1': + sscanf(&mail->message[2],"%f;%i",&duty,&periodus); + PwmO1.write(duty); + PwmO1.period_us(periodus); + snprintf (mess,MessSizePC,"ACK(%s):%s\r\n",Tstr, mail->message); + break; + default: + snprintf (mess,MessSizePC,"NAK(%s):%s\r\n",Tstr, mail->message); + break; + } + break; + case 'R': + 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 'r': + 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; + default: + snprintf (mess,MessSizePC,"NAK(%s):%s\r\n",Tstr, mail->message); + 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 2: //Send to PC a Message from CAN1 + snprintf(mess,MessSizePC,"CAN1:%s\r\n",mail->message); + break; + case 3: //Send to PC a Message from CAN2 + snprintf(mess,MessSizePC,"CAN2:%s\r\n",mail->message); + break; + default: + break; + } + PC_mail.free(mail); + PCMailNum--; + ledPC=false; + ComPC_Write(mess); + } + } +} +/************* END RS232 PC **************/ + +void GetConfig() +{ + +#define CfgNumParam 6 +#define CfgSizeParam 50 + + pc.format(8,Serial::Even,1); + pc.baud(115200); + ConfigFile cfg; + LocalFileSystem local("local"); + + int i; + char value[CfgNumParam][CfgSizeParam]; + char CfgK[CfgNumParam][CfgSizeParam]= {"InitialMessage","BaudRate","ChEnd","LOGPC","CAN1Freq","CAN2Freq"}; + + pc.printf("\r\n* * *\r\n* * *\r\n"); + + 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]); + BaudRate=atoi(value[1]); + ChEnd=(char)atoi(value[2]); + LOGPC=(bool)atoi(value[3]); + CAN1Freq=atoi(value[4]); + CAN2Freq=atoi(value[5]); + + TxBufferWait= 10000*MessSizePC/BaudRate; + + pc.printf("* * *\r\n* * *\r\n"); + + while(!pc.txBufferEmpty()) { + Thread::wait(100); + }; +} + +int main() +{ + + //char tempMessPC[MessSizePC]; + PCMailNum=0; + GetConfig(); + + // ************ PC ^^^^^^^^^^^^^ + pc.baud(BaudRate); + Thread ComPC_thread (ComPC_thread_proc,NULL,osPriorityBelowNormal); + pc.attach(&messageFromPC, MODSERIAL::RxAutoDetect); + pc.autoDetectChar(ChEnd); + + // ************ PC_end ^^^^^^^^^^^^^ + + LoadPCMail(1,""); + LoadPCMail(1,""); + LoadPCMail(1,""); + LoadPCMail(1,"*****************************"); + LoadPCMail(1,InitialMessage); + LoadPCMail(1,"*****************************"); + LoadPCMail(1,""); + LoadPCMail(1,""); + LoadPCMail(1,""); + + // ************ CAN1 ^^^^^^^^^^^ + Thread CAN1_thread (CAN1_thread_proc,NULL,osPriorityNormal); + can1.frequency(CAN1Freq); + can1.attach(&messageFromCAN1); + // ************ CAN1_end ^^^^^^^ + + // ************ CAN2 ^^^^^^^^^^^ + Thread CAN2_thread (CAN2_thread_proc,NULL,osPriorityNormal); + can2.frequency(CAN2Freq); + can2.attach(&messageFromCAN2); + // ************ CAN2_end ^^^^^^^ + + // ************ WD ************* + wd.WatchdogCausedReset(); + wd.Configure(5.0); + // ************ WD_end ********* + + // ************ Interrupts Freqs + F1.start(); + F2.start(); + F3.start(); + Period1=0; + Period2=0; + Period3=0; + + Freq1.rise(Freq1_Meas); + Freq2.rise(Freq2_Meas); + Freq3.rise(Freq3_Meas); + + // ************ End Interrupts Freqs + + while(true) { + //Thread::wait(osWaitForever); + wd.Service(); + Thread::wait(1000); + } +}