/** 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(); }