Updates for 2.0.0.11 GA release
[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 /* OSAL functions for Platform Library */
88 uint8_t *Osal_platformMalloc (uint32_t num_bytes, uint32_t alignment)
89 {
90         return malloc(num_bytes);
91 }
93 void Osal_platformFree (uint8_t *dataPtr, uint32_t num_bytes)
94 {
95     /* Free up the memory */
96     if (dataPtr)
97     {
98         free(dataPtr);
99     }
102 void Osal_platformSpiCsEnter(void)
104     return;
107 void Osal_platformSpiCsExit (void)
109     return;
112 /******************************************************************************
113  * Function:    print_platform_errno
114  ******************************************************************************/
115 void
116 print_platform_errno
118     void
121     printf ("Returned platform error number is %d\n", platform_errno);
124 /******************************************************************************
125  * Function:    form_block
126  *
127  *      Form a block of data to write to the NOR. The block is
128  *      created as a byte stream from the 4 byte stream in which
129  *      the MSB is always sent first.
130  ******************************************************************************/
131 void
132 formBlock
134     uint32_t      *data,
135     uint32_t      blockSize,
136     uint8_t       *scratch
139     uint32_t i, j;
141     /* Convert the data to a byte stream */
142     for (i = j = 0; j < blockSize; i++, j+=4)
143     {
144         scratch[j+0] = (data[i] >> 24) & 0xff;
145         scratch[j+1] = (data[i] >> 16) & 0xff;
146         scratch[j+2] = (data[i] >>  8) & 0xff;
147         scratch[j+3] = (data[i] >>  0) & 0xff;
148     }
151 /******************************************************************************
152  * Function:    flash_eeprom
153  *
154  *              Write the data from memory to EEPROM.
155  *              Returns TRUE if the data is written successfully
156  *                      FALSE if the data write fails
157  ******************************************************************************/
158 Bool
159 flash_eeprom
161     PLATFORM_DEVICE_info    *p_device
164     uint8_t       *scrach_block;
166     printf ("Writing %d bytes from DSP memory address 0x%08x to EEPROM bus address 0x%04x starting from device address 0x%04x ...\n",
167             eepromWriterInfo.writeBytes,
168             (uint32_t)eepromWriterInfo.writeData,
169             eepromWriterInfo.busAddr,
170             eepromWriterInfo.startAddr);
172     if (eepromWriterInfo.swapData)
173     {
174             scrach_block = malloc(eepromWriterInfo.deviceTotalBytes);
175             if (scrach_block == NULL)
176             {
177                 printf ("Can not allocate scratch block memory!\n");
178                 return (FALSE);
179             }
180         formBlock((uint32_t *)(eepromWriterInfo.writeData), eepromWriterInfo.deviceTotalBytes, scrach_block);
181         }
182         else
183         {
184                 scrach_block = eepromWriterInfo.writeData;
185         }
187     if(platform_device_write(p_device->handle, eepromWriterInfo.startAddr, scrach_block, eepromWriterInfo.writeBytes) != Platform_EOK)
188     {
189         print_platform_errno();
190         if (eepromWriterInfo.swapData)
191                 free (scrach_block);
192         return FALSE;
193     }
195         if(eepromWriterInfo.swapData)
196         free (scrach_block);
198     return TRUE;
201 /******************************************************************************
202  * Function:    flash_verify
203  *
204  *              Read back the data file that was just flashed.
205  *              Returns TRUE if the data verified correctly.
206  *                      FALSE if the data verification failed
207  ******************************************************************************/
208 Bool
209 flash_verify
211     PLATFORM_DEVICE_info    *p_device
214     uint32_t    i, j;
215     uint8_t     *scrach_block;
216     uint32_t    *read_data_w;
218     printf ("Reading %d bytes from EEPROM bus address 0x%04x to DSP memory address 0x%08x starting from device address 0x%04x ...\n",
219             eepromWriterInfo.writeBytes,
220             eepromWriterInfo.busAddr,
221             (uint32_t)eepromWriterInfo.readData,
222             eepromWriterInfo.startAddr);
224     if (eepromWriterInfo.swapData)
225     {
226             scrach_block = malloc(eepromWriterInfo.deviceTotalBytes);
227             if (scrach_block == NULL)
228             {
229                 printf ("Can not allocate scratch block memory!\n");
230                 return (FALSE);
231             }
232         }
233         else
234         {
235                 scrach_block = eepromWriterInfo.readData;
236         }
238     if(platform_device_read(p_device->handle, eepromWriterInfo.startAddr, scrach_block, eepromWriterInfo.writeBytes) != Platform_EOK)
239     {
240         print_platform_errno();
241         return FALSE;
242     }
244     printf ("Verifying data read ...\n");
246     if (eepromWriterInfo.swapData)
247     {
248         /* Convert the packed data */
249         read_data_w = (uint32_t *)(eepromWriterInfo.readData);
250         for  (i = 0, j = 0; i < eepromWriterInfo.deviceTotalBytes; i += 4)
251             read_data_w[j++] = (scrach_block[i+0] << 24) | (scrach_block[i+1] << 16) | (scrach_block[i+2] << 8) | scrach_block[i+3];
252    }
255     for (i = 0; i < eepromWriterInfo.writeBytes; i++)
256     {
257         if (eepromWriterInfo.readData[i] != eepromWriterInfo.writeData[i])
258         {
259             printf ("Failure at byte %d, expected 0x%08x, read 0x%08x\n", i, eepromWriterInfo.writeData[i], eepromWriterInfo.readData[i]);
260             return (FALSE);
261         }
262     }
264     return (TRUE);
267 int32_t 
268 xtoi
270     char            *xs, 
271     uint32_t        *result
274     uint32_t    szlen = strlen(xs);
275     int32_t     i, xv, fact;
276     
277     if (szlen > 0)
278     {
279         /* Converting more than 32bit hexadecimal value? */
280         if (szlen>8) return 2; /* exit */
281         
282         /* Begin conversion here */
283         *result = 0;
284         fact = 1;
285         
286         /* Run until no more character to convert */
287         for(i=szlen-1; i>=0 ;i--)
288         {
289             if (isxdigit(*(xs+i)))
290             {
291                 if (*(xs+i)>=97)
292                 {
293                     xv = ( *(xs+i) - 97) + 10;
294                 }
295                 else if ( *(xs+i) >= 65)
296                 {
297                     xv = (*(xs+i) - 65) + 10;
298                 }
299                 else
300                 {
301                     xv = *(xs+i) - 48;
302                 }
303                 *result += (xv * fact);
304                 fact *= 16;
305             }
306             else
307             {
308                 // Conversion was abnormally terminated
309                 // by non hexadecimal digit, hence
310                 // returning only the converted with
311                 // an error value 4 (illegal hex character)
312                 return 4;
313             }
314         }
315         return 0;
316     }
317     
318     // Nothing to convert
319     return 1;
323 /******************************************************************************
324  * Function:    parse_input_file
325  ******************************************************************************/
326 static Bool
327 parse_input_file
329     FILE*               fp
332     char line[MAX_LINE_LENGTH];
333     char tokens[] = " :=;\n";
334     char *key, *data;
336     memset(line, 0, MAX_LINE_LENGTH);
338     fgets(line, MAX_LINE_LENGTH, fp);
339     key  = (char *)strtok(line, tokens);
340     data = (char *)strtok(NULL, tokens);
342     if(strlen(data) == 0)
343     {
344        return FALSE;
345     }
347     if(strcmp(key, FILE_NAME) != 0)
348     {
349         return FALSE;
350     }
352     strcpy (eepromWriterInfo.file_name, data);
354     fgets(line, MAX_LINE_LENGTH, fp);
355     key  = (char *)strtok(line, tokens);
356     data = (char *)strtok(NULL, tokens);
358     if(strlen(data) == 0)
359     {
360        return FALSE;
361     }
363     if(strcmp(key, BUS_ADDR) != 0)
364     {
365         return FALSE;
366     }
368     if ((data[0] == '0') && (data[1] == 'x' || data[1] == 'X'))
369     {
370         if (xtoi (&data[2], &eepromWriterInfo.busAddr) != 0)
371         {
372             return FALSE;
373         }
374     }
375     else
376     {
377         eepromWriterInfo.busAddr = (uint32_t)atoi(data);
378     }
380     fgets(line, MAX_LINE_LENGTH, fp);
381     key  = (char *)strtok(line, tokens);
382     data = (char *)strtok(NULL, tokens);
384     if(strlen(data) == 0)
385     {
386        return FALSE;
387     }
389     if(strcmp(key, START_ADDR) != 0)
390     {
391         return FALSE;
392     }
394     eepromWriterInfo.startAddr = (uint32_t)atoi(data);
396     fgets(line, MAX_LINE_LENGTH, fp);
397     key  = (char *)strtok(line, tokens);
398     data = (char *)strtok(NULL, tokens);
400     if(strlen(data) == 0)
401     {
402        return FALSE;
403     }
405     if(strcmp(key, SWAP_DATA) != 0)
406     {
407         return FALSE;
408     }
410     eepromWriterInfo.swapData = (uint32_t)atoi(data);
412     return TRUE;
415 /******************************************************************************
416  * Function:    find_file_length
417  ******************************************************************************/
418 static Bool
419 find_file_length
421     FILE*               fp
424     char        line[MAX_LINE_LENGTH];
425     char        *pEnd;
426     char        *ext;
427     uint32_t    data_len, write_addr;
429     memset(line, 0, MAX_LINE_LENGTH);
431     ext = strrchr(eepromWriterInfo.file_name, '.');
434     if (ext && (strcmp(ext, ".dat") == 0))
435     {
436         
437         fgets(line, MAX_LINE_LENGTH, fp);
438         
439         /* Read the write address from the CCS header */
440         strtoul (line,&pEnd,16);
441         strtoul (pEnd,&pEnd,16);
442         write_addr = strtoul (pEnd,&pEnd,16);
443         strtoul (pEnd,&pEnd,16);
444         
445         /* Read the data length */
446         data_len = (strtoul (pEnd,NULL,16)) * 4;
447     }
448     else
449     {
450         /* find the data length by seeking to the end and getting position */
451         fseek(fp, 0, SEEK_END);
452         data_len = ftell(fp);
453         fseek(fp, 0, SEEK_SET);
454     }
456     if (data_len > (eepromWriterInfo.deviceTotalBytes - eepromWriterInfo.startAddr))
457     {
458         printf ("The data file is too big to fit into the device.\n");
459         return FALSE;
460     }
462     eepromWriterInfo.writeBytes = data_len;
463     if (write_addr != WRITE_DATA_ADDRESS)
464         write_addr = WRITE_DATA_ADDRESS;
465     eepromWriterInfo.writeData  = (uint8_t *)write_addr;
466     eepromWriterInfo.readData   = (uint8_t *)(write_addr + eepromWriterInfo.deviceTotalBytes);
468     return TRUE;
471 /******************************************************************************
472  * Function:    main
473  ******************************************************************************/
474 void main ()
476     FILE                    *fp;
477     platform_init_flags     init_flags;
478     platform_init_config    init_config;
479     PLATFORM_DEVICE_info    *p_device;
480     Bool                    ret;
482     printf("EEPROM Writer Utility Version %s\n\n", version);
484     fp = fopen(input_file, "r");
485     if (fp == NULL)
486     {
487         printf("Error in opening %s input file\n", input_file);
488         return;
489     }
491     ret = parse_input_file(fp);
492     fclose (fp);
494     if (ret == FALSE)
495     {
496         printf("Error in parsing %s input file\n", input_file);
497         return;
498     }
500     /* Initialize main Platform lib */
501     memset(&init_config, 0, sizeof(platform_init_config));
502     memset(&init_flags, 0x01, sizeof(platform_init_flags));
503     init_flags.phy = 0;
505     if (platform_init(&init_flags, &init_config) != Platform_EOK)
506     {
507         printf ("Platform init failed!\n");
508         print_platform_errno();
509         return;
510     }
512     p_device = platform_device_open(eepromWriterInfo.busAddr, 0);
513     if (p_device == NULL)
514     {
515         printf ("EEPROM device open failed!\n");
516         print_platform_errno();
517         return;
518     }
519     eepromWriterInfo.deviceTotalBytes = p_device->block_count * p_device->page_count * p_device->page_size;
521     /* Open and find the length of the data file */
522     fp = fopen (eepromWriterInfo.file_name, "rb");
523     if (fp == NULL)
524     {
525         printf ("Failed to open file %s\n", eepromWriterInfo.file_name);
526         print_platform_errno();
527         platform_device_close(p_device->handle);
528         return;
529     }
531     /* Parse the CCS format file */
532     ret = find_file_length(fp);
533     fclose (fp);
534     if (ret == FALSE)
535     {
536         printf("Error in parsing CCS file %s\n", eepromWriterInfo.file_name);
537         platform_device_close(p_device->handle);
538         return;
539     }
541     /* Write the EEPROM */
542     if (flash_eeprom (p_device) == FALSE)
543     {
544         printf ("EEPROM write failed\n");
545         platform_device_close(p_device->handle);
546         return;
547     }
549     /* verify the flash */
550     if(flash_verify (p_device) == FALSE)
551     {
552         printf ("EEPROM read verify failed\n");
553         platform_device_close(p_device->handle);
554         return;
555     }
558     printf ("EEPROM programming completed successfully\n");
560     platform_device_close(p_device->handle);
562     return;