Latest

Dependencies:   serial_terminal sample_hardware PLL_Config SDCard BMP280 Networkbits TextLCD SDBlockDevice

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #include "mbed.h"
00002 #include <stm32f4xx.h>
00003 #include "sample_hardware.hpp"
00004 #include "Networking.hpp"
00005 #include "serial_terminal.hpp"
00006 #include "SDCard.hpp"
00007 #include "rtos.h"
00008 #include "events/mbed_events.h"
00009 #include "LCDdisplay.hpp"
00010 //#include "PLL_Config.c"
00011 
00012 //Defines TEST FOR SD CARD MOUNT AND UNMOUNT
00013 #define EDGE_FALLEN 0
00014 #define EDGE_RISEN 1
00015 
00016 //Signals
00017 #define TAKE_SAMPLE 1
00018 #define STORE_DATA 2
00019 
00020 
00021 //Global variables
00022 
00023 
00024 unsigned int newestIndex = BUFFERSIZE-1;    //First time it is incremented, it will be 0
00025 unsigned int oldestIndex = BUFFERSIZE-1;
00026 FILE* fp;
00027 FATFileSystem* fs;
00028 
00029 //Shared mutable variables VOLATILE
00030 bool sd_init; //is it?
00031 bool logging = false;
00032 bool sampling = true;
00033 float sample_rate = 15; //is it?
00034 struct tm* timeData;
00035 char cmdBuffer[256];
00036 sensorData buffer[BUFFERSIZE];
00037 RawSerial* pc;
00038 
00039 //Thread synchronisation primatives
00040 Semaphore spaceAvailable(BUFFERSIZE);
00041 Semaphore samplesInBuffer(0, BUFFERSIZE);
00042 Mutex bufferLock;
00043 
00044 //Queues
00045 EventQueue SDqueue(1024*EVENTS_EVENT_SIZE); //changed from 32
00046 EventQueue LCDqueue(32*EVENTS_EVENT_SIZE);
00047 EventQueue serialqueue(32*EVENTS_EVENT_SIZE);
00048 
00049 //TEST
00050 EventQueue printQueue(256*EVENTS_EVENT_SIZE);
00051 
00052 
00053 
00054 //Threads
00055 Thread producer_thread(osPriorityHigh);
00056 Thread consumer_thread;
00057 Thread serial_thread(osPriorityAboveNormal);
00058 Thread SDqueue_thread; //take out queue in name?
00059 Thread LCDqueue_thread;
00060 Thread network_thread;
00061 
00062 //TEST FOR SD CARD
00063 Thread SDmount_thread;
00064 
00065 //TEST FOR PRINTF
00066 
00067 
00068 //Timers
00069 Ticker sample;
00070 
00071 //Function prototypes
00072 void sampleISR(void);
00073 void sampleProducer(void);
00074 void sampleConsumer(void);
00075 void serialISR(void);
00076 void serialData(void);
00077 
00078 
00079 
00080 //TEST FOR SD CARD MOUNT AND UNMOUNT
00081 Timeout userswTimeOut;
00082 int userswState = EDGE_FALLEN;
00083 InterruptIn   usersw(USER_BUTTON);
00084 void userswTimeOutHandler();
00085 void userswRisingEdge();
00086 void userswFallingEdge();
00087 void SDmount();
00088 
00089 Mutex printlock;
00090 Mutex LCDlock;
00091 Mutex timeLock;
00092 Mutex SDlock;
00093 
00094 
00095 //TEST FOR BUFFER CHANGES
00096 unsigned int saveIndex = BUFFERSIZE-1;
00097 
00098 int32_t Nspaces = BUFFERSIZE;
00099 int32_t Nsamples;
00100 
00101 
00102 //TEST FOR WATCHDOG
00103 char threadstates = 0;
00104 
00105 Timeout producer_tout;
00106 Timeout consumer_tout;
00107 Timeout serial_tout;
00108 Timeout SD_tout;
00109 Timeout LCD_tout;
00110 Timeout network_tout;
00111 
00112 Thread watchdog_thread(osPriorityHigh);
00113 
00114 //TSET FOR PRINTF
00115 Thread printf_thread;
00116 
00117 void producer_toutISR(void);
00118 void consumer_toutISR(void);
00119 void serial_toutISR(void);
00120 void SD_toutISR(void);
00121 void LCD_toutISR(void);
00122 void network_toutISR(void);
00123 void watchdog(void);
00124 
00125 void PLL_Config(void);
00126 
00127 osThreadId main_thread;
00128 
00129 #define PRODUCER 1<<0
00130 #define CONSUMER 1<<1
00131 #define SERIAL 1<<2
00132 #define SD 1<<3
00133 #define LCD 1<<4
00134 #define NETWORK 1<<5
00135 
00136 int main() {   
00137     PLL_Config();
00138     main_thread = Thread::gettid();
00139     timeData = new tm;
00140     pc = new RawSerial(USBTX, USBRX, 115200);
00141     
00142     //Initialisations
00143     SDcard();   
00144     
00145     //Power on self test
00146     post();
00147        
00148     //Start threads
00149     SDqueue_thread.start(callback(&SDqueue, &EventQueue::dispatch_forever));
00150     LCDqueue_thread.start(callback(&LCDqueue, &EventQueue::dispatch_forever));
00151     serial_thread.start(callback(&serialqueue, &EventQueue::dispatch_forever));
00152     network_thread.start(network);
00153     producer_thread.start(sampleProducer);
00154     consumer_thread.start(sampleConsumer);
00155     
00156     //TEST
00157     LCDqueue.call_every(5000, LCD_display);
00158     
00159     //TEST FOR SD CARD
00160     //SDmount_thread.start(SDmount);
00161     
00162     //TEST FOR WATCGDOG
00163     watchdog_thread.start(watchdog);
00164     
00165     //TEST FOR PRINTFQUEUE
00166     printf_thread.start(callback(&printQueue, &EventQueue::dispatch_forever));
00167     
00168    
00169     //Attach ISRs
00170     sample.attach(&sampleISR, sample_rate);  //Allow sampling to start  
00171     pc->attach(serialISR, Serial::RxIrq);
00172     
00173     //TEST FOR SD CARD MOUNT AND UNMOUNT
00174     usersw.rise(&userswRisingEdge);    
00175     
00176     //Flash to indicate goodness
00177     while(true) {
00178         //greenLED = !greenLED;
00179         //Thread::wait(500);    
00180     }
00181 }
00182 
00183 /*
00184 FUNCITONS BELOW NEED MOVING?
00185 */
00186 
00187 void sampleISR()
00188 {
00189     producer_thread.signal_set(TAKE_SAMPLE);   
00190 }
00191     
00192 void serialISR()
00193 {
00194     pc->attach(NULL, Serial::RxIrq);
00195     serialqueue.call(serialData);
00196 }
00197 
00198 void serialData()
00199 {    
00200     static int i = 0;
00201     
00202     if (pc->readable())
00203     {
00204         cmdBuffer[i] = pc->getc();
00205         if (i != 29)
00206         {
00207             
00208             if (cmdBuffer[i] == '\b')
00209             {
00210                 i = (i ? i-1 : 0);  
00211             }
00212             else if (cmdBuffer[i] == '\r')
00213             {
00214                 cmdBuffer[i+1]==NULL;
00215                 serialqueue.call(serialterm);
00216                 i = 0;                                
00217             }
00218             else i++;
00219         }
00220         else
00221         {
00222             serialqueue.call(serialterm);
00223             i = 0;
00224         }
00225     }
00226     pc->attach(serialISR, Serial::RxIrq);
00227 }
00228 
00229 
00230 void sampleProducer()
00231 {
00232     while(true)
00233     {
00234         //High priority thread 
00235         Thread::signal_wait(TAKE_SAMPLE);
00236         //wd_thread.signal_set(PROD_SIGNAL);
00237         //prod_stat = 0;        
00238         Nspaces = spaceAvailable.wait(0); //Non-blocking
00239         bufferLock.lock();
00240         producer_tout.attach(producer_toutISR, TOUT_TIME_DEF);
00241                
00242         //Update buffer     
00243          
00244         if ((newestIndex == oldestIndex) && (Nspaces==0))
00245         {
00246             //printQueue.call(printf, "oldest index being increased\n\r");
00247             oldestIndex = (oldestIndex+1) % BUFFERSIZE;     
00248         }
00249             
00250         newestIndex = (newestIndex+1) % BUFFERSIZE;  //CIRCULAR 
00251         /*     
00252         buffer[newestIndex].updatetemp(sensor.getTemperature());
00253         buffer[newestIndex].updatepress(sensor.getPressure());
00254         buffer[newestIndex].updatelight(adcIn.read());
00255         buffer[newestIndex].updateTime();
00256         */
00257         
00258         double temp_r = sensor.getTemperature();
00259         double press_r = sensor.getPressure();
00260         float light_r = adcIn.read();
00261         
00262         buffer[newestIndex].updatetemp(temp_r);
00263         buffer[newestIndex].updatepress(press_r);
00264         buffer[newestIndex].updatelight(light_r);
00265         buffer[newestIndex].updateTime();
00266                
00267         if (Nspaces != 0)
00268         {   
00269             Nspaces--;            
00270         } 
00271           
00272         samplesInBuffer.release();
00273              
00274         //Pass onto queues
00275         //LCDqueue.call(LCD_display,temp_r,press_r,light_r);
00276         //LCDqueue.call(LCD_display, &buffer[newestIndex]);
00277         
00278         if(logging)
00279         {
00280             /*
00281             printlock.lock();
00282             pc->printf("Sample placed in buffer at position %d\r\n", newestIndex);
00283             pc->printf("Number of spaces available in buffer:%d\r\n\n",Nspaces);
00284             printlock.unlock();  
00285             */
00286             printQueue.call(printf, "Sample placed in buffer at position %d\r\nNumber of spaces available in buffer:%d\r\n\n", newestIndex, Nspaces); 
00287         }
00288         
00289         bufferLock.unlock();
00290         producer_tout.detach();
00291     }
00292 }
00293 
00294 void sampleConsumer()
00295 {
00296     while(true)
00297     {
00298         //static time_t seconds; //possibly move into if(sd_init)
00299         //write to the SD card from oldestindex up to newestIndex.
00300         
00301         Nsamples = samplesInBuffer.wait(); //Block if no samples to take - acquires
00302         
00303         bufferLock.lock(); //Moved to here from below to try and ensure timer is started only when the buffer can be used
00304         consumer_tout.attach(consumer_toutISR,TOUT_TIME_DEF);
00305         
00306         if (sd_init)
00307         {     
00308             /*
00309             char fileDate[30];
00310             timeLock.lock();
00311             seconds = time(NULL);
00312             timeData = localtime(&seconds);
00313             
00314             //set_time(mktime(timeData));
00315             
00316             strftime(fileDate, 30, "sd/log_%d_%m_%y.csv", timeData);
00317             timeLock.unlock();           
00318             
00319             fp = fopen(fileDate,"a"); //ISSUE
00320             if (fp == NULL)
00321             {
00322                 printlock.lock();
00323                 pc->printf("WARNING: FILE COULD NOT BE OPENED\r\n\n");
00324                 sd_init = false;
00325                 printlock.unlock();  
00326                 samplesInBuffer.release();
00327             }
00328             else
00329             {
00330                 //Nested locks probably a bad idea!
00331                 //bufferLock.lock();
00332 
00333                 SDlock.lock();             
00334                 oldestIndex = (oldestIndex+1) % BUFFERSIZE;
00335                 //fprintf(fp,"%s,%5.2f,%5.2f,%5.2f\r", buffer[oldestIndex].getTime(), buffer[oldestIndex].gettemp(), buffer[oldestIndex].getpress(), buffer[oldestIndex].getlight());           
00336                 SDqueue.call(SDaddSample,buffer[oldestIndex].getTime(), buffer[oldestIndex].gettemp(), buffer[oldestIndex].getpress(), buffer[oldestIndex].getlight());
00337                 SDlock.unlock();
00338                 
00339                 if(logging)
00340                 {
00341                     printlock.lock();
00342                     pc->printf("Log file %s updated with sample from position %d in buffer\r\n",fileDate,oldestIndex);
00343                     pc->printf("newestIndex position %d\r\n",newestIndex);
00344                     pc->printf("oldestIndex position %d\r\n\n",oldestIndex);
00345                     printlock.unlock();  
00346                 }
00347                 
00348                 //bufferLock.unlock();          
00349                 fclose(fp); 
00350                 */
00351                 oldestIndex = (oldestIndex+1) % BUFFERSIZE;
00352                 //fprintf(fp,"%s,%5.2f,%5.2f,%5.2f\r", buffer[oldestIndex].getTime(), buffer[oldestIndex].gettemp(), buffer[oldestIndex].getpress(), buffer[oldestIndex].getlight());           
00353                 SDqueue.call(SDaddSample,buffer[oldestIndex].getTime(), buffer[oldestIndex].gettemp(), buffer[oldestIndex].getpress(), buffer[oldestIndex].getlight(), oldestIndex);                
00354             }      
00355         else
00356         {
00357             samplesInBuffer.release();   
00358         } 
00359         bufferLock.unlock();
00360         consumer_tout.detach();     
00361     }       
00362     
00363 }
00364 
00365 //TEST FOR MOUNTING AND UNMOUNTING SD CARD
00366 //Interrupt service routine for handling the timeout
00367 
00368 
00369 void userswTimeOutHandler() {
00370     userswTimeOut.detach();            //Stop the timeout counter firing
00371 
00372     //Which event does this follow?
00373     switch (userswState) {
00374     case EDGE_RISEN:    
00375         usersw.fall(&userswFallingEdge);  //Now wait for a falling edge
00376         break;
00377     case EDGE_FALLEN:
00378         usersw.rise(&userswRisingEdge);   //Now wait for a rising edge
00379         break;
00380     } //end switch 
00381 }
00382 
00383 //Interrupt service routine for a rising edge (press)
00384 void userswRisingEdge() {
00385     usersw.rise(NULL);             //Disable detecting more rising edges
00386     userswState = EDGE_RISEN;      //Flag state
00387     userswTimeOut.attach(&userswTimeOutHandler, 0.2);    //Start timeout timer
00388 }
00389 
00390 //Interrupt service routive for SW1 falling edge (release)
00391 void userswFallingEdge() {
00392     usersw.fall(NULL);                         //Disable this interrupt    
00393     //SDmount_thread.signal_set(SIGNAL_SD);
00394     SDqueue.call(SDmount);
00395     userswState = EDGE_FALLEN;                 //Flag state
00396     userswTimeOut.attach(&userswTimeOutHandler, 0.2);    //Start timeout counter - may want to increase this  
00397 }
00398 
00399 //TEST FOR WATCHDOG
00400 
00401 //ISR
00402 void producer_toutISR(void)
00403 {
00404     threadstates |= PRODUCER;
00405 }
00406 
00407 void consumer_toutISR(void)
00408 {
00409     threadstates |= CONSUMER;   
00410 }
00411 
00412 void serial_toutISR(void)
00413 {
00414     threadstates |= SERIAL;   
00415 }
00416 
00417 void SD_toutISR(void)
00418 {
00419     threadstates |= SD;   
00420 }
00421 
00422 void LCD_toutISR(void)
00423 {
00424     threadstates |= LCD;   
00425 }
00426 
00427 void network_toutISR(void)
00428 {
00429     threadstates |= NETWORK;   
00430 }
00431 
00432 void watchdog(void)
00433 {
00434     while(true)
00435     {
00436         Thread::wait(10000);
00437  
00438         if(threadstates)
00439         {
00440             producer_thread.terminate();
00441             consumer_thread.terminate();
00442             serial_thread.terminate();
00443             SDqueue_thread.terminate();
00444             LCDqueue_thread.terminate();
00445             network_thread.terminate();
00446             printf_thread.terminate();
00447             
00448             pc->printf("THREAD PSW: 0x%x\n\r", threadstates);
00449             
00450             switch (threadstates)
00451             {
00452                 case (PRODUCER) : 
00453                     pc->printf("PRODUCER THREAD DEADLOCK\r\n\n");
00454                     lcd.cls();
00455                     lcd.printf("PRODUCER\nDEADLOCK");
00456                     break;
00457                 
00458                 case (CONSUMER) : 
00459                     pc->printf("CONSUMER THREAD DEADLOCK\r\n\n");
00460                     lcd.cls();
00461                     lcd.printf("CONSUMER\nDEADLOCK");
00462                     break;
00463                 
00464                 case (SERIAL) : 
00465                     pc->printf("SERIAL THREAD DEADLOCK\r\n\n");
00466                     lcd.cls();
00467                     lcd.printf("SERIAL\nDEADLOCK");
00468                     break;
00469                 
00470                 case (SD) : 
00471                     pc->printf("SD CARD THREAD DEADLOCK\r\n\n");
00472                     lcd.cls();
00473                     lcd.printf("SD CARD\nDEADLOCK");
00474                     break;
00475                 
00476                 case (LCD) : 
00477                     pc->printf("LCD THREAD DEADLOCK\r\n\n");
00478                     lcd.cls();
00479                     lcd.printf("LCD\nDEADLOCK");
00480                     break;
00481                 
00482                 case (NETWORK) : 
00483                     pc->printf("NETWORK THREAD DEADLOCK\r\n\n");
00484                     lcd.cls();
00485                     lcd.printf("NETWORK\nDEADLOCK");
00486                     break;
00487                 
00488                 default:
00489                     pc->printf("MULTIPLE THREAD DEADLOCK\r\n\n");
00490                     lcd.cls();
00491                     lcd.printf("DEADLOCK");
00492                     break;
00493             }
00494         
00495             for (int i = 0;i<50;i++)
00496             {
00497                 redLED = 1;
00498                 wait(0.05);
00499                 redLED = 0;
00500                 wait(0.05);
00501             }
00502             NVIC_SystemReset();
00503         }       
00504         else if (logging) 
00505         {
00506             /*
00507             printlock.lock(); 
00508             pc->printf("WATCHDOG RAN WITH NO DEADLOCKED THREADS\r\n\n"); 
00509             printlock.unlock();
00510             */
00511             printQueue.call(printf,"WATCHDOG RAN WITH NO DEADLOCKED THREADS\r\n\n"); 
00512         } 
00513     }
00514 }
00515 
00516 void PLL_Config(void)
00517 {
00518     
00519 
00520 //*******************************************************************************
00521 //*            PLL (clocked by HSI) used as System clock source                 *
00522 //*                         By Stuart MacVeigh                                  *
00523 //*******************************************************************************
00524 
00525     RCC->APB1ENR |= RCC_APB1ENR_PWREN;  //enable power interface clock source
00526     PWR->CR |= PWR_CR_VOS;
00527 
00528     
00529         #define PLL_N   180         //SYSTEM CLOCK SPEED (FCY (MHz))
00530         #define HSI     16000000    //INTERAL OSC FREQUENCY
00531         
00532         #define PLL_M   (HSI/2000000)       //Fcy = Fxtal x PLL_N/(PLL_P x PLL_M)
00533         #define PLL_P   2
00534         #define PLL_Q   7
00535     // HCLK = SYSCLK / 1
00536     RCC->CFGR |= RCC_CFGR_HPRE_DIV1;        //CORE CLOCK = 180MHZ
00537     
00538     // PCLK2 = HCLK / 2
00539     RCC->CFGR |= RCC_CFGR_PPRE2_DIV4;       //PERIPHERAL CLOCK 2 = 180MHZ/4 = 45MHZ, THIS IS BECAUSE THE SPI MODULES (AND POSSIBLY OTHERS) DO NOT OPERATE PROPERLY WHEN PCLK > 42MHZ
00540     
00541     // PCLK1 = HCLK / 4
00542     RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;       //PERIPHERAL CLOCK 1 = 180MHZ/4 = 45MHZ, THIS IS BECAUSE THE SPI MODULES (AND POSSIBLY OTHERS) DO NOT OPERATE PROPERLY WHEN PCLK > 42MHZ
00543 
00544     // Configure the main PLL
00545     RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) | (PLL_Q << 24);
00546 
00547     // Enable the main PLL
00548     RCC->CR |= RCC_CR_PLLON;
00549 
00550     // Wait till the main PLL is ready
00551     while(!(RCC->CR & RCC_CR_PLLRDY));
00552    
00553     // Configure Flash prefetch, Instruction cache, Data cache and wait state
00554     FLASH->ACR = FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;
00555 
00556     // Select the main PLL as system clock source
00557     RCC->CFGR &=~ RCC_CFGR_SW;
00558     RCC->CFGR |= RCC_CFGR_SW_PLL;
00559 
00560     // Wait till the main PLL is used as system clock source
00561     while ((RCC->CFGR & RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);
00562     
00563 //******************************************************************************
00564 //*            END PLL (CLOCKED BY HSI) SETUP CODE                             *
00565 //******************************************************************************
00566     
00567 }