I2C boot loader

Dependencies:   mbed

Fork of I2C_HelloWorld_Mbed by mbed official

Revision:
1:c39e5581f901
Parent:
0:f76c26307f9a
--- a/main.cpp	Thu Feb 14 17:24:48 2013 +0000
+++ b/main.cpp	Sat May 23 23:04:50 2015 +0000
@@ -1,25 +1,420 @@
 #include "mbed.h"
- 
-// Read temperature from LM75BD
+#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;
 
-int main() {
-    char cmd[2];
-    while (1) {
-        cmd[0] = 0x01;
-        cmd[1] = 0x00;
-        i2c.write(addr, cmd, 2);
+#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);   
+   }    
  
-        wait(0.5);
+    
+}
+
+int
+I2CReceiveData(uint8_t *pui8Data, uint8_t ui8Size)
+{
+    if(i2c.read(addr, pui8Data, ui8Size == 0)
+    {
+        return (0);
+    }
+    
+    return (-1);
+        
+}        
  
-        cmd[0] = 0x00;
-        i2c.write(addr, cmd, 1);
-        i2c.read(addr, cmd, 2);
+
+//****************************************************************************
+//
+//! 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);
+}
+
  
-        float tmp = (float((cmd[0]<<8)|cmd[1]) / 256.0);
-        printf("Temp = %.2f\n", tmp);
+    
+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");
+
 }
\ No newline at end of file