Merge pull request #2 in PROCESSOR-SDK/mcsdk-tools from PRSDK-2194 to master
[keystone-rtos/mcsdk-tools.git] / writer / eeprom / src / eepromwriter.c
1 /******************************************************************************
2  * Copyright (c) 2011 Texas Instruments Incorporated - http://www.ti.com
3  *
4  *  Redistribution and use in source and binary forms, with or without
5  *  modification, are permitted provided that the following conditions
6  *  are met:
7  *
8  *    Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  *
11  *    Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the
14  *    distribution.
15  *
16  *    Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  *****************************************************************************/
34 /**************************************************************************************
35  * FILE PURPOSE: EEPROM writer utility
36  **************************************************************************************
37  * FILE NAME: eepromwriter.c
38  *
39  * DESCRIPTION: A simple EEPROM writer using platform lib APIs to program the EEPROM
40  *              with an image that the ibl can read.
41  *
42  ***************************************************************************************/
43 #include <stdlib.h>
44 #include <stdio.h>
45 #include<ctype.h>
46 #include <string.h>
47 #include "platform.h"
48 #include "types.h"
50 /* EEPROM writer utility version */
51 char version[] = "01.00.00.05";
54 /* The input file name is hard coded */
55 char *input_file = "eepromwriter_input.txt";
57 /* Parameters defined in the input_file */
58 #define FILE_NAME      "file_name"
59 #define BUS_ADDR       "bus_addr"
60 #define START_ADDR     "start_addr"
61 #define SWAP_DATA      "swap_data"
63 /* Memory address to store the write data */
64 #define WRITE_DATA_ADDRESS     0x0C000000
66 /******************************************************************************
67  * Structure:   EEPROM_WRITER_INFO_T
68  *
69  *              EEPROM writer control data. This structure should be filled in
70  *              by the user before running
71  ******************************************************************************/
72 #define MAX_LINE_LENGTH 40
73 typedef struct EEPROM_WRITER_INFO_tag
74 {
75     char        file_name[MAX_LINE_LENGTH]; /* CCS format data file name */
76     uint32_t    busAddr;                    /* Slave bus address */
77     uint32_t    startAddr;                  /* Start address to write */
78     uint32_t    swapData;                   /* Swap byte in the 32-bit word of the data */
79     uint32_t    deviceTotalBytes;           /* Total number of bytes available in the device */
80     uint32_t    writeBytes;                 /* Number of bytes to be written into the device */
81     uint8_t     *writeData;                 /* Address to store the write data */
82     uint8_t     *readData;                  /* Address to store the read data */
84 } EEPROM_WRITER_INFO_T;
86 EEPROM_WRITER_INFO_T eepromWriterInfo;
88 /* OSAL functions for Platform Library */
89 uint8_t *Osal_platformMalloc (uint32_t num_bytes, uint32_t alignment)
90 {
91         return malloc(num_bytes);
92 }
94 void Osal_platformFree (uint8_t *dataPtr, uint32_t num_bytes)
95 {
96     /* Free up the memory */
97     if (dataPtr)
98     {
99         free(dataPtr);
100     }
103 void Osal_platformSpiCsEnter(void)
105     return;
108 void Osal_platformSpiCsExit (void)
110     return;
113 /******************************************************************************
114  * Function:    print_platform_errno
115  ******************************************************************************/
116 void
117 print_platform_errno
119     void
122     printf ("Returned platform error number is %d\n", platform_errno);
125 /******************************************************************************
126  * Function:    form_block
127  *
128  *      Form a block of data to write to the NOR. The block is
129  *      created as a byte stream from the 4 byte stream in which
130  *      the MSB is always sent first.
131  ******************************************************************************/
132 void
133 formBlock
135     uint32_t      *data,
136     uint32_t      blockSize,
137     uint8_t       *scratch
140     uint32_t i, j;
142     /* Convert the data to a byte stream */
143     for (i = j = 0; j < blockSize; i++, j+=4)
144     {
145         scratch[j+0] = (data[i] >> 24) & 0xff;
146         scratch[j+1] = (data[i] >> 16) & 0xff;
147         scratch[j+2] = (data[i] >>  8) & 0xff;
148         scratch[j+3] = (data[i] >>  0) & 0xff;
149     }
152 /******************************************************************************
153  * Function:    flash_eeprom
154  *
155  *              Write the data from memory to EEPROM.
156  *              Returns TRUE if the data is written successfully
157  *                      FALSE if the data write fails
158  ******************************************************************************/
159 Bool
160 flash_eeprom
162     PLATFORM_DEVICE_info    *p_device
165     uint8_t       *scrach_block;
167     printf ("Writing %d bytes from DSP memory address 0x%08x to EEPROM bus address 0x%04x starting from device address 0x%04x ...\n",
168             eepromWriterInfo.writeBytes,
169             (uint32_t)eepromWriterInfo.writeData,
170             eepromWriterInfo.busAddr,
171             eepromWriterInfo.startAddr);
173     if (eepromWriterInfo.swapData)
174     {
175             scrach_block = malloc(eepromWriterInfo.deviceTotalBytes);
176             if (scrach_block == NULL)
177             {
178                 printf ("Can not allocate scratch block memory!\n");
179                 return (FALSE);
180             }
181         formBlock((uint32_t *)(eepromWriterInfo.writeData), eepromWriterInfo.deviceTotalBytes, scrach_block);
182         }
183         else
184         {
185                 scrach_block = eepromWriterInfo.writeData;
186         }
188     if(platform_device_write(p_device->handle, eepromWriterInfo.startAddr, scrach_block, eepromWriterInfo.writeBytes) != Platform_EOK)
189     {
190         print_platform_errno();
191         if (eepromWriterInfo.swapData)
192                 free (scrach_block);
193         return FALSE;
194     }
196         if(eepromWriterInfo.swapData)
197         free (scrach_block);
199     return TRUE;
202 /******************************************************************************
203  * Function:    flash_verify
204  *
205  *              Read back the data file that was just flashed.
206  *              Returns TRUE if the data verified correctly.
207  *                      FALSE if the data verification failed
208  ******************************************************************************/
209 Bool
210 flash_verify
212     PLATFORM_DEVICE_info    *p_device
215     uint32_t    i, j;
216     uint8_t     *scrach_block;
217     uint32_t    *read_data_w;
219     printf ("Reading %d bytes from EEPROM bus address 0x%04x to DSP memory address 0x%08x starting from device address 0x%04x ...\n",
220             eepromWriterInfo.writeBytes,
221             eepromWriterInfo.busAddr,
222             (uint32_t)eepromWriterInfo.readData,
223             eepromWriterInfo.startAddr);
225     if (eepromWriterInfo.swapData)
226     {
227             scrach_block = malloc(eepromWriterInfo.deviceTotalBytes);
228             if (scrach_block == NULL)
229             {
230                 printf ("Can not allocate scratch block memory!\n");
231                 return (FALSE);
232             }
233         }
234         else
235         {
236                 scrach_block = eepromWriterInfo.readData;
237         }
239     if(platform_device_read(p_device->handle, eepromWriterInfo.startAddr, scrach_block, eepromWriterInfo.writeBytes) != Platform_EOK)
240     {
241         print_platform_errno();
242         return FALSE;
243     }
245     printf ("Verifying data read ...\n");
247     if (eepromWriterInfo.swapData)
248     {
249         /* Convert the packed data */
250         read_data_w = (uint32_t *)(eepromWriterInfo.readData);
251         for  (i = 0, j = 0; i < eepromWriterInfo.deviceTotalBytes; i += 4)
252             read_data_w[j++] = (scrach_block[i+0] << 24) | (scrach_block[i+1] << 16) | (scrach_block[i+2] << 8) | scrach_block[i+3];
253    }
256     for (i = 0; i < eepromWriterInfo.writeBytes; i++)
257     {
258         if (eepromWriterInfo.readData[i] != eepromWriterInfo.writeData[i])
259         {
260             printf ("Failure at byte %d, expected 0x%08x, read 0x%08x\n", i, eepromWriterInfo.writeData[i], eepromWriterInfo.readData[i]);
261             return (FALSE);
262         }
263     }
265     return (TRUE);
268 int32_t 
269 xtoi
271     char            *xs, 
272     uint32_t        *result
275     uint32_t    szlen = strlen(xs);
276     int32_t     i, xv, fact;
277     
278     if (szlen > 0)
279     {
280         /* Converting more than 32bit hexadecimal value? */
281         if (szlen>8) return 2; /* exit */
282         
283         /* Begin conversion here */
284         *result = 0;
285         fact = 1;
286         
287         /* Run until no more character to convert */
288         for(i=szlen-1; i>=0 ;i--)
289         {
290             if (isxdigit(*(xs+i)))
291             {
292                 if (*(xs+i)>=97)
293                 {
294                     xv = ( *(xs+i) - 97) + 10;
295                 }
296                 else if ( *(xs+i) >= 65)
297                 {
298                     xv = (*(xs+i) - 65) + 10;
299                 }
300                 else
301                 {
302                     xv = *(xs+i) - 48;
303                 }
304                 *result += (xv * fact);
305                 fact *= 16;
306             }
307             else
308             {
309                 // Conversion was abnormally terminated
310                 // by non hexadecimal digit, hence
311                 // returning only the converted with
312                 // an error value 4 (illegal hex character)
313                 return 4;
314             }
315         }
316         return 0;
317     }
318     
319     // Nothing to convert
320     return 1;
324 /******************************************************************************
325  * Function:    parse_input_file
326  ******************************************************************************/
327 static Bool
328 parse_input_file
330     FILE*               fp
333     char line[MAX_LINE_LENGTH];
334     char tokens[] = " :=;\n\r";
335     char *key, *data;
337     memset(line, 0, MAX_LINE_LENGTH);
339     fgets(line, MAX_LINE_LENGTH, fp);
340     key  = (char *)strtok(line, tokens);
341     data = (char *)strtok(NULL, tokens);
343     if(strlen(data) == 0)
344     {
345        return FALSE;
346     }
348     if(strcmp(key, FILE_NAME) != 0)
349     {
350         return FALSE;
351     }
353     strcpy (eepromWriterInfo.file_name, data);
355     fgets(line, MAX_LINE_LENGTH, fp);
356     key  = (char *)strtok(line, tokens);
357     data = (char *)strtok(NULL, tokens);
359     if(strlen(data) == 0)
360     {
361        return FALSE;
362     }
364     if(strcmp(key, BUS_ADDR) != 0)
365     {
366         return FALSE;
367     }
369     if ((data[0] == '0') && (data[1] == 'x' || data[1] == 'X'))
370     {
371         if (xtoi (&data[2], &eepromWriterInfo.busAddr) != 0)
372         {
373             return FALSE;
374         }
375     }
376     else
377     {
378         eepromWriterInfo.busAddr = (uint32_t)atoi(data);
379     }
381     fgets(line, MAX_LINE_LENGTH, fp);
382     key  = (char *)strtok(line, tokens);
383     data = (char *)strtok(NULL, tokens);
385     if(strlen(data) == 0)
386     {
387        return FALSE;
388     }
390     if(strcmp(key, START_ADDR) != 0)
391     {
392         return FALSE;
393     }
395     eepromWriterInfo.startAddr = (uint32_t)atoi(data);
397     fgets(line, MAX_LINE_LENGTH, fp);
398     key  = (char *)strtok(line, tokens);
399     data = (char *)strtok(NULL, tokens);
401     if(strlen(data) == 0)
402     {
403        return FALSE;
404     }
406     if(strcmp(key, SWAP_DATA) != 0)
407     {
408         return FALSE;
409     }
411     eepromWriterInfo.swapData = (uint32_t)atoi(data);
413     return TRUE;
416 /******************************************************************************
417  * Function:    find_file_length
418  ******************************************************************************/
419 static Bool
420 find_file_length
422     FILE*               fp
425     char        line[MAX_LINE_LENGTH];
426     char        *pEnd;
427     char        *ext;
428     uint32_t    data_len, write_addr;
430     memset(line, 0, MAX_LINE_LENGTH);
432     ext = strrchr(eepromWriterInfo.file_name, '.');
435     if (ext && (strcmp(ext, ".dat") == 0))
436     {
437         
438         fgets(line, MAX_LINE_LENGTH, fp);
439         
440         /* Read the write address from the CCS header */
441         strtoul (line,&pEnd,16);
442         strtoul (pEnd,&pEnd,16);
443         write_addr = strtoul (pEnd,&pEnd,16);
444         strtoul (pEnd,&pEnd,16);
445         
446         /* Read the data length */
447         data_len = (strtoul (pEnd,NULL,16)) * 4;
448     }
449     else
450     {
451         /* find the data length by seeking to the end and getting position */
452         fseek(fp, 0, SEEK_END);
453         data_len = ftell(fp);
454         fseek(fp, 0, SEEK_SET);
455     }
457     if (data_len > (eepromWriterInfo.deviceTotalBytes - eepromWriterInfo.startAddr))
458     {
459         printf ("The data file is too big to fit into the device.\n");
460         return FALSE;
461     }
463     eepromWriterInfo.writeBytes = data_len;
464     if (write_addr != WRITE_DATA_ADDRESS)
465         write_addr = WRITE_DATA_ADDRESS;
466     eepromWriterInfo.writeData  = (uint8_t *)write_addr;
467     eepromWriterInfo.readData   = (uint8_t *)(write_addr + eepromWriterInfo.deviceTotalBytes);
469     return TRUE;
472 /******************************************************************************
473  * Function:    main
474  ******************************************************************************/
475 void main ()
477     FILE                    *fp;
478     platform_init_flags     init_flags;
479     platform_init_config    init_config;
480     PLATFORM_DEVICE_info    *p_device;
481     Bool                    ret;
483     printf("EEPROM Writer Utility Version %s\n\n", version);
485     fp = fopen(input_file, "r");
486     if (fp == NULL)
487     {
488         printf("Error in opening %s input file\n", input_file);
489         return;
490     }
492     ret = parse_input_file(fp);
493     fclose (fp);
495     if (ret == FALSE)
496     {
497         printf("Error in parsing %s input file\n", input_file);
498         return;
499     }
501     /* Initialize main Platform lib */
502     memset(&init_config, 0, sizeof(platform_init_config));
503     memset(&init_flags, 0x01, sizeof(platform_init_flags));
504     init_flags.pll = 0;
505     init_flags.ddr = 0;
506     init_flags.phy = 0;
508     if (platform_init(&init_flags, &init_config) != Platform_EOK)
509     {
510         printf ("Platform init failed!\n");
511         print_platform_errno();
512         return;
513     }
515     p_device = platform_device_open(eepromWriterInfo.busAddr, 0);
516     if (p_device == NULL)
517     {
518         printf ("EEPROM device open failed!\n");
519         print_platform_errno();
520         return;
521     }
522     eepromWriterInfo.deviceTotalBytes = p_device->block_count * p_device->page_count * p_device->page_size;
524     /* Open and find the length of the data file */
525     fp = fopen (eepromWriterInfo.file_name, "rb");
526     if (fp == NULL)
527     {
528         printf ("Failed to open file %s\n", eepromWriterInfo.file_name);
529         print_platform_errno();
530         platform_device_close(p_device->handle);
531         return;
532     }
534     /* Parse the CCS format file */
535     ret = find_file_length(fp);
536     fclose (fp);
537     if (ret == FALSE)
538     {
539         printf("Error in parsing CCS file %s\n", eepromWriterInfo.file_name);
540         platform_device_close(p_device->handle);
541         return;
542     }
544     /* Write the EEPROM */
545     if (flash_eeprom (p_device) == FALSE)
546     {
547         printf ("EEPROM write failed\n");
548         platform_device_close(p_device->handle);
549         return;
550     }
552     /* verify the flash */
553     if(flash_verify (p_device) == FALSE)
554     {
555         printf ("EEPROM read verify failed\n");
556         platform_device_close(p_device->handle);
557         return;
558     }
561     printf ("EEPROM programming completed successfully\n");
563     platform_device_close(p_device->handle);
565     return;