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 }
100 }
102 /******************************************************************************
103 * Function: print_platform_errno
104 ******************************************************************************/
105 void
106 print_platform_errno
107 (
108 void
109 )
110 {
111 printf ("Returned platform error number is %d\n", platform_errno);
112 }
114 /******************************************************************************
115 * Function: form_block
116 *
117 * Form a block of data to write to the NOR. The block is
118 * created as a byte stream from the 4 byte stream in which
119 * the MSB is always sent first.
120 ******************************************************************************/
121 void
122 formBlock
123 (
124 uint32_t *data,
125 uint32_t blockSize,
126 uint8_t *scratch
127 )
128 {
129 uint32_t i, j;
131 /* Convert the data to a byte stream */
132 for (i = j = 0; j < blockSize; i++, j+=4)
133 {
134 scratch[j+0] = (data[i] >> 24) & 0xff;
135 scratch[j+1] = (data[i] >> 16) & 0xff;
136 scratch[j+2] = (data[i] >> 8) & 0xff;
137 scratch[j+3] = (data[i] >> 0) & 0xff;
138 }
139 }
141 /******************************************************************************
142 * Function: flash_eeprom
143 *
144 * Write the data from memory to EEPROM.
145 * Returns TRUE if the data is written successfully
146 * FALSE if the data write fails
147 ******************************************************************************/
148 Bool
149 flash_eeprom
150 (
151 PLATFORM_DEVICE_info *p_device
152 )
153 {
154 uint8_t *scrach_block;
156 printf ("Writing %d bytes from DSP memory address 0x%08x to EEPROM bus address 0x%04x starting from device address 0x%04x ...\n",
157 eepromWriterInfo.writeBytes,
158 (uint32_t)eepromWriterInfo.writeData,
159 eepromWriterInfo.busAddr,
160 eepromWriterInfo.startAddr);
162 if (eepromWriterInfo.swapData)
163 {
164 scrach_block = malloc(eepromWriterInfo.deviceTotalBytes);
165 if (scrach_block == NULL)
166 {
167 printf ("Can not allocate scratch block memory!\n");
168 return (FALSE);
169 }
170 formBlock((uint32_t *)(eepromWriterInfo.writeData), eepromWriterInfo.deviceTotalBytes, scrach_block);
171 }
172 else
173 {
174 scrach_block = eepromWriterInfo.writeData;
175 }
177 if(platform_device_write(p_device->handle, eepromWriterInfo.startAddr, scrach_block, eepromWriterInfo.writeBytes) != Platform_EOK)
178 {
179 print_platform_errno();
180 if (eepromWriterInfo.swapData)
181 free (scrach_block);
182 return FALSE;
183 }
185 if(eepromWriterInfo.swapData)
186 free (scrach_block);
188 return TRUE;
189 }
191 /******************************************************************************
192 * Function: flash_verify
193 *
194 * Read back the data file that was just flashed.
195 * Returns TRUE if the data verified correctly.
196 * FALSE if the data verification failed
197 ******************************************************************************/
198 Bool
199 flash_verify
200 (
201 PLATFORM_DEVICE_info *p_device
202 )
203 {
204 uint32_t i, j;
205 uint8_t *scrach_block;
206 uint32_t *read_data_w;
208 printf ("Reading %d bytes from EEPROM bus address 0x%04x to DSP memory address 0x%08x starting from device address 0x%04x ...\n",
209 eepromWriterInfo.writeBytes,
210 eepromWriterInfo.busAddr,
211 (uint32_t)eepromWriterInfo.readData,
212 eepromWriterInfo.startAddr);
214 if (eepromWriterInfo.swapData)
215 {
216 scrach_block = malloc(eepromWriterInfo.deviceTotalBytes);
217 if (scrach_block == NULL)
218 {
219 printf ("Can not allocate scratch block memory!\n");
220 return (FALSE);
221 }
222 }
223 else
224 {
225 scrach_block = eepromWriterInfo.readData;
226 }
228 if(platform_device_read(p_device->handle, eepromWriterInfo.startAddr, scrach_block, eepromWriterInfo.writeBytes) != Platform_EOK)
229 {
230 print_platform_errno();
231 return FALSE;
232 }
234 printf ("Verifying data read ...\n");
236 if (eepromWriterInfo.swapData)
237 {
238 /* Convert the packed data */
239 read_data_w = (uint32_t *)(eepromWriterInfo.readData);
240 for (i = 0, j = 0; i < eepromWriterInfo.deviceTotalBytes; i += 4)
241 read_data_w[j++] = (scrach_block[i+0] << 24) | (scrach_block[i+1] << 16) | (scrach_block[i+2] << 8) | scrach_block[i+3];
242 }
245 for (i = 0; i < eepromWriterInfo.writeBytes; i++)
246 {
247 if (eepromWriterInfo.readData[i] != eepromWriterInfo.writeData[i])
248 {
249 printf ("Failure at byte %d, expected 0x%08x, read 0x%08x\n", i, eepromWriterInfo.writeData[i], eepromWriterInfo.readData[i]);
250 return (FALSE);
251 }
252 }
254 return (TRUE);
255 }
257 int32_t
258 xtoi
259 (
260 char *xs,
261 uint32_t *result
262 )
263 {
264 uint32_t szlen = strlen(xs);
265 int32_t i, xv, fact;
267 if (szlen > 0)
268 {
269 /* Converting more than 32bit hexadecimal value? */
270 if (szlen>8) return 2; /* exit */
272 /* Begin conversion here */
273 *result = 0;
274 fact = 1;
276 /* Run until no more character to convert */
277 for(i=szlen-1; i>=0 ;i--)
278 {
279 if (isxdigit(*(xs+i)))
280 {
281 if (*(xs+i)>=97)
282 {
283 xv = ( *(xs+i) - 97) + 10;
284 }
285 else if ( *(xs+i) >= 65)
286 {
287 xv = (*(xs+i) - 65) + 10;
288 }
289 else
290 {
291 xv = *(xs+i) - 48;
292 }
293 *result += (xv * fact);
294 fact *= 16;
295 }
296 else
297 {
298 // Conversion was abnormally terminated
299 // by non hexadecimal digit, hence
300 // returning only the converted with
301 // an error value 4 (illegal hex character)
302 return 4;
303 }
304 }
305 return 0;
306 }
308 // Nothing to convert
309 return 1;
310 }
313 /******************************************************************************
314 * Function: parse_input_file
315 ******************************************************************************/
316 static Bool
317 parse_input_file
318 (
319 FILE* fp
320 )
321 {
322 char line[MAX_LINE_LENGTH];
323 char tokens[] = " :=;\n";
324 char *key, *data;
326 memset(line, 0, MAX_LINE_LENGTH);
328 fgets(line, MAX_LINE_LENGTH, fp);
329 key = (char *)strtok(line, tokens);
330 data = (char *)strtok(NULL, tokens);
332 if(strlen(data) == 0)
333 {
334 return FALSE;
335 }
337 if(strcmp(key, FILE_NAME) != 0)
338 {
339 return FALSE;
340 }
342 strcpy (eepromWriterInfo.file_name, data);
344 fgets(line, MAX_LINE_LENGTH, fp);
345 key = (char *)strtok(line, tokens);
346 data = (char *)strtok(NULL, tokens);
348 if(strlen(data) == 0)
349 {
350 return FALSE;
351 }
353 if(strcmp(key, BUS_ADDR) != 0)
354 {
355 return FALSE;
356 }
358 if ((data[0] == '0') && (data[1] == 'x' || data[1] == 'X'))
359 {
360 if (xtoi (&data[2], &eepromWriterInfo.busAddr) != 0)
361 {
362 return FALSE;
363 }
364 }
365 else
366 {
367 eepromWriterInfo.busAddr = (uint32_t)atoi(data);
368 }
370 fgets(line, MAX_LINE_LENGTH, fp);
371 key = (char *)strtok(line, tokens);
372 data = (char *)strtok(NULL, tokens);
374 if(strlen(data) == 0)
375 {
376 return FALSE;
377 }
379 if(strcmp(key, START_ADDR) != 0)
380 {
381 return FALSE;
382 }
384 eepromWriterInfo.startAddr = (uint32_t)atoi(data);
386 fgets(line, MAX_LINE_LENGTH, fp);
387 key = (char *)strtok(line, tokens);
388 data = (char *)strtok(NULL, tokens);
390 if(strlen(data) == 0)
391 {
392 return FALSE;
393 }
395 if(strcmp(key, SWAP_DATA) != 0)
396 {
397 return FALSE;
398 }
400 eepromWriterInfo.swapData = (uint32_t)atoi(data);
402 return TRUE;
403 }
405 /******************************************************************************
406 * Function: find_file_length
407 ******************************************************************************/
408 static Bool
409 find_file_length
410 (
411 FILE* fp
412 )
413 {
414 char line[MAX_LINE_LENGTH];
415 char *pEnd;
416 char *ext;
417 uint32_t data_len, write_addr;
419 memset(line, 0, MAX_LINE_LENGTH);
421 ext = strrchr(eepromWriterInfo.file_name, '.');
424 if (ext && (strcmp(ext, ".dat") == 0))
425 {
427 fgets(line, MAX_LINE_LENGTH, fp);
429 /* Read the write address from the CCS header */
430 strtoul (line,&pEnd,16);
431 strtoul (pEnd,&pEnd,16);
432 write_addr = strtoul (pEnd,&pEnd,16);
433 strtoul (pEnd,&pEnd,16);
435 /* Read the data length */
436 data_len = (strtoul (pEnd,NULL,16)) * 4;
437 }
438 else
439 {
440 /* find the data length by seeking to the end and getting position */
441 fseek(fp, 0, SEEK_END);
442 data_len = ftell(fp);
443 fseek(fp, 0, SEEK_SET);
444 }
446 if (data_len > (eepromWriterInfo.deviceTotalBytes - eepromWriterInfo.startAddr))
447 {
448 printf ("The data file is too big to fit into the device.\n");
449 return FALSE;
450 }
452 eepromWriterInfo.writeBytes = data_len;
453 if (write_addr != WRITE_DATA_ADDRESS)
454 write_addr = WRITE_DATA_ADDRESS;
455 eepromWriterInfo.writeData = (uint8_t *)write_addr;
456 eepromWriterInfo.readData = (uint8_t *)(write_addr + eepromWriterInfo.deviceTotalBytes);
458 return TRUE;
459 }
461 /******************************************************************************
462 * Function: main
463 ******************************************************************************/
464 void main ()
465 {
466 FILE *fp;
467 platform_init_flags init_flags;
468 platform_init_config init_config;
469 PLATFORM_DEVICE_info *p_device;
470 Bool ret;
472 printf("EEPROM Writer Utility Version %s\n\n", version);
474 fp = fopen(input_file, "r");
475 if (fp == NULL)
476 {
477 printf("Error in opening %s input file\n", input_file);
478 return;
479 }
481 ret = parse_input_file(fp);
482 fclose (fp);
484 if (ret == FALSE)
485 {
486 printf("Error in parsing %s input file\n", input_file);
487 return;
488 }
490 /* Initialize main Platform lib */
491 memset(&init_config, 0, sizeof(platform_init_config));
492 memset(&init_flags, 0x01, sizeof(platform_init_flags));
493 init_flags.phy = 0;
495 if (platform_init(&init_flags, &init_config) != Platform_EOK)
496 {
497 printf ("Platform init failed!\n");
498 print_platform_errno();
499 return;
500 }
502 p_device = platform_device_open(eepromWriterInfo.busAddr, 0);
503 if (p_device == NULL)
504 {
505 printf ("EEPROM device open failed!\n");
506 print_platform_errno();
507 return;
508 }
509 eepromWriterInfo.deviceTotalBytes = p_device->block_count * p_device->page_count * p_device->page_size;
511 /* Open and find the length of the data file */
512 fp = fopen (eepromWriterInfo.file_name, "rb");
513 if (fp == NULL)
514 {
515 printf ("Failed to open file %s\n", eepromWriterInfo.file_name);
516 print_platform_errno();
517 platform_device_close(p_device->handle);
518 return;
519 }
521 /* Parse the CCS format file */
522 ret = find_file_length(fp);
523 fclose (fp);
524 if (ret == FALSE)
525 {
526 printf("Error in parsing CCS file %s\n", eepromWriterInfo.file_name);
527 platform_device_close(p_device->handle);
528 return;
529 }
531 /* Write the EEPROM */
532 if (flash_eeprom (p_device) == FALSE)
533 {
534 printf ("EEPROM write failed\n");
535 platform_device_close(p_device->handle);
536 return;
537 }
539 /* verify the flash */
540 if(flash_verify (p_device) == FALSE)
541 {
542 printf ("EEPROM read verify failed\n");
543 platform_device_close(p_device->handle);
544 return;
545 }
548 printf ("EEPROM programming completed successfully\n");
550 platform_device_close(p_device->handle);
552 return;
553 }