diff --git a/Makefile b/Makefile index 67b21f8..15ab07a 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ BIN=bootloader.bin DUMP=bootloader.dump ENABLE_TESTER = 1 ASMFLAGS= -FILES=rst_vectors.asm boot.asm uart.asm systems.asm video.asm menu.asm +FILES=rst_vectors.asm boot.asm uart.asm systems.asm video.asm menu.asm format.asm # SRCS must be lazily evaluated since it depends FILES, which may be altered below SRCS=$(addprefix src/,$(FILES)) DISASSEMBLER=$(shell which z88dk-dis z88dk.z88dk-dis | head -1) @@ -34,7 +34,7 @@ all: clean version.txt @# Concatenate the SYS_TABLE cat $(BUILDIR)/src/*SYS_TABLE.bin >> $(BUILDIR)/$(BIN) @# Generate the disassembly dump for debugging - $(DISASSEMBLER) -x $(BUILDIR)/src/*.map $(BUILDIR)/$(BIN) > $(BUILDIR)/$(DUMP) + $(DISASSEMBLER) -o 0x0000 -x $(BUILDIR)/src/*.map $(BUILDIR)/$(BIN) > $(BUILDIR)/$(DUMP) version.txt: @echo `git describe --always --tags` > version.txt diff --git a/src/format.asm b/src/format.asm new file mode 100644 index 0000000..9359e95 --- /dev/null +++ b/src/format.asm @@ -0,0 +1,169 @@ +; SPDX-FileCopyrightText: 2022 Zeal 8-bit Computer +; +; SPDX-License-Identifier: Apache-2.0 + + INCLUDE "mmu_h.asm" + INCLUDE "video_h.asm" + INCLUDE "pio_h.asm" + INCLUDE "sys_table_h.asm" + INCLUDE "uart_h.asm" + + EXTERN newline + EXTERN uart_send_one_byte + EXTERN i2c_write_device + + DEFC I2C_EEPROM_ADDRESS = 0x50 + + SECTION BOOTLOADER + + PUBLIC format_eeprom +format_eeprom: + PRINT_STR(size_choice) + ; Wait for the user input + call uart_receive_one_byte + ; Print it back + push af + call uart_send_one_byte + call newline + pop af + ; Convert the baudrate choice to the actual values + cp '0' + ld b, 64 + jr z, format_size_b + cp '1' + ld b, 32 + jr z, format_size_b + cp '2' + ld b, 16 + jr z, format_size_b + ; Invalid choice, ask again + jp format_eeprom + +format_size_b: + call clear_buffer + ; Write the header in the buffer + ld hl, page + ; Magic byte + ld (hl), 'Z' + inc hl + ; File system version + ld (hl), 1 + inc hl + ; Bitmap size, in 256-byte page unit. Divide B by 2 and store it. + ; (= B * 1024 / 256 / 8 = B / 2) + ld a, b + rrca + ld (hl), a + inc hl + ; Free pages count, bitmap size (A) * 8 - 1 (first page allocated) + rlca + rlca + rlca + dec a + ld (hl), a + inc hl + ; Only modify the first byte of the bitmap, set it to 1. + ld (hl), 1 + ; The rest can be skipped as the buffer has already been set to 0 + ; Write this page to the EEPROM + ; A - 7-bit device address + ; HL - Buffer to write on the bus + ; B - Size of the buffer + ld a, I2C_EEPROM_ADDRESS + ld hl, reg_addr + ld b, page_end - reg_addr + call i2c_write_device + ; Check the return value + or a + jr nz, format_error + ; We just wrote the first 64 bytes. We still have to write 256 - 64 bytes = 192 bytes + ; These remaining bytes must be filled with 0s + call clear_buffer + ; 3 * 64 = 192 + ld b, page_end - reg_addr + ld c, 3 + ld de, 6 +_format_empty_page: + ; Wait 6 milliseconds + push bc + push de + call sleep_ms + pop de + pop bc + ; Set the new physical address to write to + ld hl, reg_addr + 1 ; High byte always 0 + ; C * 64 = C << 6 = C rotate right twice + ld a, c + rrca + rrca + ld (hl), a + ; Reposition HL to the 16-bit address + dec hl + ld a, I2C_EEPROM_ADDRESS + ; BC and DE are not altered by the routine + call i2c_write_device + or a + jr nz, format_error + dec c + jr nz, _format_empty_page + ; Now, we need to also clear the next + ; Success + PRINT_STR(success_msg) + ret +format_error: + PRINT_STR(write_error_msg) + ret + + +clear_buffer: + ; Clear the RAM buffer that will contain the ZealFS header + push bc + xor a + ld hl, reg_addr + ld (hl), 0 + ld d, h + ld e, l + inc de + ld bc, page_end - reg_addr - 1 + ldir + pop bc + ret + + + PUBLIC sleep_ms +sleep_ms: +_sleep_ms_again: + ; 24 is the number of T-states below + ld bc, 10000 / 24 +_sleep_ms_waste_time: + dec bc + ld a, b + or c + jp nz, _sleep_ms_waste_time + ; If we are here, a milliseconds has elapsed + dec de + ld a, d + or e + jp nz, _sleep_ms_again + ret + + +success_msg: + DEFM 0x1b, "[1;32mSuccess", 0x1b, "[0m\r\n" +success_msg_end: + +write_error_msg: + DEFM 0x1b, "[1;31mI2C write error", 0x1b, "[0m\r\n" +write_error_msg_end: + +size_choice: + DEFM "0 - 64KB\r\n" + DEFM "1 - 32KB\r\n" + DEFM "2 - 16KB\r\n" + DEFM "Choose EEPROM size [0-2]: " +size_choice_end: + + SECTION BSS +reg_addr: DEFS 2 +page: DEFS 64 +page_end: \ No newline at end of file diff --git a/src/menu.asm b/src/menu.asm index 37f6bad..51ee306 100644 --- a/src/menu.asm +++ b/src/menu.asm @@ -10,6 +10,7 @@ EXTERN newline EXTERN test_hardware + EXTERN format_eeprom SECTION BOOTLOADER @@ -217,6 +218,8 @@ process_menu_choice: cp 't' jp z, test_hardware ENDIF ; ENABLE_TESTER + cp 'q' + jp z, format_eeprom ; Fall-through invalid_choice: ld hl, invalid_str @@ -827,6 +830,7 @@ advanced_msg: DEFM "s - Save configuration to flash\r\n" DEFM "b - Change baudrate\r\n" DEFM "f - Flash/Program the ROM\r\n" + DEFM "q - Quick format I2C EEPROM (ZealFS)\r\n" IFDEF ENABLE_TESTER DEFM "t - Test hardware\r\n" ENDIF diff --git a/src/tester.asm b/src/tester.asm index 5b53870..4a111fa 100644 --- a/src/tester.asm +++ b/src/tester.asm @@ -541,24 +541,33 @@ rtc_warning_msg_end: DEFC I2C_EEPROM_ADDRESS = 0x50 EXTERN i2c_write_device -sleep_ms: -_sleep_ms_again: - ; 24 is the number of T-states below - ld bc, 10000 / 24 -_sleep_ms_waste_time: - dec bc - ld a, b - or c - jp nz, _sleep_ms_waste_time - ; If we are here, a milliseconds has elapsed - dec de - ld a, d - or e - jp nz, _sleep_ms_again - ret + EXTERN sleep_ms test_eeprom: PRINT_STR(eeprom_start_msg) + ; Make a backup of the EEPROM content (4 bytes) + ld hl, eeprom_write_buffer + ld de, buffer_backup + 2 + ld a, I2C_EEPROM_ADDRESS + ld b, 2 + ld c, 4 + call i2c_write_read_device + or a + jp nz, test_eeprom_error + call test_eeprom_size + ; No matter what the return value is we have to restore the EEPROM content + xor a + ld hl, buffer_backup + ld (hl), a + inc hl + ld (hl), a + dec hl + ld b, 6 + ld a, I2C_EEPROM_ADDRESS + jp i2c_write_device + + +test_eeprom_size: ; Write random bytes into the first page. Read all the remaining pages to check where it rolls ld hl, eeprom_write_buffer ; Parameters: @@ -711,4 +720,5 @@ keyboard_start_msg: keyboard_start_msg_end: SECTION BSS -buffer: DEFS 16 \ No newline at end of file +buffer: DEFS 16 +buffer_backup: DEFS 8