upload_mcs.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2009-2010, Willow Garage, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * Neither the name of the Willow Garage nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *********************************************************************/
34 
35 // Author: Blaise Gassend
36 
37 #include <assert.h>
38 #include <iostream>
39 #include <fstream>
40 #include <memory> // for std::auto_ptr
41 
42 #include <string.h> // for memset(3)
43 #include <stdlib.h> // for atoi(3)
44 
45 #include <ros/time.h>
46 
50 
51 #include <boost/format.hpp>
52 
53 // We are assuming that the firmware will fit in the first half of the
54 // pages. This may not turn out to be true later...
55 #define FLASH_SIZE (FLASH_PAGE_SIZE * (FLASH_MAX_PAGENO + 1) / 2)
57 int firmwarelen = 0;
58 
59 int hexval(char c)
60 {
61  assert(isxdigit(c));
62 
63  if (isdigit(c))
64  return c - '0';
65  if (isupper(c))
66  return c - 'A' + 10;
67  if (islower(c))
68  return c - 'a' + 10;
69 
70  return 0;
71 }
72 
73 int read_mcs(std::string fname)
74 {
75  memset(firmware, 0xFF, FLASH_SIZE);
76  firmwarelen = 0;
77  std::ifstream file;
78  file.open(fname.c_str());
79  std::auto_ptr<std::vector<uint8_t> > data;
80  int curseg = -1; // This will work for the forearm camera, but will break for larger address spaces.
81  int linenum = 0;
82 
83  if (!file.is_open())
84  {
85  fprintf(stderr, "Failed to open file %s\n", fname.c_str());
86  return -1;
87  }
88 
89  while (!file.eof())
90  {
91  linenum++;
92  char line[100];
93  file.getline(line, sizeof(line));
94  unsigned char *curchar = (unsigned char *)line;
95 
96  if (*curchar++ != ':')
97  {
98  fprintf(stderr, "Line %i did not start with a colon.\n", linenum);
99  return -1;
100  }
101 
102  // Declare bytes as int to avoid casting later.
103  int bytes[100]; // Big enough because the line is only 100 characters.
104  int bytecount = 0;
105  unsigned char checksum = 0;
106 
107  while (isxdigit(curchar[0]) && isxdigit(curchar[1]))
108  {
109  bytes[bytecount] = 16 * hexval(*curchar++);
110  bytes[bytecount] += hexval(*curchar++);
111  checksum += bytes[bytecount++];
112  }
113 
114  while (*curchar && isspace(*curchar))
115  curchar++;
116 
117  if (*curchar)
118  {
119  fprintf(stderr, "Unexpected character 0x%02X at end of line %i.\n",
120  (int) *curchar, linenum);
121  return -1;
122  }
123 
124  /*for (int i = 0; i < bytecount; i++)
125  printf("%02X ", bytes[i]);
126  printf("\n");*/
127 
128  if (bytecount < 5)
129  {
130  fprintf(stderr, "Line %i was too short (%i < 5).\n", linenum, bytecount);
131  return -1;
132  }
133 
134  int len = bytes[0];
135 
136  if (len != bytecount - 5)
137  {
138  fprintf(stderr, "Line %i contained %i bytes, but reported %i bytes.\n",
139  linenum, bytecount, bytes[0]);
140  return -1;
141  }
142 
143  int addr = (bytes[1] << 8) + bytes[2];
144 
145  switch (bytes[3])
146  {
147  case 0: // Data
148  if (curseg + addr != firmwarelen)
149  {
150  fprintf(stderr, "Non contiguous address (%08x != %08x), line %i\n",
151  curseg + addr, firmwarelen, linenum);
152  return -1;
153  }
154  if (curseg + addr + len >= FLASH_SIZE)
155  {
156  fprintf(stderr, "Exceeded reserved flash size (note: upload_mcs code can be edited to allow larger values) at line %i.\n", linenum);
157  return -1;
158  }
159  for (int i = 0; i < len; i++)
160  firmware[firmwarelen++] = bytes[i + 4];
161  break;
162 
163  case 1: // EOF
164  while (true)
165  {
166  char c;
167  file.get(c);
168  if (file.eof())
169  return 0;
170  if (!isspace(c))
171  {
172  fprintf(stderr, "EOF record on line %i was followed by character %02X.\n",
173  linenum, (int) c);
174  return -1;
175  }
176  }
177 
178  case 4: // Extended address record
179  if (len != 2)
180  {
181  fprintf(stderr, "Extended record had wrong length (%i != 2) on line %i\n",
182  len, linenum);
183  return -1;
184  }
185  curseg = ((bytes[4] << 8) + bytes[5]) << 16;
186  break;
187 
188  default:
189  fprintf(stderr, "Unknown record type %i at line %i.\n", bytes[3], linenum);
190  return -1;
191  }
192  }
193 
194  fprintf(stderr, "Unexpected EOF after line %i.\n", linenum);
195  return -1;
196 }
197 
198 // For a serial flash, the bits in each byte need to be swapped around.
199 void bitswap()
200 {
201  // Precompute bit-swap table
202  uint8_t swapped[256];
203 
204  for (int i = 0; i < 256; i++)
205  {
206  uint8_t shift = i;
207  swapped[i] = 0;
208  for (int j = 0; j < 8; j++)
209  {
210  swapped[i] = (swapped[i] << 1) | (shift & 1);
211  shift >>= 1;
212  }
213  }
214 
215  // Bit-swap the whole firmware.
216  for (int i = 0; i < FLASH_SIZE; i++)
217  firmware[i] = swapped[firmware[i]];
218 }
219 
220 int write_flash(char *camera_url)
221 {
222  IpCamList camera;
223  const char *errmsg;
224 
225  fprintf(stderr, "Searching for camera: %s", camera_url);
226  for (int i = 0; i < 5; i++)
227  {
228  fprintf(stderr, ".");
229  int outval = wge100FindByUrl(camera_url, &camera, SEC_TO_USEC(0.1), &errmsg);
230  if (!outval)
231  {
232  fprintf(stderr, "\n");
233  goto found;
234  }
235  sleep(1);
236  }
237 
238  fprintf(stderr, "\nMatching URL %s : %s\n", camera_url, errmsg);
239  return -1;
240 found:
241 
242  // Configure the camera with its IP address, wait up to 500ms for completion
243  int retval = wge100Configure(&camera, camera.ip_str, SEC_TO_USEC(0.5));
244  if (retval != 0) {
245  if (retval == ERR_CONFIG_ARPFAIL) {
246  fprintf(stderr, "Unable to create ARP entry (are you root?), continuing anyway\n");
247  } else {
248  fprintf(stderr, "IP address configuration failed\n");
249  return -1;
250  }
251  }
252 
253  if ( wge100TriggerControl( &camera, TRIG_STATE_INTERNAL ) != 0) {
254  fprintf(stderr, "Could not communicate with camera after configuring IP. Is ARP set? Is %s accessible from %s?\n", camera.ip_str, camera.ifName);
255  return -1;
256  }
257 
258  fprintf(stderr, "******************************************************************\n");
259  fprintf(stderr, "Firmware file parsed successfully. Will start writing to flash in 5 seconds.\n");
260  fprintf(stderr, "Make sure that no other software is accessing the camera during reflashing.\n");
261  fprintf(stderr, "Hit CTRL+C to abort now.\n");
262  fprintf(stderr, "******************************************************************\n");
263  sleep(5);
264 
265  fprintf(stderr, "Writing to flash. DO NOT ABORT OR TURN OFF CAMERA!!\n");
266 
267  unsigned char buff[FLASH_PAGE_SIZE];
268 
269  for (int page = 0; page < (firmwarelen + FLASH_PAGE_SIZE - 1) / FLASH_PAGE_SIZE;
270  page++)
271  {
272  if (page % 100 == 0)
273  {
274  fprintf(stderr, ".");
275  fflush(stderr);
276  }
277 
278  int addr = page * FLASH_PAGE_SIZE;
279  int startretries = 10;
280  int retries = startretries;
281 
282  if (wge100ReliableFlashWrite(&camera, page, (uint8_t *) firmware + addr, &retries) != 0)
283  {
284  fprintf(stderr, "\nFlash write error on page %i.\n", page);
285  fprintf(stderr, "If you reset the camera it will probably not come up.\n");
286  fprintf(stderr, "Try reflashing NOW, to possibly avoid a hard JTAG reflash.\n");
287  fprintf(stderr, "Be sure that you are not streaming images. Reflash will not\n");
288  fprintf(stderr, "work while streaming.\n");
289  return -2;
290  }
291 
292  if (retries < startretries)
293  {
294  fprintf(stderr, "x(%i)\n", startretries - retries);
295  }
296  }
297 
298  fprintf(stderr, "\n");
299 
300  fprintf(stderr, "Verifying flash.\n");
301 
302  for (int page = 0; page < (firmwarelen + FLASH_PAGE_SIZE - 1) / FLASH_PAGE_SIZE;
303  page++)
304  {
305  int addr = page * FLASH_PAGE_SIZE;
306  if (page % 100 == 0)
307  {
308  fprintf(stderr, ".");
309  fflush(stderr);
310  }
311 
312  if (wge100ReliableFlashRead(&camera, page, (uint8_t *) buff, NULL) != 0)
313  {
314  fprintf(stderr, "\nFlash read error on page %i.\n", page);
315  fprintf(stderr, "If you reset the camera it will probably not come up.\n");
316  fprintf(stderr, "Try reflashing NOW, to possibly avoid a hard JTAG reflash.\n");
317  return -2;
318  }
319 
320  if (memcmp(buff, (uint8_t *) firmware + addr, FLASH_PAGE_SIZE))
321  {
322  fprintf(stderr, "\nFlash compare error on page %i.\n", page);
323  fprintf(stderr, "If you reset the camera it will probably not come up.\n");
324  fprintf(stderr, "Try reflashing NOW, to possibly avoid a hard JTAG reflash.\n");
325  return -3;
326  }
327  }
328  fprintf(stderr, "\n");
329 
330  fprintf(stderr, "Success! Restarting camera, should take about 10 seconds to come back up after this.\n");
331 
332  wge100ReconfigureFPGA(&camera);
333 
334  return 0;
335 }
336 
337 int main(int argc, char **argv)
338 {
339  if ((argc != 3 && argc != 2) || !strcmp(argv[1], "--help")) {
340  fprintf(stderr, "Usage: %s <file.mcs> <camera_url>\n", argv[0]);
341  fprintf(stderr, " %s <file.mcs> > dump.bin\n", argv[0]);
342  fprintf(stderr, "Reads a .mcs file and uploads it to the camera or dumps it as binary to stdout.\n");
343  return -1;
344  }
345 
346  if (read_mcs(argv[1]))
347  return -1;
348 
349  if (firmware[4] == 0x55)
350  bitswap();
351  else if (firmware[4] != 0xaa)
352  {
353  fprintf(stderr, "Unexpected value at position 4. Don't know whether to bit-swap.\n");
354  return -1;
355  }
356 
357  if (argc == 2)
358  {
359  fwrite(firmware, FLASH_SIZE, 1, stdout);
360  return 0;
361  }
362 
363  char* camera_url = argv[2];
364 
365  int retval = 1;
366  const int max_retries = 5;
367  for (int i = 0; i < max_retries; i++)
368  {
369  retval = -write_flash(camera_url);
370  if (!retval)
371  break;
372  fprintf(stderr, "\nUpload failed. Retrying... %u/%u\n\n", i+1, max_retries);
373  sleep(1);
374  }
375 
376  return retval;
377 }
#define FLASH_PAGE_SIZE
Definition: ipcam_packet.h:60
int firmwarelen
Definition: upload_mcs.cpp:57
int wge100ReliableFlashRead(const IpCamList *camInfo, uint32_t address, uint8_t *pageDataOut, int *retries)
Definition: wge100lib.c:906
int wge100ReliableFlashWrite(const IpCamList *camInfo, uint32_t address, const uint8_t *pageDataIn, int *retries)
Definition: wge100lib.c:1014
int main(int argc, char **argv)
Definition: upload_mcs.cpp:337
#define TRIG_STATE_INTERNAL
Definition: wge100lib.h:58
int wge100Configure(IpCamList *camInfo, const char *ipAddress, unsigned wait_us)
Definition: wge100lib.c:532
#define ERR_CONFIG_ARPFAIL
Definition: wge100lib.h:116
data
uint8_t firmware[FLASH_SIZE]
Definition: upload_mcs.cpp:56
uint16_t checksum(uint16_t *data)
#define SEC_TO_USEC(sec)
Definition: host_netutil.h:65
int wge100FindByUrl(const char *url, IpCamList *camera, unsigned wait_us, const char **errmsg)
Definition: wge100lib.c:94
char ip_str[16]
Definition: list.h:296
int wge100TriggerControl(const IpCamList *camInfo, uint32_t triggerType)
Definition: wge100lib.c:1135
int read_mcs(std::string fname)
Definition: upload_mcs.cpp:73
int hexval(char c)
Definition: upload_mcs.cpp:59
#define FLASH_SIZE
Definition: upload_mcs.cpp:55
char ifName[128]
Definition: list.h:293
int wge100ReconfigureFPGA(IpCamList *camInfo)
Definition: wge100lib.c:750
void bitswap()
Definition: upload_mcs.cpp:199
int write_flash(char *camera_url)
Definition: upload_mcs.cpp:220


wge100_camera
Author(s): Blaise Gassend, Patrick Mihelich, Eric MacIntosh, David Palchak
autogenerated on Mon Jun 10 2019 15:44:15