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 void Osal_platformSpiCsEnter(void)
103 {
104 return;
105 }
107 void Osal_platformSpiCsExit (void)
108 {
109 return;
110 }
112 /******************************************************************************
113 * Function: print_platform_errno
114 ******************************************************************************/
115 void
116 print_platform_errno
117 (
118 void
119 )
120 {
121 printf ("Returned platform error number is %d\n", platform_errno);
122 }
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
133 (
134 uint32_t *data,
135 uint32_t blockSize,
136 uint8_t *scratch
137 )
138 {
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 }
149 }
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
160 (
161 PLATFORM_DEVICE_info *p_device
162 )
163 {
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;
199 }
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
210 (
211 PLATFORM_DEVICE_info *p_device
212 )
213 {
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);
265 }
267 int32_t
268 xtoi
269 (
270 char *xs,
271 uint32_t *result
272 )
273 {
274 uint32_t szlen = strlen(xs);
275 int32_t i, xv, fact;
277 if (szlen > 0)
278 {
279 /* Converting more than 32bit hexadecimal value? */
280 if (szlen>8) return 2; /* exit */
282 /* Begin conversion here */
283 *result = 0;
284 fact = 1;
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 }
318 // Nothing to convert
319 return 1;
320 }
323 /******************************************************************************
324 * Function: parse_input_file
325 ******************************************************************************/
326 static Bool
327 parse_input_file
328 (
329 FILE* fp
330 )
331 {
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;
413 }
415 /******************************************************************************
416 * Function: find_file_length
417 ******************************************************************************/
418 static Bool
419 find_file_length
420 (
421 FILE* fp
422 )
423 {
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 {
437 fgets(line, MAX_LINE_LENGTH, fp);
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);
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;
469 }
471 /******************************************************************************
472 * Function: main
473 ******************************************************************************/
474 void main ()
475 {
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;
563 }