/** * 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); }
void SafeWriteBytesFlash(unsigned long startaddr, unsigned int num_bytes, unsigned char *flash_array) { if (startaddr >= PROG_START) WriteBytesFlash(startaddr, num_bytes, flash_array); }