示例#1
0
caddr_t _sbrk(int incr)
{
	char *prev_heap_end;

	if (heap_end == 0) {
		heap_end = &_end;
	}
	prev_heap_end = heap_end;

#if SBRK_VERBOSE
	xprintf("_sbrk called with incr %d heap-end before at 0x%08lX, stack_top at 0x%08lX",
			incr, (uint32_t)heap_end, (uint32_t)get_stack_top());
#endif

	if (heap_end + incr > get_stack_top()) {
#if SBRK_VERBOSE
		xprintf(" *** Heap and stack collision ***\n");
#endif
		abort();
	}

	heap_end += incr;

#if SBRK_VERBOSE
	xprintf(", heap-end after at 0x%08lX\n", (uint32_t)heap_end);
#endif

	return (caddr_t) prev_heap_end;
}
示例#2
0
int
main()
{
	int ar[] = {1,2,3,4};
	int idx ;
	void *ret;
	struct  stack *st;
	st = stack_constructor(sizeof(int), CAPACITY);
	for (idx = 0; idx < sizeof(ar)/sizeof(ar[0]); idx++ ) {
		push( st, &ar[idx],sizeof(int));
	}
	/*test get_stack_top */
	ret = get_stack_top(st);
	printf("get_stack_top : %d\n",*(int *)ret);
	
	/*test get_stack_size()*/
	printf("current get_stack_size : %d\n",get_stack_size(st));

	/*test pop() */
	pop(st);
	ret = get_stack_top(st);
	printf("get_stack_top : %d\n",*(int *)ret);

	/*test get_stack_empty()*/
	pop(st);
	pop(st);
	pop(st);
	pop(st);
	printf("get_stack_empty : %d \n",get_stack_empty(st));
	
	ret = get_stack_top(st);
	if (NULL == ret) {
		printf("It empty now! \n");
	} else {
		printf("get_stack_top : %d\n",*(int *)ret);
	}
	/*test stack_destroy()*/
	stack_destroy(st);
	printf("clean up ~ \n");

return 0;
}
示例#3
0
文件: smp.c 项目: hugelgupf/akaros
void smp_idle(void)
{
	/* FP must be zeroed before SP.  Ideally, we'd do both atomically.  If we
	 * take an IRQ/NMI in between and set SP first, then a backtrace would be
	 * confused since FP points *below* the SP that the *IRQ handler* is now
	 * using.  By zeroing FP first, at least we won't BT at all (though FP is
	 * still out of sync with SP). */
	set_frame_pointer(0);
	set_stack_pointer(get_stack_top());
	__smp_idle();
}
示例#4
0
文件: test5.c 项目: hsk/docs
void gc_collect() {
  int prev_num = heap_num;
  //printf("gc %p ptr %p\n", &prev_num+1, ptr);// スタックトップ

  gc_mark(get_stack_top(), NULL);
  gc_sweep();

  heap_max = prev_num * 2;

  debug("Collected %d objects, %d remaining.\n", prev_num - heap_num,
         heap_num);
}
示例#5
0
void flush_thread_stack() {
  uintptr_t top = get_stack_top() & ~(PAGE_SIZE - 1);
  // s_stackLimit is already aligned
  ASSERT(top >= s_stackLimit);
  size_t len = top - s_stackLimit;
  ASSERT((len & (PAGE_SIZE - 1)) == 0);
  if (madvise((void*)s_stackLimit, len, MADV_DONTNEED) != 0 &&
      errno != EAGAIN) {
    fprintf(stderr, "%s failed to madvise with error %d\n", __func__, errno);
    abort();
  }
}
示例#6
0
caddr_t _sbrk(int incr)
{
	char *prev_heap_end;

	// Initialize 'heap_end' the firsts time the function gets called
	if (heap_end == 0) {
		heap_end = &_end;
	}
	prev_heap_end = heap_end;


	char* stackTop = get_stack_top();
	if (heap_end + incr > get_stack_top()) {

		abort();
	}

	heap_end += incr;

	return (caddr_t) prev_heap_end;
}
示例#7
0
extern "C" caddr_t _sbrk(int incr)
{
	char *prev_heap_end;
	if (heap_end == 0) {
		heap_end = &_end;
	}
	prev_heap_end = heap_end;
	if (heap_end + incr > get_stack_top()) {
		
		abort();
	}
	heap_end += incr;
	return (caddr_t) prev_heap_end;
}
示例#8
0
文件: syscalls.c 项目: minimaster/4pi
caddr_t _sbrk(int incr)
{
	int *prev_heap_end;
	if (heap_end == 0) {
		heap_end = &__HEAP_START;
	}
	prev_heap_end = heap_end;
#if 1
	if (heap_end + incr > get_stack_top()) {
		//xprintf("Heap and stack collision\n");
		abort();
	}
#endif
	heap_end += incr;
	return (caddr_t) prev_heap_end;
}
示例#9
0
caddr_t _sbrk(int incr)
{
	char *prev_heap_end;
	if (heap_end == 0) {
		heap_end = &__end__;
	}
	prev_heap_end = heap_end;
#if 1
	if (heap_end + incr > get_stack_top()) {
	//	xprintf("Heap and stack collision\n");
		//abort();
	    errno = ENOMEM;
	    return (caddr_t) -1;
	}
#endif
	heap_end += incr;
	return (caddr_t) prev_heap_end;
}
示例#10
0
文件: smp.c 项目: hugelgupf/akaros
/* Arch-independent per-cpu initialization.  This will call the arch dependent
 * init first. */
void smp_percpu_init(void)
{
	uint32_t coreid = core_id();
	struct per_cpu_info *pcpui = &per_cpu_info[coreid];
	void *trace_buf;
	struct kthread *kthread;
	/* Don't initialize __ctx_depth here, since it is already 1 (at least on
	 * x86), since this runs in irq context. */
	/* Do this first */
	__arch_pcpu_init(coreid);
	/* init our kthread (tracks our currently running context) */
	kthread = __kthread_zalloc();
	kthread->stacktop = get_stack_top();	/* assumes we're on the 1st page */
	pcpui->cur_kthread = kthread;
	/* Treat the startup threads as ktasks.  This will last until smp_idle when
	 * they clear it, either in anticipation of being a user-backing kthread or
	 * to handle an RKM. */
	kthread->flags = KTH_KTASK_FLAGS;
	per_cpu_info[coreid].spare = 0;
	/* Init relevant lists */
	spinlock_init_irqsave(&per_cpu_info[coreid].immed_amsg_lock);
	STAILQ_INIT(&per_cpu_info[coreid].immed_amsgs);
	spinlock_init_irqsave(&per_cpu_info[coreid].routine_amsg_lock);
	STAILQ_INIT(&per_cpu_info[coreid].routine_amsgs);
	/* Initialize the per-core timer chain */
	init_timer_chain(&per_cpu_info[coreid].tchain, set_pcpu_alarm_interrupt);
#ifdef CONFIG_KTHREAD_POISON
	*kstack_bottom_addr(kthread->stacktop) = 0xdeadbeef;
#endif /* CONFIG_KTHREAD_POISON */
	/* Init generic tracing ring */
	trace_buf = kpage_alloc_addr();
	assert(trace_buf);
	trace_ring_init(&pcpui->traces, trace_buf, PGSIZE,
	                sizeof(struct pcpu_trace_event));
	for (int i = 0; i < NR_CPU_STATES; i++)
		pcpui->state_ticks[i] = 0;
	pcpui->last_tick_cnt = read_tsc();
	/* Core 0 is in the KERNEL state, called from smp_boot.  The other cores are
	 * too, at least on x86, where we were called from asm (woken by POKE). */
	pcpui->cpu_state = CPU_STATE_KERNEL;
	/* Enable full lock debugging, after all pcpui work is done */
	pcpui->__lock_checking_enabled = 1;
}
示例#11
0
文件: syscalls.c 项目: glockwork/dfu
caddr_t _sbrk(int incr)
{
	char *prev_heap_end;
#if SBRK_VERBOSE
	xprintf("_sbrk called with incr %d\n", incr);
#endif
	if (heap_end == 0) {
		heap_end = &_end;
	}
	prev_heap_end = heap_end;
#if 1
	if (heap_end + incr > get_stack_top()) {
		xprintf("Heap and stack collision\n");
		abort();
	}
#endif
	heap_end += incr;
	return (caddr_t) prev_heap_end;
}
示例#12
0
文件: smp.c 项目: brho/akaros
void smp_idle(void)
{
	disable_irq();
	__reset_stack_pointer(0, get_stack_top(), __smp_idle);
}
示例#13
0
文件: test5.c 项目: hsk/docs
void gc_init() {
  gc_top_ptr = get_stack_top();
  heap_list = NULL;
  heap_num = 0;
  heap_max = 8;
}
示例#14
0
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();
			}
		}
	}

}
示例#15
0
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;
}