1 /*********************************************************************
2  *
3  *   LPC ISP Commands for flash tool
4  *
5  *
6  * Written by Nathael Pajani <nathael.pajani@nathael.net>
7  *
8  * This programm is released under the terms of the GNU GPLv3 licence
9  * as can be found on the GNU website : <http://www.gnu.org/licenses/>
10  *
11  *********************************************************************/
13 #include <stdlib.h> /* strtoul */
14 #include <stdio.h> /* printf, snprintf */
15 #include <stdint.h>
16 #include <unistd.h>
17 #include <string.h> /* strncmp, memset */
18 #include <ctype.h>
19 #include <errno.h>
21 #include <unistd.h> /* for open, close */
22 #include <fcntl.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
26 #include "isp_utils.h"
27 #include "isp_commands.h"
28 #include "parts.h"
30 #define REP_BUFSIZE 40
32 extern int trace_on;
35 int get_ids(void)
36 {
37         int ret = 0;
39         isp_cmd_part_id(0);
40         isp_cmd_read_uid();
41         isp_cmd_boot_version();
43         return ret;
44 }
47 int dump_to_file(struct part_desc* part, char* filename)
48 {
49         int ret = 0, len = 0;
50         char* data;
52         /* Allocate buffer */
53         data = malloc(part->flash_size);
54         if (data == NULL) {
55                 printf("Unable to allocate read buffer, asked %u.\n", part->flash_size);
56                 return -10;
57         }
59         /* Read data */
60         len = isp_read_memory(data, part->flash_base, part->flash_size);
61         if (len != (int)(part->flash_size)) {
62                 printf("Read returned %d bytes instead of %u.\n", len, part->flash_size);
63         }
65         /* Write data to file */
66         ret = isp_buff_to_file(data, part->flash_size, filename);
68         /* Free memory */
69         free(data);
71         return ret;
72 }
75 int erase_flash(struct part_desc* part)
76 {
77         int ret = 0;
78         int i = 0;
80         /* Unlock device */
81         ret = isp_cmd_unlock(1);
82         if (ret != 0) {
83                 printf("Unable to unlock device, aborting.\n");
84                 return -1;
85         }
87         for (i=0; i<(int)(part->flash_nb_sectors); i++) {
88                 ret = isp_send_cmd_sectors("blank-check", 'I', i, i, 1);
89                 if (ret == CMD_SUCCESS) {
90                         /* sector already blank, preserve the flash, skip to next one :) */
91                         continue;
92                 }
93                 if (ret < 0) {
94                         /* Error ? */
95                         printf("Initial blank check error (%d) at sector %d!\n", ret, i);
96                         return ret;
97                 } else {
98                         /* Controller replyed with first non blank offset and data, remove it from buffer */
99                         char buf[REP_BUFSIZE];
100                         usleep( 5000 ); /* Some devices are slow to scan flash, give them some time */
101                         isp_serial_read(buf, REP_BUFSIZE, 3);
102                 }
103                 /* Sector not blank, perform erase */
104                 ret = isp_send_cmd_sectors("prepare-for-write", 'P', i, i, 1);
105                 if (ret != 0) {
106                         printf("Error (%d) when trying to prepare sector %d for erase operation!\n", ret, i);
107                         return ret;
108                 }
109                 ret = isp_send_cmd_sectors("erase", 'E', i, i, 1);
110                 if (ret != 0) {
111                         printf("Error (%d) when trying to erase sector %d!\n", ret, i);
112                         return ret;
113                 }
114         }
115         printf("Flash now all blank.\n");
117         return 0;
120 int start_prog(struct part_desc* part)
122         int ret = 0, len = 0;
123         uint32_t addr = 0;
125         len = isp_read_memory((char*)&addr, (part->flash_base + part->reset_vector_offset), sizeof(addr));
126         if (len != sizeof(addr)) {
127                 printf("Unable to read reset address from flash.\n");
128                 return len;
129         }
130         /* FIXME : the following value (0x200) may be LPC111x specific */
131         if (addr < 0x200) {
132                 printf("Actual reset address is 0x%08x, which is under the lowest allowed address of 0x200.\n", addr);
133         }
134         /* Unlock device */
135         ret = isp_cmd_unlock(1);
136         if (ret != 0) {
137                 printf("Unable to unlock device, aborting.\n");
138                 return -1;
139         }
140         /* Read address in thumb or arm mode ? */
141         if (addr & 0x01) {
142                 addr &= ~1UL;
143                 ret = isp_send_cmd_go(addr, 'T');
144         } else {
145                 ret = isp_send_cmd_go(addr, 'A');
146         }
148         /* FIXME : start terminal */
150         return ret;
154 static unsigned int calc_write_size(unsigned int sector_size, unsigned int ram_buff_size)
156         unsigned int write_size = 0;
158         write_size = ((sector_size < ram_buff_size) ? sector_size : ram_buff_size);
159         /* According to section 21.5.7 of LPC11xx user's manual (UM10398), number of bytes
160          * written should be 256 | 512 | 1024 | 4096 */
161         if (write_size >= 4096) {
162                 write_size = 4096;
163         } else if (write_size >= 1024) {
164                 write_size = 1024;
165         } else if (write_size >= 512) {
166                 write_size = 512;
167         } else if (write_size >= 256) {
168                 write_size = 256;
169         } else if (write_size >= 64) {
170                 write_size = 64;
171         } else {
172                 write_size = 0;
173         }
174         return write_size;
177 int flash_target(struct part_desc* part, char* filename, int calc_user_code)
179         int ret = 0;
180         char* data = NULL;
181         int size = 0;
182         int i = 0, blocks = 0;
183         unsigned int write_size = 0;
184         unsigned int sector_size = (part->flash_size / part->flash_nb_sectors);
185         uint32_t ram_addr = (part->ram_base + part->ram_buff_offset);
186         uint32_t uuencode = part->uuencode;
187         uint32_t* v = NULL; /* Used for checksum computing */
188         uint32_t cksum = 0;
190         /**  Sanity checks  *********************************/
191         /* RAM buffer address within RAM */
192         if (ram_addr > (part->ram_base + part->ram_size)) {
193                 printf("Invalid configuration, asked to use buffer out of RAM, aborting.\n");
194                 return -1;
195         }
196         /* Calc write block size */
197         write_size = calc_write_size(sector_size, part->ram_buff_size);
198         if (write_size == 0) {
199                 printf("Config error, I cannot flash using blocks of nul size !\nAborted.\n");
200                 return -2;
201         }
203         /* Just make sure flash is erased */
204         ret = erase_flash(part);
205         if (ret != 0) {
206                 printf("Unable to erase device, aborting.\n");
207                 return -3;
208         }
210         /* Allocate a buffer as big as the flash */
211         data = malloc(part->flash_size);
212         if (data == NULL) {
213                 printf("Unable to get a buffer to load the image!");
214                 return -4;
215         }
216         /* And fill the buffer with the image */
217         size = isp_file_to_buff(data, part->flash_size, filename);
218         if (size <= 0){
219                 free(data);
220                 return -5;
221         }
222         /* Fill unused buffer with 0's so we can flash blocks of data of "write_size" */
223         memset(&data[size], 0, (part->flash_size - size));
224         /* And check checksum of first 7 vectors if asked, according to section 21.3.3 of
225          * LPC11xx user's manual (UM10398) */
226         v = (uint32_t *)data;
227         cksum = 0 - v[0] - v[1] - v[2] - v[3] - v[4] - v[5] - v[6];
228         if (calc_user_code == 1) {
229                 v[7] = cksum;
230         } else if (cksum != v[7]) {
231                 printf("Checksum is 0x%08x, should be 0x%08x\n", cksum, v[7]);
232                 free(data);
233                 return -5;
234         }
235         printf("Checksum check OK\n");
237         blocks = (size / write_size) + ((size % write_size) ? 1 : 0);
238         /* Gonna write out of flash ? */
239         if ((blocks * write_size) > part->flash_size) {
240                 printf("Config error, I cannot flash beyond end of flash !\n");
241                 printf("Flash size : %d, trying to flash %d blocks of %d bytes : %d\n",
242                                 part->flash_size, blocks, write_size, (blocks * write_size));
243                 free(data);
244                 return -6;
245         }
246         printf("Flash size : %d, trying to flash %d blocks of %d bytes : %d\n",
247                         part->flash_size, blocks, write_size, (blocks * write_size));
249         /* Now flash the device */
250         printf("Writing started, %d blocks of %d bytes ...\n", blocks, write_size);
251         for (i=0; i<blocks; i++) {
252                 unsigned int current_sector = (i * write_size) / sector_size;
253                 uint32_t flash_addr = part->flash_base + (i * write_size);
254                 /* Prepare sector for writting (must be done before each write) */
255                 ret = isp_send_cmd_sectors("prepare-for-write", 'P', current_sector, current_sector, 1);
256                 if (ret != 0) {
257                         printf("Error (%d) when trying to prepare sector %d for erase operation!\n", ret, i);
258                         free(data);
259                         return ret;
260                 }
261                 /* Send data to RAM */
262                 ret = isp_send_buf_to_ram(&data[i * write_size], ram_addr, write_size, uuencode);
263                 if (ret != 0) {
264                         printf("Unable to perform write-to-ram operation for block %d (block size: %d)\n",
265                                         i, write_size);
266                         free(data);
267                         return ret;
268                 }
269                 /* Copy from RAM to FLASH */
270                 ret = isp_send_cmd_address('C', flash_addr, ram_addr, write_size, "write_to_ram");
271                 if (ret != 0) {
272                         printf("Unable to copy data to flash for block %d (block size: %d)\n", i, write_size);
273                         free(data);
274                         return ret;
275                 }
276         }
278         free(data);
279         return ret;