示例#1
0
/**************************************************************************//**
\brief Function to do an erase-write on one page in the flash.

\note The maximum pageAddress must not be exceeded. The maximum number of
      pages can be found in the datasheet.

\param[in] pageAddress Page address to the page to erase/write.
******************************************************************************/
static void flashEraseWritePage(uint16_t pageAddress)
{
  // Calculate actual start address of the page.
  uint32_t tableAddress = (uint32_t)pageAddress * (uint32_t)FLASH_PAGE_SIZE;

  // Perform page erase.
  SP_EraseApplicationPage(tableAddress);
  // Wait for SPM to finish.
  flashWaitForSPM();
  // Perform page write.
  SP_WriteApplicationPage(tableAddress);
  // Wait for SPM to finish.
  flashWaitForSPM();
  // enable rww section
  SP_RWWSectionEnable();
  // Wait for SPM to finish.
  flashWaitForSPM();
}
示例#2
0
void pollEndpoint(void){
	if (USB_ep_out_received(1)){		
		
		pageOffs += EP1_SIZE;

		if (pageOffs == APP_SECTION_PAGE_SIZE){
			// Write a page to flash
			SP_LoadFlashPage(pageBuf);
			NVM.CMD = NVM_CMD_NO_OPERATION_gc;
			SP_WriteApplicationPage(page*APP_SECTION_PAGE_SIZE);
			SP_WaitForSPM();
			NVM.CMD = NVM_CMD_NO_OPERATION_gc;
			
			page++;
			pageOffs = 0;
		}

		if (page * APP_SECTION_PAGE_SIZE < APP_SECTION_END){
			// If there's remaining room in flash, configure the endpoint to accept more data
			USB_ep_out_start(1, &pageBuf[pageOffs]);
		}
	}
}
示例#3
0
/**************************************************************************************************
* Handle received HID set feature reports
*/
void HID_set_feature_report_out(uint8_t *report)
{
	uint8_t		response[UDI_HID_REPORT_OUT_SIZE];
	response[0] = report[0] | 0x80;
	response[1] = report[1];
	response[2] = report[2];
	
	uint16_t	addr;
	addr = *(uint16_t *)(report+1);

	switch(report[0])
	{
		// no-op
		case CMD_NOP:
			break;
		
		// write to RAM page buffer
		case CMD_RESET_POINTER:
			page_ptr = 0;
			return;

		// read from RAM page buffer
		case CMD_READ_BUFFER:
			memcpy(response, &page_buffer[page_ptr], UDI_HID_REPORT_OUT_SIZE);
			page_ptr += UDI_HID_REPORT_OUT_SIZE;
			page_ptr &= APP_SECTION_PAGE_SIZE-1;
			break;

		// erase entire application section
		case CMD_ERASE_APP_SECTION:
			SP_WaitForSPM();
			SP_EraseApplicationSection();
			return;

		// calculate application and bootloader section CRCs
		case CMD_READ_FLASH_CRCS:
			SP_WaitForSPM();
			*(uint32_t *)&response[3] = SP_ApplicationCRC();
			*(uint32_t *)&response[7] = SP_BootCRC();
			break;

		// read MCU IDs
		case CMD_READ_MCU_IDS:
			response[3] = MCU.DEVID0;
			response[4] = MCU.DEVID1;
			response[5] = MCU.DEVID2;
			response[6] = MCU.REVID;
			break;
		
		// read fuses
		case CMD_READ_FUSES:
			response[3] = SP_ReadFuseByte(0);
			response[4] = SP_ReadFuseByte(1);
			response[5] = SP_ReadFuseByte(2);
			response[6] = 0xFF;
			response[7] = SP_ReadFuseByte(4);
			response[8] = SP_ReadFuseByte(5);
			break;
		
		// write RAM page buffer to application section page
		case CMD_WRITE_PAGE:
			if (addr > (APP_SECTION_SIZE / APP_SECTION_PAGE_SIZE))	// out of range
			{
				response[1] = 0xFF;
				response[2] = 0xFF;
				break;
			}
			SP_WaitForSPM();
			SP_LoadFlashPage(page_buffer);
			SP_WriteApplicationPage(APP_SECTION_START + ((uint32_t)addr * APP_SECTION_PAGE_SIZE));
			page_ptr = 0;
			break;

		// read application page to RAM buffer and return first 32 bytes
		case CMD_READ_PAGE:
			if (addr > (APP_SECTION_SIZE / APP_SECTION_PAGE_SIZE))	// out of range
			{
				response[1] = 0xFF;
				response[2] = 0xFF;
			}
			else
			{
				memcpy_P(page_buffer, (const void *)(APP_SECTION_START + (APP_SECTION_PAGE_SIZE * addr)), APP_SECTION_PAGE_SIZE);
				memcpy(&response[3], page_buffer, 32);
				page_ptr = 0;
			}
			break;
		
		// erase user signature row
		case CMD_ERASE_USER_SIG_ROW:
			SP_WaitForSPM();
			SP_EraseUserSignatureRow();
			break;
		
		// write RAM buffer to user signature row
		case CMD_WRITE_USER_SIG_ROW:
			SP_WaitForSPM();
			SP_LoadFlashPage(page_buffer);
			SP_WriteUserSignatureRow();
			break;

		// read user signature row to RAM buffer and return first 32 bytes
		case CMD_READ_USER_SIG_ROW:
			if (addr > (USER_SIGNATURES_PAGE_SIZE - 32))
			{
				response[1] = 0xFF;
				response[2] = 0xFF;
			}
			else
			{
				memcpy_P(page_buffer, (const void *)(USER_SIGNATURES_START + addr), USER_SIGNATURES_SIZE);
				memcpy(&response[3], page_buffer, 32);
				page_ptr = 0;
			}
			break;

		case CMD_READ_SERIAL:
			{
				uint8_t	i;
				uint8_t	j = 3;
				uint8_t b;
	
				for (i = 0; i < 6; i++)
				{
					b = SP_ReadCalibrationByte(offsetof(NVM_PROD_SIGNATURES_t, LOTNUM0) + i);
					response[j++] = hex_to_char(b >> 4);
					response[j++] = hex_to_char(b & 0x0F);
				}
				response[j++] = '-';
				b = SP_ReadCalibrationByte(offsetof(NVM_PROD_SIGNATURES_t, LOTNUM0) + 6);
				response[j++] = hex_to_char(b >> 4);
				response[j++] = hex_to_char(b & 0x0F);
				response[j++] = '-';

				for (i = 7; i < 11; i++)
				{
					b = SP_ReadCalibrationByte(offsetof(NVM_PROD_SIGNATURES_t, LOTNUM0) + i);
					response[j++] = hex_to_char(b >> 4);
					response[j++] = hex_to_char(b & 0x0F);
				}

				response[j] = '\0';
				break;
			}
		
		case CMD_READ_BOOTLOADER_VERSION:
			response[3] = BOOTLOADER_VERSION;
			break;
		
		case CMD_RESET_MCU:
			reset_do_soft_reset();
			response[1] = 0xFF;	// failed
			break;
		
		case CMD_READ_EEPROM:
			if (addr > (EEPROM_SIZE - 32))
			{
				response[1] = 0xFF;
				response[2] = 0xFF;
			}
			else
			{
				EEP_EnableMapping();
				memcpy_P(page_buffer, (const void *)(MAPPED_EEPROM_START + addr), APP_SECTION_PAGE_SIZE);
				EEP_DisableMapping();
				memcpy(&response[3], page_buffer, 32);
				page_ptr = 0;
			}
			break;

		case CMD_WRITE_EEPROM:
			if (addr > (EEPROM_SIZE / EEPROM_PAGE_SIZE))
			{
				response[1] = 0xFF;
				response[2] = 0xFF;
			}
			else
			{
				EEP_LoadPageBuffer(&report[3], EEPROM_PAGE_SIZE);
				EEP_AtomicWritePage(addr);
			}
			break;
		
		// unknown command
		default:
			response[0] = 0xFF;
			break;
	}

	udi_hid_generic_send_report_in(response);
}