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.04";
54 /* The input file name is hard coded */
55 char *input_file = "eepromwriter_input.txt";
57 /* Parameters defined in the input_file */
58 #define FILE_NAME "file_name"
59 #define BUS_ADDR "bus_addr"
60 #define START_ADDR "start_addr"
61 #define SWAP_DATA "swap_data"
63 /* Memory address to store the write data */
64 #define WRITE_DATA_ADDRESS 0x80000000
66 /******************************************************************************
67 * Structure: EEPROM_WRITER_INFO_T
68 *
69 * EEPROM writer control data. This structure should be filled in
70 * by the user before running
71 ******************************************************************************/
72 #define MAX_LINE_LENGTH 40
73 typedef struct EEPROM_WRITER_INFO_tag
74 {
75 char file_name[MAX_LINE_LENGTH]; /* CCS format data file name */
76 uint32_t busAddr; /* Slave bus address */
77 uint32_t startAddr; /* Start address to write */
78 uint32_t swapData; /* Swap byte in the 32-bit word of the data */
79 uint32_t deviceTotalBytes; /* Total number of bytes available in the device */
80 uint32_t writeBytes; /* Number of bytes to be written into the device */
81 uint8_t *writeData; /* Address to store the write data */
82 uint8_t *readData; /* Address to store the read data */
84 } EEPROM_WRITER_INFO_T;
86 EEPROM_WRITER_INFO_T eepromWriterInfo;
88 /* OSAL functions for Platform Library */
89 uint8_t *Osal_platformMalloc (uint32_t num_bytes, uint32_t alignment)
90 {
91 return malloc(num_bytes);
92 }
94 void Osal_platformFree (uint8_t *dataPtr, uint32_t num_bytes)
95 {
96 /* Free up the memory */
97 if (dataPtr)
98 {
99 free(dataPtr);
100 }
101 }
103 void Osal_platformSpiCsEnter(void)
104 {
105 return;
106 }
108 void Osal_platformSpiCsExit (void)
109 {
110 return;
111 }
113 /******************************************************************************
114 * Function: print_platform_errno
115 ******************************************************************************/
116 void
117 print_platform_errno
118 (
119 void
120 )
121 {
122 printf ("Returned platform error number is %d\n", platform_errno);
123 }
125 /******************************************************************************
126 * Function: form_block
127 *
128 * Form a block of data to write to the NOR. The block is
129 * created as a byte stream from the 4 byte stream in which
130 * the MSB is always sent first.
131 ******************************************************************************/
132 void
133 formBlock
134 (
135 uint32_t *data,
136 uint32_t blockSize,
137 uint8_t *scratch
138 )
139 {
140 uint32_t i, j;
142 /* Convert the data to a byte stream */
143 for (i = j = 0; j < blockSize; i++, j+=4)
144 {
145 scratch[j+0] = (data[i] >> 24) & 0xff;
146 scratch[j+1] = (data[i] >> 16) & 0xff;
147 scratch[j+2] = (data[i] >> 8) & 0xff;
148 scratch[j+3] = (data[i] >> 0) & 0xff;
149 }
150 }
152 /******************************************************************************
153 * Function: flash_eeprom
154 *
155 * Write the data from memory to EEPROM.
156 * Returns TRUE if the data is written successfully
157 * FALSE if the data write fails
158 ******************************************************************************/
159 Bool
160 flash_eeprom
161 (
162 PLATFORM_DEVICE_info *p_device
163 )
164 {
165 uint8_t *scrach_block;
167 printf ("Writing %d bytes from DSP memory address 0x%08x to EEPROM bus address 0x%04x starting from device address 0x%04x ...\n",
168 eepromWriterInfo.writeBytes,
169 (uint32_t)eepromWriterInfo.writeData,
170 eepromWriterInfo.busAddr,
171 eepromWriterInfo.startAddr);
173 if (eepromWriterInfo.swapData)
174 {
175 scrach_block = malloc(eepromWriterInfo.deviceTotalBytes);
176 if (scrach_block == NULL)
177 {
178 printf ("Can not allocate scratch block memory!\n");
179 return (FALSE);
180 }
181 formBlock((uint32_t *)(eepromWriterInfo.writeData), eepromWriterInfo.deviceTotalBytes, scrach_block);
182 }
183 else
184 {
185 scrach_block = eepromWriterInfo.writeData;
186 }
188 if(platform_device_write(p_device->handle, eepromWriterInfo.startAddr, scrach_block, eepromWriterInfo.writeBytes) != Platform_EOK)
189 {
190 print_platform_errno();
191 if (eepromWriterInfo.swapData)
192 free (scrach_block);
193 return FALSE;
194 }
196 if(eepromWriterInfo.swapData)
197 free (scrach_block);
199 return TRUE;
200 }
202 /******************************************************************************
203 * Function: flash_verify
204 *
205 * Read back the data file that was just flashed.
206 * Returns TRUE if the data verified correctly.
207 * FALSE if the data verification failed
208 ******************************************************************************/
209 Bool
210 flash_verify
211 (
212 PLATFORM_DEVICE_info *p_device
213 )
214 {
215 uint32_t i, j;
216 uint8_t *scrach_block;
217 uint32_t *read_data_w;
219 printf ("Reading %d bytes from EEPROM bus address 0x%04x to DSP memory address 0x%08x starting from device address 0x%04x ...\n",
220 eepromWriterInfo.writeBytes,
221 eepromWriterInfo.busAddr,
222 (uint32_t)eepromWriterInfo.readData,
223 eepromWriterInfo.startAddr);
225 if (eepromWriterInfo.swapData)
226 {
227 scrach_block = malloc(eepromWriterInfo.deviceTotalBytes);
228 if (scrach_block == NULL)
229 {
230 printf ("Can not allocate scratch block memory!\n");
231 return (FALSE);
232 }
233 }
234 else
235 {
236 scrach_block = eepromWriterInfo.readData;
237 }
239 if(platform_device_read(p_device->handle, eepromWriterInfo.startAddr, scrach_block, eepromWriterInfo.writeBytes) != Platform_EOK)
240 {
241 print_platform_errno();
242 return FALSE;
243 }
245 printf ("Verifying data read ...\n");
247 if (eepromWriterInfo.swapData)
248 {
249 /* Convert the packed data */
250 read_data_w = (uint32_t *)(eepromWriterInfo.readData);
251 for (i = 0, j = 0; i < eepromWriterInfo.deviceTotalBytes; i += 4)
252 read_data_w[j++] = (scrach_block[i+0] << 24) | (scrach_block[i+1] << 16) | (scrach_block[i+2] << 8) | scrach_block[i+3];
253 }
256 for (i = 0; i < eepromWriterInfo.writeBytes; i++)
257 {
258 if (eepromWriterInfo.readData[i] != eepromWriterInfo.writeData[i])
259 {
260 printf ("Failure at byte %d, expected 0x%08x, read 0x%08x\n", i, eepromWriterInfo.writeData[i], eepromWriterInfo.readData[i]);
261 return (FALSE);
262 }
263 }
265 return (TRUE);
266 }
268 int32_t
269 xtoi
270 (
271 char *xs,
272 uint32_t *result
273 )
274 {
275 uint32_t szlen = strlen(xs);
276 int32_t i, xv, fact;
278 if (szlen > 0)
279 {
280 /* Converting more than 32bit hexadecimal value? */
281 if (szlen>8) return 2; /* exit */
283 /* Begin conversion here */
284 *result = 0;
285 fact = 1;
287 /* Run until no more character to convert */
288 for(i=szlen-1; i>=0 ;i--)
289 {
290 if (isxdigit(*(xs+i)))
291 {
292 if (*(xs+i)>=97)
293 {
294 xv = ( *(xs+i) - 97) + 10;
295 }
296 else if ( *(xs+i) >= 65)
297 {
298 xv = (*(xs+i) - 65) + 10;
299 }
300 else
301 {
302 xv = *(xs+i) - 48;
303 }
304 *result += (xv * fact);
305 fact *= 16;
306 }
307 else
308 {
309 // Conversion was abnormally terminated
310 // by non hexadecimal digit, hence
311 // returning only the converted with
312 // an error value 4 (illegal hex character)
313 return 4;
314 }
315 }
316 return 0;
317 }
319 // Nothing to convert
320 return 1;
321 }
324 /******************************************************************************
325 * Function: parse_input_file
326 ******************************************************************************/
327 static Bool
328 parse_input_file
329 (
330 FILE* fp
331 )
332 {
333 char line[MAX_LINE_LENGTH];
334 char tokens[] = " :=;\n\r";
335 char *key, *data;
337 memset(line, 0, MAX_LINE_LENGTH);
339 fgets(line, MAX_LINE_LENGTH, fp);
340 key = (char *)strtok(line, tokens);
341 data = (char *)strtok(NULL, tokens);
343 if(strlen(data) == 0)
344 {
345 return FALSE;
346 }
348 if(strcmp(key, FILE_NAME) != 0)
349 {
350 return FALSE;
351 }
353 strcpy (eepromWriterInfo.file_name, data);
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, BUS_ADDR) != 0)
365 {
366 return FALSE;
367 }
369 if ((data[0] == '0') && (data[1] == 'x' || data[1] == 'X'))
370 {
371 if (xtoi (&data[2], &eepromWriterInfo.busAddr) != 0)
372 {
373 return FALSE;
374 }
375 }
376 else
377 {
378 eepromWriterInfo.busAddr = (uint32_t)atoi(data);
379 }
381 fgets(line, MAX_LINE_LENGTH, fp);
382 key = (char *)strtok(line, tokens);
383 data = (char *)strtok(NULL, tokens);
385 if(strlen(data) == 0)
386 {
387 return FALSE;
388 }
390 if(strcmp(key, START_ADDR) != 0)
391 {
392 return FALSE;
393 }
395 eepromWriterInfo.startAddr = (uint32_t)atoi(data);
397 fgets(line, MAX_LINE_LENGTH, fp);
398 key = (char *)strtok(line, tokens);
399 data = (char *)strtok(NULL, tokens);
401 if(strlen(data) == 0)
402 {
403 return FALSE;
404 }
406 if(strcmp(key, SWAP_DATA) != 0)
407 {
408 return FALSE;
409 }
411 eepromWriterInfo.swapData = (uint32_t)atoi(data);
413 return TRUE;
414 }
416 /******************************************************************************
417 * Function: find_file_length
418 ******************************************************************************/
419 static Bool
420 find_file_length
421 (
422 FILE* fp
423 )
424 {
425 char line[MAX_LINE_LENGTH];
426 char *pEnd;
427 char *ext;
428 uint32_t data_len, write_addr;
430 memset(line, 0, MAX_LINE_LENGTH);
432 ext = strrchr(eepromWriterInfo.file_name, '.');
435 if (ext && (strcmp(ext, ".dat") == 0))
436 {
438 fgets(line, MAX_LINE_LENGTH, fp);
440 /* Read the write address from the CCS header */
441 strtoul (line,&pEnd,16);
442 strtoul (pEnd,&pEnd,16);
443 write_addr = strtoul (pEnd,&pEnd,16);
444 strtoul (pEnd,&pEnd,16);
446 /* Read the data length */
447 data_len = (strtoul (pEnd,NULL,16)) * 4;
448 }
449 else
450 {
451 /* find the data length by seeking to the end and getting position */
452 fseek(fp, 0, SEEK_END);
453 data_len = ftell(fp);
454 fseek(fp, 0, SEEK_SET);
455 }
457 if (data_len > (eepromWriterInfo.deviceTotalBytes - eepromWriterInfo.startAddr))
458 {
459 printf ("The data file is too big to fit into the device.\n");
460 return FALSE;
461 }
463 eepromWriterInfo.writeBytes = data_len;
464 if (write_addr != WRITE_DATA_ADDRESS)
465 write_addr = WRITE_DATA_ADDRESS;
466 eepromWriterInfo.writeData = (uint8_t *)write_addr;
467 eepromWriterInfo.readData = (uint8_t *)(write_addr + eepromWriterInfo.deviceTotalBytes);
469 return TRUE;
470 }
472 /******************************************************************************
473 * Function: main
474 ******************************************************************************/
475 void main ()
476 {
477 FILE *fp;
478 platform_init_flags init_flags;
479 platform_init_config init_config;
480 PLATFORM_DEVICE_info *p_device;
481 Bool ret;
483 printf("EEPROM Writer Utility Version %s\n\n", version);
485 fp = fopen(input_file, "r");
486 if (fp == NULL)
487 {
488 printf("Error in opening %s input file\n", input_file);
489 return;
490 }
492 ret = parse_input_file(fp);
493 fclose (fp);
495 if (ret == FALSE)
496 {
497 printf("Error in parsing %s input file\n", input_file);
498 return;
499 }
501 /* Initialize main Platform lib */
502 memset(&init_config, 0, sizeof(platform_init_config));
503 memset(&init_flags, 0x01, sizeof(platform_init_flags));
504 init_flags.pll = 0;
505 init_flags.ddr = 0;
506 init_flags.phy = 0;
508 if (platform_init(&init_flags, &init_config) != Platform_EOK)
509 {
510 printf ("Platform init failed!\n");
511 print_platform_errno();
512 return;
513 }
515 p_device = platform_device_open(eepromWriterInfo.busAddr, 0);
516 if (p_device == NULL)
517 {
518 printf ("EEPROM device open failed!\n");
519 print_platform_errno();
520 return;
521 }
522 eepromWriterInfo.deviceTotalBytes = p_device->block_count * p_device->page_count * p_device->page_size;
524 /* Open and find the length of the data file */
525 fp = fopen (eepromWriterInfo.file_name, "rb");
526 if (fp == NULL)
527 {
528 printf ("Failed to open file %s\n", eepromWriterInfo.file_name);
529 print_platform_errno();
530 platform_device_close(p_device->handle);
531 return;
532 }
534 /* Parse the CCS format file */
535 ret = find_file_length(fp);
536 fclose (fp);
537 if (ret == FALSE)
538 {
539 printf("Error in parsing CCS file %s\n", eepromWriterInfo.file_name);
540 platform_device_close(p_device->handle);
541 return;
542 }
544 /* Write the EEPROM */
545 if (flash_eeprom (p_device) == FALSE)
546 {
547 printf ("EEPROM write failed\n");
548 platform_device_close(p_device->handle);
549 return;
550 }
552 /* verify the flash */
553 if(flash_verify (p_device) == FALSE)
554 {
555 printf ("EEPROM read verify failed\n");
556 platform_device_close(p_device->handle);
557 return;
558 }
561 printf ("EEPROM programming completed successfully\n");
563 platform_device_close(p_device->handle);
565 return;
566 }