Example #1
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;
	}
}
Example #2
0
void vTaskVCP(void *pvParameters)
{
	static u32 address = 0;
	static uint8_t usb_inited = 0;
	uint8_t c;
	int arg;
	uint8_t tmpbuf[EERROM_SIZE];
	
	for(;;)
	{
	    //Give the change to the OS scheduling. It is really a fool idea. Change me!
	    //TODO - should use semaphore
	    vTaskDelay( 1 / portTICK_RATE_MS );
//		xSemaphoreTake(onVCPSemaphore, portMAX_DELAY);

		if(usb_inited == 0)
		{
		    GPIO_InitTypeDef  gpio;
            //This is a trick to perform a USB re-enumerate
            gpio.GPIO_Pin = GPIO_Pin_12;
            gpio.GPIO_Speed = GPIO_Speed_100MHz;
            gpio.GPIO_Mode = GPIO_Mode_OUT;
            gpio.GPIO_OType = GPIO_OType_PP;
            gpio.GPIO_PuPd = GPIO_PuPd_NOPULL;
            GPIO_Init(GPIOB, &gpio);
            GPIO_SetBits(GPIOB, GPIO_Pin_12 );
            vTaskDelay(500 / portTICK_RATE_MS);
            GPIO_ResetBits(GPIOB, GPIO_Pin_12 );

            // Initialize USB VCP. Do it ASAP
            USBD_Init(&USB_OTG_dev, USB_OTG_FS_CORE_ID, &USR_desc, &USBD_CDC_cb,
                    &USR_cb);
            usb_inited = 1;
		}

		if (VCP_get_char(&c))
		{
			switch(c) {
				case PROTO_GET_SYNC:
					if (cin_wait(usb_vcp_timeout) != PROTO_EOC)
						goto cmd_bad;
					break;
				case PROTO_GET_DEVICE:
					arg = cin_wait(usb_vcp_timeout);
					if (arg < 0)
						goto cmd_bad;
					if (cin_wait(usb_vcp_timeout) != PROTO_EOC)
						goto cmd_bad;
					
					switch (arg) {
						case PROTO_DEVICE_BL_REV:
						    VCP_send_str((uint8_t*)&bl_proto_rev);
							break;
						default:
							goto cmd_bad;
					}
			
					break;
				case PROTO_START_TRANS:
					if (cin_wait(usb_vcp_timeout) != PROTO_EOC)
						goto cmd_bad;
					address = 0;
					memset(tmpbuf,0,EERROM_SIZE);
					break;
				case PROTO_SET_PARAMS:
					arg = cin_wait(usb_vcp_timeout);
					if (arg < 0)
						goto cmd_bad;

					// sanity-check arguments
					if (arg % 4)
						goto cmd_bad;
					if ((address + arg) > EERROM_SIZE)
						goto cmd_bad;
					for (int i = 0; i < arg; i++) 
					{
						c = cin_wait(usb_vcp_timeout);
						if (c < 0)
							goto cmd_bad;
						
						tmpbuf[address++] = c;
					}
					
					break;
				case PROTO_END_TRANS:
					if (cin_wait(usb_vcp_timeout) != PROTO_EOC)
						goto cmd_bad;
					
					//ensure we receive right size
					if(address == EERROM_SIZE)
					{
						memcpy(eeprom_buffer.c,tmpbuf,EERROM_SIZE); 
//						bool ret = StoreParams();
//						if(!ret)
//						{
//							//TODO - handle flash write error here
//						}
					}
					break;
				case PROTO_SAVE_TO_FLASH:
					if (cin_wait(usb_vcp_timeout) != PROTO_EOC)
						goto cmd_bad;
					
					//ensure we receive right size
					if(address == EERROM_SIZE)
					{
						bool ret = StoreParams();
						if(!ret)
						{
							//TODO - handle flash write error here
						}
					}
					break;	
				case PROTO_GET_PARAMS:
					if (cin_wait(usb_vcp_timeout) != PROTO_EOC)
						goto cmd_bad;
					for (int i = 0; i < EERROM_SIZE; i++)
					{
					    VCP_put_char(eeprom_buffer.c[i]);
						//TM_USB_VCP_Putc(testbuf[i]);
						//vTaskDelay( 1 / portTICK_RATE_MS );
					}
					
					break;
				case PROTO_BL_UPLOAD:
					if (cin_wait(usb_vcp_timeout) != PROTO_EOC)
						goto cmd_bad;

					sync_response();
					vTaskDelay( 200 / portTICK_RATE_MS );
					
					GPIO_SetBits(GPIOB,GPIO_Pin_12);
					vTaskDelay( 500 / portTICK_RATE_MS );
					GPIO_ResetBits(GPIOB,GPIO_Pin_12);
					
					__DSB();  /* Ensure all outstanding memory accesses included
                                buffered write are completed before reset */
					SCB->AIRCR  = ((0x5FA << SCB_AIRCR_VECTKEY_Pos)      |
								 (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |
								 SCB_AIRCR_SYSRESETREQ_Msk);                   /* Keep priority group unchanged */
					__DSB();                                                     /* Ensure completion of memory access */
					
					while(1);  
					break;
				default:
					continue;
							
			}
			
			// send the sync response for this command
			sync_response();
			continue;
		}
		
		vTaskDelay( 10 / portTICK_RATE_MS );
		continue;
cmd_bad:
		// send an 'invalid' response but don't kill the timeout - could be garbage
		invalid_response();
		continue;

cmd_fail:
		// send a 'command failed' response but don't kill the timeout - could be garbage
		failure_response();
		continue;		
	}
}
Example #3
0
// Bootloader protocol logic
//
static void
bootloader(void)
{
	uint8_t		c;
	uint8_t		count, i;
	static uint16_t	address;

	// Wait for a command byte
	LED_BOOTLOADER = LED_ON;
	c = cin();
	LED_BOOTLOADER = LED_OFF;

	// common tests for EOC
	switch (c) {
	case PROTO_GET_SYNC:
	case PROTO_GET_DEVICE:
	case PROTO_CHIP_ERASE:
	case PROTO_PARAM_ERASE:
	case PROTO_READ_FLASH:
	case PROTO_DEBUG:
		if (cin() != PROTO_EOC)
			goto cmd_bad;
	}

	switch (c) {

	case PROTO_GET_SYNC:		// sync
		break;

	case PROTO_GET_DEVICE:
		cout(BOARD_ID);
		cout(board_frequency);
		break;

	case PROTO_CHIP_ERASE:		// erase the program area
		flash_erase_app();
		break;

	case PROTO_PARAM_ERASE:
		flash_erase_scratch();
		break;

	case PROTO_LOAD_ADDRESS:	// set address
		address = cin();
		address |= (uint16_t)cin() << 8;
		if (cin() != PROTO_EOC)
			goto cmd_bad;
		break;

	case PROTO_PROG_FLASH:		// program byte
		c = cin();
		if (cin() != PROTO_EOC)
			goto cmd_bad;
		flash_write_byte(address++, c);
		break;

	case PROTO_READ_FLASH:		// readback byte
		c = flash_read_byte(address++);
		cout(c);
		break;

	case PROTO_PROG_MULTI:
		count = cin();
		if (count > sizeof(buf))
			goto cmd_bad;
		for (i = 0; i < count; i++)
			buf[i] = cin();
		if (cin() != PROTO_EOC)
			goto cmd_bad;
		for (i = 0; i < count; i++)
			flash_write_byte(address++, buf[i]);
		break;

	case PROTO_READ_MULTI:
		count = cin();
		if (cin() != PROTO_EOC)
			goto cmd_bad;
		for (i = 0; i < count; i++) {
			c = flash_read_byte(address++);
			cout(c);
		}
		break;

	case PROTO_REBOOT:
		// generate a software reset, which should boot to the application
		RSTSRC |= (1 << 4);

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

	default:
		goto cmd_bad;
	}
	sync_response();
cmd_bad:
	return;
}