Latest
Dependencies: serial_terminal sample_hardware PLL_Config SDCard BMP280 Networkbits TextLCD SDBlockDevice
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 }
Generated on Wed Jul 13 2022 03:16:30 by 1.7.2