...
diff --git a/32blit-stm32/Src/usb-serial.cpp b/32blit-stm32/Src/usb-serial.cpp index c68a8d5..b373299 100644 --- a/32blit-stm32/Src/usb-serial.cpp +++ b/32blit-stm32/Src/usb-serial.cpp
@@ -87,7 +87,7 @@ std::map<std::string, CommandHandler> handlers; - constexpr uint32_t MAX_PACKETS = 16; + constexpr uint32_t MAX_PACKETS = 64; Packet packets[MAX_PACKETS]; std::vector<Packet*> free_packets; @@ -174,7 +174,7 @@ // the command handle must return true when it has finished processing // the entire command (even if this is across multiple packets) CommandState result = handler(CommandState::STREAM, packet->data, packet->length); - + if(result == CommandState::END) { // command stream is complete, detach handler handler = nullptr;
diff --git a/32blit.toolchain b/32blit.toolchain index 30feb5f..4df35df 100644 --- a/32blit.toolchain +++ b/32blit.toolchain
@@ -37,7 +37,6 @@ set(CMAKE_C_FLAGS_INIT "${COMMON_FLAGS}") set(CMAKE_CXX_FLAGS_INIT "${COMMON_FLAGS}") set(CMAKE_CXX_FLAGS_DEBUG_INIT "-g -Og") -#set(CMAKE_EXE_LINKER_FLAGS_INIT "-specs=nano.specs -T ${MCU_LINKER_SCRIPT} -Wl,--gc-sections") set(CMAKE_EXE_LINKER_FLAGS_INIT "-specs=nosys.specs -Wl,--gc-sections,--no-wchar-size-warning")
diff --git a/examples/flash b/examples/flash index a7136a0..786c751 100644 --- a/examples/flash +++ b/examples/flash
@@ -7,20 +7,23 @@ import os import os.path import time +import threading from tqdm import tqdm parser = argparse.ArgumentParser(description='32blit binary flasher.') -parser.add_argument("file", help="Path to the binary file (e.g. 'build.stm32/voxel.bin')") +parser.add_argument("command", help="Command to perform (e.g. 'save', 'dfu', 'reset')", default="save") parser.add_argument("port", help="Name of the serial port (e.g. 'COM4', '/dev/ttyS4', etc.)") parser.add_argument("--target", help="Target either 'sd' or 'flash'", default="sd", choices=["sd", "flash"]) +parser.add_argument("--no-read", help="Do not wait to read responses", action="store_true") +parser.add_argument("file", help="Path to the binary file (e.g. 'build.stm32/voxel.bin')", nargs='?') args = parser.parse_args() print("32blit binary flasher.") port = args.port +command = args.command target = args.target -path = args.file valid_ports = [port[0] for port in serial.tools.list_ports.comports()] @@ -28,40 +31,83 @@ print("Specified port '{0}' not valid".format(port)) sys.exit(os.EX_OSFILE) -if not os.path.isfile(path): - print("Specified binary file '{0}' does not exist".format(path)) - sys.exit(os.EX_NOINPUT) - serial_port = None try: serial_port = serial.Serial(port, 115200, timeout=1) + serial_port.reset_output_buffer() except OSError: print("Could not open port '{0}'".format(port)) print("The port may not exist or you may not have permission to access it.") sys.exit(os.EX_OSFILE) -file_size = os.stat(path).st_size -file_name = os.path.basename(path) -sent_byte_count = 0 -chunk_size = 64 +if not args.no_read: + # read thread constantly polls for responses from 32blit and + # outputs them to the screen + def read_serial(serial_port): + while True: + data = serial_port.read_until(b"\0").decode() + if data: + print(data) -# such reset, very boot -#serial_port.write(b"32BL_RST\x00") -#sys.exit() + read_thread = threading.Thread(target=read_serial, args=(serial_port,)) + read_thread.start() -serial_port.reset_output_buffer() +print(command) -command = "SAVE\x00{0}\x00{1}\x00".format(file_name, file_size) -serial_port.write(bytes(command, "ascii")) +if command == "save": + path = args.file + if not os.path.isfile(path): + print("Specified binary file '{0}' does not exist".format(path)) + sys.exit(os.EX_NOINPUT) -with open(path, "rb") as f: - progress = tqdm(total=file_size, desc="Flashing...", unit_scale=True, unit_divisor=1024, unit="B", ncols=70, dynamic_ncols=True) + file_size = os.stat(path).st_size + file_name = os.path.basename(path) - while sent_byte_count < file_size: - data = f.read(chunk_size) - serial_port.write(data) - sent_byte_count += chunk_size - progress.update(chunk_size) - - progress.close() \ No newline at end of file + # send the save command to 32blit + data = "SAVE\x00{0}\x00{1}\x00".format(file_name, file_size) + serial_port.write(bytes(data, "ascii")) + + # transmit the file data to 32blit + sent_byte_count = 0 + chunk_size = 64 + with open(path, "rb") as f: + progress = tqdm(total=file_size, desc="Flashing...", unit_scale=True, unit_divisor=1024, unit="B", ncols=70, dynamic_ncols=True) + + while sent_byte_count < file_size: + # last chunk may be smaller than 64 bytes + if file_size - sent_byte_count < chunk_size: + chunk_size = file_size - sent_byte_count + + # read chunk from file + data = f.read(chunk_size) + + # transmit it to 32blit + serial_port.write(data) + sent_byte_count += chunk_size + + # update progress bar + progress.update(chunk_size) + + progress.close() + +if command == "dfu": + # send the dfu command to 32blit + data = "DFU\x00" + serial_port.write(bytes(data, "ascii")) + +if command == "reset": + # send the dfu command to 32blit + data = "RESET\x00" + serial_port.write(bytes(data, "ascii")) + +if not args.no_read: + # wait for any responses + print("Reading responses from 32blit. Press Ctrl+C to quit.") + try: + while True: + pass + except KeyboardInterrupt: + read_thread.stop() + +time.sleep(1) \ No newline at end of file
diff --git a/firmware/firmware.cpp b/firmware/firmware.cpp index a5aac92..995d886 100644 --- a/firmware/firmware.cpp +++ b/firmware/firmware.cpp
@@ -54,14 +54,23 @@ Vec2 list_offset(5.0f, 0.0f); -CommandState usb_cdc_save_to_sd_card(CommandState state, char *data, uint32_t length); +CommandState usb_serial_save_to_sd_card(CommandState state, char *data, uint32_t length); -CommandState usb_cdc_reset(CommandState state, char *data, uint32_t length) { +CommandState usb_serial_reset(CommandState state, char *data, uint32_t length) { NVIC_SystemReset(); return CommandState::END; } -CommandState usb_cdc_application_location(CommandState state, char *data, uint32_t length) { +CommandState usb_serial_dfu(CommandState state, char *data, uint32_t length) { + *((uint32_t *)0x2001FFFC) = 0xCAFEBABE; + + SCB_CleanDCache(); + NVIC_SystemReset(); + + return CommandState::END; +} + +CommandState usb_serial_application_location(CommandState state, char *data, uint32_t length) { while(USBD_BUSY == transmit("32BL_EXT")) {}; HAL_Delay(250); return CommandState::END; @@ -73,9 +82,10 @@ set_screen_mode(ScreenMode::hires); load_file_list(); - register_command_handler("RESET", usb_cdc_reset); - register_command_handler("INFO", usb_cdc_application_location); - register_command_handler("SAVE", usb_cdc_save_to_sd_card); + register_command_handler("RESET", usb_serial_reset); + register_command_handler( "INFO", usb_serial_application_location); + register_command_handler( "SAVE", usb_serial_save_to_sd_card); + register_command_handler( "DFU", usb_serial_dfu); } void background(uint32_t time_ms) { @@ -193,7 +203,7 @@ bool flash_from_sd_to_qspi_flash(const std::string &filename) { - static uint8_t file_buffer[4 * 1024]; + static uint8_t file_buffer[256]; FIL file; if(f_open(&file, filename.c_str(), FA_READ) != FR_OK) { @@ -248,7 +258,7 @@ // when a command is issued (e.g. "PROG" or "SAVE") then this function is called // whenever new data is received to allow the firmware to process it. -CommandState usb_cdc_save_to_sd_card(CommandState state, char *data, uint32_t length) { +CommandState usb_serial_save_to_sd_card(CommandState state, char *data, uint32_t length) { static char filename[64] = {'\0'}; static FIL file; @@ -301,6 +311,8 @@ f_close(&file); return CommandState::ERROR; } + + //f_sync(&file); bytes_processed += bytes_written; @@ -310,6 +322,7 @@ load_file_list(); select_file(filename); f_close(&file); + memset(filename, 0, sizeof(filename)); return CommandState::END; }else{