Added makefile support for writer utilities
[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.03";
53 /* The input file name is hard coded */
54 char *input_file = "eepromwriter_input.txt";
56 /* Parameters defined in the input_file */
57 #define FILE_NAME      "file_name"
58 #define BUS_ADDR       "bus_addr"
59 #define START_ADDR     "start_addr"
60 #define SWAP_DATA      "swap_data"
62 /* Memory address to store the write data */
63 #define WRITE_DATA_ADDRESS     0x80000000
65 /******************************************************************************
66  * Structure:   EEPROM_WRITER_INFO_T
67  *
68  *              EEPROM writer control data. This structure should be filled in
69  *              by the user before running
70  ******************************************************************************/
71 #define MAX_LINE_LENGTH 40
72 typedef struct EEPROM_WRITER_INFO_tag
73 {
74     char        file_name[MAX_LINE_LENGTH]; /* CCS format data file name */
75     uint32_t    busAddr;                    /* Slave bus address */
76     uint32_t    startAddr;                  /* Start address to write */
77     uint32_t    swapData;                   /* Swap byte in the 32-bit word of the data */
78     uint32_t    deviceTotalBytes;           /* Total number of bytes available in the device */
79     uint32_t    writeBytes;                 /* Number of bytes to be written into the device */
80     uint8_t     *writeData;                 /* Address to store the write data */
81     uint8_t     *readData;                  /* Address to store the read data */
83 } EEPROM_WRITER_INFO_T;
85 EEPROM_WRITER_INFO_T eepromWriterInfo;
87 /******************************************************************************
88  * Function:    print_platform_errno
89  ******************************************************************************/
90 void
91 print_platform_errno
92 (
93     void
94 )
95 {
96     printf ("Returned platform error number is %d\n", platform_errno);
97 }
99 /******************************************************************************
100  * Function:    form_block
101  *
102  *      Form a block of data to write to the NOR. The block is
103  *      created as a byte stream from the 4 byte stream in which
104  *      the MSB is always sent first.
105  ******************************************************************************/
106 void
107 formBlock
109     uint32_t      *data,
110     uint32_t      blockSize,
111     uint8_t       *scratch
114     uint32_t i, j;
116     /* Convert the data to a byte stream */
117     for (i = j = 0; j < blockSize; i++, j+=4)
118     {
119         scratch[j+0] = (data[i] >> 24) & 0xff;
120         scratch[j+1] = (data[i] >> 16) & 0xff;
121         scratch[j+2] = (data[i] >>  8) & 0xff;
122         scratch[j+3] = (data[i] >>  0) & 0xff;
123     }
126 /******************************************************************************
127  * Function:    flash_eeprom
128  *
129  *              Write the data from memory to EEPROM.
130  *              Returns TRUE if the data is written successfully
131  *                      FALSE if the data write fails
132  ******************************************************************************/
133 Bool
134 flash_eeprom
136     PLATFORM_DEVICE_info    *p_device
139     uint8_t       *scrach_block;
141     printf ("Writing %d bytes from DSP memory address 0x%08x to EEPROM bus address 0x%04x starting from device address 0x%04x ...\n",
142             eepromWriterInfo.writeBytes,
143             (uint32_t)eepromWriterInfo.writeData,
144             eepromWriterInfo.busAddr,
145             eepromWriterInfo.startAddr);
147     if (eepromWriterInfo.swapData)
148     {
149             scrach_block = malloc(eepromWriterInfo.deviceTotalBytes);
150             if (scrach_block == NULL)
151             {
152                 printf ("Can not allocate scratch block memory!\n");
153                 return (FALSE);
154             }
155         formBlock((uint32_t *)(eepromWriterInfo.writeData), eepromWriterInfo.deviceTotalBytes, scrach_block);
156         }
157         else
158         {
159                 scrach_block = eepromWriterInfo.writeData;
160         }
162     if(platform_device_write(p_device->handle, eepromWriterInfo.startAddr, scrach_block, eepromWriterInfo.writeBytes) != Platform_EOK)
163     {
164         print_platform_errno();
165         if (eepromWriterInfo.swapData)
166                 free (scrach_block);
167         return FALSE;
168     }
170         if(eepromWriterInfo.swapData)
171         free (scrach_block);
173     return TRUE;
176 /******************************************************************************
177  * Function:    flash_verify
178  *
179  *              Read back the data file that was just flashed.
180  *              Returns TRUE if the data verified correctly.
181  *                      FALSE if the data verification failed
182  ******************************************************************************/
183 Bool
184 flash_verify
186     PLATFORM_DEVICE_info    *p_device
189     uint32_t    i, j;
190     uint8_t     *scrach_block;
191     uint32_t    *read_data_w;
193     printf ("Reading %d bytes from EEPROM bus address 0x%04x to DSP memory address 0x%08x starting from device address 0x%04x ...\n",
194             eepromWriterInfo.writeBytes,
195             eepromWriterInfo.busAddr,
196             (uint32_t)eepromWriterInfo.readData,
197             eepromWriterInfo.startAddr);
199     if (eepromWriterInfo.swapData)
200     {
201             scrach_block = malloc(eepromWriterInfo.deviceTotalBytes);
202             if (scrach_block == NULL)
203             {
204                 printf ("Can not allocate scratch block memory!\n");
205                 return (FALSE);
206             }
207         }
208         else
209         {
210                 scrach_block = eepromWriterInfo.readData;
211         }
213     if(platform_device_read(p_device->handle, eepromWriterInfo.startAddr, scrach_block, eepromWriterInfo.writeBytes) != Platform_EOK)
214     {
215         print_platform_errno();
216         return FALSE;
217     }
219     printf ("Verifying data read ...\n");
221     if (eepromWriterInfo.swapData)
222     {
223         /* Convert the packed data */
224         read_data_w = (uint32_t *)(eepromWriterInfo.readData);
225         for  (i = 0, j = 0; i < eepromWriterInfo.deviceTotalBytes; i += 4)
226             read_data_w[j++] = (scrach_block[i+0] << 24) | (scrach_block[i+1] << 16) | (scrach_block[i+2] << 8) | scrach_block[i+3];
227    }
230     for (i = 0; i < eepromWriterInfo.writeBytes; i++)
231     {
232         if (eepromWriterInfo.readData[i] != eepromWriterInfo.writeData[i])
233         {
234             printf ("Failure at byte %d, expected 0x%08x, read 0x%08x\n", i, eepromWriterInfo.writeData[i], eepromWriterInfo.readData[i]);
235             return (FALSE);
236         }
237     }
239     return (TRUE);
242 int32_t 
243 xtoi
245     char            *xs, 
246     uint32_t        *result
249     uint32_t    szlen = strlen(xs);
250     int32_t     i, xv, fact;
251     
252     if (szlen > 0)
253     {
254         /* Converting more than 32bit hexadecimal value? */
255         if (szlen>8) return 2; /* exit */
256         
257         /* Begin conversion here */
258         *result = 0;
259         fact = 1;
260         
261         /* Run until no more character to convert */
262         for(i=szlen-1; i>=0 ;i--)
263         {
264             if (isxdigit(*(xs+i)))
265             {
266                 if (*(xs+i)>=97)
267                 {
268                     xv = ( *(xs+i) - 97) + 10;
269                 }
270                 else if ( *(xs+i) >= 65)
271                 {
272                     xv = (*(xs+i) - 65) + 10;
273                 }
274                 else
275                 {
276                     xv = *(xs+i) - 48;
277                 }
278                 *result += (xv * fact);
279                 fact *= 16;
280             }
281             else
282             {
283                 // Conversion was abnormally terminated
284                 // by non hexadecimal digit, hence
285                 // returning only the converted with
286                 // an error value 4 (illegal hex character)
287                 return 4;
288             }
289         }
290         return 0;
291     }
292     
293     // Nothing to convert
294     return 1;
298 /******************************************************************************
299  * Function:    parse_input_file
300  ******************************************************************************/
301 static Bool
302 parse_input_file
304     FILE*               fp
307     char line[MAX_LINE_LENGTH];
308     char tokens[] = " :=;\n";
309     char *key, *data;
311     memset(line, 0, MAX_LINE_LENGTH);
313     fgets(line, MAX_LINE_LENGTH, fp);
314     key  = (char *)strtok(line, tokens);
315     data = (char *)strtok(NULL, tokens);
317     if(strlen(data) == 0)
318     {
319        return FALSE;
320     }
322     if(strcmp(key, FILE_NAME) != 0)
323     {
324         return FALSE;
325     }
327     strcpy (eepromWriterInfo.file_name, data);
329     fgets(line, MAX_LINE_LENGTH, fp);
330     key  = (char *)strtok(line, tokens);
331     data = (char *)strtok(NULL, tokens);
333     if(strlen(data) == 0)
334     {
335        return FALSE;
336     }
338     if(strcmp(key, BUS_ADDR) != 0)
339     {
340         return FALSE;
341     }
343     if ((data[0] == '0') && (data[1] == 'x' || data[1] == 'X'))
344     {
345         if (xtoi (&data[2], &eepromWriterInfo.busAddr) != 0)
346         {
347             return FALSE;
348         }
349     }
350     else
351     {
352         eepromWriterInfo.busAddr = (uint32_t)atoi(data);
353     }
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, START_ADDR) != 0)
365     {
366         return FALSE;
367     }
369     eepromWriterInfo.startAddr = (uint32_t)atoi(data);
371     fgets(line, MAX_LINE_LENGTH, fp);
372     key  = (char *)strtok(line, tokens);
373     data = (char *)strtok(NULL, tokens);
375     if(strlen(data) == 0)
376     {
377        return FALSE;
378     }
380     if(strcmp(key, SWAP_DATA) != 0)
381     {
382         return FALSE;
383     }
385     eepromWriterInfo.swapData = (uint32_t)atoi(data);
387     return TRUE;
390 /******************************************************************************
391  * Function:    find_file_length
392  ******************************************************************************/
393 static Bool
394 find_file_length
396     FILE*               fp
399     char        line[MAX_LINE_LENGTH];
400     char        *pEnd;
401     char        *ext;
402     uint32_t    data_len, write_addr;
404     memset(line, 0, MAX_LINE_LENGTH);
406     ext = strrchr(eepromWriterInfo.file_name, '.');
409     if (ext && (strcmp(ext, ".dat") == 0))
410     {
411         
412         fgets(line, MAX_LINE_LENGTH, fp);
413         
414         /* Read the write address from the CCS header */
415         strtoul (line,&pEnd,16);
416         strtoul (pEnd,&pEnd,16);
417         write_addr = strtoul (pEnd,&pEnd,16);
418         strtoul (pEnd,&pEnd,16);
419         
420         /* Read the data length */
421         data_len = (strtoul (pEnd,NULL,16)) * 4;
422     }
423     else
424     {
425         /* find the data length by seeking to the end and getting position */
426         fseek(fp, 0, SEEK_END);
427         data_len = ftell(fp);
428         fseek(fp, 0, SEEK_SET);
429     }
431     if (data_len > (eepromWriterInfo.deviceTotalBytes - eepromWriterInfo.startAddr))
432     {
433         printf ("The data file is too big to fit into the device.\n");
434         return FALSE;
435     }
437     eepromWriterInfo.writeBytes = data_len;
438     if (write_addr != WRITE_DATA_ADDRESS)
439         write_addr = WRITE_DATA_ADDRESS;
440     eepromWriterInfo.writeData  = (uint8_t *)write_addr;
441     eepromWriterInfo.readData   = (uint8_t *)(write_addr + eepromWriterInfo.deviceTotalBytes);
443     return TRUE;
446 /******************************************************************************
447  * Function:    main
448  ******************************************************************************/
449 void main ()
451     FILE                    *fp;
452     platform_init_flags     init_flags;
453     platform_init_config    init_config;
454     PLATFORM_DEVICE_info    *p_device;
455     Bool                    ret;
457     printf("EEPROM Writer Utility Version %s\n\n", version);
459     fp = fopen(input_file, "r");
460     if (fp == NULL)
461     {
462         printf("Error in opening %s input file\n", input_file);
463         return;
464     }
466     ret = parse_input_file(fp);
467     fclose (fp);
469     if (ret == FALSE)
470     {
471         printf("Error in parsing %s input file\n", input_file);
472         return;
473     }
475     /* Initialize main Platform lib */
476     memset(&init_config, 0, sizeof(platform_init_config));
477     memset(&init_flags, 0x01, sizeof(platform_init_flags));
478     init_flags.phy = 0;
480     if (platform_init(&init_flags, &init_config) != Platform_EOK)
481     {
482         printf ("Platform init failed!\n");
483         print_platform_errno();
484         return;
485     }
487     p_device = platform_device_open(eepromWriterInfo.busAddr, 0);
488     if (p_device == NULL)
489     {
490         printf ("EEPROM device open failed!\n");
491         print_platform_errno();
492         return;
493     }
494     eepromWriterInfo.deviceTotalBytes = p_device->block_count * p_device->page_count * p_device->page_size;
496     /* Open and find the length of the data file */
497     fp = fopen (eepromWriterInfo.file_name, "rb");
498     if (fp == NULL)
499     {
500         printf ("Failed to open file %s\n", eepromWriterInfo.file_name);
501         print_platform_errno();
502         platform_device_close(p_device->handle);
503         return;
504     }
506     /* Parse the CCS format file */
507     ret = find_file_length(fp);
508     fclose (fp);
509     if (ret == FALSE)
510     {
511         printf("Error in parsing CCS file %s\n", eepromWriterInfo.file_name);
512         platform_device_close(p_device->handle);
513         return;
514     }
516     /* Write the EEPROM */
517     if (flash_eeprom (p_device) == FALSE)
518     {
519         printf ("EEPROM write failed\n");
520         platform_device_close(p_device->handle);
521         return;
522     }
524     /* verify the flash */
525     if(flash_verify (p_device) == FALSE)
526     {
527         printf ("EEPROM read verify failed\n");
528         platform_device_close(p_device->handle);
529         return;
530     }
533     printf ("EEPROM programming completed successfully\n");
535     platform_device_close(p_device->handle);
537     return;