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"
49 #include "ti/csl/csl_semAux.h"
51 /* EEPROM writer utility version */
52 char version[] = "01.00.00.03";
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 /* Get the hardware semaphore.
106 *
107 * Acquire Multi core CPPI synchronization lock
108 */
109 while ((CSL_semAcquireDirect (3)) == 0);
111 return;
112 }
114 void Osal_platformSpiCsExit (void)
115 {
116 /* Release the hardware semaphore
117 *
118 * Release multi-core lock.
119 */
120 CSL_semReleaseSemaphore (3);
122 return;
123 }
125 /******************************************************************************
126 * Function: print_platform_errno
127 ******************************************************************************/
128 void
129 print_platform_errno
130 (
131 void
132 )
133 {
134 printf ("Returned platform error number is %d\n", platform_errno);
135 }
137 /******************************************************************************
138 * Function: form_block
139 *
140 * Form a block of data to write to the NOR. The block is
141 * created as a byte stream from the 4 byte stream in which
142 * the MSB is always sent first.
143 ******************************************************************************/
144 void
145 formBlock
146 (
147 uint32_t *data,
148 uint32_t blockSize,
149 uint8_t *scratch
150 )
151 {
152 uint32_t i, j;
154 /* Convert the data to a byte stream */
155 for (i = j = 0; j < blockSize; i++, j+=4)
156 {
157 scratch[j+0] = (data[i] >> 24) & 0xff;
158 scratch[j+1] = (data[i] >> 16) & 0xff;
159 scratch[j+2] = (data[i] >> 8) & 0xff;
160 scratch[j+3] = (data[i] >> 0) & 0xff;
161 }
162 }
164 /******************************************************************************
165 * Function: flash_eeprom
166 *
167 * Write the data from memory to EEPROM.
168 * Returns TRUE if the data is written successfully
169 * FALSE if the data write fails
170 ******************************************************************************/
171 Bool
172 flash_eeprom
173 (
174 PLATFORM_DEVICE_info *p_device
175 )
176 {
177 uint8_t *scrach_block;
179 printf ("Writing %d bytes from DSP memory address 0x%08x to EEPROM bus address 0x%04x starting from device address 0x%04x ...\n",
180 eepromWriterInfo.writeBytes,
181 (uint32_t)eepromWriterInfo.writeData,
182 eepromWriterInfo.busAddr,
183 eepromWriterInfo.startAddr);
185 if (eepromWriterInfo.swapData)
186 {
187 scrach_block = malloc(eepromWriterInfo.deviceTotalBytes);
188 if (scrach_block == NULL)
189 {
190 printf ("Can not allocate scratch block memory!\n");
191 return (FALSE);
192 }
193 formBlock((uint32_t *)(eepromWriterInfo.writeData), eepromWriterInfo.deviceTotalBytes, scrach_block);
194 }
195 else
196 {
197 scrach_block = eepromWriterInfo.writeData;
198 }
200 if(platform_device_write(p_device->handle, eepromWriterInfo.startAddr, scrach_block, eepromWriterInfo.writeBytes) != Platform_EOK)
201 {
202 print_platform_errno();
203 if (eepromWriterInfo.swapData)
204 free (scrach_block);
205 return FALSE;
206 }
208 if(eepromWriterInfo.swapData)
209 free (scrach_block);
211 return TRUE;
212 }
214 /******************************************************************************
215 * Function: flash_verify
216 *
217 * Read back the data file that was just flashed.
218 * Returns TRUE if the data verified correctly.
219 * FALSE if the data verification failed
220 ******************************************************************************/
221 Bool
222 flash_verify
223 (
224 PLATFORM_DEVICE_info *p_device
225 )
226 {
227 uint32_t i, j;
228 uint8_t *scrach_block;
229 uint32_t *read_data_w;
231 printf ("Reading %d bytes from EEPROM bus address 0x%04x to DSP memory address 0x%08x starting from device address 0x%04x ...\n",
232 eepromWriterInfo.writeBytes,
233 eepromWriterInfo.busAddr,
234 (uint32_t)eepromWriterInfo.readData,
235 eepromWriterInfo.startAddr);
237 if (eepromWriterInfo.swapData)
238 {
239 scrach_block = malloc(eepromWriterInfo.deviceTotalBytes);
240 if (scrach_block == NULL)
241 {
242 printf ("Can not allocate scratch block memory!\n");
243 return (FALSE);
244 }
245 }
246 else
247 {
248 scrach_block = eepromWriterInfo.readData;
249 }
251 if(platform_device_read(p_device->handle, eepromWriterInfo.startAddr, scrach_block, eepromWriterInfo.writeBytes) != Platform_EOK)
252 {
253 print_platform_errno();
254 return FALSE;
255 }
257 printf ("Verifying data read ...\n");
259 if (eepromWriterInfo.swapData)
260 {
261 /* Convert the packed data */
262 read_data_w = (uint32_t *)(eepromWriterInfo.readData);
263 for (i = 0, j = 0; i < eepromWriterInfo.deviceTotalBytes; i += 4)
264 read_data_w[j++] = (scrach_block[i+0] << 24) | (scrach_block[i+1] << 16) | (scrach_block[i+2] << 8) | scrach_block[i+3];
265 }
268 for (i = 0; i < eepromWriterInfo.writeBytes; i++)
269 {
270 if (eepromWriterInfo.readData[i] != eepromWriterInfo.writeData[i])
271 {
272 printf ("Failure at byte %d, expected 0x%08x, read 0x%08x\n", i, eepromWriterInfo.writeData[i], eepromWriterInfo.readData[i]);
273 return (FALSE);
274 }
275 }
277 return (TRUE);
278 }
280 int32_t
281 xtoi
282 (
283 char *xs,
284 uint32_t *result
285 )
286 {
287 uint32_t szlen = strlen(xs);
288 int32_t i, xv, fact;
290 if (szlen > 0)
291 {
292 /* Converting more than 32bit hexadecimal value? */
293 if (szlen>8) return 2; /* exit */
295 /* Begin conversion here */
296 *result = 0;
297 fact = 1;
299 /* Run until no more character to convert */
300 for(i=szlen-1; i>=0 ;i--)
301 {
302 if (isxdigit(*(xs+i)))
303 {
304 if (*(xs+i)>=97)
305 {
306 xv = ( *(xs+i) - 97) + 10;
307 }
308 else if ( *(xs+i) >= 65)
309 {
310 xv = (*(xs+i) - 65) + 10;
311 }
312 else
313 {
314 xv = *(xs+i) - 48;
315 }
316 *result += (xv * fact);
317 fact *= 16;
318 }
319 else
320 {
321 // Conversion was abnormally terminated
322 // by non hexadecimal digit, hence
323 // returning only the converted with
324 // an error value 4 (illegal hex character)
325 return 4;
326 }
327 }
328 return 0;
329 }
331 // Nothing to convert
332 return 1;
333 }
336 /******************************************************************************
337 * Function: parse_input_file
338 ******************************************************************************/
339 static Bool
340 parse_input_file
341 (
342 FILE* fp
343 )
344 {
345 char line[MAX_LINE_LENGTH];
346 char tokens[] = " :=;\n";
347 char *key, *data;
349 memset(line, 0, MAX_LINE_LENGTH);
351 fgets(line, MAX_LINE_LENGTH, fp);
352 key = (char *)strtok(line, tokens);
353 data = (char *)strtok(NULL, tokens);
355 if(strlen(data) == 0)
356 {
357 return FALSE;
358 }
360 if(strcmp(key, FILE_NAME) != 0)
361 {
362 return FALSE;
363 }
365 strcpy (eepromWriterInfo.file_name, data);
367 fgets(line, MAX_LINE_LENGTH, fp);
368 key = (char *)strtok(line, tokens);
369 data = (char *)strtok(NULL, tokens);
371 if(strlen(data) == 0)
372 {
373 return FALSE;
374 }
376 if(strcmp(key, BUS_ADDR) != 0)
377 {
378 return FALSE;
379 }
381 if ((data[0] == '0') && (data[1] == 'x' || data[1] == 'X'))
382 {
383 if (xtoi (&data[2], &eepromWriterInfo.busAddr) != 0)
384 {
385 return FALSE;
386 }
387 }
388 else
389 {
390 eepromWriterInfo.busAddr = (uint32_t)atoi(data);
391 }
393 fgets(line, MAX_LINE_LENGTH, fp);
394 key = (char *)strtok(line, tokens);
395 data = (char *)strtok(NULL, tokens);
397 if(strlen(data) == 0)
398 {
399 return FALSE;
400 }
402 if(strcmp(key, START_ADDR) != 0)
403 {
404 return FALSE;
405 }
407 eepromWriterInfo.startAddr = (uint32_t)atoi(data);
409 fgets(line, MAX_LINE_LENGTH, fp);
410 key = (char *)strtok(line, tokens);
411 data = (char *)strtok(NULL, tokens);
413 if(strlen(data) == 0)
414 {
415 return FALSE;
416 }
418 if(strcmp(key, SWAP_DATA) != 0)
419 {
420 return FALSE;
421 }
423 eepromWriterInfo.swapData = (uint32_t)atoi(data);
425 return TRUE;
426 }
428 /******************************************************************************
429 * Function: find_file_length
430 ******************************************************************************/
431 static Bool
432 find_file_length
433 (
434 FILE* fp
435 )
436 {
437 char line[MAX_LINE_LENGTH];
438 char *pEnd;
439 char *ext;
440 uint32_t data_len, write_addr;
442 memset(line, 0, MAX_LINE_LENGTH);
444 ext = strrchr(eepromWriterInfo.file_name, '.');
447 if (ext && (strcmp(ext, ".dat") == 0))
448 {
450 fgets(line, MAX_LINE_LENGTH, fp);
452 /* Read the write address from the CCS header */
453 strtoul (line,&pEnd,16);
454 strtoul (pEnd,&pEnd,16);
455 write_addr = strtoul (pEnd,&pEnd,16);
456 strtoul (pEnd,&pEnd,16);
458 /* Read the data length */
459 data_len = (strtoul (pEnd,NULL,16)) * 4;
460 }
461 else
462 {
463 /* find the data length by seeking to the end and getting position */
464 fseek(fp, 0, SEEK_END);
465 data_len = ftell(fp);
466 fseek(fp, 0, SEEK_SET);
467 }
469 if (data_len > (eepromWriterInfo.deviceTotalBytes - eepromWriterInfo.startAddr))
470 {
471 printf ("The data file is too big to fit into the device.\n");
472 return FALSE;
473 }
475 eepromWriterInfo.writeBytes = data_len;
476 if (write_addr != WRITE_DATA_ADDRESS)
477 write_addr = WRITE_DATA_ADDRESS;
478 eepromWriterInfo.writeData = (uint8_t *)write_addr;
479 eepromWriterInfo.readData = (uint8_t *)(write_addr + eepromWriterInfo.deviceTotalBytes);
481 return TRUE;
482 }
484 /******************************************************************************
485 * Function: main
486 ******************************************************************************/
487 void main ()
488 {
489 FILE *fp;
490 platform_init_flags init_flags;
491 platform_init_config init_config;
492 PLATFORM_DEVICE_info *p_device;
493 Bool ret;
495 printf("EEPROM Writer Utility Version %s\n\n", version);
497 fp = fopen(input_file, "r");
498 if (fp == NULL)
499 {
500 printf("Error in opening %s input file\n", input_file);
501 return;
502 }
504 ret = parse_input_file(fp);
505 fclose (fp);
507 if (ret == FALSE)
508 {
509 printf("Error in parsing %s input file\n", input_file);
510 return;
511 }
513 /* Initialize main Platform lib */
514 memset(&init_config, 0, sizeof(platform_init_config));
515 memset(&init_flags, 0x01, sizeof(platform_init_flags));
516 init_flags.phy = 0;
518 if (platform_init(&init_flags, &init_config) != Platform_EOK)
519 {
520 printf ("Platform init failed!\n");
521 print_platform_errno();
522 return;
523 }
525 p_device = platform_device_open(eepromWriterInfo.busAddr, 0);
526 if (p_device == NULL)
527 {
528 printf ("EEPROM device open failed!\n");
529 print_platform_errno();
530 return;
531 }
532 eepromWriterInfo.deviceTotalBytes = p_device->block_count * p_device->page_count * p_device->page_size;
534 /* Open and find the length of the data file */
535 fp = fopen (eepromWriterInfo.file_name, "rb");
536 if (fp == NULL)
537 {
538 printf ("Failed to open file %s\n", eepromWriterInfo.file_name);
539 print_platform_errno();
540 platform_device_close(p_device->handle);
541 return;
542 }
544 /* Parse the CCS format file */
545 ret = find_file_length(fp);
546 fclose (fp);
547 if (ret == FALSE)
548 {
549 printf("Error in parsing CCS file %s\n", eepromWriterInfo.file_name);
550 platform_device_close(p_device->handle);
551 return;
552 }
554 /* Write the EEPROM */
555 if (flash_eeprom (p_device) == FALSE)
556 {
557 printf ("EEPROM write failed\n");
558 platform_device_close(p_device->handle);
559 return;
560 }
562 /* verify the flash */
563 if(flash_verify (p_device) == FALSE)
564 {
565 printf ("EEPROM read verify failed\n");
566 platform_device_close(p_device->handle);
567 return;
568 }
571 printf ("EEPROM programming completed successfully\n");
573 platform_device_close(p_device->handle);
575 return;
576 }