FTDI SPI Programming Errors

Discussion in 'Programmer's Corner' started by Druzyek, Feb 4, 2014.

  1. Druzyek

    Thread Starter New Member

    May 19, 2013
    21
    0
    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:

    Code ( (Unknown Language)):
    1.  
    2. bool progInitialize(FT_HANDLE *handle)
    3. {
    4.     unsigned char outbuff;
    5.     DWORD bytes;
    6.     if (FT_Open(0, handle)!=FT_OK) return false;
    7.     if (FT_SetBitMode(*handle, PIN_CLOCK|PIN_TX|PIN_SS, 1)!=FT_OK) return false;
    8.     if (FT_SetBaudRate(*handle,38400)!=FT_OK) return false;
    9.     outbuff=PIN_SS;//start with SS high
    10.     if (FT_Write(*handle,&outbuff,1,&bytes)!=FT_OK) return false;
    11.     Sleep(1);
    12.     return true;
    13. }
    14.  
    15. unsigned char progSend(FT_HANDLE handle, unsigned char data)
    16. {
    17.     int i;
    18.     unsigned char retbuff=0, inbuff, outbuff;
    19.     DWORD bytes;
    20.     for (i=0;i<8;i++)
    21.     {
    22.         if (data&0x80) outbuff=PIN_TX;
    23.         else outbuff=0;
    24.         data<<=1;
    25.         FT_Write(handle,&outbuff,1,&bytes);//write TX
    26.         outbuff|=PIN_CLOCK;
    27.         FT_Write(handle,&outbuff,1,&bytes);//clock up
    28.         outbuff&=PIN_CLOCK;
    29.         FT_Write(handle,&outbuff,1,&bytes);//clock down
    30.         FT_GetBitMode(handle,&inbuff);//read RX
    31.         retbuff<<=1;
    32.         if (inbuff&PIN_RX) retbuff++;
    33.     }
    34.     return retbuff;
    35. }
    36.  
    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.

    Code ( (Unknown Language)):
    1.  
    2. bool progSend(FT_HANDLE handle, unsigned char data)
    3. {
    4.     int i;
    5.     unsigned char outbuff[24];
    6.     unsigned char inbuff;
    7.     DWORD bytes;
    8.     DWORD rx,tx,estat;
    9.     FT_STATUS stat;
    10.  
    11.     for (i=0;i<8;i++)
    12.     {
    13.         if (data&0x80) outbuff[i*3]=PIN_TX;
    14.         else outbuff[i*3]=0;
    15.         data<<=1;
    16.         outbuff[i*3+1]=outbuff[i*3]|PIN_CLOCK;
    17.         outbuff[i*3+2]=outbuff[i*3];
    18.     }
    19.     FT_Write(handle,outbuff,sizeof(outbuff),&bytes);
    20.     Sleep(1);
    21.     return true;
    22. }
    23.  
    24. unsigned char progRead(FT_HANDLE handle)
    25. {
    26.     int i;
    27.     unsigned char retbuff=0, inbuff, outbuff[2]={PIN_CLOCK,0};
    28.     DWORD bytes;
    29.  
    30.     for (i=0;i<8;i++)
    31.     {
    32.         retbuff<<=1;
    33.         FT_GetBitMode(handle,&inbuff);
    34.         if (inbuff&PIN_RX) retbuff++;
    35.         FT_Write(handle,outbuff,sizeof(outbuff),&bytes);
    36.         Sleep(1);
    37.     }
    38.     return retbuff;
    39. }
    40.  
    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:

    Code ( (Unknown Language)):
    1.  
    2. bool progSend(FT_HANDLE handle, unsigned char data)
    3. {
    4.     int i;
    5.     unsigned char outbuff[24];
    6.     unsigned char inbuff;
    7.  
    8.     DWORD bytes;
    9.     DWORD rx,tx,estat;
    10.     FT_STATUS stat;
    11.  
    12.     for (i=0;i<8;i++)
    13.     {
    14.         if (data&0x80) outbuff[i*3]=PIN_TX;
    15.         else outbuff[i*3]=0;
    16.         data<<=1;
    17.         outbuff[i*3+1]=outbuff[i*3]|PIN_CLOCK;
    18.         outbuff[i*3+2]=outbuff[i*3];
    19.     }
    20.     FT_Write(handle,outbuff,sizeof(outbuff),&bytes);
    21.     ByteCount+=sizeof(outbuff);
    22.     return true;
    23. }
    24.  
    25. unsigned char progReadNew(FT_HANDLE handle)
    26. {
    27.     int i;
    28.     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};
    29.  
    30.     DWORD bytes;
    31.     DWORD rx;
    32.     FT_STATUS status=0;
    33.    
    34.     //Flush all the bytes recorded from the calls to progSend
    35.     while (ByteCount)
    36.     {
    37.         FT_Read(handle,&outbuff[0],1,&bytes);
    38.         ByteCount--;
    39.     }
    40.     FT_Write(handle,outbuff,sizeof(outbuff),&bytes);
    41.     FT_Read(handle,outbuff,sizeof(outbuff),&bytes);
    42.     retbuff=0;
    43.     for (i=0;i<sizeof(outbuff);i+=2)
    44.     {
    45.         retbuff<<=1;
    46.         if (outbuff[i]&PIN_RX) retbuff++;
    47.     }
    48.     return retbuff;
    49. }
    50. [/i]


    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.
     
Loading...