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.
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
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
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>
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)
56 /* naive conversion of \n to \r\n for serial terminal */
57 static void report_info(void *data
, const char * format
, va_list args
)
60 vsnprintf(buffer
, sizeof(buffer
), format
, args
);
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",
78 APPLICATION_FPGA_OFFSET
- FACTORY_FPGA_OFFSET
,
79 "ZylinNiosBootloader\n",
83 struct cyg_upgrade_info firmware
=
85 (cyg_uint8
*)UNCACHED_EXT_FLASH_BASE
,
88 APPLICATION_FPGA_OFFSET
,
89 JFFS2_OFFSET
- APPLICATION_FPGA_OFFSET
,
90 "ZylinNiosFirmware\n",
95 static char IP_FILE
[] = "/config/ip";
96 static const int WRITE_BUF_SIZE
= 4096;
97 static char WRITE_BUF
[WRITE_BUF_SIZE
];
106 /* 1000ms is necessary to let everything "calm down" */
107 cyg_thread_delay(100);
110 bool getChar(char *key
)
115 /* Watch stdin (fd 0) to see when it has input. */
119 retval
= select(1, &rfds
, NULL
, NULL
, NULL
);
120 /* Don't rely on the value of tv now! */
123 if (FD_ISSET(ser
, &rfds
))
125 if (read(ser
, key
, 1) == 1)
134 bool waitChar1(int seconds
, char *key
)
139 static char chr
[1024];
141 /* Watch stdin (fd 0) to see when it has input. */
144 /* Wait this long seconds. */
148 retval
= select(1, &rfds
, NULL
, NULL
, &tv
);
149 /* Don't rely on the value of tv now! */
152 if (FD_ISSET(ser
, &rfds
))
153 { // linux, for win see getChar
154 if (read(ser
, chr
, 1024) > 0)
167 bool waitChar(int seconds
, char *key
)
173 /* Watch stdin (fd 0) to see when it has input. */
177 /* Wait this long seconds. */
181 retval
= select(1, &rfds
, NULL
, NULL
, seconds
> 0 ? &tv
: NULL
);
182 /* Don't rely on the value of tv now! */
185 if (FD_ISSET(ser
, &rfds
))
187 if (read(ser
, key
, 1) == 1)
198 fprintf(ser_fp
, "Resetting\r\n");
202 /* DEBUG: should have reconfigured here, disabled to make debugging easier.
203 * We no longer have serial output capability */
206 IOWR(REMOTE_UPDATE_BASE
, 0x20, 0x1);
212 ser
= open(UART_0_NAME
, O_RDWR
|O_SYNC
|O_NONBLOCK
);
215 diag_printf("Error: serial device problems %s\r\n", UART_0_NAME
);
219 ser_fp
= fdopen(ser
, "r+");
223 diag_printf("Error: serial device problems %s\r\n", UART_0_NAME
);
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
236 err
= cyg_flash_init(NULL
);
239 fprintf(ser_fp
, "Error: could not init flash\r\n");
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");
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
);
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. */
268 if ((err
= mount("", "/ram", "ramfs")) < 0)
270 fprintf(ser_fp
, "Error: could not mount RAMFS %d\r\n", err
);
275 /* erase all sectors in this address range */
276 static void flash_erase_range(void *address
, int length
)
281 if ((stat
= flash_init(0)) != 0)
283 fprintf(ser_fp
, "Error: %s\r\n", "Initializing flash failed");
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");
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");
306 /* Format jffs2 area and reset */
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");
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
333 fprintf(ser_fp
, "%s\r\n", "\r\nCtrl-c pressed");
339 fprintf(ser_fp
, "%s\r\n", "\r\nEmpty string not allowed");
342 buffer
[index
] = '\0';
343 fprintf(ser_fp
, "\r\n");
350 fprintf(ser_fp
, "%c %c", c
, c
);
354 if (index
>= (maxLen
- 1))
356 fprintf(ser_fp
, "%s\r\n", "\r\nString too long");
359 fprintf(ser_fp
, "%c", c
);
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)
381 int fd
= creat(fileName
, O_CREAT
| O_TRUNC
);
384 fprintf(ser_fp
, "unable to create %s\r\n", fileName
);
388 write(fd
, string
, strlen(string
));
394 static void enterParameter()
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()
411 fprintf(ser_fp
, "Enter filename: ");
412 readLine(name
, sizeof(name
));
415 if ((param
= open(name
, O_RDONLY
)) < 0)
417 fprintf(ser_fp
, "Could not open %s\r\n", name
);
421 fprintf(ser_fp
, "Displaying up to 1024 bytes of that parameter\r\n");
422 for (int i
= 0; i
< 1024; i
++)
426 actual
= read(param
, &c
, 1);
429 fprintf(ser_fp
, "\r\nFailed while reading %s", name
);
434 fprintf(ser_fp
, "%c", c
);
436 fprintf(ser_fp
, "\r\n");
441 static void wrongMAC()
443 fprintf(ser_fp
, "Error: wrong MAC address syntax\r\n");
447 static void transformMacAddress(char* buffer
, cyg_uint8 mac_addr
[6])
449 memset(mac_addr
, 0, 6);
451 if (strlen(buffer
) != 12)
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)));
465 if ('A' <= c
&& c
<= 'F')
467 cyg_uint8 val
= c
- 'A' + 10;
468 mac_addr
[i
/ 2] += (val
<< (4 * ((i
+ 1) % 2)));
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
];
490 static void printMACAddress()
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]);
500 fprintf(ser_fp
, "Mac address not set\r\n");
504 static void changeMac(void)
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]);
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");
528 if ((stat
= flash_erase((void *) (macAddr
), macAddrLen
, (void **) &err_addr
)) != 0)
530 fprintf(ser_fp
, "Error: %s\r\n", "Erasing flash failed");
533 printf("erasing done\n");
535 if ((stat
= FLASH_PROGRAM(macAddr
, ui_mac
, macAddrLen
, (void **)&err_addr
))
538 fprintf(ser_fp
, "Error: %s\r\n", "Programming flash failed");
544 static void changeIP()
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
);
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
)
563 if (stat(name
, &results
) != 0)
565 fprintf(ser_fp
, "Error: could not get length of file");
570 if ((runfile_fd
= open(name
, O_RDONLY
)) <= 0)
572 fprintf(ser_fp
, "Error: failed to open file");
575 void * mem
= malloc(results
.st_size
);
578 fprintf(ser_fp
, "Error: out of memory");
582 read(runfile_fd
, mem
, results
.st_size
);
584 cyg_interrupt_disable();
585 ((void(*)(void)) (mem
))();
594 static void ymodemUpload(const char *fileName
)
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
);
612 firmwareFile
= creat(fileName
, O_TRUNC
| O_CREAT
);
613 if (firmwareFile
< 0)
615 // close yModem connection so we can see error message in HyperTerminal
617 xyzModem_stream_close(&moreError
);
618 fprintf(ser_fp
, "Error: could not create firmware file\r\n");
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
633 actual
= xyzModem_stream_read(WRITE_BUF
+ pos
, sizeof(WRITE_BUF
)
641 /* avoid lots of tiny writes, by flushing 0x100 bytes from
643 if (((actual
== 0) && (pos
> 0)) || (pos
> (WRITE_BUF_SIZE
- 0x100)))
645 int written
= write(firmwareFile
, WRITE_BUF
, pos
);
648 fprintf(ser_fp
, "Writing %s failed\r\n", fileName
);
649 abortedByWrite
= true;
662 xyzModem_stream_close(&moreError
);
664 if ((!abortedByWrite
) && (actual
== 0) && (err
== 0))
666 fprintf(ser_fp
, "\r\nYmodem transfer complete\r\n");
677 fprintf(ser_fp
, "\r\nFirmware upload failed: %s\r\n", xyzModem_error(err
));
683 void printAvailableRAM()
685 struct mallinfo info
;
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
;
697 //get existing serial configuration
698 len
= sizeof(cyg_serial_info_t
);
700 cyg_io_handle_t serial_handle
;
702 err
= cyg_io_lookup(UART_0_NAME
, &serial_handle
);
705 fprintf(ser_fp
, "Error: could not get port handle\r\n");
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
,
715 fprintf(ser_fp
, "Error: could not get port settings\r\n");
720 err
= cyg_io_set_config(serial_handle
, CYG_IO_SET_CONFIG_SERIAL_INFO
, &buf
,
724 fprintf(ser_fp
, "Error: could not set baud rate\r\n");
732 char fileName
[NAME_MAX
];
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__
);
750 fprintf(ser_fp
, "Press <space> for advanced help\r\n");
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");
758 fprintf(ser_fp
, "Press <m> to set MAC address\r\n");
761 //use default firmware file name
762 strcpy(fileName
, firmware
.file
);
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
))
790 fprintf(ser_fp
, "Erasing MAC address...");
791 flash_erase_range(macAddr
, macAddrLen
);
792 fprintf(ser_fp
, "done\r\n");
795 fprintf(ser_fp
, "File name: ");
796 getFileName(fileName
, sizeof(fileName
));
797 ymodemUpload(fileName
);
800 fprintf(ser_fp
, "Default firmware file update\r\n");
801 ymodemUpload(firmware
.file
);
802 cyg_firmware_upgrade(NULL
, firmware
);
806 fprintf(ser_fp
, "Single shot bootloader update\r\n");
807 ymodemUpload(bootloader
.file
);
808 cyg_firmware_upgrade(NULL
, bootloader
);
812 fprintf(ser_fp
, "Upload and run file from RAM\r\n");
813 ymodemUpload("/ram/run");
820 fprintf(ser_fp
, "\r\nAdvanced menu:\r\n\r\n");
821 fprintf(ser_fp
, "Press <F> format flash\r\n");
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");
836 /* ignore unknown keys... */
840 /* FIX!!!! we should only be able to change mac address if we don't
845 if ((key
== 'M') || (key
== 'm'))
852 if (!hasMacAddress())
854 /* do not allow running application without mac address */
855 fprintf(ser_fp
, "Error: MAC address not set\r\n");
863 /********************************************************************************
864 * Function: CycloneIII_Reconfig
865 * Purpose: Uses the ALT_REMOTE_UPDATE megafunction to reconfigure a Cyclone III FPGA.
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
;
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
);
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 );
912 int tmp
= IORD(REMOTE_UPDATE_BASE
, 0x0);
922 /* DEBUG: should have reconfigured here, disabled to make debugging easier.
923 * We no longer have serial output capability */
930 fprintf(ser_fp
, "Start application image\r\n");
932 CycloneIIIReconfig(REMOTE_UPDATE_BASE
, UNCACHED_EXT_FLASH_BASE
,
933 APPLICATION_FPGA_OFFSET
, 0, 16);
936 fprintf(ser_fp
, "Jump to application\r\n");
938 cyg_interrupt_disable();
939 ((void(*)(void)) (UNCACHED_EXT_FLASH_BASE
+ APPLICATION_OFFSET
))();