// License: BSD
#include <stdio.h>
+#include <stdint.h>
#include <console.h>
#include <uart.h>
#include <system.h>
#include <net/tftp.h>
#endif
+#ifdef CSR_SPIFLASH_BASE
+#include <spiflash.h>
+#endif
+
#include "sfl.h"
#include "boot.h"
return ACK_TIMEOUT;
}
+static uint32_t get_uint32(unsigned char* data)
+{
+ return ((uint32_t) data[0] << 24) |
+ ((uint32_t) data[1] << 16) |
+ ((uint32_t) data[2] << 8) |
+ (uint32_t) data[3];
+}
+
#define MAX_FAILED 5
/* Returns 1 if other boot methods should be tried */
char *writepointer;
failed = 0;
- writepointer = (char *)(
- ((unsigned long)frame.payload[0] << 24)
- |((unsigned long)frame.payload[1] << 16)
- |((unsigned long)frame.payload[2] << 8)
- |((unsigned long)frame.payload[3] << 0));
+ writepointer = (char *) get_uint32(&frame.payload[0]);
for(i=4;i<frame.length;i++)
*(writepointer++) = frame.payload[i];
if (frame.cmd == SFL_CMD_LOAD)
break;
}
case SFL_CMD_JUMP: {
- unsigned long addr;
+ uint32_t addr;
failed = 0;
- addr = ((unsigned long)frame.payload[0] << 24)
- |((unsigned long)frame.payload[1] << 16)
- |((unsigned long)frame.payload[2] << 8)
- |((unsigned long)frame.payload[3] << 0);
+ addr = get_uint32(&frame.payload[0]);
uart_write(SFL_ACK_SUCCESS);
boot(0, 0, 0, addr);
break;
}
+ case SFL_CMD_FLASH: {
+#if (defined CSR_SPIFLASH_BASE && defined SPIFLASH_PAGE_SIZE)
+ uint32_t addr;
+
+ failed = 0;
+ addr = get_uint32(&frame.payload[0]);
+
+ for (i = 4; i < frame.length; i++) {
+ // erase page at sector boundaries before writing
+ if ((addr & (SPIFLASH_SECTOR_SIZE - 1)) == 0) {
+ erase_flash_sector(addr);
+ }
+ write_to_flash(addr, &frame.payload[i], 1);
+ addr++;
+ }
+ uart_write(SFL_ACK_SUCCESS);
+#endif
+ break;
+ }
+ case SFL_CMD_REBOOT:
+#ifdef CSR_CTRL_BASE
+ uart_write(SFL_ACK_SUCCESS);
+ ctrl_reset_write(1);
+#endif
+ break;
default:
failed++;
if(failed == MAX_FAILED) {
sfl_cmd_load = b"\x01"
sfl_cmd_load_no_crc = b"\x03"
sfl_cmd_jump = b"\x02"
+sfl_cmd_flash = b"\x04"
+sfl_cmd_reboot = b"\x05"
# Replies
sfl_ack_success = b"K"
class LiteXTerm:
- def __init__(self, serial_boot, kernel_image, kernel_address, json_images, no_crc):
+ def __init__(self, serial_boot, kernel_image, kernel_address, json_images, no_crc, flash):
self.serial_boot = serial_boot
assert not (kernel_image is not None and json_images is not None)
self.mem_regions = {}
self.boot_address = self.mem_regions[list(self.mem_regions.keys())[-1]]
f.close()
self.no_crc = no_crc
+ self.flash = flash
+ self.ignore_download = False
self.reader_alive = False
self.writer_alive = False
f.seek(0, 2)
length = f.tell()
f.seek(0, 0)
- print("[LXTERM] Uploading {} to 0x{:08x} ({} bytes)...".format(filename, address, length))
- current_address = address
+ if self.flash:
+ print("[LXTERM] Flashing {} ({} bytes)...".format(filename, length))
+ current_address = 0
+ else:
+ print("[LXTERM] Uploading {} to 0x{:08x} ({} bytes)...".format(filename, address, length))
+ current_address = address
position = 0
start = time.time()
remaining = length
sys.stdout.flush()
frame = SFLFrame()
frame_data = f.read(min(remaining, sfl_payload_length))
- frame.cmd = sfl_cmd_load if not self.no_crc else sfl_cmd_load_no_crc
+ if self.flash:
+ frame.cmd = sfl_cmd_flash
+ else:
+ frame.cmd = sfl_cmd_load if not self.no_crc else sfl_cmd_load_no_crc
frame.payload = current_address.to_bytes(4, "big")
frame.payload += frame_data
if self.send_frame(frame) == 0:
frame.payload = int(self.boot_address, 16).to_bytes(4, "big")
self.send_frame(frame)
+ def reboot(self):
+ print("[LXTERM] Rebooting the device.")
+ frame = SFLFrame()
+ frame.cmd = sfl_cmd_reboot
+ self.send_frame(frame)
+
def detect_prompt(self, data):
if len(data):
self.prompt_detect_buffer = self.prompt_detect_buffer[1:] + data
return False
def answer_magic(self):
+ if self.ignore_download:
+ self.ignore_download = False
+ return
print("[LXTERM] Received firmware download request from the device.")
if(len(self.mem_regions)):
self.port.write(sfl_magic_ack)
for filename, base in self.mem_regions.items():
self.upload(filename, int(base, 16))
- self.boot()
+ if self.flash:
+ # ignore next download request to do a reboot to the flashed image
+ self.ignore_download = True
+ self.reboot()
+ else:
+ self.boot()
print("[LXTERM] Done.");
def reader(self):
parser.add_argument("--kernel-adr", default="0x40000000", help="kernel address")
parser.add_argument("--images", default=None, help="json description of the images to load to memory")
parser.add_argument("--no-crc", default=False, action='store_true', help="disable CRC check (speedup serialboot)")
+ parser.add_argument("--flash", default=False, action='store_true', help="flash data with serialboot command")
return parser.parse_args()
def main():
args = _get_args()
- term = LiteXTerm(args.serial_boot, args.kernel, args.kernel_adr, args.images, args.no_crc)
+ term = LiteXTerm(args.serial_boot, args.kernel, args.kernel_adr, args.images, args.no_crc, args.flash)
term.open(args.port, int(float(args.speed)))
term.console.configure()
+
term.start()
term.join(True)