FTDI SPI Programming Errors

Thread Starter

Druzyek

Joined May 19, 2013
21
I have an Atmel AT89LP6440 but no parallel programmer so I made a PC program that uses an FTDI cable in SPI mode to program it instead. This works well and I am able to both program the chip and read back the firmware. The chip uses a synchronous SPI format. Here is the code I have that works using the D2XX library in asynchronous SPI mode:

Rich (BB code):
bool progInitialize(FT_HANDLE *handle)
{
    unsigned char outbuff;
    DWORD bytes;
    if (FT_Open(0, handle)!=FT_OK) return false;
    if (FT_SetBitMode(*handle, PIN_CLOCK|PIN_TX|PIN_SS, 1)!=FT_OK) return false;
    if (FT_SetBaudRate(*handle,38400)!=FT_OK) return false;
    outbuff=PIN_SS;//start with SS high
    if (FT_Write(*handle,&outbuff,1,&bytes)!=FT_OK) return false;
    Sleep(1);
    return true;
}

unsigned char progSend(FT_HANDLE handle, unsigned char data)
{
    int i;
    unsigned char retbuff=0, inbuff, outbuff;
    DWORD bytes;
    for (i=0;i<8;i++)
    {
        if (data&0x80) outbuff=PIN_TX;
        else outbuff=0;
        data<<=1;
        FT_Write(handle,&outbuff,1,&bytes);//write TX
        outbuff|=PIN_CLOCK;
        FT_Write(handle,&outbuff,1,&bytes);//clock up
        outbuff&=PIN_CLOCK;
        FT_Write(handle,&outbuff,1,&bytes);//clock down
        FT_GetBitMode(handle,&inbuff);//read RX
        retbuff<<=1;
        if (inbuff&PIN_RX) retbuff++;
    }
    return retbuff;
}
progSend reads and writes a byte at the same time. To write, you can ignore what is read and to read you can write any value you want and only pay attention to the read value. This is a little slow and I think it is because of all of the calls to FT_Write and reading the RX pin even when it's not necessary during writes. I decided to split it into to two different functions to make it faster. progSend loads an array of pin states to be written and calls FT_Write only once ignoring the value of the RX pin.

Rich (BB code):
bool progSend(FT_HANDLE handle, unsigned char data)
{
    int i;
    unsigned char outbuff[24];
    unsigned char inbuff;
    DWORD bytes;
    DWORD rx,tx,estat;
    FT_STATUS stat;

    for (i=0;i<8;i++)
    {
        if (data&0x80) outbuff[i*3]=PIN_TX;
        else outbuff[i*3]=0;
        data<<=1;
        outbuff[i*3+1]=outbuff[i*3]|PIN_CLOCK;
        outbuff[i*3+2]=outbuff[i*3];
    }
    FT_Write(handle,outbuff,sizeof(outbuff),&bytes);
    Sleep(1);
    return true;
}

unsigned char progRead(FT_HANDLE handle)
{
    int i;
    unsigned char retbuff=0, inbuff, outbuff[2]={PIN_CLOCK,0};
    DWORD bytes;

    for (i=0;i<8;i++)
    {
        retbuff<<=1;
        FT_GetBitMode(handle,&inbuff);
        if (inbuff&PIN_RX) retbuff++;
        FT_Write(handle,outbuff,sizeof(outbuff),&bytes);
        Sleep(1);
    }
    return retbuff;
}
I can write to the chip but when I try to read the firmware back and compare it to the file on the PC, it randomly gives me the wrong value (sometimes after a few hundred successful reads). I know the firmware on the chip is correct because the incorrect value is always at a different location. Without the call to Sleep(1) it doesn't work at all. Increasing the sleep value does not help either.

I tried rewriting the routines to use the synchronous mode of the FTDI chip but it also works fine for a while then randomly gives me incorrect values:

Rich (BB code):
bool progSend(FT_HANDLE handle, unsigned char data)
{
    int i;
    unsigned char outbuff[24];
    unsigned char inbuff;

    DWORD bytes;
    DWORD rx,tx,estat;
    FT_STATUS stat;

    for (i=0;i<8;i++)
    {
        if (data&0x80) outbuff[i*3]=PIN_TX;
        else outbuff[i*3]=0;
        data<<=1;
        outbuff[i*3+1]=outbuff[i*3]|PIN_CLOCK;
        outbuff[i*3+2]=outbuff[i*3];
    }
    FT_Write(handle,outbuff,sizeof(outbuff),&bytes);
    ByteCount+=sizeof(outbuff);
    return true;
}

unsigned char progReadNew(FT_HANDLE handle)
{
    int i;
    unsigned char retbuff=0, inbuff, outbuff[16]={PIN_CLOCK,0,PIN_CLOCK,0,PIN_CLOCK,0,PIN_CLOCK,0,PIN_CLOCK,0,PIN_CLOCK,0,PIN_CLOCK,0,PIN_CLOCK,0};

    DWORD bytes;
    DWORD rx;
    FT_STATUS status=0;
    
    //Flush all the bytes recorded from the calls to progSend
    while (ByteCount)
    {
        FT_Read(handle,&outbuff[0],1,&bytes);
        ByteCount--;
    }
    FT_Write(handle,outbuff,sizeof(outbuff),&bytes);
    FT_Read(handle,outbuff,sizeof(outbuff),&bytes);
    retbuff=0;
    for (i=0;i<sizeof(outbuff);i+=2)
    {
        retbuff<<=1;
        if (outbuff&PIN_RX) retbuff++;
    }
    return retbuff;
}


I checked the status of all the return values and none of them are giving errors. Any idea what I am doing wrong? I have been scratching my head for a while on this one.
 
Top