Exemplo n.º 1
0
/**
 * ProcessIO:
 **/
static void
ProcessIO(void)
{
	uint16_t address;
	uint16_t erase_length;
	uint8_t length;
	uint8_t checksum;
	uint8_t cmd;
	uint8_t rc = CH_ERROR_NONE;

	/* reset the LED state */
	led_counter--;
	if (led_counter == 0) {
		CHugSetLEDsInternal(led_color);
		led_color *= 2;
		if (led_color > CH_STATUS_LED_BLUE)
			led_color = CH_STATUS_LED_GREEN;
		led_counter = BOOTLOADER_FLASH_INTERVAL;
	}

	/* User Application USB tasks */
	if ((USBDeviceState < CONFIGURED_STATE) ||
	    (USBSuspendControl == 1))
		return;

	/* no data was received */
	if(HIDRxHandleBusy(USBOutHandle)) {
		if (idle_counter++ == 0xff &&
		    idle_command != 0x00)
			CHugDeviceIdle();
		return;
	}

	/* got data, reset idle counter */
	idle_counter = 0;

	/* clear for debugging */
	memset (TxBuffer, 0xff, sizeof (TxBuffer));

	cmd = RxBuffer[CH_BUFFER_INPUT_CMD];
	switch(cmd) {
	case CH_CMD_GET_HARDWARE_VERSION:
		TxBuffer[CH_BUFFER_OUTPUT_DATA] = PORTB & 0x0f;
		break;
	case CH_CMD_RESET:
		/* only reset when USB stack is not busy */
		idle_command = CH_CMD_RESET;
		break;
	case CH_CMD_GET_FIRMWARE_VERSION:
		memcpy (&TxBuffer[CH_BUFFER_OUTPUT_DATA],
			&FirmwareVersion,
			2 * 3);
		break;
	case CH_CMD_ERASE_FLASH:
		/* are we lost or stolen */
		if (flash_success == 0xff) {
			rc = CH_ERROR_DEVICE_DEACTIVATED;
			break;
		}
		memcpy (&address,
			(const void *) &RxBuffer[CH_BUFFER_INPUT_DATA+0],
			2);
		/* allow to erase any address but not the bootloader */
		if (address < CH_EEPROM_ADDR_RUNCODE) {
			rc = CH_ERROR_INVALID_ADDRESS;
			break;
		}
		memcpy (&erase_length,
			(const void *) &RxBuffer[CH_BUFFER_INPUT_DATA+2],
			2);
		EraseFlash(address, address + erase_length);
		break;
	case CH_CMD_READ_FLASH:
		/* are we lost or stolen */
		if (flash_success == 0xff) {
			rc = CH_ERROR_DEVICE_DEACTIVATED;
			break;
		}
		/* allow to read any address */
		memcpy (&address,
			(const void *) &RxBuffer[CH_BUFFER_INPUT_DATA+0],
			2);
		length = RxBuffer[CH_BUFFER_INPUT_DATA+2];
		if (length > 60) {
			rc = CH_ERROR_INVALID_LENGTH;
			break;
		}
		ReadFlash(address, length,
			  (unsigned char *) &TxBuffer[CH_BUFFER_OUTPUT_DATA+1]);
		checksum = CHugCalculateChecksum (&TxBuffer[CH_BUFFER_OUTPUT_DATA+1],
						  length);
		TxBuffer[CH_BUFFER_OUTPUT_DATA+0] = checksum;
		break;
	case CH_CMD_WRITE_FLASH:
		/* are we lost or stolen */
		if (flash_success == 0xff) {
			rc = CH_ERROR_DEVICE_DEACTIVATED;
			break;
		}
		/* write to flash that's not the bootloader */
		memcpy (&address,
			(const void *) &RxBuffer[CH_BUFFER_INPUT_DATA+0],
			2);
		if (address < CH_EEPROM_ADDR_RUNCODE) {
			rc = CH_ERROR_INVALID_ADDRESS;
			break;
		}
		length = RxBuffer[CH_BUFFER_INPUT_DATA+2];
		if (length > CH_FLASH_TRANSFER_BLOCK_SIZE) {
			rc = CH_ERROR_INVALID_LENGTH;
			break;
		}
		checksum = CHugCalculateChecksum(&RxBuffer[CH_BUFFER_INPUT_DATA+4],
						 length);
		if (checksum != RxBuffer[CH_BUFFER_INPUT_DATA+3]) {
			rc = CH_ERROR_INVALID_CHECKSUM;
			break;
		}

		/* copy low 32 bytes into flash buffer, and only write
		 * in 64 byte chunks as this is a limitation of the
		 * hardware */
		if ((address & CH_FLASH_TRANSFER_BLOCK_SIZE) == 0) {
			memset (FlashBuffer,
				0xff,
				CH_FLASH_WRITE_BLOCK_SIZE);
			memcpy (FlashBuffer,
				(const void *) &RxBuffer[CH_BUFFER_INPUT_DATA+4],
				length);
		} else {
			memcpy (FlashBuffer + CH_FLASH_TRANSFER_BLOCK_SIZE,
				(const void *) &RxBuffer[CH_BUFFER_INPUT_DATA+4],
				length);
			WriteBytesFlash(address - CH_FLASH_TRANSFER_BLOCK_SIZE,
					CH_FLASH_WRITE_BLOCK_SIZE,
					(unsigned char *) FlashBuffer);
		}
		break;
	case CH_CMD_BOOT_FLASH:
		/* are we lost or stolen */
		if (flash_success == 0xff) {
			rc = CH_ERROR_DEVICE_DEACTIVATED;
			break;
		}
		/* only boot when USB stack is not busy */
		idle_command = CH_CMD_BOOT_FLASH;
		break;
	case CH_CMD_SET_FLASH_SUCCESS:
		if (RxBuffer[CH_BUFFER_INPUT_DATA] != 0x00) {
			rc = CH_ERROR_INVALID_VALUE;
			break;
		}
		flash_success = RxBuffer[CH_BUFFER_INPUT_DATA];
		EraseFlash(CH_EEPROM_ADDR_FLASH_SUCCESS,
			   CH_EEPROM_ADDR_FLASH_SUCCESS + 1);
		WriteBytesFlash(CH_EEPROM_ADDR_FLASH_SUCCESS, 1,
				(unsigned char *) &RxBuffer[CH_BUFFER_INPUT_DATA]);
		break;
	case CH_CMD_SELF_TEST:
		rc = CHugSelfTest();
		break;
	default:
		rc = CH_ERROR_UNKNOWN_CMD_FOR_BOOTLOADER;
		break;
	}

	/* always send return code */
	if(!HIDTxHandleBusy(USBInHandle)) {
		TxBuffer[CH_BUFFER_OUTPUT_RETVAL] = rc;
		TxBuffer[CH_BUFFER_OUTPUT_CMD] = cmd;
		USBInHandle = HIDTxPacket(HID_EP,
					  (BYTE*)&TxBuffer[0],
					  CH_USB_HID_EP_SIZE);
	}

	/* re-arm the OUT endpoint for the next packet */
	USBOutHandle = HIDRxPacket(HID_EP,
				   (BYTE*)&RxBuffer,
				   CH_USB_HID_EP_SIZE);
}
Exemplo n.º 2
0
void SafeWriteBytesFlash(unsigned long startaddr, unsigned int num_bytes, unsigned char *flash_array) {
    if (startaddr >= PROG_START)
        WriteBytesFlash(startaddr, num_bytes, flash_array);
}