Esempio n. 1
0
int
main(void)
{
	bool try_boot = true;			/* try booting before we drop to the bootloader */
	unsigned timeout = BOOTLOADER_DELAY;	/* if nonzero, drop out of the bootloader after this time */

	/* Enable the FPU before we hit any FP instructions */
	SCB_CPACR |= ((3UL << 10*2) | (3UL << 11*2)); /* set CP10 Full Access and set CP11 Full Access */

#if defined(BOARD_VRBRAINV40) || defined(BOARD_VRBRAINV45)
	if(!board_test_force_pin() && !(board_get_rtc_signature() == BOOT_RTC_SIGNATURE)) {
		jump_to_app();
	}
#endif
	/* do board-specific initialisation */
	board_init();

	/* 
	 * Check the force-bootloader register; if we find the signature there, don't
	 * try booting.
	 */
	if (board_get_rtc_signature() == BOOT_RTC_SIGNATURE) {

		/*
		 * Don't even try to boot before dropping to the bootloader.
		 */
		try_boot = false;

		/*
		 * Don't drop out of the bootloader until something has been uploaded.
		 */
		timeout = 0;

#if defined(BOARD_VRBRAINV40) || defined(BOARD_VRBRAINV45)
		// force an erase of the first sector because version 4.x
		// of the board is not able to reset USB after first boot.
		// This will force the bootloader to stay until a program has been flashed.
		flash_unlock();
		flash_func_erase_sector(0);
		flash_lock();
#endif
		/* 
		 * Clear the signature so that if someone resets us while we're
		 * in the bootloader we'll try to boot next time.
		 */
		board_set_rtc_signature(0);
	}

#ifdef INTERFACE_USB
	/*
	 * Check for USB connection - if present, don't try to boot, but set a timeout after
	 * which we will fall out of the bootloader.
	 *
	 * If the force-bootloader pins are tied, we will stay here until they are removed and
	 * we then time out.
	 */
#if defined(BOARD_VRBRAINV40) || defined(BOARD_VRBRAINV45)
	if (gpio_get(BOARD_PRESENCE_PORT, BOARD_PRESENCE_PIN) != 0  && board_test_force_pin()) {

		/* don't try booting before we set up the bootloader */
		try_boot = false;
	}

#else
	if (gpio_get(BOARD_PRESENCE_PORT, BOARD_PRESENCE_PIN) != 0) {

		/* don't try booting before we set up the bootloader */
		try_boot = false;
	}
#endif
#endif

	/* Try to boot the app if we think we should just go straight there */
	if (try_boot) {

		/* set the boot-to-bootloader flag so that if boot fails on reset we will stop here */
#ifdef BOARD_BOOT_FAIL_DETECT
		board_set_rtc_signature(BOOT_RTC_SIGNATURE);
#endif

		/* try to boot immediately */
		jump_to_app();

		/* booting failed, stay in the bootloader forever */
		timeout = 0;
	}

	/* configure the clock for bootloader activity */
	rcc_clock_setup_hse_3v3(&clock_setup);

	/* start the interface */
	cinit(BOARD_INTERFACE_CONFIG);

#if 0
	// MCO1/02
	gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO8);
	gpio_set_output_options(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_100MHZ, GPIO8);
	gpio_set_af(GPIOA, GPIO_AF0, GPIO8);
	gpio_mode_setup(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO9);
	gpio_set_af(GPIOC, GPIO_AF0, GPIO9);
#endif

	while (1)
	{
		/* run the bootloader, come back after an app is uploaded or we time out */
		bootloader(timeout);

		/* if the force-bootloader pins are strapped, just loop back */
		if (board_test_force_pin())
			continue;

		/* set the boot-to-bootloader flag so that if boot fails on reset we will stop here */
#ifdef BOARD_BOOT_FAIL_DETECT
		board_set_rtc_signature(BOOT_RTC_SIGNATURE);
#endif

		/* look to see if we can boot the app */
		jump_to_app();

		/* launching the app failed - stay in the bootloader forever */
		timeout = 0;
	}
}
Esempio n. 2
0
void
bootloader(unsigned timeout)
{
	int             c;
	int		arg = 0;
	unsigned	i;
	unsigned	address = board_info.fw_size;	/* force erase before upload will work */
	uint32_t	first_word = 0xffffffff;
	static union {
		uint8_t		c[256];
		uint32_t	w[64];
	} flash_buffer;

	/* (re)start the timer system */
	systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB);
	systick_set_reload(board_info.systick_mhz * 1000);	/* 1ms tick, magic number */
	systick_interrupt_enable();
	systick_counter_enable();

	/* if we are working with a timeout, start it running */
	if (timeout)
		timer[TIMER_BL_WAIT] = timeout;

	while (true) {
		// Wait for a command byte
		led_off(LED_ACTIVITY);
		do {
			/* if we have a timeout and the timer has expired, return now */
			if (timeout && !timer[TIMER_BL_WAIT])
				return;

			/* try to get a byte from the host */
			c = cin_wait(0);

		} while (c < 0);
		led_on(LED_ACTIVITY);

		// common argument handling for commands
		switch (c) {
		case PROTO_GET_SYNC:
		case PROTO_CHIP_ERASE:
		case PROTO_CHIP_VERIFY:
		case PROTO_DEBUG:
			/* expect EOC */
			if (cin_wait(1000) != PROTO_EOC)
				goto cmd_bad;
			break;

		case PROTO_PROG_MULTI:
			/* expect count */
			arg = cin_wait(1000);
			if (arg < 0)
				goto cmd_bad;
			break;

		case PROTO_GET_DEVICE:
		case PROTO_READ_MULTI:
			/* expect arg/count then EOC */
			arg = cin_wait(1000);
			if (arg < 0)
				goto cmd_bad;
			if (cin_wait(1000) != PROTO_EOC)
				goto cmd_bad;
			break;
		}

		// handle the command byte
		switch (c) {

		case PROTO_GET_SYNC:            // sync
			break;

		case PROTO_GET_DEVICE:		// report board info

			switch (arg) {
			case PROTO_DEVICE_BL_REV:
				cout((uint8_t *)&bl_proto_rev, sizeof(bl_proto_rev));
				break;

			case PROTO_DEVICE_BOARD_ID:
				cout((uint8_t *)&board_info.board_type, sizeof(board_info.board_type));
				break;

			case PROTO_DEVICE_BOARD_REV:
				cout((uint8_t *)&board_info.board_rev, sizeof(board_info.board_rev));
				break;

			case PROTO_DEVICE_FW_SIZE:
				cout((uint8_t *)&board_info.fw_size, sizeof(board_info.fw_size));
				break;
			default:
				goto cmd_bad;
			}
			break;

		case PROTO_CHIP_ERASE:          // erase the program area + read for programming
			flash_unlock();
			for (i = 0; flash_func_sector_size(i) != 0; i++)
				flash_func_erase_sector(i);
			address = 0;
			break;

		case PROTO_CHIP_VERIFY:		// reset for verification of the program area
			address = 0;
			break;

		case PROTO_PROG_MULTI:		// program bytes
                        if (arg % 4)
                                goto cmd_bad;
                        if ((address + arg) > board_info.fw_size)
                                goto cmd_bad;
                        if (arg > sizeof(flash_buffer.c))
                                goto cmd_bad;
                        for (i = 0; i < arg; i++) {
                                c = cin_wait(1000);
				if (c < 0)
                                        goto cmd_bad;
				flash_buffer.c[i] = c;
			}
                        if (cin_wait(1000) != PROTO_EOC)
                                goto cmd_bad;
			if (address == 0) {
				// save the first word and don't program it until 
                                // everything else is done
				first_word = flash_buffer.w[0];
				// replace first word with bits we can overwrite later
				flash_buffer.w[0] = 0xffffffff;
			}
			arg /= 4;
			for (i = 0; i < arg; i++) {
				flash_func_write_word(address, flash_buffer.w[i]);
				address += 4;
			}
			break;

		case PROTO_READ_MULTI:			// readback bytes
			if (arg % 4)
				goto cmd_bad;
			if ((address + arg) > board_info.fw_size)
				goto cmd_bad;
			arg /= 4;

			/* handle readback of the not-yet-programmed first word */
			if ((address == 0) && (first_word != 0xffffffff)) {
				cout((uint8_t *)&first_word, 4);
				address += 4;
				arg--;
			}
			while (arg-- > 0) {
				cout_word(flash_func_read_word(address));
				address += 4;
			}
			break;

		case PROTO_BOOT:
			// program the deferred first word
			if (first_word != 0xffffffff) {
				flash_func_write_word(0, first_word);

				// revert in case the flash was bad...
				first_word = 0xffffffff;
			}

			// quiesce and jump to the app
			return;

		case PROTO_DEBUG:
			// XXX reserved for ad-hoc debugging as required
			break;

		default:
			continue;
		}
		// we got a command worth syncing, so kill the timeout because
		// we are probably talking to the uploader
		timeout = 0;

		// send the sync response for this command
		sync_response();
		continue;
cmd_bad:
		// Currently we do nothing & let the programming tool time out
		// if that's what it wants to do.
		// Let the initial delay keep counting down so that we ignore
		// random chatter from a device.
		while(true);
		continue;
	}
}