Latest
Dependencies: serial_terminal sample_hardware PLL_Config SDCard BMP280 Networkbits TextLCD SDBlockDevice
main.cpp
- Committer:
- Swabey89
- Date:
- 2019-01-03
- Revision:
- 32:8c9d8f2dfe89
- Parent:
- 31:087e295cc859
File content as of revision 32:8c9d8f2dfe89:
#include "mbed.h" #include <stm32f4xx.h> #include "sample_hardware.hpp" #include "Networking.hpp" #include "serial_terminal.hpp" #include "SDCard.hpp" #include "rtos.h" #include "events/mbed_events.h" #include "LCDdisplay.hpp" //#include "PLL_Config.c" //Defines TEST FOR SD CARD MOUNT AND UNMOUNT #define EDGE_FALLEN 0 #define EDGE_RISEN 1 //Signals #define TAKE_SAMPLE 1 #define STORE_DATA 2 //Global variables unsigned int newestIndex = BUFFERSIZE-1; //First time it is incremented, it will be 0 unsigned int oldestIndex = BUFFERSIZE-1; FILE* fp; FATFileSystem* fs; //Shared mutable variables VOLATILE bool sd_init; //is it? bool logging = false; bool sampling = true; float sample_rate = 15; //is it? struct tm* timeData; char cmdBuffer[256]; sensorData buffer[BUFFERSIZE]; RawSerial* pc; //Thread synchronisation primatives Semaphore spaceAvailable(BUFFERSIZE); Semaphore samplesInBuffer(0, BUFFERSIZE); Mutex bufferLock; //Queues EventQueue SDqueue(1024*EVENTS_EVENT_SIZE); //changed from 32 EventQueue LCDqueue(32*EVENTS_EVENT_SIZE); EventQueue serialqueue(32*EVENTS_EVENT_SIZE); //TEST EventQueue printQueue(256*EVENTS_EVENT_SIZE); //Threads Thread producer_thread(osPriorityHigh); Thread consumer_thread; Thread serial_thread(osPriorityAboveNormal); Thread SDqueue_thread; //take out queue in name? Thread LCDqueue_thread; Thread network_thread; //TEST FOR SD CARD Thread SDmount_thread; //TEST FOR PRINTF //Timers Ticker sample; //Function prototypes void sampleISR(void); void sampleProducer(void); void sampleConsumer(void); void serialISR(void); void serialData(void); //TEST FOR SD CARD MOUNT AND UNMOUNT Timeout userswTimeOut; int userswState = EDGE_FALLEN; InterruptIn usersw(USER_BUTTON); void userswTimeOutHandler(); void userswRisingEdge(); void userswFallingEdge(); void SDmount(); Mutex printlock; Mutex LCDlock; Mutex timeLock; Mutex SDlock; //TEST FOR BUFFER CHANGES unsigned int saveIndex = BUFFERSIZE-1; int32_t Nspaces = BUFFERSIZE; int32_t Nsamples; //TEST FOR WATCHDOG char threadstates = 0; Timeout producer_tout; Timeout consumer_tout; Timeout serial_tout; Timeout SD_tout; Timeout LCD_tout; Timeout network_tout; Thread watchdog_thread(osPriorityHigh); //TSET FOR PRINTF Thread printf_thread; void producer_toutISR(void); void consumer_toutISR(void); void serial_toutISR(void); void SD_toutISR(void); void LCD_toutISR(void); void network_toutISR(void); void watchdog(void); void PLL_Config(void); osThreadId main_thread; #define PRODUCER 1<<0 #define CONSUMER 1<<1 #define SERIAL 1<<2 #define SD 1<<3 #define LCD 1<<4 #define NETWORK 1<<5 int main() { PLL_Config(); main_thread = Thread::gettid(); timeData = new tm; pc = new RawSerial(USBTX, USBRX, 115200); //Initialisations SDcard(); //Power on self test post(); //Start threads SDqueue_thread.start(callback(&SDqueue, &EventQueue::dispatch_forever)); LCDqueue_thread.start(callback(&LCDqueue, &EventQueue::dispatch_forever)); serial_thread.start(callback(&serialqueue, &EventQueue::dispatch_forever)); network_thread.start(network); producer_thread.start(sampleProducer); consumer_thread.start(sampleConsumer); //TEST LCDqueue.call_every(5000, LCD_display); //TEST FOR SD CARD //SDmount_thread.start(SDmount); //TEST FOR WATCGDOG watchdog_thread.start(watchdog); //TEST FOR PRINTFQUEUE printf_thread.start(callback(&printQueue, &EventQueue::dispatch_forever)); //Attach ISRs sample.attach(&sampleISR, sample_rate); //Allow sampling to start pc->attach(serialISR, Serial::RxIrq); //TEST FOR SD CARD MOUNT AND UNMOUNT usersw.rise(&userswRisingEdge); //Flash to indicate goodness while(true) { //greenLED = !greenLED; //Thread::wait(500); } } /* FUNCITONS BELOW NEED MOVING? */ void sampleISR() { producer_thread.signal_set(TAKE_SAMPLE); } void serialISR() { pc->attach(NULL, Serial::RxIrq); serialqueue.call(serialData); } void serialData() { static int i = 0; if (pc->readable()) { cmdBuffer[i] = pc->getc(); if (i != 29) { if (cmdBuffer[i] == '\b') { i = (i ? i-1 : 0); } else if (cmdBuffer[i] == '\r') { cmdBuffer[i+1]==NULL; serialqueue.call(serialterm); i = 0; } else i++; } else { serialqueue.call(serialterm); i = 0; } } pc->attach(serialISR, Serial::RxIrq); } void sampleProducer() { while(true) { //High priority thread Thread::signal_wait(TAKE_SAMPLE); //wd_thread.signal_set(PROD_SIGNAL); //prod_stat = 0; Nspaces = spaceAvailable.wait(0); //Non-blocking bufferLock.lock(); producer_tout.attach(producer_toutISR, TOUT_TIME_DEF); //Update buffer if ((newestIndex == oldestIndex) && (Nspaces==0)) { //printQueue.call(printf, "oldest index being increased\n\r"); oldestIndex = (oldestIndex+1) % BUFFERSIZE; } newestIndex = (newestIndex+1) % BUFFERSIZE; //CIRCULAR /* buffer[newestIndex].updatetemp(sensor.getTemperature()); buffer[newestIndex].updatepress(sensor.getPressure()); buffer[newestIndex].updatelight(adcIn.read()); buffer[newestIndex].updateTime(); */ double temp_r = sensor.getTemperature(); double press_r = sensor.getPressure(); float light_r = adcIn.read(); buffer[newestIndex].updatetemp(temp_r); buffer[newestIndex].updatepress(press_r); buffer[newestIndex].updatelight(light_r); buffer[newestIndex].updateTime(); if (Nspaces != 0) { Nspaces--; } samplesInBuffer.release(); //Pass onto queues //LCDqueue.call(LCD_display,temp_r,press_r,light_r); //LCDqueue.call(LCD_display, &buffer[newestIndex]); if(logging) { /* printlock.lock(); pc->printf("Sample placed in buffer at position %d\r\n", newestIndex); pc->printf("Number of spaces available in buffer:%d\r\n\n",Nspaces); printlock.unlock(); */ printQueue.call(printf, "Sample placed in buffer at position %d\r\nNumber of spaces available in buffer:%d\r\n\n", newestIndex, Nspaces); } bufferLock.unlock(); producer_tout.detach(); } } void sampleConsumer() { while(true) { //static time_t seconds; //possibly move into if(sd_init) //write to the SD card from oldestindex up to newestIndex. Nsamples = samplesInBuffer.wait(); //Block if no samples to take - acquires bufferLock.lock(); //Moved to here from below to try and ensure timer is started only when the buffer can be used consumer_tout.attach(consumer_toutISR,TOUT_TIME_DEF); if (sd_init) { /* char fileDate[30]; timeLock.lock(); seconds = time(NULL); timeData = localtime(&seconds); //set_time(mktime(timeData)); strftime(fileDate, 30, "sd/log_%d_%m_%y.csv", timeData); timeLock.unlock(); fp = fopen(fileDate,"a"); //ISSUE if (fp == NULL) { printlock.lock(); pc->printf("WARNING: FILE COULD NOT BE OPENED\r\n\n"); sd_init = false; printlock.unlock(); samplesInBuffer.release(); } else { //Nested locks probably a bad idea! //bufferLock.lock(); SDlock.lock(); oldestIndex = (oldestIndex+1) % BUFFERSIZE; //fprintf(fp,"%s,%5.2f,%5.2f,%5.2f\r", buffer[oldestIndex].getTime(), buffer[oldestIndex].gettemp(), buffer[oldestIndex].getpress(), buffer[oldestIndex].getlight()); SDqueue.call(SDaddSample,buffer[oldestIndex].getTime(), buffer[oldestIndex].gettemp(), buffer[oldestIndex].getpress(), buffer[oldestIndex].getlight()); SDlock.unlock(); if(logging) { printlock.lock(); pc->printf("Log file %s updated with sample from position %d in buffer\r\n",fileDate,oldestIndex); pc->printf("newestIndex position %d\r\n",newestIndex); pc->printf("oldestIndex position %d\r\n\n",oldestIndex); printlock.unlock(); } //bufferLock.unlock(); fclose(fp); */ oldestIndex = (oldestIndex+1) % BUFFERSIZE; //fprintf(fp,"%s,%5.2f,%5.2f,%5.2f\r", buffer[oldestIndex].getTime(), buffer[oldestIndex].gettemp(), buffer[oldestIndex].getpress(), buffer[oldestIndex].getlight()); SDqueue.call(SDaddSample,buffer[oldestIndex].getTime(), buffer[oldestIndex].gettemp(), buffer[oldestIndex].getpress(), buffer[oldestIndex].getlight(), oldestIndex); } else { samplesInBuffer.release(); } bufferLock.unlock(); consumer_tout.detach(); } } //TEST FOR MOUNTING AND UNMOUNTING SD CARD //Interrupt service routine for handling the timeout void userswTimeOutHandler() { userswTimeOut.detach(); //Stop the timeout counter firing //Which event does this follow? switch (userswState) { case EDGE_RISEN: usersw.fall(&userswFallingEdge); //Now wait for a falling edge break; case EDGE_FALLEN: usersw.rise(&userswRisingEdge); //Now wait for a rising edge break; } //end switch } //Interrupt service routine for a rising edge (press) void userswRisingEdge() { usersw.rise(NULL); //Disable detecting more rising edges userswState = EDGE_RISEN; //Flag state userswTimeOut.attach(&userswTimeOutHandler, 0.2); //Start timeout timer } //Interrupt service routive for SW1 falling edge (release) void userswFallingEdge() { usersw.fall(NULL); //Disable this interrupt //SDmount_thread.signal_set(SIGNAL_SD); SDqueue.call(SDmount); userswState = EDGE_FALLEN; //Flag state userswTimeOut.attach(&userswTimeOutHandler, 0.2); //Start timeout counter - may want to increase this } //TEST FOR WATCHDOG //ISR void producer_toutISR(void) { threadstates |= PRODUCER; } void consumer_toutISR(void) { threadstates |= CONSUMER; } void serial_toutISR(void) { threadstates |= SERIAL; } void SD_toutISR(void) { threadstates |= SD; } void LCD_toutISR(void) { threadstates |= LCD; } void network_toutISR(void) { threadstates |= NETWORK; } void watchdog(void) { while(true) { Thread::wait(10000); if(threadstates) { producer_thread.terminate(); consumer_thread.terminate(); serial_thread.terminate(); SDqueue_thread.terminate(); LCDqueue_thread.terminate(); network_thread.terminate(); printf_thread.terminate(); pc->printf("THREAD PSW: 0x%x\n\r", threadstates); switch (threadstates) { case (PRODUCER) : pc->printf("PRODUCER THREAD DEADLOCK\r\n\n"); lcd.cls(); lcd.printf("PRODUCER\nDEADLOCK"); break; case (CONSUMER) : pc->printf("CONSUMER THREAD DEADLOCK\r\n\n"); lcd.cls(); lcd.printf("CONSUMER\nDEADLOCK"); break; case (SERIAL) : pc->printf("SERIAL THREAD DEADLOCK\r\n\n"); lcd.cls(); lcd.printf("SERIAL\nDEADLOCK"); break; case (SD) : pc->printf("SD CARD THREAD DEADLOCK\r\n\n"); lcd.cls(); lcd.printf("SD CARD\nDEADLOCK"); break; case (LCD) : pc->printf("LCD THREAD DEADLOCK\r\n\n"); lcd.cls(); lcd.printf("LCD\nDEADLOCK"); break; case (NETWORK) : pc->printf("NETWORK THREAD DEADLOCK\r\n\n"); lcd.cls(); lcd.printf("NETWORK\nDEADLOCK"); break; default: pc->printf("MULTIPLE THREAD DEADLOCK\r\n\n"); lcd.cls(); lcd.printf("DEADLOCK"); break; } for (int i = 0;i<50;i++) { redLED = 1; wait(0.05); redLED = 0; wait(0.05); } NVIC_SystemReset(); } else if (logging) { /* printlock.lock(); pc->printf("WATCHDOG RAN WITH NO DEADLOCKED THREADS\r\n\n"); printlock.unlock(); */ printQueue.call(printf,"WATCHDOG RAN WITH NO DEADLOCKED THREADS\r\n\n"); } } } void PLL_Config(void) { //******************************************************************************* //* PLL (clocked by HSI) used as System clock source * //* By Stuart MacVeigh * //******************************************************************************* RCC->APB1ENR |= RCC_APB1ENR_PWREN; //enable power interface clock source PWR->CR |= PWR_CR_VOS; #define PLL_N 180 //SYSTEM CLOCK SPEED (FCY (MHz)) #define HSI 16000000 //INTERAL OSC FREQUENCY #define PLL_M (HSI/2000000) //Fcy = Fxtal x PLL_N/(PLL_P x PLL_M) #define PLL_P 2 #define PLL_Q 7 // HCLK = SYSCLK / 1 RCC->CFGR |= RCC_CFGR_HPRE_DIV1; //CORE CLOCK = 180MHZ // PCLK2 = HCLK / 2 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 // PCLK1 = HCLK / 4 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 // Configure the main PLL RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) | (PLL_Q << 24); // Enable the main PLL RCC->CR |= RCC_CR_PLLON; // Wait till the main PLL is ready while(!(RCC->CR & RCC_CR_PLLRDY)); // Configure Flash prefetch, Instruction cache, Data cache and wait state FLASH->ACR = FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS; // Select the main PLL as system clock source RCC->CFGR &=~ RCC_CFGR_SW; RCC->CFGR |= RCC_CFGR_SW_PLL; // Wait till the main PLL is used as system clock source while ((RCC->CFGR & RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL); //****************************************************************************** //* END PLL (CLOCKED BY HSI) SETUP CODE * //****************************************************************************** }