mirror of
https://github.com/fhgwright/SCSI2SD.git
synced 2025-02-07 21:30:56 +00:00
- A USB Bootloader is now used. Use either the bootloader host supplied with PSoC Creator 3.0, or else the standalone app included with Cypress AN73503. You have 2 seconds between connecting the USB cable and hitting the "program" button. - The bootloaderhost program included in this repository doesn't quite work yet. When functional it should simplify firmware updates on Linux and Mac OSX - Fixed an error in the parts spreadsheet which had a 22k resistor for USB termination instead of a 22 Ohm resistor. - Updated parts spreadsheet with part number of PSoC actually used (CY8C5267AXI-LP051).
304 lines
10 KiB
C
304 lines
10 KiB
C
/*******************************************************************************
|
|
* Copyright 2011-2012, Cypress Semiconductor Corporation. All rights reserved.
|
|
* You may use this file only in accordance with the license, terms, conditions,
|
|
* disclaimers, and limitations in the end user license agreement accompanying
|
|
* the software package with which this file was provided.
|
|
********************************************************************************/
|
|
|
|
#include "cybtldr_command.h"
|
|
#include "cybtldr_api.h"
|
|
|
|
/* The highest number of flash array for any device */
|
|
#define MAX_FLASH_ARRAYS 4
|
|
/* The default value if a flash array has not yet received data */
|
|
#define NO_FLASH_ARRAY_DATA 0
|
|
|
|
unsigned long g_validRows[MAX_FLASH_ARRAYS];
|
|
static CyBtldr_CommunicationsData* g_comm;
|
|
|
|
int CyBtldr_TransferData(unsigned char* inBuf, int inSize, unsigned char* outBuf, int outSize)
|
|
{
|
|
int err = g_comm->WriteData(inBuf, inSize);
|
|
|
|
if (CYRET_SUCCESS == err)
|
|
err = g_comm->ReadData(outBuf, outSize);
|
|
|
|
if (CYRET_SUCCESS != err)
|
|
err |= CYRET_ERR_COMM_MASK;
|
|
|
|
return err;
|
|
}
|
|
|
|
int CyBtldr_ValidateRow(unsigned char arrayId, unsigned short rowNum)
|
|
{
|
|
unsigned long inSize;
|
|
unsigned long outSize;
|
|
unsigned short minRow = 0;
|
|
unsigned short maxRow = 0;
|
|
unsigned char inBuf[MAX_COMMAND_SIZE];
|
|
unsigned char outBuf[MAX_COMMAND_SIZE];
|
|
unsigned char status = CYRET_SUCCESS;
|
|
int err = CYRET_SUCCESS;
|
|
|
|
if (arrayId < MAX_FLASH_ARRAYS)
|
|
{
|
|
if (NO_FLASH_ARRAY_DATA == g_validRows[arrayId])
|
|
{
|
|
err = CyBtldr_CreateGetFlashSizeCmd(arrayId, inBuf, &inSize, &outSize);
|
|
if (CYRET_SUCCESS == err)
|
|
err = CyBtldr_TransferData(inBuf, inSize, outBuf, outSize);
|
|
if (CYRET_SUCCESS == err)
|
|
err = CyBtldr_ParseGetFlashSizeCmdResult(outBuf, outSize, &minRow, &maxRow, &status);
|
|
if (CYRET_SUCCESS != status)
|
|
err = status | CYRET_ERR_BTLDR_MASK;
|
|
|
|
if (CYRET_SUCCESS == err)
|
|
{
|
|
if (CYRET_SUCCESS == status)
|
|
g_validRows[arrayId] = (minRow << 16) + maxRow;
|
|
else
|
|
err = status | CYRET_ERR_BTLDR_MASK;
|
|
}
|
|
}
|
|
if (CYRET_SUCCESS == err)
|
|
{
|
|
minRow = (unsigned short)(g_validRows[arrayId] >> 16);
|
|
maxRow = (unsigned short)g_validRows[arrayId];
|
|
if (rowNum < minRow || rowNum > maxRow)
|
|
err = CYRET_ERR_ROW;
|
|
}
|
|
}
|
|
else
|
|
err = CYRET_ERR_ARRAY;
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
int CyBtldr_StartBootloadOperation(CyBtldr_CommunicationsData* comm, unsigned long expSiId, unsigned char expSiRev, unsigned long* blVer)
|
|
{
|
|
const unsigned long SUPPORTED_BOOTLOADER = 0x010000;
|
|
const unsigned long BOOTLOADER_VERSION_MASK = 0xFF0000;
|
|
unsigned long i;
|
|
unsigned long inSize = 0;
|
|
unsigned long outSize = 0;
|
|
unsigned long siliconId = 0;
|
|
unsigned char inBuf[MAX_COMMAND_SIZE];
|
|
unsigned char outBuf[MAX_COMMAND_SIZE];
|
|
unsigned char siliconRev = 0;
|
|
unsigned char status = CYRET_SUCCESS;
|
|
int err;
|
|
|
|
g_comm = comm;
|
|
for (i = 0; i < MAX_FLASH_ARRAYS; i++)
|
|
g_validRows[i] = NO_FLASH_ARRAY_DATA;
|
|
|
|
err = g_comm->OpenConnection();
|
|
if (CYRET_SUCCESS != err)
|
|
err |= CYRET_ERR_COMM_MASK;
|
|
|
|
if (CYRET_SUCCESS == err)
|
|
err = CyBtldr_CreateEnterBootLoaderCmd(inBuf, &inSize, &outSize);
|
|
if (CYRET_SUCCESS == err)
|
|
err = CyBtldr_TransferData(inBuf, inSize, outBuf, outSize);
|
|
if (CYRET_SUCCESS == err)
|
|
err = CyBtldr_ParseEnterBootLoaderCmdResult(outBuf, outSize, &siliconId, &siliconRev, blVer, &status);
|
|
|
|
|
|
if (CYRET_SUCCESS == err)
|
|
{
|
|
if (CYRET_SUCCESS != status)
|
|
err = status | CYRET_ERR_BTLDR_MASK;
|
|
if (expSiId != siliconId || expSiRev != siliconRev)
|
|
err = CYRET_ERR_DEVICE;
|
|
else if ((*blVer & BOOTLOADER_VERSION_MASK) != SUPPORTED_BOOTLOADER)
|
|
err = CYRET_ERR_VERSION;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
int CyBtldr_GetApplicationStatus(unsigned char appID, unsigned char* isValid, unsigned char* isActive)
|
|
{
|
|
unsigned long inSize = 0;
|
|
unsigned long outSize = 0;
|
|
unsigned char inBuf[MAX_COMMAND_SIZE];
|
|
unsigned char outBuf[MAX_COMMAND_SIZE];
|
|
unsigned char status = CYRET_SUCCESS;
|
|
int err;
|
|
|
|
err = CyBtldr_CreateGetAppStatusCmd(appID, inBuf, &inSize, &outSize);
|
|
if (CYRET_SUCCESS == err)
|
|
err = CyBtldr_TransferData(inBuf, inSize, outBuf, outSize);
|
|
if (CYRET_SUCCESS == err)
|
|
err = CyBtldr_ParseGetAppStatusCmdResult(outBuf, outSize, isValid, isActive, &status);
|
|
|
|
if (CYRET_SUCCESS == err)
|
|
{
|
|
if (CYRET_SUCCESS != status)
|
|
err = status | CYRET_ERR_BTLDR_MASK;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
int CyBtldr_SetApplicationStatus(unsigned char appID)
|
|
{
|
|
unsigned long inSize = 0;
|
|
unsigned long outSize = 0;
|
|
unsigned char inBuf[MAX_COMMAND_SIZE];
|
|
unsigned char outBuf[MAX_COMMAND_SIZE];
|
|
unsigned char status = CYRET_SUCCESS;
|
|
int err;
|
|
|
|
err = CyBtldr_CreateSetActiveAppCmd(appID, inBuf, &inSize, &outSize);
|
|
if (CYRET_SUCCESS == err)
|
|
err = CyBtldr_TransferData(inBuf, inSize, outBuf, outSize);
|
|
if (CYRET_SUCCESS == err)
|
|
err = CyBtldr_ParseSetActiveAppCmdResult(outBuf, outSize, &status);
|
|
|
|
if (CYRET_SUCCESS == err)
|
|
{
|
|
if (CYRET_SUCCESS != status)
|
|
err = status | CYRET_ERR_BTLDR_MASK;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
int CyBtldr_EndBootloadOperation(void)
|
|
{
|
|
const unsigned char RESET = 0x00;
|
|
unsigned long inSize;
|
|
unsigned long outSize;
|
|
unsigned char inBuf[MAX_COMMAND_SIZE];
|
|
|
|
int err = CyBtldr_CreateExitBootLoaderCmd(RESET, inBuf, &inSize, &outSize);
|
|
if (CYRET_SUCCESS == err)
|
|
{
|
|
err = g_comm->WriteData(inBuf, inSize);
|
|
|
|
if (CYRET_SUCCESS == err)
|
|
err = g_comm->CloseConnection();
|
|
|
|
if (CYRET_SUCCESS != err)
|
|
err |= CYRET_ERR_COMM_MASK;
|
|
}
|
|
g_comm = NULL;
|
|
|
|
return err;
|
|
}
|
|
|
|
int CyBtldr_ProgramRow(unsigned char arrayID, unsigned short rowNum, unsigned char* buf, unsigned short size)
|
|
{
|
|
const int TRANSFER_HEADER_SIZE = 11;
|
|
|
|
unsigned char inBuf[MAX_COMMAND_SIZE];
|
|
unsigned char outBuf[MAX_COMMAND_SIZE];
|
|
unsigned long inSize;
|
|
unsigned long outSize;
|
|
unsigned long offset = 0;
|
|
unsigned short subBufSize;
|
|
unsigned char status = CYRET_SUCCESS;
|
|
|
|
int err = CyBtldr_ValidateRow(arrayID, rowNum);
|
|
|
|
//Break row into pieces to ensure we don't send too much for the transfer protocol
|
|
while ((CYRET_SUCCESS == err) && ((size - offset + TRANSFER_HEADER_SIZE) > g_comm->MaxTransferSize))
|
|
{
|
|
subBufSize = (unsigned short)(g_comm->MaxTransferSize - TRANSFER_HEADER_SIZE);
|
|
|
|
err = CyBtldr_CreateSendDataCmd(&buf[offset], subBufSize, inBuf, &inSize, &outSize);
|
|
if (CYRET_SUCCESS == err)
|
|
err = CyBtldr_TransferData(inBuf, inSize, outBuf, outSize);
|
|
if (CYRET_SUCCESS == err)
|
|
err = CyBtldr_ParseSendDataCmdResult(outBuf, outSize, &status);
|
|
if (CYRET_SUCCESS != status)
|
|
err = status | CYRET_ERR_BTLDR_MASK;
|
|
|
|
offset += subBufSize;
|
|
}
|
|
|
|
if (CYRET_SUCCESS == err)
|
|
{
|
|
subBufSize = (unsigned short)(size - offset);
|
|
|
|
err = CyBtldr_CreateProgramRowCmd(arrayID, rowNum, &buf[offset], subBufSize, inBuf, &inSize, &outSize);
|
|
if (CYRET_SUCCESS == err)
|
|
err = CyBtldr_TransferData(inBuf, inSize, outBuf, outSize);
|
|
if (CYRET_SUCCESS == err)
|
|
err = CyBtldr_ParseProgramRowCmdResult(outBuf, outSize, &status);
|
|
if (CYRET_SUCCESS != status)
|
|
err = status | CYRET_ERR_BTLDR_MASK;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
int CyBtldr_EraseRow(unsigned char arrayID, unsigned short rowNum)
|
|
{
|
|
unsigned char inBuf[MAX_COMMAND_SIZE];
|
|
unsigned char outBuf[MAX_COMMAND_SIZE];
|
|
unsigned long inSize = 0;
|
|
unsigned long outSize = 0;
|
|
unsigned char status = CYRET_SUCCESS;
|
|
|
|
int err = CyBtldr_ValidateRow(arrayID, rowNum);
|
|
if (CYRET_SUCCESS == err)
|
|
err = CyBtldr_CreateEraseRowCmd(arrayID, rowNum, inBuf, &inSize, &outSize);
|
|
if (CYRET_SUCCESS == err)
|
|
err = CyBtldr_TransferData(inBuf, inSize, outBuf, outSize);
|
|
if (CYRET_SUCCESS == err)
|
|
err = CyBtldr_ParseEraseRowCmdResult(outBuf, outSize, &status);
|
|
if (CYRET_SUCCESS != status)
|
|
err = status | CYRET_ERR_BTLDR_MASK;
|
|
|
|
return err;
|
|
}
|
|
|
|
int CyBtldr_VerifyRow(unsigned char arrayID, unsigned short rowNum, unsigned char checksum)
|
|
{
|
|
unsigned char inBuf[MAX_COMMAND_SIZE];
|
|
unsigned char outBuf[MAX_COMMAND_SIZE];
|
|
unsigned long inSize = 0;
|
|
unsigned long outSize = 0;
|
|
unsigned char rowChecksum = 0;
|
|
unsigned char status = CYRET_SUCCESS;
|
|
|
|
int err = CyBtldr_ValidateRow(arrayID, rowNum);
|
|
if (CYRET_SUCCESS == err)
|
|
err = CyBtldr_CreateVerifyRowCmd(arrayID, rowNum, inBuf, &inSize, &outSize);
|
|
if (CYRET_SUCCESS == err)
|
|
err = CyBtldr_TransferData(inBuf, inSize, outBuf, outSize);
|
|
if (CYRET_SUCCESS == err)
|
|
err = CyBtldr_ParseVerifyRowCmdResult(outBuf, outSize, &rowChecksum, &status);
|
|
if (CYRET_SUCCESS != status)
|
|
err = status | CYRET_ERR_BTLDR_MASK;
|
|
if ((CYRET_SUCCESS == err) && (rowChecksum != checksum))
|
|
err = CYRET_ERR_CHECKSUM;
|
|
|
|
return err;
|
|
}
|
|
|
|
int CyBtldr_VerifyApplication()
|
|
{
|
|
unsigned char inBuf[MAX_COMMAND_SIZE];
|
|
unsigned char outBuf[MAX_COMMAND_SIZE];
|
|
unsigned long inSize = 0;
|
|
unsigned long outSize = 0;
|
|
unsigned char checksumValid = 0;
|
|
unsigned char status = CYRET_SUCCESS;
|
|
|
|
int err = CyBtldr_CreateVerifyChecksumCmd(inBuf, &inSize, &outSize);
|
|
if (CYRET_SUCCESS == err)
|
|
err = CyBtldr_TransferData(inBuf, inSize, outBuf, outSize);
|
|
if (CYRET_SUCCESS == err)
|
|
err = CyBtldr_ParseVerifyChecksumCmdResult(outBuf, outSize, &checksumValid, &status);
|
|
if (CYRET_SUCCESS != status)
|
|
err = status | CYRET_ERR_BTLDR_MASK;
|
|
if ((CYRET_SUCCESS == err) && (!checksumValid))
|
|
err = CYRET_ERR_CHECKSUM;
|
|
|
|
return err;
|
|
}
|