I2C boot loader with Blinky code Should test it with Freescale boards fingers crossed should work

Dependencies:   mbed

Fork of I2Cboot_betav1_01 by Siva ram

main.cpp

Committer:
Piasiv1206
Date:
2015-05-23
Revision:
1:c39e5581f901
Parent:
0:f76c26307f9a
Child:
5:0801179037cd

File content as of revision 1:c39e5581f901:

#include "mbed.h"
#include <stdbool.h>
#include <stdint.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <memory.h>


// BootLoader

Serial pc(USBTX, USBRX); // tx, rx

I2C i2c(p28, p27);

const int addr = 0x90;

#define COMMAND_PING            0x20
#define COMMAND_DOWNLOAD        0x21
#define COMMAND_RUN             0x22
#define COMMAND_GET_STATUS      0x23
#define COMMAND_SEND_DATA       0x24
#define COMMAND_RESET           0x25
#define COMMAND_RET_SUCCESS     0x40
#define COMMAND_RET_UNKNOWN_CMD 0x41
#define COMMAND_RET_INVALID_CMD 0x42
#define COMMAND_RET_INVALID_ADR 0x43
#define COMMAND_RET_FLASH_FAIL  0x44
#define COMMAND_RET_CRC_FAIL    0x45
#define COMMAND_ACK             0xcc
#define COMMAND_NAK             0x33

//*****************************************************************************
//
//! This variable will be set to the starting address of the binary will be
//! programmed into to device.
//
//*****************************************************************************
static uint32_t g_ui32DownloadAddress;

//*****************************************************************************
//
//! This variable will be set to the start execution address for the binary
//! that is downloaded.
//
//*****************************************************************************
static uint32_t g_ui32StartAddress;

//*****************************************************************************


uint32_t g_ui32DataSize;
uint8_t g_pui8Buffer[256];


//

int 
I2CSendData(uint8_t const *pui8Data, uint8_t ui8Size)
{
   
   if(i2c.write(addr, pui8Data, ui8Size) == 1)
   {
       return (0);
   }
   
   else
   
   {
       return (-1);   
   }    
 
    
}

int
I2CReceiveData(uint8_t *pui8Data, uint8_t ui8Size)
{
    if(i2c.read(addr, pui8Data, ui8Size == 0)
    {
        return (0);
    }
    
    return (-1);
        
}        
 

//****************************************************************************
//
//! AckPacket() sends an Acknowledge a packet.
//!
//! This function acknowledges a packet has been received from the device.
//!
//! \return The function returns zero to indicated success while any non-zero
//! value indicates a failure.
//
//****************************************************************************
int32_t
AckPacket(void)
{
    uint8_t ui8Ack;

    ui8Ack = COMMAND_ACK;
    return(I2CSendData(&ui8Ack, 1));
}

//****************************************************************************
//
//! NakPacket() sends a No Acknowledge packet.
//!
//! This function sends a no acknowledge for a packet that has been
//! received unsuccessfully from the device.
//!
//! \return The function returns zero to indicated success while any non-zero
//! value indicates a failure.
//
//****************************************************************************
int32_t
NakPacket(void)
{
    uint8_t ui8Nak;

    ui8Nak = COMMAND_NAK;
    return(I2CSendData(&ui8Nak, 1));
}

//*****************************************************************************
//
//! GetPacket() receives a data packet.
//!
//! \param pui8Data is the location to store the data received from the device.
//! \param pui8Size is the number of bytes returned in the pui8Data buffer that
//! was provided.
//!
//! This function receives a packet of data from UART port.
//!
//! \returns The function returns zero to indicated success while any non-zero
//! value indicates a failure.
//
//*****************************************************************************
int32_t
GetPacket(uint8_t *pui8Data, uint8_t *pui8Size)
{
    uint8_t ui8CheckSum;
    uint8_t ui8Size;

    //
    // Get the size and the checksum.
    //
    do
    {
        if(I2CReceiveData(&ui8Size, 1))
        {
            return(-1);
        }
    }
    while(ui8Size == 0);

    if(I2CReceiveData(&ui8CheckSum, 1))
    {
        return(-1);
    }
    *pui8Size = ui8Size - 2;

    if(I2CReceiveData(pui8Data, *pui8Size))
    {
        *pui8Size = 0;
        return(-1);
    }

    //
    // Calculate the checksum from the data.
    //
    if(CheckSum(pui8Data, *pui8Size) != ui8CheckSum)
    {
        *pui8Size = 0;
        return(NakPacket());
    }

    return(AckPacket());
}

//*****************************************************************************
//
//! CheckSum() Calculates an 8 bit checksum
//!
//! \param pui8Data is a pointer to an array of 8 bit data of size ui8Size.
//! \param ui8Size is the size of the array that will run through the checksum
//!     algorithm.
//!
//! This function simply calculates an 8 bit checksum on the data passed in.
//!
//! \return The function returns the calculated checksum.
//
//*****************************************************************************
uint8_t
CheckSum(uint8_t *pui8Data, uint8_t ui8Size)
{
    int32_t i;
    uint8_t ui8CheckSum;

    ui8CheckSum = 0;

    for(i = 0; i < ui8Size; ++i)
    {
        ui8CheckSum += pui8Data[i];
    }
    return(ui8CheckSum);
}

//*****************************************************************************
//
//! SendPacket() sends a data packet.
//!
//! \param pui8Data is the location of the data to be sent to the device.
//! \param ui8Size is the number of bytes to send from puData.
//! \param bAck is a boolean that is true if an ACK/NAK packet should be
//! received in response to this packet.
//!
//! This function sends a packet of data to the device.
//!
//! \returns The function returns zero to indicated success while any non-zero
//!     value indicates a failure.
//
//*****************************************************************************
int32_t
SendPacket(uint8_t *pui8Data, uint8_t ui8Size, bool bAck)
{
    uint8_t ui8CheckSum;
    uint8_t ui8Ack;

    ui8CheckSum = CheckSum(pui8Data, ui8Size);

    //
    // Make sure that we add the bytes for the size and checksum to the total.
    //
    ui8Size += 2;

    //
    // Send the Size in bytes.
    //
    if(I2CSendData(&ui8Size, 1))
    {
        return(-1);
    }

    //
    // Send the CheckSum
    //
    if(I2CSendData(&ui8CheckSum, 1))
    {
        return(-1);
    }

    //
    // Now send the remaining bytes out.
    //
    ui8Size -= 2;

    //
    // Send the Data
    //
    if(I2CSendData(pui8Data, ui8Size))
    {
        return(-1);
    }

    //
    // Return immediately if no ACK/NAK is expected.
    //
    if(!bAck)
    {
        return(0);
    }

    //
    // Wait for the acknowledge from the device.
    //
    do
    {
        if(I2CReceiveData(&ui8Ack, 1))
        {
            return(-1);
        }
    }
    while(ui8Ack == 0);

    if(ui8Ack != COMMAND_ACK)
    {
        return(-1);
    }
    return(0);
}


int32_t
SendCommand(uint8_t *pui8Command, uint8_t ui8Size)
{
    uint8_t ui8Status;

    //
    // Send the command itself.
    //
    if(SendPacket(pui8Command, ui8Size, 1) < 0)
    {
        return(-1);
    }

    //
    // Send the get status command to tell the device to return status to
    // the host.
    //
    ui8Status = COMMAND_GET_STATUS;
    if(SendPacket(&ui8Status, 1, 1) < 0)
    {
        pc.printf("Failed to Get Status\n");
        return(-1);
    }

    //
    // Read back the status provided from the device.
    //
    ui8Size = sizeof(ui8Status);
    if(GetPacket(&ui8Status, &ui8Size) < 0)
    {
        pc.printf("Failed to Get Packet\n");
        return(-1);
    }
    if(ui8Status != COMMAND_RET_SUCCESS)
    {
        pc.printf("Failed to get download command Return Code: %04x\n",
            ui8Status);
        return(-1);
    }
    return(0);
}

 
    
int main() {
    
    g_ui32DownloadAddress = 0;
    g_ui32StartAddress = 0xffffffff;    
    g_ui32DataSize = 8;
    uint8_t ui8Command;
    
    
    uint32_t ui32TransferLength;
    uint8_t *pui8FileBuffer;
    uint32_t ui32Offset;
    
    g_pui8Buffer[0] = COMMAND_DOWNLOAD;
    g_pui8Buffer[1] = (uint8_t)(g_ui32DownloadAddress >> 24);
    g_pui8Buffer[2] = (uint8_t)(g_ui32DownloadAddress >> 16);
    g_pui8Buffer[3] = (uint8_t)(g_ui32DownloadAddress >> 8);
    g_pui8Buffer[4] = (uint8_t)g_ui32DownloadAddress;
    g_pui8Buffer[5] = (uint8_t)(ui32TransferLength>>24);
    g_pui8Buffer[6] = (uint8_t)(ui32TransferLength>>16);
    g_pui8Buffer[7] = (uint8_t)(ui32TransferLength>>8);
    g_pui8Buffer[8] = (uint8_t)ui32TransferLength;
    
    ui8Command = COMMAND_PING;
    if(SendCommand(&ui8Command, 1) < 0)
    {
        pc.printf("Ping fail");
        return(-1);
    }
    
    if(SendCommand(g_pui8Buffer, 9) < 0)
    {
        printf("Failed to Send Download Command\n");
        return(-1);
    }
    
    
ui32Offset = 0;

    printf("Remaining Bytes: ");
    do
    {
        uint8_t ui8BytesSent;

        g_pui8Buffer[0] = COMMAND_SEND_DATA;

        printf("%08ld", ui32TransferLength);

        //
        // Send out 8 bytes at a time to throttle download rate and avoid
        // overruning the device since it is programming flash on the fly.
        //
        if(ui32TransferLength >= g_ui32DataSize)
        {
            memcpy(&g_pui8Buffer[1], &pui8FileBuffer[ui32Offset], g_ui32DataSize);

            ui32Offset += g_ui32DataSize;
            ui32TransferLength -= g_ui32DataSize;
            ui8BytesSent = g_ui32DataSize + 1;
        }
        else
        {
            memcpy(&g_pui8Buffer[1], &pui8FileBuffer[ui32Offset], ui32TransferLength);
            ui32Offset += ui32TransferLength;
            ui8BytesSent = ui32TransferLength + 1;
            ui32TransferLength = 0;
        }
        //
        // Send the Send Data command to the device.
        //
        if(SendCommand(g_pui8Buffer, ui8BytesSent) < 0)
        {
            printf("Failed to Send Packet data\n");
            break;
        }

        printf("\b\b\b\b\b\b\b\b");
    } while (ui32TransferLength);
    printf("00000000\n");

}