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 <string.h>
46 #include "platform.h"
47 #include "types.h"
49 /* EEPROM writer utility version */
50 char version[] = "01.00.00.01";
52 /* The input file name is hard coded */
53 char *input_file = "eepromwriter_input.txt";
55 /* Parameters defined in the input_file */
56 #define FILE_NAME "file_name"
57 #define BUS_ADDR "bus_addr"
58 #define START_ADDR "start_addr"
59 #define SWAP_DATA "swap_data"
61 /* Memory address to store the write data */
62 #define WRITE_DATA_ADDRESS 0x80000000
64 /******************************************************************************
65 * Structure: EEPROM_WRITER_INFO_T
66 *
67 * EEPROM writer control data. This structure should be filled in
68 * by the user before running
69 ******************************************************************************/
70 #define MAX_LINE_LENGTH 40
71 typedef struct EEPROM_WRITER_INFO_tag
72 {
73 char file_name[MAX_LINE_LENGTH]; /* CCS format data file name */
74 uint32_t busAddr; /* Slave bus address */
75 uint32_t startAddr; /* Start address to write */
76 uint32_t swapData; /* Swap byte in the 32-bit word of the data */
77 uint32_t deviceTotalBytes; /* Total number of bytes available in the device */
78 uint32_t writeBytes; /* Number of bytes to be written into the device */
79 uint8_t *writeData; /* Address to store the write data */
80 uint8_t *readData; /* Address to store the read data */
82 } EEPROM_WRITER_INFO_T;
84 EEPROM_WRITER_INFO_T eepromWriterInfo;
86 /******************************************************************************
87 * Function: print_platform_errno
88 ******************************************************************************/
89 void
90 print_platform_errno
91 (
92 void
93 )
94 {
95 printf ("Returned platform error number is %d\n", platform_errno);
96 }
98 /******************************************************************************
99 * Function: form_block
100 *
101 * Form a block of data to write to the NOR. The block is
102 * created as a byte stream from the 4 byte stream in which
103 * the MSB is always sent first.
104 ******************************************************************************/
105 void
106 formBlock
107 (
108 uint32_t *data,
109 uint32_t blockSize,
110 uint8_t *scratch
111 )
112 {
113 uint32_t i, j;
115 /* Convert the data to a byte stream */
116 for (i = j = 0; j < blockSize; i++, j+=4)
117 {
118 scratch[j+0] = (data[i] >> 24) & 0xff;
119 scratch[j+1] = (data[i] >> 16) & 0xff;
120 scratch[j+2] = (data[i] >> 8) & 0xff;
121 scratch[j+3] = (data[i] >> 0) & 0xff;
122 }
123 }
125 /******************************************************************************
126 * Function: flash_eeprom
127 *
128 * Write the data from memory to EEPROM.
129 * Returns TRUE if the data is written successfully
130 * FALSE if the data write fails
131 ******************************************************************************/
132 Bool
133 flash_eeprom
134 (
135 PLATFORM_DEVICE_info *p_device
136 )
137 {
138 uint8_t *scrach_block;
140 printf ("Writing %d bytes from DSP memory address 0x%08x to EEPROM bus address 0x%04x starting from device address 0x%04x ...\n",
141 eepromWriterInfo.writeBytes,
142 (uint32_t)eepromWriterInfo.writeData,
143 eepromWriterInfo.busAddr,
144 eepromWriterInfo.startAddr);
146 if (eepromWriterInfo.swapData)
147 {
148 scrach_block = malloc(eepromWriterInfo.deviceTotalBytes);
149 if (scrach_block == NULL)
150 {
151 printf ("Can not allocate scratch block memory!\n");
152 return (FALSE);
153 }
154 formBlock((uint32_t *)(eepromWriterInfo.writeData), eepromWriterInfo.deviceTotalBytes, scrach_block);
155 }
156 else
157 {
158 scrach_block = eepromWriterInfo.writeData;
159 }
161 if(platform_device_write(p_device->handle, eepromWriterInfo.startAddr, scrach_block, eepromWriterInfo.writeBytes) != Platform_EOK)
162 {
163 print_platform_errno();
164 if (eepromWriterInfo.swapData)
165 free (scrach_block);
166 return FALSE;
167 }
169 if(eepromWriterInfo.swapData)
170 free (scrach_block);
172 return TRUE;
173 }
175 /******************************************************************************
176 * Function: flash_verify
177 *
178 * Read back the data file that was just flashed.
179 * Returns TRUE if the data verified correctly.
180 * FALSE if the data verification failed
181 ******************************************************************************/
182 Bool
183 flash_verify
184 (
185 PLATFORM_DEVICE_info *p_device
186 )
187 {
188 uint32_t i, j;
189 uint8_t *scrach_block;
190 uint32_t *read_data_w;
192 printf ("Reading %d bytes from EEPROM bus address 0x%04x to DSP memory address 0x%08x starting from device address 0x%04x ...\n",
193 eepromWriterInfo.writeBytes,
194 eepromWriterInfo.busAddr,
195 (uint32_t)eepromWriterInfo.readData,
196 eepromWriterInfo.startAddr);
198 if (eepromWriterInfo.swapData)
199 {
200 scrach_block = malloc(eepromWriterInfo.deviceTotalBytes);
201 if (scrach_block == NULL)
202 {
203 printf ("Can not allocate scratch block memory!\n");
204 return (FALSE);
205 }
206 }
207 else
208 {
209 scrach_block = eepromWriterInfo.readData;
210 }
212 if(platform_device_read(p_device->handle, eepromWriterInfo.startAddr, scrach_block, eepromWriterInfo.writeBytes) != Platform_EOK)
213 {
214 print_platform_errno();
215 return FALSE;
216 }
218 printf ("Verifying data read ...\n");
220 if (eepromWriterInfo.swapData)
221 {
222 /* Convert the packed data */
223 read_data_w = (uint32_t *)(eepromWriterInfo.readData);
224 for (i = 0, j = 0; i < eepromWriterInfo.deviceTotalBytes; i += 4)
225 read_data_w[j++] = (scrach_block[i+0] << 24) | (scrach_block[i+1] << 16) | (scrach_block[i+2] << 8) | scrach_block[i+3];
226 }
229 for (i = 0; i < eepromWriterInfo.writeBytes; i++)
230 {
231 if (eepromWriterInfo.readData[i] != eepromWriterInfo.writeData[i])
232 {
233 printf ("Failure at byte %d, expected 0x%08x, read 0x%08x\n", i, eepromWriterInfo.writeData[i], eepromWriterInfo.readData[i]);
234 return (FALSE);
235 }
236 }
238 return (TRUE);
239 }
241 /******************************************************************************
242 * Function: parse_input_file
243 ******************************************************************************/
244 static Bool
245 parse_input_file
246 (
247 FILE* fp
248 )
249 {
250 char line[MAX_LINE_LENGTH];
251 char tokens[] = " :=;\n";
252 char *key, *data;
254 memset(line, 0, MAX_LINE_LENGTH);
256 fgets(line, MAX_LINE_LENGTH, fp);
257 key = (char *)strtok(line, tokens);
258 data = (char *)strtok(NULL, tokens);
260 if(strlen(data) == 0)
261 {
262 return FALSE;
263 }
265 if(strcmp(key, FILE_NAME) != 0)
266 {
267 return FALSE;
268 }
270 strcpy (eepromWriterInfo.file_name, data);
272 fgets(line, MAX_LINE_LENGTH, fp);
273 key = (char *)strtok(line, tokens);
274 data = (char *)strtok(NULL, tokens);
276 if(strlen(data) == 0)
277 {
278 return FALSE;
279 }
281 if(strcmp(key, BUS_ADDR) != 0)
282 {
283 return FALSE;
284 }
286 eepromWriterInfo.busAddr = (uint32_t)atoi(data);
288 fgets(line, MAX_LINE_LENGTH, fp);
289 key = (char *)strtok(line, tokens);
290 data = (char *)strtok(NULL, tokens);
292 if(strlen(data) == 0)
293 {
294 return FALSE;
295 }
297 if(strcmp(key, START_ADDR) != 0)
298 {
299 return FALSE;
300 }
302 eepromWriterInfo.startAddr = (uint32_t)atoi(data);
304 fgets(line, MAX_LINE_LENGTH, fp);
305 key = (char *)strtok(line, tokens);
306 data = (char *)strtok(NULL, tokens);
308 if(strlen(data) == 0)
309 {
310 return FALSE;
311 }
313 if(strcmp(key, SWAP_DATA) != 0)
314 {
315 return FALSE;
316 }
318 eepromWriterInfo.swapData = (uint32_t)atoi(data);
320 return TRUE;
321 }
323 /******************************************************************************
324 * Function: parse_ccs_file
325 ******************************************************************************/
326 static Bool
327 parse_ccs_file
328 (
329 FILE* fp
330 )
331 {
332 char line[MAX_LINE_LENGTH];
333 char *pEnd;
334 uint32_t data_len, write_addr;
336 memset(line, 0, MAX_LINE_LENGTH);
338 fgets(line, MAX_LINE_LENGTH, fp);
340 /* Read the write address from the CCS header */
341 strtoul (line,&pEnd,16);
342 strtoul (pEnd,&pEnd,16);
343 write_addr = strtoul (pEnd,&pEnd,16);
344 strtoul (pEnd,&pEnd,16);
346 /* Read the data length */
347 data_len = (strtoul (pEnd,NULL,16)) * 4;
348 if (data_len > (eepromWriterInfo.deviceTotalBytes - eepromWriterInfo.startAddr))
349 {
350 printf ("The data file is too big to fit into the device.\n");
351 return FALSE;
352 }
354 eepromWriterInfo.writeBytes = data_len;
355 if (write_addr != WRITE_DATA_ADDRESS)
356 write_addr = WRITE_DATA_ADDRESS;
357 eepromWriterInfo.writeData = (uint8_t *)write_addr;
358 eepromWriterInfo.readData = (uint8_t *)(write_addr + eepromWriterInfo.deviceTotalBytes);
360 return TRUE;
361 }
363 /******************************************************************************
364 * Function: main
365 ******************************************************************************/
366 void main ()
367 {
368 FILE *fp;
369 platform_init_flags init_flags;
370 platform_init_config init_config;
371 PLATFORM_DEVICE_info *p_device;
372 Bool ret;
374 printf("EEPROM Writer Utility Version %s\n\n", version);
376 fp = fopen(input_file, "r");
377 if (fp == NULL)
378 {
379 printf("Error in opening %s input file\n", input_file);
380 return;
381 }
383 ret = parse_input_file(fp);
384 fclose (fp);
386 if (ret == FALSE)
387 {
388 printf("Error in parsing %s input file\n", input_file);
389 return;
390 }
392 /* Initialize main Platform lib */
393 memset(&init_config, 0, sizeof(platform_init_config));
394 memset(&init_flags, 0x01, sizeof(platform_init_flags));
395 init_flags.phy = 0;
397 if (platform_init(&init_flags, &init_config) != Platform_EOK)
398 {
399 printf ("Platform init failed!\n");
400 print_platform_errno();
401 return;
402 }
404 p_device = platform_device_open(eepromWriterInfo.busAddr, 0);
405 if (p_device == NULL)
406 {
407 printf ("EEPROM device open failed!\n");
408 print_platform_errno();
409 return;
410 }
411 eepromWriterInfo.deviceTotalBytes = p_device->block_count * p_device->page_count * p_device->page_size;
413 /* Open and find the length of the data file */
414 fp = fopen (eepromWriterInfo.file_name, "rb");
415 if (fp == NULL)
416 {
417 printf ("Failed to open file %s\n", eepromWriterInfo.file_name);
418 print_platform_errno();
419 platform_device_close(p_device->handle);
420 return;
421 }
423 /* Parse the CCS format file */
424 ret = parse_ccs_file(fp);
425 fclose (fp);
426 if (ret == FALSE)
427 {
428 printf("Error in parsing CCS file %s\n", eepromWriterInfo.file_name);
429 platform_device_close(p_device->handle);
430 return;
431 }
433 /* Write the EEPROM */
434 if (flash_eeprom (p_device) == FALSE)
435 {
436 printf ("EEPROM write failed\n");
437 platform_device_close(p_device->handle);
438 return;
439 }
441 /* verify the flash */
442 if(flash_verify (p_device) == FALSE)
443 {
444 printf ("EEPROM read verify failed\n");
445 platform_device_close(p_device->handle);
446 return;
447 }
450 printf ("EEPROM programming completed successfully\n");
452 platform_device_close(p_device->handle);
454 return;
455 }