示例#1
0
/** Handler for the XPROG WRITE_MEMORY command to write to a specific memory space within the attached device. */
static void XPROGProtocol_WriteMemory(void)
{
	uint8_t ReturnStatus = XPROG_ERR_OK;

	struct
	{
		uint8_t  MemoryType;
		uint8_t  PageMode;
		uint32_t Address;
		uint16_t Length;
		uint8_t  ProgData[256];
	} WriteMemory_XPROG_Params;

	Endpoint_Read_Stream_LE(&WriteMemory_XPROG_Params, (sizeof(WriteMemory_XPROG_Params) -
	                                                    sizeof(WriteMemory_XPROG_Params).ProgData), NULL);
	WriteMemory_XPROG_Params.Address = SwapEndian_32(WriteMemory_XPROG_Params.Address);
	WriteMemory_XPROG_Params.Length  = SwapEndian_16(WriteMemory_XPROG_Params.Length);
	Endpoint_Read_Stream_LE(&WriteMemory_XPROG_Params.ProgData, WriteMemory_XPROG_Params.Length, NULL);

	// The driver will terminate transfers that are a round multiple of the endpoint bank in size with a ZLP, need
	// to catch this and discard it before continuing on with packet processing to prevent communication issues
	if (((sizeof(uint8_t) + sizeof(WriteMemory_XPROG_Params) - sizeof(WriteMemory_XPROG_Params.ProgData)) +
	    WriteMemory_XPROG_Params.Length) % AVRISP_DATA_EPSIZE == 0)
	{
		Endpoint_ClearOUT();
		Endpoint_WaitUntilReady();
	}

	Endpoint_ClearOUT();
	Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPADDR);
	Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);

	if (XPROG_SelectedProtocol == XPROG_PROTOCOL_PDI)
	{
		/* Assume FLASH page programming by default, as it is the common case */
		uint8_t WriteCommand     = XMEGA_NVM_CMD_WRITEFLASHPAGE;
		uint8_t WriteBuffCommand = XMEGA_NVM_CMD_LOADFLASHPAGEBUFF;
		uint8_t EraseBuffCommand = XMEGA_NVM_CMD_ERASEFLASHPAGEBUFF;
		bool    PagedMemory      = true;

		switch (WriteMemory_XPROG_Params.MemoryType)
		{
			case XPROG_MEM_TYPE_APPL:
				WriteCommand     = XMEGA_NVM_CMD_WRITEAPPSECPAGE;
				break;
			case XPROG_MEM_TYPE_BOOT:
				WriteCommand     = XMEGA_NVM_CMD_WRITEBOOTSECPAGE;
				break;
			case XPROG_MEM_TYPE_EEPROM:
				WriteCommand     = XMEGA_NVM_CMD_ERASEWRITEEEPROMPAGE;
				WriteBuffCommand = XMEGA_NVM_CMD_LOADEEPROMPAGEBUFF;
				EraseBuffCommand = XMEGA_NVM_CMD_ERASEEEPROMPAGEBUFF;
				break;
			case XPROG_MEM_TYPE_USERSIG:
				WriteCommand     = XMEGA_NVM_CMD_WRITEUSERSIG;
				break;
			case XPROG_MEM_TYPE_FUSE:
				WriteCommand     = XMEGA_NVM_CMD_WRITEFUSE;
				PagedMemory      = false;
				break;
			case XPROG_MEM_TYPE_LOCKBITS:
				WriteCommand     = XMEGA_NVM_CMD_WRITELOCK;
				PagedMemory      = false;
				break;
		}

		/* Send the appropriate memory write commands to the device, indicate timeout if occurred */
		if ((PagedMemory && !(XMEGANVM_WritePageMemory(WriteBuffCommand, EraseBuffCommand, WriteCommand,
													   WriteMemory_XPROG_Params.PageMode, WriteMemory_XPROG_Params.Address,
													   WriteMemory_XPROG_Params.ProgData, WriteMemory_XPROG_Params.Length))) ||
		   (!PagedMemory && !(XMEGANVM_WriteByteMemory(WriteCommand, WriteMemory_XPROG_Params.Address,
													   WriteMemory_XPROG_Params.ProgData[0]))))
		{
			ReturnStatus = XPROG_ERR_TIMEOUT;
		}
	}
	else
	{
		/* Send write command to the TPI device, indicate timeout if occurred */
		if (!(TINYNVM_WriteMemory(WriteMemory_XPROG_Params.Address, WriteMemory_XPROG_Params.ProgData,
		      WriteMemory_XPROG_Params.Length)))
		{
			ReturnStatus = XPROG_ERR_TIMEOUT;
		}
	}

	Endpoint_Write_8(CMD_XPROG);
	Endpoint_Write_8(XPROG_CMD_WRITE_MEM);
	Endpoint_Write_8(ReturnStatus);
	Endpoint_ClearIN();
}
/** Handler for the XPROG WRITE_MEMORY command to write to a specific memory space within the attached device. */
static void XPROGProtocol_WriteMemory(void)
{
    uint8_t ReturnStatus = XPRG_ERR_OK;

    struct
    {
        uint8_t  MemoryType;
        uint8_t  PageMode;
        uint32_t Address;
        uint16_t Length;
        uint8_t  ProgData[256];
    } WriteMemory_XPROG_Params;

    Endpoint_Read_Stream_LE(&WriteMemory_XPROG_Params, (sizeof(WriteMemory_XPROG_Params) -
                            sizeof(WriteMemory_XPROG_Params).ProgData), NO_STREAM_CALLBACK);
    WriteMemory_XPROG_Params.Address = SwapEndian_32(WriteMemory_XPROG_Params.Address);
    WriteMemory_XPROG_Params.Length  = SwapEndian_16(WriteMemory_XPROG_Params.Length);
    Endpoint_Read_Stream_LE(&WriteMemory_XPROG_Params.ProgData, WriteMemory_XPROG_Params.Length, NO_STREAM_CALLBACK);

    Endpoint_ClearOUT();
    Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPNUM);
    Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);

    if (XPROG_SelectedProtocol == XPRG_PROTOCOL_PDI)
    {
        /* Assume FLASH page programming by default, as it is the common case */
        uint8_t WriteCommand     = XMEGA_NVM_CMD_WRITEFLASHPAGE;
        uint8_t WriteBuffCommand = XMEGA_NVM_CMD_LOADFLASHPAGEBUFF;
        uint8_t EraseBuffCommand = XMEGA_NVM_CMD_ERASEFLASHPAGEBUFF;
        bool    PagedMemory      = true;

        switch (WriteMemory_XPROG_Params.MemoryType)
        {
        case XPRG_MEM_TYPE_APPL:
            WriteCommand     = XMEGA_NVM_CMD_WRITEAPPSECPAGE;
            break;
        case XPRG_MEM_TYPE_BOOT:
            WriteCommand     = XMEGA_NVM_CMD_WRITEBOOTSECPAGE;
            break;
        case XPRG_MEM_TYPE_EEPROM:
            WriteCommand     = XMEGA_NVM_CMD_ERASEWRITEEEPROMPAGE;
            WriteBuffCommand = XMEGA_NVM_CMD_LOADEEPROMPAGEBUFF;
            EraseBuffCommand = XMEGA_NVM_CMD_ERASEEEPROMPAGEBUFF;
            break;
        case XPRG_MEM_TYPE_USERSIG:
            /* User signature is paged, but needs us to manually indicate the mode bits since the host doesn't set them */
            WriteMemory_XPROG_Params.PageMode = (XPRG_PAGEMODE_ERASE | XPRG_PAGEMODE_WRITE);
            WriteCommand     = XMEGA_NVM_CMD_WRITEUSERSIG;
            break;
        case XPRG_MEM_TYPE_FUSE:
            WriteCommand     = XMEGA_NVM_CMD_WRITEFUSE;
            PagedMemory      = false;
            break;
        case XPRG_MEM_TYPE_LOCKBITS:
            WriteCommand     = XMEGA_NVM_CMD_WRITELOCK;
            PagedMemory      = false;
            break;
        }

        /* Send the appropriate memory write commands to the device, indicate timeout if occurred */
        if ((PagedMemory && !(XMEGANVM_WritePageMemory(WriteBuffCommand, EraseBuffCommand, WriteCommand,
                              WriteMemory_XPROG_Params.PageMode, WriteMemory_XPROG_Params.Address,
                              WriteMemory_XPROG_Params.ProgData, WriteMemory_XPROG_Params.Length))) ||
                (!PagedMemory && !(XMEGANVM_WriteByteMemory(WriteCommand, WriteMemory_XPROG_Params.Address,
                                   WriteMemory_XPROG_Params.ProgData[0]))))
        {
            ReturnStatus = XPRG_ERR_TIMEOUT;
        }
    }
    else
    {
        /* Send write command to the TPI device, indicate timeout if occurred */
        if (!(TINYNVM_WriteMemory(WriteMemory_XPROG_Params.Address, WriteMemory_XPROG_Params.ProgData,
                                  WriteMemory_XPROG_Params.Length)))
        {
            ReturnStatus = XPRG_ERR_TIMEOUT;
        }
    }

    Endpoint_Write_Byte(CMD_XPROG);
    Endpoint_Write_Byte(XPRG_CMD_WRITE_MEM);
    Endpoint_Write_Byte(ReturnStatus);
    Endpoint_ClearIN();
}