update to Platform Library 00.06: header file updates
[keystone-rtos/mcsdk-tools.git] / writer / qspi_flash / src / qspiflashwriter.c
1 /*\r
2  * Copyright (c) 2015, Texas Instruments Incorporated\r
3  * All rights reserved.\r
4  *\r
5  * Redistribution and use in source and binary forms, with or without\r
6  * modification, are permitted provided that the following conditions\r
7  * are met:\r
8  *\r
9  * *  Redistributions of source code must retain the above copyright\r
10  *    notice, this list of conditions and the following disclaimer.\r
11  *\r
12  * *  Redistributions in binary form must reproduce the above copyright\r
13  *    notice, this list of conditions and the following disclaimer in the\r
14  *    documentation and/or other materials provided with the distribution.\r
15  *\r
16  * *  Neither the name of Texas Instruments Incorporated nor the names of\r
17  *    its contributors may be used to endorse or promote products derived\r
18  *    from this software without specific prior written permission.\r
19  *\r
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,\r
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\r
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\r
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\r
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\r
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\r
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
31  *\r
32  */\r
33 \r
34 /**************************************************************************************\r
35  * FILE PURPOSE: QSPI Flash writer utility\r
36  **************************************************************************************\r
37  * FILE NAME: qspiflashwriter.c\r
38  *\r
39  * DESCRIPTION: A simple flash writer using platform lib APIs to program the\r
40  *              QSPI flash with an image that the ibl can read.\r
41  *\r
42  ***************************************************************************************/\r
43 #include <stdlib.h>\r
44 #include <stdio.h>\r
45 #include <string.h>\r
46 #include "platform.h"\r
47 #include "types.h"\r
48 \r
49 /* QSPI flash writer utility version */\r
50 char version[] = "01.00.00.00";\r
51 \r
52 /* The input file name is hard coded */\r
53 char *input_file = "qspi_flash_writer_input.txt";\r
54 \r
55 uint32_t swap_byte = 0;\r
56 \r
57 /* Parameters defined in the input_file */\r
58 #define FILE_NAME      "file_name"\r
59 #define START_ADDR     "start_addr"\r
60 \r
61 /* Memory address to store the write data */\r
62 #define WRITE_DATA_ADDRESS     0x80000000\r
63 \r
64 /******************************************************************************\r
65  * Structure:   QSPI_FLASH_WRITER_INFO_T\r
66  *\r
67  *              QSPI Flash writer control data. This structure should be\r
68  *              filled in by the user before running\r
69  ******************************************************************************/\r
70 #define MAX_LINE_LENGTH 40\r
71 typedef struct QSPI_FLASH_WRITER_INFO_tag\r
72 {\r
73     char        file_name[MAX_LINE_LENGTH]; /* CCS format data file name */\r
74     uint32_t    blockSizeBytes;             /* The size of each sector */\r
75     uint32_t    deviceTotalBytes;           /* Total number of bytes available in the device */\r
76     uint32_t    startAddr;                  /* Start address to write */\r
77     uint32_t    writeBytes;                 /* Number of bytes to be written into the device */\r
78     uint8_t     *writeData;                 /* Address to store the write data */\r
79     uint8_t     *readData;                  /* Address to store the read data */\r
80 \r
81 } QSPI_FLASH_WRITER_INFO_T;\r
82 \r
83 QSPI_FLASH_WRITER_INFO_T qspiFlashWriterInfo;\r
84 \r
85 /* OSAL functions for Platform Library */\r
86 uint8_t *Osal_platformMalloc (uint32_t num_bytes, uint32_t alignment)\r
87 {\r
88         return malloc(num_bytes);\r
89 }\r
90 \r
91 void Osal_platformFree (uint8_t *dataPtr, uint32_t num_bytes)\r
92 {\r
93     /* Free up the memory */\r
94     if (dataPtr)\r
95     {\r
96         free(dataPtr);\r
97     }\r
98 }\r
99 \r
100 void Osal_platformSpiCsEnter(void)\r
101 {\r
102     return;\r
103 }\r
104 \r
105 void Osal_platformSpiCsExit (void)\r
106 {\r
107     return;\r
108 }\r
109 \r
110 /******************************************************************************\r
111  * Function:    print_platform_errno\r
112  ******************************************************************************/\r
113 void\r
114 print_platform_errno\r
115 (\r
116     void\r
117 )\r
118 {\r
119     printf ("Returned platform error number is %d\n", platform_errno);\r
120 }\r
121 \r
122 /******************************************************************************\r
123  * Function:    formBlock\r
124  *\r
125  *      Form a block of data to write to the QSPI flash. The block is\r
126  *      created as a byte stream from the 4 byte stream in which\r
127  *      the MSB is always sent first.\r
128  ******************************************************************************/\r
129 void\r
130 formBlock\r
131 (\r
132     uint32_t      *data,\r
133     uint32_t      blockSize,\r
134     uint8_t       *scratch\r
135 )\r
136 {\r
137     uint32_t i, j;\r
138 \r
139     /* Convert the data to a byte stream */\r
140     for (i = j = 0; j < blockSize; i++, j+=4)\r
141     {\r
142         scratch[j+0] = (data[i] >> 24) & 0xff;\r
143         scratch[j+1] = (data[i] >> 16) & 0xff;\r
144         scratch[j+2] = (data[i] >>  8) & 0xff;\r
145         scratch[j+3] = (data[i] >>  0) & 0xff;\r
146     }\r
147 }\r
148 \r
149 /******************************************************************************\r
150  * Function:    write_qspi_flash\r
151  *\r
152  *              Write the image to flash.\r
153  *              Returns TRUE if the image is written successfully\r
154  *                      FALSE if the image write fails\r
155  ******************************************************************************/\r
156 Bool\r
157 write_qspi_flash\r
158 (\r
159     PLATFORM_DEVICE_info    *p_device\r
160 )\r
161 {\r
162     uint32_t      wPos, wLen;\r
163     uint32_t      block, start_block;\r
164     uint8_t       *scrach_block;\r
165 \r
166     if (swap_byte)\r
167     {\r
168         scrach_block = malloc(qspiFlashWriterInfo.blockSizeBytes);\r
169         if (scrach_block == NULL)\r
170         {\r
171             printf ("Can not allocate scratch block memory!\n");\r
172             return (FALSE);\r
173         }\r
174     }\r
175 \r
176     start_block = qspiFlashWriterInfo.startAddr / qspiFlashWriterInfo.blockSizeBytes;\r
177 \r
178     /* Program the QSPI flash */\r
179     for (block = start_block, wPos = 0; wPos < qspiFlashWriterInfo.writeBytes; block++, wPos += qspiFlashWriterInfo.blockSizeBytes)\r
180     {\r
181         printf ("Flashing sector %d (%d bytes of %d)\n", block, wPos, qspiFlashWriterInfo.writeBytes);\r
182 \r
183         wLen = qspiFlashWriterInfo.blockSizeBytes;\r
184         if ((qspiFlashWriterInfo.writeBytes - wPos) < qspiFlashWriterInfo.blockSizeBytes)\r
185         {\r
186             wLen = (qspiFlashWriterInfo.writeBytes - wPos);\r
187         }\r
188 \r
189         if (swap_byte)\r
190         {\r
191             formBlock((uint32_t *)(&qspiFlashWriterInfo.writeData[wPos]), wLen, scrach_block);\r
192         }\r
193         else\r
194         {\r
195             scrach_block = &qspiFlashWriterInfo.writeData[wPos];\r
196         }\r
197 \r
198         if (platform_device_write(p_device->handle,\r
199                                   (block * qspiFlashWriterInfo.blockSizeBytes),\r
200                                   scrach_block,\r
201                                   wLen) != Platform_EOK)\r
202         {\r
203             printf ("platform_device_write sector # %d failed!\n", block);\r
204             print_platform_errno();\r
205             if (swap_byte) free (scrach_block);\r
206             return (FALSE);\r
207         }\r
208     }\r
209 \r
210     if (swap_byte) free (scrach_block);\r
211     return (TRUE);\r
212 }\r
213 \r
214 /******************************************************************************\r
215  * Function:    flash_verify\r
216  *\r
217  *              Read back the data file that was just flashed.\r
218  *              Returns TRUE if the image verified correctly.\r
219  *                      FALSE if the image verification failed\r
220  ******************************************************************************/\r
221 Bool\r
222 flash_verify\r
223 (\r
224     PLATFORM_DEVICE_info    *p_device\r
225 )\r
226 {\r
227     uint32_t      rPos, rLen;\r
228     uint32_t      i, j;\r
229     uint32_t      block, start_block;\r
230     uint8_t       *scrach_block;\r
231     uint32_t      *read_data_w;\r
232 \r
233     if (swap_byte)\r
234     {\r
235         scrach_block = malloc(qspiFlashWriterInfo.blockSizeBytes);\r
236         if (scrach_block == NULL)\r
237         {\r
238             printf ("Can not allocate scratch block memory!\n");\r
239             return (FALSE);\r
240         }\r
241     }\r
242 \r
243     start_block = qspiFlashWriterInfo.startAddr / qspiFlashWriterInfo.blockSizeBytes;\r
244 \r
245     for (block = start_block, rPos = 0; rPos < qspiFlashWriterInfo.writeBytes; block++, rPos += qspiFlashWriterInfo.blockSizeBytes)\r
246     {\r
247         printf ("Reading and verifying sector %d (%d bytes of %d)\n", block, rPos, qspiFlashWriterInfo.writeBytes);\r
248 \r
249         if (!swap_byte)\r
250         {\r
251             scrach_block = &qspiFlashWriterInfo.readData[rPos];\r
252 \r
253         }\r
254 \r
255         /* Read a sector of data */\r
256         if(platform_device_read(p_device->handle,\r
257                                 (block * qspiFlashWriterInfo.blockSizeBytes),\r
258                                 scrach_block,\r
259                                 qspiFlashWriterInfo.blockSizeBytes) != Platform_EOK)\r
260         {\r
261             printf ("Failure in sector %d\n", block);\r
262             print_platform_errno();\r
263             if (swap_byte) free (scrach_block);\r
264             return (FALSE);\r
265         }\r
266 \r
267         /* Convert the packed data */\r
268         if (swap_byte)\r
269         {\r
270             read_data_w = (uint32_t *)(&qspiFlashWriterInfo.readData[rPos]);\r
271             for  (i = 0, j = 0; i < qspiFlashWriterInfo.blockSizeBytes; i += 4)\r
272             {\r
273                 read_data_w[j++] = (scrach_block[i+0] << 24) |\r
274                                    (scrach_block[i+1] << 16) |\r
275                                    (scrach_block[i+2] << 8)  |\r
276                                     scrach_block[i+3];\r
277                         }\r
278         }\r
279 \r
280         /* Read the data from the file */\r
281         rLen = qspiFlashWriterInfo.blockSizeBytes;\r
282         if ((qspiFlashWriterInfo.writeBytes - rPos) < qspiFlashWriterInfo.blockSizeBytes)\r
283         {\r
284             rLen = (qspiFlashWriterInfo.writeBytes - rPos);\r
285         }\r
286 \r
287         for (i = rPos; i < rLen; i++)\r
288         {\r
289             if (qspiFlashWriterInfo.readData[i] != qspiFlashWriterInfo.writeData[i])\r
290             {\r
291                 printf ("Failure in sector %d, at byte %d, (at byte %d in the data file) expected 0x%08x, read 0x%08x\n",\r
292                         block, i, rPos, qspiFlashWriterInfo.writeData[i], qspiFlashWriterInfo.readData[i]);\r
293                 if (swap_byte) free (scrach_block);\r
294                 return (FALSE);\r
295             }\r
296         }\r
297 \r
298     }\r
299 \r
300     if (swap_byte) free (scrach_block);\r
301     return (TRUE);\r
302 }\r
303 \r
304 /******************************************************************************\r
305  * Function:    parse_input_file\r
306  ******************************************************************************/\r
307 static Bool\r
308 parse_input_file\r
309 (\r
310     FILE*               fp\r
311 )\r
312 {\r
313     char line[MAX_LINE_LENGTH];\r
314     char tokens[] = " :=;\n\r";\r
315     char *key, *data;\r
316 \r
317     memset(line, 0, MAX_LINE_LENGTH);\r
318 \r
319     fgets(line, MAX_LINE_LENGTH, fp);\r
320     key  = (char *)strtok(line, tokens);\r
321     data = (char *)strtok(NULL, tokens);\r
322 \r
323     if(strlen(data) == 0)\r
324     {\r
325        return FALSE;\r
326     }\r
327 \r
328     if(strcmp(key, FILE_NAME) != 0)\r
329     {\r
330         return FALSE;\r
331     }\r
332 \r
333     strcpy (qspiFlashWriterInfo.file_name, data);\r
334 \r
335     fgets(line, MAX_LINE_LENGTH, fp);\r
336     key  = (char *)strtok(line, tokens);\r
337     data = (char *)strtok(NULL, tokens);\r
338 \r
339     if(strlen(data) == 0)\r
340     {\r
341        return FALSE;\r
342     }\r
343 \r
344     if(strcmp(key, START_ADDR) != 0)\r
345     {\r
346         return FALSE;\r
347     }\r
348 \r
349     qspiFlashWriterInfo.startAddr = (uint32_t)atoi(data);\r
350 \r
351     return TRUE;\r
352 }\r
353 \r
354 /******************************************************************************\r
355  * Function:    find_file_length\r
356  ******************************************************************************/\r
357 static Bool\r
358 find_file_length\r
359 (\r
360     FILE*               fp\r
361 )\r
362 {\r
363     char        line[MAX_LINE_LENGTH];\r
364     char        *pEnd;\r
365     char        *ext;\r
366     uint32_t    data_len, write_addr;\r
367 \r
368     memset(line, 0, MAX_LINE_LENGTH);\r
369 \r
370     ext = strrchr(qspiFlashWriterInfo.file_name, '.');\r
371 \r
372 \r
373     if (ext && (strcmp(ext, ".dat") == 0))\r
374     {\r
375     fgets(line, MAX_LINE_LENGTH, fp);\r
376 \r
377     /* Read the write address from the CCS header */\r
378     strtoul (line,&pEnd,16);\r
379     strtoul (pEnd,&pEnd,16);\r
380     write_addr = strtoul (pEnd,&pEnd,16);\r
381     strtoul (pEnd,&pEnd,16);\r
382 \r
383     /* Read the data length */\r
384     data_len = (strtoul (pEnd,NULL,16)) * 4;\r
385     }\r
386     else\r
387     {\r
388         /* find the data length by seeking to the end and getting position */\r
389         fseek(fp, 0, SEEK_END);\r
390         data_len = ftell(fp);\r
391         fseek(fp, 0, SEEK_SET);\r
392     }\r
393 \r
394     if (data_len > (qspiFlashWriterInfo.deviceTotalBytes - qspiFlashWriterInfo.startAddr))\r
395     {\r
396         printf ("The data file is too big to fit into the device.\n");\r
397         return FALSE;\r
398     }\r
399 \r
400     qspiFlashWriterInfo.writeBytes = data_len;\r
401     if (write_addr != WRITE_DATA_ADDRESS)\r
402         write_addr = WRITE_DATA_ADDRESS;\r
403     qspiFlashWriterInfo.writeData  = (uint8_t *)write_addr;\r
404     qspiFlashWriterInfo.readData   = (uint8_t *)(write_addr + qspiFlashWriterInfo.deviceTotalBytes);\r
405 \r
406     return TRUE;\r
407 }\r
408 \r
409 /******************************************************************************\r
410  * Function:    main\r
411  ******************************************************************************/\r
412 void main ()\r
413 {\r
414     FILE                    *fp;\r
415     platform_init_flags     init_flags;\r
416     platform_init_config    init_config;\r
417     PLATFORM_DEVICE_info    *p_device;\r
418     Bool                    ret;\r
419 \r
420     printf("QSPI Flash Writer Utility Version %s\n\n", version);\r
421 \r
422     fp = fopen(input_file, "r");\r
423     if (fp == NULL)\r
424     {\r
425         printf("Error in opening %s input file\n", input_file);\r
426         return;\r
427     }\r
428 \r
429     ret = parse_input_file(fp);\r
430     fclose (fp);\r
431 \r
432     if (ret == FALSE)\r
433     {\r
434         printf("Error in parsing %s input file\n", input_file);\r
435         return;\r
436     }\r
437 \r
438     /* Initialize main Platform lib */\r
439     memset(&init_config, 0, sizeof(platform_init_config));\r
440     memset(&init_flags, 1, sizeof(platform_init_flags));\r
441     init_flags.pll = 0;\r
442     init_flags.ddr = 0;\r
443     init_flags.phy = 0;\r
444     if (platform_init(&init_flags, &init_config) != Platform_EOK)\r
445     {\r
446         printf ("Platform init failed!\n");\r
447         print_platform_errno();\r
448         return;\r
449     }\r
450 \r
451     p_device = platform_device_open(PLATFORM_DEVID_QSPIFLASH_S25FL512S, 0);\r
452     if (p_device == NULL)\r
453     {\r
454         printf ("QSPI Flash device open failed!\n");\r
455         print_platform_errno();\r
456         return;\r
457     }\r
458     qspiFlashWriterInfo.deviceTotalBytes  = p_device->block_count * p_device->page_count * p_device->page_size;\r
459     qspiFlashWriterInfo.blockSizeBytes    = p_device->page_count * p_device->page_size;\r
460 \r
461     if ((qspiFlashWriterInfo.startAddr % qspiFlashWriterInfo.blockSizeBytes) != 0)\r
462     {\r
463         printf ("The start programming address 0x%8x set in %s is not at the beginning of a block, block size = 0x%4x\n",\r
464                 qspiFlashWriterInfo.startAddr,\r
465                 qspiFlashWriterInfo.file_name,\r
466                 qspiFlashWriterInfo.blockSizeBytes);\r
467         return;\r
468     }\r
469 \r
470     /* Open and find the length of the data file */\r
471     fp = fopen (qspiFlashWriterInfo.file_name, "rb");\r
472     if (fp == NULL)\r
473     {\r
474       printf ("Failed to open file %s\n", qspiFlashWriterInfo.file_name);\r
475       platform_device_close(p_device->handle);\r
476       return;\r
477     }\r
478 \r
479     /* Parse the CCS format file */\r
480     ret = find_file_length(fp);\r
481     fclose (fp);\r
482 \r
483     qspiFlashWriterInfo.writeBytes += qspiFlashWriterInfo.blockSizeBytes - 1;\r
484     qspiFlashWriterInfo.writeBytes -= qspiFlashWriterInfo.writeBytes % qspiFlashWriterInfo.blockSizeBytes;\r
485 \r
486     if (ret == FALSE)\r
487     {\r
488         printf("Error in parsing CCS file %s\n", qspiFlashWriterInfo.file_name);\r
489         platform_device_close(p_device->handle);\r
490         return;\r
491     }\r
492 \r
493     /* Write the flash */\r
494     if (write_qspi_flash (p_device) == FALSE)\r
495     {\r
496         printf ("QSPI Flash write failed\n");\r
497         platform_device_close(p_device->handle);\r
498         return;\r
499     }\r
500 \r
501     /* verify the flash */\r
502     if(flash_verify (p_device) == FALSE)\r
503     {\r
504         printf ("QSPI Flash read verify failed\n");\r
505         platform_device_close(p_device->handle);\r
506         return;\r
507     }\r
508 \r
509 \r
510     printf ("QSPI Flash programming completed successfully\n");\r
511 \r
512     platform_device_close(p_device->handle);\r
513 \r
514     return;\r
515 }\r
516 \r