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
108 (
109 uint32_t *data,
110 uint32_t blockSize,
111 uint8_t *scratch
112 )
113 {
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 }
124 }
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
135 (
136 PLATFORM_DEVICE_info *p_device
137 )
138 {
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;
174 }
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
185 (
186 PLATFORM_DEVICE_info *p_device
187 )
188 {
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);
240 }
242 int32_t
243 xtoi
244 (
245 char *xs,
246 uint32_t *result
247 )
248 {
249 uint32_t szlen = strlen(xs);
250 int32_t i, xv, fact;
252 if (szlen > 0)
253 {
254 /* Converting more than 32bit hexadecimal value? */
255 if (szlen>8) return 2; /* exit */
257 /* Begin conversion here */
258 *result = 0;
259 fact = 1;
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 }
293 // Nothing to convert
294 return 1;
295 }
298 /******************************************************************************
299 * Function: parse_input_file
300 ******************************************************************************/
301 static Bool
302 parse_input_file
303 (
304 FILE* fp
305 )
306 {
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;
388 }
390 /******************************************************************************
391 * Function: find_file_length
392 ******************************************************************************/
393 static Bool
394 find_file_length
395 (
396 FILE* fp
397 )
398 {
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 {
412 fgets(line, MAX_LINE_LENGTH, fp);
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);
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;
444 }
446 /******************************************************************************
447 * Function: main
448 ******************************************************************************/
449 void main ()
450 {
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;
538 }