bootloader: print version 2.0
[nios2ecos.git] / bootloader / bootloader / bootloader.c
blobe7575975c32e3297623ca03eb00ceeb195b9baaa
1 //========================================================================
2 // ####ECOSGPLCOPYRIGHTBEGIN####
3 // -------------------------------------------
4 // This file is part of eCos, the Embedded Configurable Operating System.
5 // Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
6 //
7 // eCos is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU General Public License as published by the Free
9 // Software Foundation; either version 2 or (at your option) any later
10 // version.
12 // eCos is distributed in the hope that it will be useful, but WITHOUT
13 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 // for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with eCos; if not, write to the Free Software Foundation, Inc.,
19 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 // As a special exception, if other files instantiate templates or use
22 // macros or inline functions from this file, or you compile this file
23 // and link it with other works to produce a work based on this file,
24 // this file does not by itself cause the resulting work to be covered by
25 // the GNU General Public License. However the source code for this file
26 // must still be made available in accordance with section (3) of the GNU
27 // General Public License v2.
29 // This exception does not invalidate any other reasons why a work based
30 // on this file might be covered by the GNU General Public License.
31 // -------------------------------------------
32 // ####ECOSGPLCOPYRIGHTEND####
33 //========================================================================
35 #include <cyg/hal/io.h>
36 #include <cyg/hal/system.h>
38 #include <sys/stat.h>
39 #include <cyg/io/serialio.h>
41 #include <cyg/compress/zlib.h>
43 #include <cyg/firmwareutil/firmwareutil.h>
45 #include "addresses.h"
46 #include "bootloader.h"
48 /* nios2-gdb-server will go ga-ga when we invoke the remote
49 * update stuff, disable while debugging */
50 #define DEBUG_NO_RESET() 0
52 #define UNCACHED_EXT_FLASH_BASE (0x80000000 + EXT_FLASH_BASE)
54 static FILE *ser_fp;
56 /* naive conversion of \n to \r\n for serial terminal */
57 static void report_info(void *data, const char * format, va_list args)
59 char buffer[1024];
60 vsnprintf(buffer, sizeof(buffer), format, args);
61 int i;
62 for (i = 0; i < strlen(buffer); i++)
64 if (buffer[i] == '\n')
66 fprintf(ser_fp, "\r");
68 fprintf(ser_fp, "%c", buffer[i]);
72 struct cyg_upgrade_info bootloader =
74 (cyg_uint8 *)UNCACHED_EXT_FLASH_BASE,
75 "/ram/bootloader.phi",
76 "Bootloader",
77 FACTORY_FPGA_OFFSET,
78 APPLICATION_FPGA_OFFSET - FACTORY_FPGA_OFFSET,
79 "ZylinNiosBootloader\n",
80 report_info
83 struct cyg_upgrade_info firmware =
85 (cyg_uint8 *)UNCACHED_EXT_FLASH_BASE,
86 "/ram/firmware.phi",
87 "Firmware",
88 APPLICATION_FPGA_OFFSET,
89 JFFS2_OFFSET - APPLICATION_FPGA_OFFSET,
90 "ZylinNiosFirmware\n",
91 report_info
95 static char IP_FILE[] = "/config/ip";
96 static const int WRITE_BUF_SIZE = 4096;
97 static char WRITE_BUF[WRITE_BUF_SIZE];
99 int ser = -1;
101 void cleaning()
103 fclose(ser_fp);
104 close(ser);
106 /* 1000ms is necessary to let everything "calm down" */
107 cyg_thread_delay(100);
110 bool getChar(char *key)
112 fd_set rfds;
113 int retval;
115 /* Watch stdin (fd 0) to see when it has input. */
116 FD_ZERO(&rfds);
117 FD_SET(ser, &rfds);
119 retval = select(1, &rfds, NULL, NULL, NULL);
120 /* Don't rely on the value of tv now! */
121 if (retval)
123 if (FD_ISSET(ser, &rfds))
125 if (read(ser, key, 1) == 1)
127 return true;
131 return false;
134 bool waitChar1(int seconds, char *key)
136 fd_set rfds;
137 struct timeval tv;
138 int retval;
139 static char chr[1024];
141 /* Watch stdin (fd 0) to see when it has input. */
142 FD_ZERO(&rfds);
143 FD_SET(ser, &rfds);
144 /* Wait this long seconds. */
145 tv.tv_sec = seconds;
146 tv.tv_usec = 0;
148 retval = select(1, &rfds, NULL, NULL, &tv);
149 /* Don't rely on the value of tv now! */
150 if (retval)
152 if (FD_ISSET(ser, &rfds))
153 { // linux, for win see getChar
154 if (read(ser, chr, 1024) > 0)
156 *key = chr[0];
157 return true;
160 return true;
164 return false;
167 bool waitChar(int seconds, char *key)
169 fd_set rfds;
170 struct timeval tv;
171 int retval;
173 /* Watch stdin (fd 0) to see when it has input. */
174 FD_ZERO(&rfds);
175 FD_SET(ser, &rfds);
177 /* Wait this long seconds. */
178 tv.tv_sec = seconds;
179 tv.tv_usec = 0;
181 retval = select(1, &rfds, NULL, NULL, seconds > 0 ? &tv : NULL);
182 /* Don't rely on the value of tv now! */
183 if (retval)
185 if (FD_ISSET(ser, &rfds))
187 if (read(ser, key, 1) == 1)
189 return true;
193 return false;
196 void reset(void)
198 fprintf(ser_fp, "Resetting\r\n");
199 umount("/config");
200 cleaning();
201 #if DEBUG_NO_RESET()
202 /* DEBUG: should have reconfigured here, disabled to make debugging easier.
203 * We no longer have serial output capability */
204 for (;;);
205 #else
206 IOWR(REMOTE_UPDATE_BASE, 0x20, 0x1);
207 #endif
210 void openSerial()
212 ser = open(UART_0_NAME, O_RDWR|O_SYNC|O_NONBLOCK);
213 if (ser < 0)
215 diag_printf("Error: serial device problems %s\r\n", UART_0_NAME);
216 reset();
219 ser_fp = fdopen(ser, "r+");
221 if (ser_fp == NULL)
223 diag_printf("Error: serial device problems %s\r\n", UART_0_NAME);
224 reset();
229 /* Try to mount jffs2, if it fails print error message and return.
230 * Failing is "normal" in that formatting jffs2 might fix it for
231 * instance.
233 void mountJFFS2()
235 Cyg_ErrNo err = 0;
236 err = cyg_flash_init(NULL);
237 if (err)
239 fprintf(ser_fp, "Error: could not init flash\r\n");
240 return;
243 cyg_flashaddr_t err_address;
245 #ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
246 if ((err = flash_unlock((void *) UNCACHED_EXT_FLASH_BASE, EXT_FLASH_SPAN,
247 (void **) &err_address)) != 0)
249 fprintf(ser_fp, "Error: could not unlock flash\r\n");
250 return;
252 #endif
254 if ((err = mount(CYGDAT_IO_FLASH_BLOCK_DEVICE_NAME_1, "/config", "jffs2")) < 0)
256 fprintf(ser_fp, "Error: could not mount flash %d\r\n", err);
257 return;
261 /* mount ramfs, print error message and return in case of error.
263 * This fn can not really fail, except if we run out of memory. */
264 void mountRamFS()
266 Cyg_ErrNo err = 0;
268 if ((err = mount("", "/ram", "ramfs")) < 0)
270 fprintf(ser_fp, "Error: could not mount RAMFS %d\r\n", err);
271 return;
275 /* erase all sectors in this address range */
276 static void flash_erase_range(void *address, int length)
278 int stat;
279 void *err_addr;
281 if ((stat = flash_init(0)) != 0)
283 fprintf(ser_fp, "Error: %s\r\n", "Initializing flash failed");
284 reset();
287 #ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
288 if ((stat = flash_unlock((void *) UNCACHED_EXT_FLASH_BASE, EXT_FLASH_SPAN,
289 (void **) &err_addr)) != 0)
291 fprintf(ser_fp, "Error: %s\r\n", "Unlocking flash failed");
292 reset();
294 #endif
296 fprintf(ser_fp, "Erasing flash at %p, 0x%08x bytes\r\n", address, length);
297 if ((stat = flash_erase((void *)address, length,
298 (void **) &err_addr)) != 0)
300 fprintf(ser_fp, "Error: %s\r\n", "Erasing flash failed");
301 reset();
306 /* Format jffs2 area and reset */
307 void format(void)
309 fprintf(ser_fp, "Formatting JFFS2...\r\n");
311 flash_erase_range((void *)(UNCACHED_EXT_FLASH_BASE + JFFS2_OFFSET), JFFS2_LENGTH);
313 fprintf(ser_fp, "/config formatted successfully\r\n");
314 reset();
317 int firmwareFile;
319 // Read a string in from serial port and reset if
320 // anything goes wrong.
321 static void readLine(char *buffer,
322 // Including terminating \0
323 int maxLen)
325 int index = 0;
326 for (;;)
328 char c = 0;
329 getChar(&c);
330 switch (c)
332 case 0x3:
333 fprintf(ser_fp, "%s\r\n", "\r\nCtrl-c pressed");
334 reset();
335 case '\n':
336 case '\r':
337 if (index == 0)
339 fprintf(ser_fp, "%s\r\n", "\r\nEmpty string not allowed");
340 reset();
342 buffer[index] = '\0';
343 fprintf(ser_fp, "\r\n");
344 return;
345 // backspace
346 case 0x08:
347 if (index > 0)
349 index--;
350 fprintf(ser_fp, "%c %c", c, c);
352 break;
353 default:
354 if (index >= (maxLen - 1))
356 fprintf(ser_fp, "%s\r\n", "\r\nString too long");
357 reset();
359 fprintf(ser_fp, "%c", c);
360 buffer[index] = c;
361 index++;
362 break;
367 static void getFileName(char *name, int maxLen)
369 readLine(name, maxLen);
372 /* write config file based on 0 terminated string */
373 static void writeFile(const char *fileName, const char *string)
375 if (strlen(string) == 0)
377 unlink(fileName);
379 else
381 int fd = creat(fileName, O_CREAT | O_TRUNC);
382 if (fd < 0)
384 fprintf(ser_fp, "unable to create %s\r\n", fileName);
386 else
388 write(fd, string, strlen(string));
389 close(fd);
394 static void enterParameter()
396 char name[81];
397 char param[128];
398 //get IP
399 fprintf(ser_fp, "Enter file name: ");
400 readLine(name, sizeof(name));
401 fprintf(ser_fp, "Enter parameter: ");
402 readLine(param, sizeof(param));
403 writeFile(name, param);
407 static void showParameter()
409 char name[81];
410 //get IP
411 fprintf(ser_fp, "Enter filename: ");
412 readLine(name, sizeof(name));
414 int param;
415 if ((param = open(name, O_RDONLY)) < 0)
417 fprintf(ser_fp, "Could not open %s\r\n", name);
418 return;
421 fprintf(ser_fp, "Displaying up to 1024 bytes of that parameter\r\n");
422 for (int i = 0; i < 1024; i++)
424 char c;
425 int actual;
426 actual = read(param, &c, 1);
427 if (actual < 0)
429 fprintf(ser_fp, "\r\nFailed while reading %s", name);
430 reset();
432 if (actual != 1)
433 break;
434 fprintf(ser_fp, "%c", c);
436 fprintf(ser_fp, "\r\n");
437 close(param);
441 static void wrongMAC()
443 fprintf(ser_fp, "Error: wrong MAC address syntax\r\n");
444 reset();
447 static void transformMacAddress(char* buffer, cyg_uint8 mac_addr[6])
449 memset(mac_addr, 0, 6);
451 if (strlen(buffer) != 12)
453 wrongMAC();
456 for (size_t i = 0; i < strlen(buffer); i++)
458 char c = toupper(buffer[i]);
459 if ('0' <= c && c <= '9')
461 cyg_uint8 val = c - '0';
462 mac_addr[i / 2] += (val << (4 * ((i + 1) % 2)));
464 else
465 if ('A' <= c && c <= 'F')
467 cyg_uint8 val = c - 'A' + 10;
468 mac_addr[i / 2] += (val << (4 * ((i + 1) % 2)));
470 else
472 wrongMAC();
477 static cyg_uint8 * const macAddr = (cyg_uint8 *) (UNCACHED_EXT_FLASH_BASE + FACTORY_FPGA_OFFSET - 6);
478 static const int macAddrLen = 6;
480 static bool hasMacAddress()
482 cyg_uint8 ret = 0xFF;
483 for(int i = 0; i < macAddrLen; i++)
485 ret = ret & macAddr[i];
487 return ret != 0xFF;
490 static void printMACAddress()
492 if (hasMacAddress())
494 cyg_uint8* mac = (cyg_uint8 *) (UNCACHED_EXT_FLASH_BASE + FACTORY_FPGA_OFFSET - 6);
495 fprintf(ser_fp, "Mac address %02x:%02x:%02x:%02x:%02x:%02x\r\n", mac[0],
496 mac[1], mac[2], mac[3], mac[4], mac[5]);
498 else
500 fprintf(ser_fp, "Mac address not set\r\n");
504 static void changeMac(void)
506 char mac[13];
507 cyg_uint8 ui_mac[6];
509 fprintf(ser_fp, "Enter the mac address in the format XXXXXXXXXXXX\r\n");
510 readLine(mac, sizeof(mac));
512 transformMacAddress(mac, ui_mac);
513 fprintf(ser_fp, "New MAC address: %02x:%02x:%02x:%02x:%02x:%02x\r\n", ui_mac[0],
514 ui_mac[1], ui_mac[2], ui_mac[3], ui_mac[4], ui_mac[5]);
516 int stat;
517 void *err_addr;
519 #ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
520 if ((stat = flash_unlock((void *) macAddr, macAddrLen,
521 (void **) &err_addr)) != 0)
523 fprintf(ser_fp, "Error: %s\r\n", "Unlocking flash failed");
524 reset();
526 #endif
528 if ((stat = flash_erase((void *) (macAddr), macAddrLen, (void **) &err_addr)) != 0)
530 fprintf(ser_fp, "Error: %s\r\n", "Erasing flash failed");
531 reset();
533 printf("erasing done\n");
535 if ((stat = FLASH_PROGRAM(macAddr, ui_mac, macAddrLen, (void **)&err_addr))
536 != 0)
538 fprintf(ser_fp, "Error: %s\r\n", "Programming flash failed");
539 reset();
544 static void changeIP()
546 char ip[81];
547 //get IP
548 fprintf(ser_fp,
549 "\r\nEnter ip, mask and gateway(optional) (x.x.x.x,y.y.y.y[,z.z.z.z]):\r\n");
550 readLine(ip, sizeof(ip));
551 writeFile(IP_FILE, ip);
552 reset();
556 /* load app into ram and run it. The application will need
557 * a memory independent piece of code to begin with that
558 * can be used to launch itself.
560 static void runfile(const char *name)
562 struct stat results;
563 if (stat(name, &results) != 0)
565 fprintf(ser_fp, "Error: could not get length of file");
566 reset();
569 int runfile_fd;
570 if ((runfile_fd = open(name, O_RDONLY)) <= 0)
572 fprintf(ser_fp, "Error: failed to open file");
573 reset();
575 void * mem = malloc(results.st_size);
576 if(mem == NULL)
578 fprintf(ser_fp, "Error: out of memory");
579 reset();
582 read(runfile_fd, mem, results.st_size);
584 cyg_interrupt_disable();
585 ((void(*)(void)) (mem))();
586 for (;;)
590 /* never reached */
594 static void ymodemUpload(const char *fileName)
596 int err = 0;
598 fprintf(ser_fp, "Start Ymodem upload of %s\r\n", fileName);
600 connection_info_t connection;
601 memset(&connection, 0, sizeof(connection));
602 connection.mode = xyzModem_ymodem;
604 fprintf(ser_fp, "Connection over %s\r\n", fileName);
606 if (xyzModem_stream_open(&connection, &err) != 0)
608 fprintf(ser_fp, "Could not open Ymodem connection %d\r\n", err);
609 reset();
612 firmwareFile = creat(fileName, O_TRUNC | O_CREAT);
613 if (firmwareFile < 0)
615 // close yModem connection so we can see error message in HyperTerminal
616 int moreError;
617 xyzModem_stream_close(&moreError);
618 fprintf(ser_fp, "Error: could not create firmware file\r\n");
619 reset();
622 bool ok = false;
623 bool abortedByWrite = false;
625 /* make sure we don't write too small blocks as this will
626 * increase memory usage catastrophically when reading the file
628 int actual;
629 int pos = 0;
630 for (;;)
632 err = 0;
633 actual = xyzModem_stream_read(WRITE_BUF + pos, sizeof(WRITE_BUF)
634 - pos, &err);
635 if (actual < 0)
637 break;
639 pos += actual;
641 /* avoid lots of tiny writes, by flushing 0x100 bytes from
642 * end of buffer */
643 if (((actual == 0) && (pos > 0)) || (pos > (WRITE_BUF_SIZE - 0x100)))
645 int written = write(firmwareFile, WRITE_BUF, pos);
646 if (written < pos)
648 fprintf(ser_fp, "Writing %s failed\r\n", fileName);
649 abortedByWrite = true;
650 break;
652 pos = 0;
655 if (actual == 0)
657 break;
661 int moreError;
662 xyzModem_stream_close(&moreError);
664 if ((!abortedByWrite) && (actual == 0) && (err == 0))
666 fprintf(ser_fp, "\r\nYmodem transfer complete\r\n");
667 ok = true;
670 close(firmwareFile);
672 if (!ok)
674 remove(fileName);
675 if (!abortedByWrite)
677 fprintf(ser_fp, "\r\nFirmware upload failed: %s\r\n", xyzModem_error(err));
678 reset();
683 void printAvailableRAM()
685 struct mallinfo info;
686 info = mallinfo();
687 fprintf(ser_fp, "Available RAM: %d\r\n", info.fordblks);
690 static void set115200(void)
692 cyg_serial_baud_rate_t baud;
693 baud = CYGNUM_SERIAL_BAUD_115200;
695 cyg_serial_info_t buf;
696 cyg_uint32 len;
697 //get existing serial configuration
698 len = sizeof(cyg_serial_info_t);
699 int err;
700 cyg_io_handle_t serial_handle;
702 err = cyg_io_lookup(UART_0_NAME, &serial_handle);
703 if (err != ENOERR)
705 fprintf(ser_fp, "Error: could not get port handle\r\n");
706 return;
709 err = cyg_io_get_config(serial_handle,
710 CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN, &buf, &len);
711 err = cyg_io_get_config(serial_handle, CYG_IO_GET_CONFIG_SERIAL_INFO, &buf,
712 &len);
713 if (err != ENOERR)
715 fprintf(ser_fp, "Error: could not get port settings\r\n");
716 return;
718 buf.baud = baud;
720 err = cyg_io_set_config(serial_handle, CYG_IO_SET_CONFIG_SERIAL_INFO, &buf,
721 &len);
722 if (err != ENOERR)
724 fprintf(ser_fp, "Error: could not set baud rate\r\n");
725 return;
730 void menu(void)
732 char fileName[NAME_MAX];
733 int waiting;
735 /* 2.x is the major revision. Use build date to distinguish between minor
736 * version differences.
738 fprintf(ser_fp, "Bootloader 2.0.\r\nCopyright FSF 2006-2010 All rights reserved\r\n");
739 fprintf(ser_fp, "eCos license (GPL with exception)\r\n");
740 fprintf(ser_fp, "Build date %s %s\r\n", __DATE__, __TIME__);
742 mountJFFS2();
743 mountRamFS();
745 printMACAddress();
747 start_menu:
748 waiting = 5;
750 fprintf(ser_fp, "Press <space> for advanced help\r\n");
751 if (hasMacAddress())
753 fprintf(ser_fp, "Press <i> to set static IP address\r\n");
754 fprintf(ser_fp, "Press <enter> to start Ymodem upload of firmware\r\n");
756 else
758 fprintf(ser_fp, "Press <m> to set MAC address\r\n");
761 //use default firmware file name
762 strcpy(fileName, firmware.file);
763 char key;
764 /* 5 second wait is a wee bit long here for normal execution,
765 * but it makes the bootloader a lot easier to use and debug
767 waitMoreChar: if (waitChar(waiting, &key))
769 switch (key)
771 case 'F':
772 format();
773 /* never reached */
774 break;
775 case 'i':
776 case 'I':
777 changeIP();
778 /* never reached */
779 break;
780 case 'P':
781 enterParameter();
782 goto start_menu;
783 case 'D':
784 showParameter();
785 goto start_menu;
786 case 'B':
787 set115200();
788 goto waitMoreChar;
789 case 'X':
790 fprintf(ser_fp, "Erasing MAC address...");
791 flash_erase_range(macAddr, macAddrLen);
792 fprintf(ser_fp, "done\r\n");
793 goto start_menu;
794 case 'U':
795 fprintf(ser_fp, "File name: ");
796 getFileName(fileName, sizeof(fileName));
797 ymodemUpload(fileName);
798 goto start_menu;
799 case '\r':
800 fprintf(ser_fp, "Default firmware file update\r\n");
801 ymodemUpload(firmware.file);
802 cyg_firmware_upgrade(NULL, firmware);
803 reset();
804 break;
805 case 'Y':
806 fprintf(ser_fp, "Single shot bootloader update\r\n");
807 ymodemUpload(bootloader.file);
808 cyg_firmware_upgrade(NULL, bootloader);
809 reset();
810 break;
811 case 'E':
812 fprintf(ser_fp, "Upload and run file from RAM\r\n");
813 ymodemUpload("/ram/run");
814 runfile("/ram/run");
815 break;
816 case 'R':
817 reset();
818 break;
819 case ' ':
820 fprintf(ser_fp, "\r\nAdvanced menu:\r\n\r\n");
821 fprintf(ser_fp, "Press <F> format flash\r\n");
822 fprintf(ser_fp,
823 "Press <U> to start Ymodem upload of a file to a specified file name\r\n");
824 fprintf(ser_fp, "Press <E> execute file from RAM\r\n");
825 fprintf(ser_fp, "Press <Y> start single shot update of bootloader\r\n");
826 fprintf(ser_fp, "Press <P> set parameter\r\n");
827 fprintf(ser_fp, "Press <D> show parameter\r\n");
828 fprintf(ser_fp, "Press <B> set 115200 serial speed\r\n");
829 fprintf(ser_fp, "Press <X> erase MAC address\r\n");
830 fprintf(ser_fp, "Press <R> reset\r\n");
831 fprintf(ser_fp, "Press <C> continue\r\n");
832 waiting = 0;
833 goto waitMoreChar;
835 default:
836 /* ignore unknown keys... */
837 break;
840 /* FIX!!!! we should only be able to change mac address if we don't
841 * have one already.
843 if(!hasMacAddress())
845 if ((key == 'M') || (key == 'm'))
847 changeMac();
852 if (!hasMacAddress())
854 /* do not allow running application without mac address */
855 fprintf(ser_fp, "Error: MAC address not set\r\n");
856 reset();
859 umount("/config");
860 umount("/ram");
863 /********************************************************************************
864 * Function: CycloneIII_Reconfig
865 * Purpose: Uses the ALT_REMOTE_UPDATE megafunction to reconfigure a Cyclone III FPGA.
866 * Parameters:
867 * remote_update_base - base address of the remote update controller
868 * flash_base - base address of flash device
869 * reconfig_offset - offset in flash from which to reconfigure
870 * watchdog_timeout - 29-bit watchdog timeout value
871 * width_of_flash - data-width of flash device
872 * Returns: 0 ( but never exits since it reconfigures the FPGA )
873 ****************************************************************************/
874 void CycloneIIIReconfig(int remote_update_base, int flash_base,
875 int reconfig_offset, int watchdog_timeout, int width_of_flash)
877 int offset_shift, addr;
878 int tmp;
879 // Obtain upper 12 bits of 29-bit watchdog timeout value
880 watchdog_timeout = watchdog_timeout >> 17;
881 // Only enable the watchdog timer if its timeout value is greater than 0.
882 if (watchdog_timeout > 0)
884 // Set the watchdog timeout value
885 IOWR( remote_update_base, 0x2, watchdog_timeout );
887 else
889 // Disable the watchdog timer
890 IOWR( remote_update_base, 0x3, 0 );
893 tmp = IORD( remote_update_base, 0x0 );
895 tmp = IORD( remote_update_base, 0xF );
897 // Calculate how much to shift the reconfig offset location:
898 // width_of_flash == 8->offset_shift = 2.
899 // width_of_flash == 16->offset_shift = 3
900 offset_shift = ((width_of_flash / 8) + 1);
901 // Write the offset of the desired reconfiguration image in flash
902 IOWR( remote_update_base, 0x4, reconfig_offset >> offset_shift );
904 addr = IORD( remote_update_base, 0x4);
905 // Perform the reconfiguration by setting bit 0 in the
906 // control/status register
907 IOWR( remote_update_base, 0x20, 0x1 );
910 int needReset()
912 int tmp = IORD(REMOTE_UPDATE_BASE, 0x0);
913 return !tmp;
916 int main()
918 openSerial();
920 #if DEBUG_NO_RESET()
921 menu();
922 /* DEBUG: should have reconfigured here, disabled to make debugging easier.
923 * We no longer have serial output capability */
924 for (;;);
925 #else
926 if (needReset())
928 menu();
930 fprintf(ser_fp, "Start application image\r\n");
931 cleaning();
932 CycloneIIIReconfig(REMOTE_UPDATE_BASE, UNCACHED_EXT_FLASH_BASE,
933 APPLICATION_FPGA_OFFSET, 0, 16);
935 #endif
936 fprintf(ser_fp, "Jump to application\r\n");
937 cleaning();
938 cyg_interrupt_disable();
939 ((void(*)(void)) (UNCACHED_EXT_FLASH_BASE + APPLICATION_OFFSET))();
940 for (;;)
941 ; // never reached