/* Round the heap up to the given alignment. */ void round_heap (size_t align) { DWORD_PTR needs_to_be; DWORD_PTR need_to_alloc; needs_to_be = (DWORD_PTR) ROUND_UP (get_heap_end (), align); need_to_alloc = needs_to_be - (DWORD_PTR) get_heap_end (); if (need_to_alloc) sbrk (need_to_alloc); }
/* Round the heap up to the given alignment. */ void round_heap (unsigned long align) { unsigned long needs_to_be; unsigned long need_to_alloc; needs_to_be = (unsigned long) ROUND_UP (get_heap_end (), align); need_to_alloc = needs_to_be - (unsigned long) get_heap_end (); if (need_to_alloc) sbrk (need_to_alloc); }
void OpenOBC::mainloop() { printf("stack: 0x%lx heap: 0x%lx free: %li\r\n", get_stack_top(), get_heap_end(), get_mem_free()); printf("starting mainloop...\r\n"); wdt.start(5); Timer coolantTemperatureTimer(interruptManager); Timer displayRefreshTimer(interruptManager); while(1) { wdt.feed(); if(!disableComms) { if(coolantTemperatureTimer.read_ms() >= 1000) { coolantTemperatureTimer.start(); coolantTemperature = kombi->getCoolantTemperature(); } } else { coolantTemperature = 0; } ui->task(); ccm->task(); diag->task(); callback->task(); // if(displayRefreshTimer.read_ms() >= 100) if(0) { displayRefreshTimer.start(); if(*stalkButton) lcd->printfClock(" :D"); else { if(clockDisplayMode == CLOCKDISPLAY_CLOCK) { lcd->printfClock("%02i%02i", rtc->getHour(), rtc->getMinute()); } else if(clockDisplayMode == CLOCKDISPLAY_DATE) { lcd->printfClock("%02i%02i", rtc->getMonth(), rtc->getDay()); } } if(0) switch(displayMode) { case DISPLAY_CALIBRATE: { lcd->printf("set %.2fV", batteryVoltage->read()); break; } case DISPLAY_CLOCKSET: { lcd->printf("set clock"); break; } case DISPLAY_DATESET: { lcd->printf("set date %4i", rtc->getYear()); break; } default: { lcd->printf("invalid displayMode"); break; } } } if(doQuery) { printf("querying...\r\n"); zke->query(); srs->query(); ihkr->query(); kombi->query(); mk4->query(); printf("finished querying\r\n"); doQuery = false; } if(doUnlock) { printf("doing unlock\r\n"); zke->unlock(); printf("done\r\n"); doUnlock = false; } if(doLock) { printf("doing lock\r\n"); zke->lock(); printf("done\r\n"); doLock = false; } static Timer sleepTimer; if(!doSleep) { sleepTimer.start(); } else { if(sleepTimer.read_ms() >= 1000) { // while(doSleep) sleep(); wake(); } } } }
OpenOBC::OpenOBC() : displayMode(reinterpret_cast<volatile DisplayMode_Type&>(LPC_RTC->GPREG0)), averageLitresPer100km(reinterpret_cast<volatile float&>(LPC_RTC->GPREG1)), averageFuelConsumptionSeconds(reinterpret_cast<volatile uint32_t&>(LPC_RTC->GPREG2)) { wdt.start(10); GPIO_IntDisable(0, 0xffffffff, 0); GPIO_IntDisable(0, 0xffffffff, 1); GPIO_IntDisable(2, 0xffffffff, 0); GPIO_IntDisable(2, 0xffffffff, 1); //enable bus, usage, and memmanage faults SCB->SHCSR |= (1<<18) | (1<<17) | (1<<16); idle = new IO(2, 0, true); isr = new IO(2, 1, true); obcS = this; doHardwareTest = false; callback = new Callback(); // callback->addCallback(this, &OpenOBC::buttonMemo, 10000); __enable_irq(); SysTick_Config(SystemCoreClock/1000 - 1); //interrupt period 1ms debug = new Debug(DEBUG_TX_PORTNUM, DEBUG_TX_PINNUM, DEBUG_RX_PORTNUM, DEBUG_RX_PINNUM, DEBUG_BAUD, &interruptManager); debugS = debug; // printf("-"); fflush(stdout); delay(250); printf("-"); fflush(stdout); delay(250); printf("-"); fflush(stdout); delay(250); printf(">\r\n"); delay(250); printf("--->\r\n"); printf("clock speed: %i MHz\r\n", SystemCoreClock / 1000000); printf("stack: 0x%lx heap: 0x%lx free: %li\r\n", get_stack_top(), get_heap_end(), get_mem_free()); vrefEn = new IO(VREF_EN_PORT, VREF_EN_PIN, true, false); //spi coniguration spi0 = new SPI(SPI0_MOSI_PORT, SPI0_MOSI_PIN, SPI0_MISO_PORT, SPI0_MISO_PIN, SPI0_SCK_PORT, SPI0_SCK_PIN); spi1 = new SPI(SPI1_MOSI_PORT, SPI1_MOSI_PIN, SPI1_MISO_PORT, SPI1_MISO_PIN, SPI1_SCK_PORT, SPI1_SCK_PIN); //i2c configuration i2c0 = new I2C(I2C0_SDA_PORT, I2C0_SDA_PIN, I2C0_SCL_PORT, I2C0_SCL_PIN); i2c1 = new I2C(I2C1_SDA_PORT, I2C1_SDA_PIN, I2C1_SCL_PORT, I2C1_SCL_PIN); //i/o expander configuration Input* io0Interrupt = new Input(PCA95XX_INTERRUPT_PORT, PCA95XX_INTERRUPT_PIN); io = new PCA95xx(*i2c0, PCA95XX_ADDRESS, *io0Interrupt, 400000); codeLed = new PCA95xxPin(*io, CODE_LED_PORT, CODE_LED_PIN, true); limitLed = new PCA95xxPin(*io, LIMIT_LED_PORT, LIMIT_LED_PIN, true); timerLed = new PCA95xxPin(*io, TIMER_LED_PORT, TIMER_LED_PIN, true); ccmLight = new PCA95xxPin(*io, CCM_LIGHT_PORT, CCM_LIGHT_PIN, true); chime0 = new PCA95xxPin(*io, CHIME0_PORT, CHIME0_PIN, true); chime1 = new PCA95xxPin(*io, CHIME1_PORT, CHIME1_PIN, true); ventilation = new PCA95xxPin(*io, VENTILATION_PORT, VENTILATION_PIN, true); antitheftHorn = new PCA95xxPin(*io, ANTITHEFT_HORN_PORT, ANTITHEFT_HORN_PIN, true); ews = new PCA95xxPin(*io, EWS_PORT, EWS_PIN, true); out0 = new PCA95xxPin(*io, OUT0_PORT, OUT0_PIN, true); out1 = new PCA95xxPin(*io, OUT1_PORT, OUT1_PIN, true); out2 = new PCA95xxPin(*io, OUT2_PORT, OUT2_PIN, true); out3 = new PCA95xxPin(*io, OUT3_PORT, OUT3_PIN, true); io0 = new PCA95xxPin(*io, IO0_PORT, IO0_PIN, false); io1 = new PCA95xxPin(*io, IO1_PORT, IO1_PIN, false); //lcd configuration lcdBiasEn = new PCA95xxPin(*io, LCD_BIAS_EN_PORT, LCD_BIAS_EN_PIN, true); lcdReset = new IO(LCD_RESET_PORT, LCD_RESET_PIN, false); // IO lcdBias(LCD_BIASCLOCK_PORT, LCD_BIASCLOCK_PIN, true); lcdBiasClock = new PWM(LCD_BIASCLOCK_PORT, LCD_BIASCLOCK_PIN, .99); IO* lcdSel = new IO(LCD_SELECT_PORT, LCD_SELECT_PIN, true); IO* lcdRefresh = new IO(LCD_REFRESH_PORT, LCD_REFRESH_PIN, false); IO* lcdUnk0 = new IO(LCD_UNK0_PORT, LCD_UNK0_PIN, true); IO* lcdUnk1 = new IO(LCD_UNK1_PORT, LCD_UNK1_PIN, false); lcd = new ObcLcd(*spi1, *lcdSel, *lcdRefresh, *lcdUnk0, *lcdUnk1); *lcdReset = true; *lcdBiasEn = true; //backlight configuration lcdLight = new IO(LCD_BACKLIGHT_PORT, LCD_BACKLIGHT_PIN, true); clockLight = new IO(CLOCK_BACKLIGHT_PORT, CLOCK_BACKLIGHT_PIN, true); auxLight = new IO(AUX_BACKLIGHT_PORT, AUX_BACKLIGHT_PIN, true); keypadLight = new IO(KEYPAD_BACKLIGHT_PORT, KEYPAD_BACKLIGHT_PIN, true); // lcdBacklight = new PWM(LCD_BACKLIGHT_PORT, LCD_BACKLIGHT_PIN, .2); // clockBacklight = new PWM(CLOCK_BACKLIGHT_PORT, CLOCK_BACKLIGHT_PIN); printf("openOBC firmware version: %s\r\n", GIT_VERSION); //config file configuration IO* sdcardCs = new IO(SDCARD_CS_PORT, SDCARD_CS_PIN); sd = new SDFS(*spi1, *sdcardCs); sd->mount("sd"); config = new ConfigFile("/sd/openobc.cfg"); //parse the config file; create one with default parameters if it doesn't exist if(config->readConfig() < 0) { int32_t result = config->writeConfig(); if(result >= 0) { DEBUG("created new config file: %s\r\n", config->getFilename().c_str()); } else { DEBUG("couldn't open file for writing: %s\r\n", config->getFilename().c_str()); } } ObcBootupText::mode mode; std::string bootupTextMode = config->getValueByNameWithDefault("BootupTextMode", "GitHash"); std::string bootupText; std::string customBootupText = config->getValueByNameWithDefault("CustomBootupText", "openOBC"); uint bootupDelay = atoi(config->getValueByNameWithDefault("BootupDelay", "800").c_str()); if(bootupTextMode == "GitHash") { mode = ObcBootupText::GitHash; bootupText = "openOBC " GIT_VERSION; lcd->printfClock("%s", GIT_TAG); } else if(bootupTextMode == "Custom") { mode = ObcBootupText::Custom; bootupText = customBootupText; } else if(bootupTextMode == "None") { mode = ObcBootupText::None; bootupText = ""; } lcd->printf("%s", bootupText.c_str()); ccmLight->on(); codeLed->on(); limitLed->on(); timerLed->on(); delay(bootupDelay); if(config->getValueByNameWithDefault("LogConsoleToFile", "no") == "yes") freopen("/sd/stdout.log", "a", stdout); //default config file parameters if(config->getValueByName("DefaultDisplayMode") == "") config->setValueByName("DefaultDisplayMode", "DISPLAY_LAST_DISPLAYMODE"); if(config->getValueByName("BatteryVoltageCalibration") == "") config->setValueByName("BatteryVoltageCalibration", "1.0000"); //default display mode configuration std::string defaultDisplayModeString = config->getValueByName("DefaultDisplayMode"); if(defaultDisplayModeString == "DISPLAY_LAST_DISPLAYMODE") displayMode = displayMode; else if(defaultDisplayModeString == "DISPLAY_CHECK") displayMode = DISPLAY_CHECK; else if(defaultDisplayModeString == "DISPLAY_CONSUM1") displayMode = DISPLAY_CONSUM1; else if(defaultDisplayModeString == "DISPLAY_CONSUM2") displayMode = DISPLAY_CONSUM2; else if(defaultDisplayModeString == "DISPLAY_CONSUM3") displayMode = DISPLAY_CONSUM3; else if(defaultDisplayModeString == "DISPLAY_CONSUM4") displayMode = DISPLAY_CONSUM4; else if(defaultDisplayModeString == "DISPLAY_FREEMEM") displayMode = DISPLAY_FREEMEM; else if(defaultDisplayModeString == "DISPLAY_RANGE1") displayMode = DISPLAY_RANGE1; else if(defaultDisplayModeString == "DISPLAY_RANGE2") displayMode = DISPLAY_RANGE2; else if(defaultDisplayModeString == "DISPLAY_ACCELEROMETER") displayMode = DISPLAY_ACCELEROMETER; else if(defaultDisplayModeString == "DISPLAY_OPENOBC") displayMode = DISPLAY_OPENOBC; else if(defaultDisplayModeString == "DISPLAY_SPEED") displayMode = DISPLAY_SPEED; else if(defaultDisplayModeString == "DISPLAY_TEMP") displayMode = DISPLAY_TEMP; else if(defaultDisplayModeString == "DISPLAY_VOLTAGE") displayMode = DISPLAY_VOLTAGE; else displayMode = DISPLAY_OPENOBC; clockDisplayMode = CLOCKDISPLAY_CLOCK; batteryVoltageCalibration = atof(config->getValueByName("BatteryVoltageCalibration").c_str()); //rtc configuration rtc = new RTC(); rtcS = rtc; RTC_TIME_Type settime; settime.YEAR = 2012; settime.MONTH = 9; settime.DOM = 20; settime.HOUR = 20; settime.MIN = 29; settime.SEC = 0; // rtc->setTime(&settime); //accelerometer configuration Input* accelInterrupt = new Input(ACCEL_INTERRUPT_PORT, ACCEL_INTERRUPT_PIN); accel = new MMA845x(*i2c0, ACCEL_ADDRESS, *accelInterrupt, interruptManager); //ccm configuration Input* ccmData = new Input(CCM_DATA_PORT, CCM_DATA_PIN); IO* ccmClock = new IO(CCM_CLOCK_PORT, CCM_CLOCK_PIN); IO* ccmLatch = new IO(CCM_LATCH_PORT, CCM_LATCH_PIN); uint8_t ccmDisableMask = strtoul(config->getValueByNameWithDefault("ObcCheckDisableMask", "0x%02x", DEFAULT_CCM_DISABLE_MASK).c_str(), NULL, 0); uint8_t ccmInvertMask = strtoul(config->getValueByNameWithDefault("ObcCheckInvertMask", "0x%02x", DEFAULT_CCM_INVERT_MASK).c_str(), NULL, 0); ccm = new CheckControlModule(*ccmData, *ccmClock, *ccmLatch, ccmDisableMask, ccmInvertMask); //fuel level configuration Input* fuelLevelInput = new Input(FUEL_LEVEL_PORT, FUEL_LEVEL_PIN); fuelLevel = new FuelLevel(*fuelLevelInput, interruptManager); //stalk button configuration stalkButton = new Input(STALK_BUTTON_PORT, STALK_BUTTON_PIN, false); //brake switch configuration brakeSwitch = new Input(BRAKE_SWITCH_PORT, BRAKE_SWITCH_PIN); brakeCheck = new Input(BRAKE_CHECK_PORT, BRAKE_CHECK_PIN); //illumination input configuration illumination = new Input(ILLUMINATION_PORT, ILLUMINATION_PIN); //ambient light input configuration ambientLight = new Input(AMBIENT_LIGHT_PORT, AMBIENT_LIGHT_PIN); //diagnostics interface configuration klWake = new IO(KL_WAKE_PORT, KL_WAKE_PIN, true); kline = new Uart(KLINE_TX_PORTNUM, KLINE_TX_PINNUM, KLINE_RX_PORTNUM, KLINE_RX_PINNUM, KLINE_BAUD, UART_PARITY_EVEN, &interruptManager); lline = new Uart(LLINE_TX_PORTNUM, LLINE_TX_PINNUM, LLINE_RX_PORTNUM, LLINE_RX_PINNUM, LLINE_BAUD, UART_PARITY_EVEN, &interruptManager); DS2Bus* k = new Bus(*kline); DS2Bus* l = new Bus(*lline); diag = new DS2(*k, *l); disableComms = false; // while(1) // { // int length = (rand() % 15) + 1; // uint8_t* data = new uint8_t[length]; // uint32_t r = rand(); // for(int i = 0; i < length; i++) // data[i] = r >> (i*2); // DS2Packet packet(0x55, data, length, DS2_16BIT); // delete[] data; // k->write(packet.getRawPacket(), packet.getPacketLength()); // // diag->query(packet, DS2_K); // delay(200); // } zke = new E36ZKE4(*diag); srs = new E36SRS(*diag); ihkr = new E36IHKR(*diag); kombi = new E36Kombi(*diag); mk4 = new E36MK4(*diag); //ignition/run/on input configuration run = new Input(RUN_PORT, RUN_PIN); PINSEL_CFG_Type pincfg; pincfg.Funcnum = PINSEL_FUNC_1; pincfg.OpenDrain = PINSEL_PINMODE_NORMAL; pincfg.Pinmode = PINSEL_PINMODE_TRISTATE; pincfg.Portnum = RUN_PORT; pincfg.Pinnum = RUN_PIN; interruptManager.attach(IRQ_EINT1, &runHandler); //do this first... PINSEL_ConfigPin(&pincfg); //because this immediately triggers an unwanted interrupt EXTI_Init(); EXTI_InitTypeDef EXTICfg; EXTICfg.EXTI_Line = EXTI_EINT1; EXTICfg.EXTI_Mode = EXTI_MODE_EDGE_SENSITIVE; EXTICfg.EXTI_polarity = EXTI_POLARITY_HIGH_ACTIVE_OR_RISING_EDGE; EXTI_ClearEXTIFlag(EXTI_EINT1); EXTI_Config(&EXTICfg); NVIC_SetPriorityGrouping(4); NVIC_SetPriority(EINT1_IRQn, 0); NVIC_EnableIRQ(EINT1_IRQn); //fuel consumption configuration Input* fuelConsInput = new Input(FUEL_CONS_PORT, FUEL_CONS_PIN); fuelConsInput->setPullup(); fuelCons = new FuelConsumption(*fuelConsInput, interruptManager); //speed configuration Input* speedPin = new Input(SPEED_PORT, SPEED_PIN); // speedPin->setPullup(); //for bench use only speed = new SpeedInput(*speedPin, interruptManager); //sd card configuration sdcardDetect = new Input(SDCARD_DETECT_PORT, SDCARD_DETECT_PIN, false); sdcardDetect->setPullup(); //keypad configuration IO* x0 = new IO(1, 20); IO* x1 = new IO(1, 21); IO* x2 = new IO(1, 22); IO* x3 = new IO(1, 25); IO* x4 = new IO(1, 27); Input* y0 = new Input(0, 0); Input* y1 = new Input(0, 1); Input* y2 = new Input(0, 10); Input* y3 = new Input(0, 11); keypad = new ObcKeypad(*x0, *x1, *x2, *x3, *x4, *y0, *y1, *y2, *y3, interruptManager); keypad->attach(BUTTON_1000, this, &OpenOBC::button1000); keypad->attach(BUTTON_100, this, &OpenOBC::button100); keypad->attach(BUTTON_10, this, &OpenOBC::button10); keypad->attach(BUTTON_1, this, &OpenOBC::button1); //analog input configuration batteryVoltage = new AnalogIn(BATTERY_VOLTAGE_PORT, BATTERY_VOLTAGE_PIN, REFERENCE_VOLTAGE, (10.0 + 1.0) / 1.0 * REFERENCE_VOLTAGE, atof(config->getValueByName("BatteryVoltageCalibration").c_str())); temperature = new AnalogIn(EXT_TEMP_PORT,EXT_TEMP_PIN, REFERENCE_VOLTAGE); analogIn1 = new AnalogIn(ANALOG_IN1_PORT, ANALOG_IN1_PIN, REFERENCE_VOLTAGE); analogIn2 = new AnalogIn(ANALOG_IN2_PORT, ANALOG_IN2_PIN, REFERENCE_VOLTAGE); vstart = new AnalogIn(VSTART_PORT, VSTART_PIN, REFERENCE_VOLTAGE, (10.0 + 1.0) / 1.0 * REFERENCE_VOLTAGE); //analog output configuration analogOut = new AnalogOut(ANALOG_OUT_PORT, ANALOG_OUT_PIN, REFERENCE_VOLTAGE); analogOut->writeVoltage(1.0); // averageFuelConsumptionSeconds = 0; // averageLitresPer100km = 0; debug->attach(this, &OpenOBC::uartHandler); if(wdt.wasReset()) { printf("WATCHDOG RESET\r\n"); lcd->printfClock("!!!!"); Timer flashTimer; while((keypad->getKeys() & BUTTON_SET_MASK) != BUTTON_SET_MASK) { if(flashTimer.read_ms() <= 1500) { lcd->printf("WATCHDOG RESET"); } else if(flashTimer.read_ms() <= 3000) { lcd->printf("push SET to continue"); } else { flashTimer.start(); } wdt.feed(); } lcd->clear(); lcd->clearClock(); } coolantTemperature = 0; ui = new ObcUI(*lcd, *keypad, *config); keypad->attachRaw(ui, &ObcUI::handleButtonEvent); ui->addTask(new ObcClock(*this)); ui->addTask(new ObcOdometer(*this)); ui->addTask(new ObcSpeed(*this)); ui->addTask(new ObcMemo(*this)); ui->addTask(new ObcTemp(*this)); ui->addTask(new ObcCheck(*this)); ui->addTask(new ObcLimit(*this)); ui->addTask(new ObcConsum(*this)); ui->addTask(new ObcDist(*this)); ui->addTask(new ObcRange(*this)); ui->addTask(new ObcTimer(*this)); ui->addTask(new ObcKmmls(*this)); ui->addTask(new ObcCode(*this)); ui->wake(); lcd->printf(""); lcd->printfClock(""); ccmLight->off(); codeLed->off(); limitLed->off(); timerLed->off(); // if(keypad->getKeys() == (BUTTON_1000_MASK | BUTTON_10_MASK)) // if(*stalkButton) if(doHardwareTest) hardwareTest(); doSleepCheck = true; }