diff --git a/Makefile b/Makefile index 51a0b29..fbe636d 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,7 @@ BOOTLOADER_ADDRESS=0x100 VERSION=0.1.0 IMAGESIZE = 524288 +DEFAULT_CONFIG_LOCATION = 454656 CONFIG_LOCATION = 458752 HTML_LOCATION = 262144 @@ -37,6 +38,7 @@ $(VERSION_HEADER): @echo "#ifndef VERSION_H" > $(VERSION_HEADER) @echo "#define VERSION_H" >> $(VERSION_HEADER) @echo "#define VERSION_SW \"v$(VERSION)-g$(shell git rev-parse --short HEAD)\"" >> $(VERSION_HEADER) + @echo "#define BUILD_DATE \"$(shell date +"%Y-%m-%d %H:%M:%S")\"" >> $(VERSION_HEADER) @echo "#endif" >> $(VERSION_HEADER) httpd: html_data.h @@ -72,6 +74,7 @@ $(BUILDDIR)rtlplayground.img: $(BUILDDIR)rtlplayground.ihx $(BUILDDIR)rtlplayground.bin: $(BUILDDIR)rtlplayground.img if [ -e $@ ]; then rm $@; fi tools/$(BUILDDIR)imagebuilder -i $^ $@ + tools/$(BUILDDIR)fileadder -a $(DEFAULT_CONFIG_LOCATION) -s $(IMAGESIZE) -d config.txt $@ tools/$(BUILDDIR)fileadder -a $(CONFIG_LOCATION) -s $(IMAGESIZE) -d config.txt $@ tools/$(BUILDDIR)fileadder -a $(HTML_LOCATION) -s $(IMAGESIZE) -d html -p html_data $@ tools/$(BUILDDIR)crc_calculator -u $@ diff --git a/cmd_parser.c b/cmd_parser.c index 847e847..51dd9bf 100644 --- a/cmd_parser.c +++ b/cmd_parser.c @@ -33,7 +33,7 @@ extern volatile __xdata uint8_t sfr_data[4]; extern __code uint8_t * __code greeting; extern __code uint8_t * __code hex; -extern __xdata uint8_t flash_buf[512]; +extern __xdata uint8_t flash_buf[FLASH_BUF_SIZE]; extern __xdata struct flash_region_t flash_region; extern __xdata char passwd[21]; @@ -760,9 +760,8 @@ void print_gpio_status(void) { // Show software version void print_sw_version(void) __banked { - print_string("Software version: "); - print_string(VERSION_SW); - print_string("\nBuild: " __DATE__ " " __TIME__); + print_string("Software version: " VERSION_SW); + print_string("\nBuild date: " BUILD_DATE); print_string("\nHardware: "); print_string(machine.machine_name); write_char('\n'); diff --git a/httpd/httpd.c b/httpd/httpd.c index b1ede96..7b9cd47 100644 --- a/httpd/httpd.c +++ b/httpd/httpd.c @@ -14,9 +14,6 @@ #define SESSION_ID_LENGTH 12 #define SESSION_TIMEOUT 200 -// Upload Firmware to 1M -#define FIRMWARE_UPLOAD_START 0x100000 - // SPI FLASH MEMORY PAGE SIZE. #define FLASHMEM_PAGE_SIZE 0x100 @@ -32,7 +29,7 @@ extern __code char * __code mime_strings[]; extern __xdata struct flash_region_t flash_region; // Flash buffer to optimize flash writing speed, write_len is the current filling position -extern __xdata uint8_t flash_buf[512]; +extern __xdata uint8_t flash_buf[FLASH_BUF_SIZE]; __xdata uint32_t uptr; // Current flash write position __xdata uint16_t write_len; diff --git a/httpd/page_impl.c b/httpd/page_impl.c index 7033680..45b2e84 100644 --- a/httpd/page_impl.c +++ b/httpd/page_impl.c @@ -230,6 +230,8 @@ void send_basic_info(void) byte_to_html(uip_ethaddr.addr[5]); slen += strtox(outbuf + slen, "\",\"sw_ver\":\""); slen += strtox(outbuf + slen, VERSION_SW); + slen += strtox(outbuf + slen, "\",\"build_date\":\""); + slen += strtox(outbuf + slen, BUILD_DATE); slen += strtox(outbuf + slen, "\",\"hw_ver\":\""); slen += strtox(outbuf + slen, machine.machine_name); slen += strtox(outbuf + slen, "\",\"sfp_slot_0\":\""); diff --git a/machine.h b/machine.h index 954c66b..7763d32 100644 --- a/machine.h +++ b/machine.h @@ -56,7 +56,7 @@ typedef struct machine { uint8_t is_sfp[9]; // 0 for non-SFP ports 1 or 2 for the I2C port number // sfp_port[0] is the first SFP-port from the left on the device, sfp_port[1] the next if present struct sfp_port sfp_port[2]; - int8_t reset_pin; + uint8_t reset_pin; struct high_leds high_leds; uint8_t port_led_set[9]; uint32_t led_sets[4][4]; diff --git a/rtl837x_common.h b/rtl837x_common.h index 6f02ed3..f6c9dd7 100644 --- a/rtl837x_common.h +++ b/rtl837x_common.h @@ -29,6 +29,9 @@ // Size of the memory area dedicated to VLAN-names #define VLAN_NAMES_SIZE 1024 +// Size of the flash buffer used for writing to flash, must be a multiple of the flash page size (0x100) +#define FLASH_BUF_SIZE 512 + // For RX data, a propriatary RTL FRAME is inserted. Instead of 0x0800 for IPv4, // the RTL_FRAME_TAG_ID is used as part of an 8-byte tag. When VLAN is activated, // the VLAN tag is inserted after the RTL tag @@ -57,11 +60,15 @@ struct vlan_tag { // This is the standard size of an Ethernet frame header #define ETHER_HEADER_SIZE 14 +#define DEFAULT_CONFIG_START 0x6f000 #define CONFIG_START 0x70000 #define CONFIG_LEN 0x1000 #define CODE0_SIZE 0x4000 #define CODE_BANK_SIZE 0xc000 +// Store update image after running image +#define FIRMWARE_UPLOAD_START 0x80000 + // Constants for the circular command buffer, the size must be 2^n #define CMD_HISTORY_SIZE 0x400 #define CMD_HISTORY_MASK (CMD_HISTORY_SIZE - 1) diff --git a/rtlplayground.c b/rtlplayground.c index fdaae9c..55b6d52 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -22,7 +22,6 @@ #include "machine.h" #include "phy.h" - extern __code const struct machine machine; extern __xdata uint16_t crc_value; @@ -30,9 +29,6 @@ __xdata uint8_t crc_testbytes[10]; __xdata struct machine_runtime machine_detected; void crc16(__xdata uint8_t *v) __naked; -// Upload Firmware to 1M -#define FIRMWARE_UPLOAD_START 0x100000 - // See setup_serial_timer1() for valid baudrate settings! #define SERIAL_BAUD_RATE 115200 @@ -103,7 +99,7 @@ extern __xdata struct flash_region_t flash_region; __code uint8_t * __code greeting = "\nA minimal prompt to explore the RTL8372:\n"; __code uint8_t * __code hex = "0123456789abcdef"; -__xdata uint8_t flash_buf[512]; +__xdata uint8_t flash_buf[FLASH_BUF_SIZE]; // NIC buffers for packet RX/TX __xdata uint8_t rx_headers[16]; // Packet header(s) on RX @@ -128,6 +124,8 @@ __xdata char sfp_module_vendor[2][17]; __xdata char sfp_module_model[2][17]; __xdata char sfp_module_serial[2][17]; __xdata uint8_t sfp_options[2]; +__xdata bool button_last; +__xdata uint8_t button_sec_counter_last; __sbit tx_buf_empty; #define ETHERTYPE_OFFSET (12 + VLAN_TAG_SIZE + RTL_TAG_SIZE) @@ -1064,6 +1062,72 @@ void handle_sfp(void) } } +void flash_default_config(void) +{ + __xdata uint32_t source = DEFAULT_CONFIG_START; + __xdata uint32_t dest = CONFIG_START; + + flash_region.addr = CONFIG_START; + flash_sector_erase(); + + for (uint8_t i = 0; i < 8; i++) // 8 * 512 Byte = 4 kByte (1 sector) + { + flash_region.addr = source; + flash_region.len = FLASH_BUF_SIZE; + flash_read_bulk(flash_buf); + flash_region.addr = dest; + flash_region.len = FLASH_BUF_SIZE; + flash_write_bytes(flash_buf); + dest += FLASH_BUF_SIZE; + source += FLASH_BUF_SIZE; + } + + print_string("Written default config to flash\n"); +} + +void handle_button(void) +{ + if (machine.reset_pin == GPIO_NA) { + return; + } + + bool button_pressed = !gpio_pin_test(machine.reset_pin); + if (button_last != button_pressed) + { + print_string(button_pressed ? "Button pressed\n" : "Button released\n"); + reg_read_m(RTL837X_REG_SEC_COUNTER); + uint8_t diff_sec_counter = sfr_data[3] - button_sec_counter_last; + button_last = button_pressed; + button_sec_counter_last = sfr_data[3]; + + if (!button_pressed) + { + if (diff_sec_counter > 10) + { + print_string(">10s button detected; reverting to default settings:\n"); + flash_default_config(); + print_string("Now resetting...\n"); + reset_chip(); + } + else if (diff_sec_counter > 3) + { + print_string(">3s button detected; resetting chip...\n"); + reset_chip(); + } + else + { + print_string("Short button press detected; no action.\n"); + set_sys_led_state(SYS_LED_ON); + } + } + else + { + // Give the user feedback for button press + set_sys_led_state(SYS_LED_SLOW); + } + } +} + // // An idle function that sleeps for 1 tick and does all the house-keeping // @@ -1096,6 +1160,10 @@ void idle(void) } reg_write_m(RTL837X_REG_SEC_COUNTER); reg_read_m(RTL837X_REG_SEC_COUNTER); + + // Check for button presses once a second + handle_button(); + #ifdef DEBUG print_sfr_data(); write_char('\n'); @@ -1135,11 +1203,6 @@ void idle(void) // Check for changes with SFP modules handle_sfp(); - /* Button pressed on KL-8xhm-x2: - reg_read(RTL837X_REG_GPIO_32_63_INPUT); - if (!(sfr_data[2] & 0x40)) - print_string("Button pressed\n"); - */ // Check new Packets RX handle_rx(); // Check UIP for packets to transmit @@ -1800,6 +1863,82 @@ void setup_i2c(void) } +void check_and_flash_update_image(void) +{ + // Check if an update image is in flash + flash_region.addr = FIRMWARE_UPLOAD_START; + flash_region.len = 0x100; + flash_read_bulk(flash_buf); + if (flash_buf[0] == 0x00 && flash_buf[1] == 0x40) + { + // Yes, flash the new image to the start of flash and reset + __xdata uint32_t dest = 0x0; + __xdata uint32_t source = FIRMWARE_UPLOAD_START; + __xdata uint16_t i = 0; + __xdata uint16_t j = 0; + __xdata uint8_t * __xdata bptr; + print_string("Identified update image. Checking integrity..."); + flash_init(0); // Re-initialize flash for non-DIO operation, otherwise flashing will fail + set_sys_led_state(SYS_LED_FAST); + crc_value = 0x0000; + for (i = 0; i < 1024; i++) { + flash_region.addr = source; + flash_region.len = FLASH_BUF_SIZE; + flash_read_bulk(flash_buf); + bptr = flash_buf; + for (j = 0; j < FLASH_BUF_SIZE; j++) { + crc16(bptr++); + } + source += FLASH_BUF_SIZE; + if (i%16 == 0) + write_char('.'); + } + if (crc_value == 0xb001) { + print_string("\nChecksum OK\n"); + print_string("Update in progress, moving firmware to start of FLASH."); + source = FIRMWARE_UPLOAD_START; + // A 512kByte = 4MBit Flash has 128*8=1024 512byte blocks, we copy only 896 + // (don't overwrite config @ 0x70000) + for (i = 0; i < 896; i++) { + // print_string("Writing block: "); + // print_short(dest); + flash_region.addr = source; + flash_region.len = FLASH_BUF_SIZE; + flash_read_bulk(flash_buf); + if (!(i & 0x7)) { + flash_region.addr = dest; + flash_sector_erase(); + write_char('.'); + } + flash_region.addr = dest; + flash_region.len = FLASH_BUF_SIZE; + flash_write_bytes(flash_buf); + dest += FLASH_BUF_SIZE; + source += FLASH_BUF_SIZE; + } + print_string("\nDeleting uploaded flash image\n"); + dest = FIRMWARE_UPLOAD_START; + for (register uint8_t i=0; i < 128; i++) // TODO: Erasing the entire 512kByte upload area is probably not necessary + { + flash_region.addr = dest; + flash_sector_erase(); + dest += 0x1000; + } + print_string("Resetting now"); + delay(200); + reset_chip(); + } + print_string("Checksum incorrect, please upload the image again\n"); + print_string("Erasing bad uploaded flash image\n"); + dest = FIRMWARE_UPLOAD_START; + for (register uint8_t i=0; i < 128; i++) { + flash_region.addr = dest; + flash_sector_erase(); + dest += 0x1000; + } + } +} + void bootloader(void) { ticks = 0; @@ -1837,6 +1976,9 @@ void bootloader(void) // We have not detected any link linkbits_last[0] = linkbits_last[1] = linkbits_last[2] = linkbits_last[3] = linkbits_last_p89 = 0; + button_last = 0; + button_sec_counter_last = 0; + machine_detected.isRTL8373 = 0; machine_detected.isN = 0; print_string("Detecting CPU: RTL837"); @@ -1910,80 +2052,7 @@ void bootloader(void) rtl8372_init(); delay(1000); - // Check update in progress and move blocks - flash_region.addr = FIRMWARE_UPLOAD_START; - flash_region.len = 0x100; - flash_read_bulk(flash_buf); - if (flash_buf[0] == 0x00 && flash_buf[1] == 0x40) { - __xdata uint32_t dest = 0x0; - __xdata uint32_t source = FIRMWARE_UPLOAD_START; - __xdata uint16_t i = 0; - __xdata uint16_t j = 0; - __xdata uint8_t * __xdata bptr; - print_string("Identified update image. Checking integrity..."); - - flash_init(0); // Re-initialize flash for non-DIO operation, otherwise flashing will fail - set_sys_led_state(SYS_LED_FAST); - - crc_value = 0x0000; - for (i = 0; i < 1024; i++) { - flash_region.addr = source; - flash_region.len = 0x200; - flash_read_bulk(flash_buf); - bptr = flash_buf; - for (j = 0; j < 0x200; j++) { - // print_byte(*bptr); write_char(' '); - crc16(bptr++); - // print_short(crc_value); write_char(':'); - } - source += 0x200; - // write_char('\n'); print_short(crc_value); write_char(' '); - if (i%16 == 0) - write_char('.'); - } - if (crc_value == 0xb001) { - print_string("\nChecksum OK\n"); - print_string("Update in progress, moving firmware to start of FLASH."); - source = FIRMWARE_UPLOAD_START; - // A 512kByte = 4MBit Flash has 128*8=1024 512byte blocks, we copy only 896 - // (don't overwrite config @ 0x700000) - for (i = 0; i < 896; i++) { - // print_string("Writing block: "); - // print_short(dest); - flash_region.addr = source; - flash_region.len = 0x200; - flash_read_bulk(flash_buf); - if (!(i & 0x7)) { - flash_region.addr = dest; - flash_sector_erase(); - write_char('.'); - } - flash_region.addr = dest; - flash_region.len = 0x200; - flash_write_bytes(flash_buf); - dest += 0x200; - source += 0x200; - } - print_string("\nDeleting uploaded flash image\n"); - dest = FIRMWARE_UPLOAD_START; - for (register uint8_t i=0; i < 128; i++) { - flash_region.addr = dest; - flash_sector_erase(); - dest += 0x1000; - } - print_string("Resetting now"); - delay(200); - reset_chip(); - } - print_string("Checksum incorrect, please upload the image again\n"); - print_string("Erasing bad uploaded flash image\n"); - dest = FIRMWARE_UPLOAD_START; - for (register uint8_t i=0; i < 128; i++) { - flash_region.addr = dest; - flash_sector_erase(); - dest += 0x1000; - } - } + check_and_flash_update_image(); #ifdef DEBUG // This register seems to work on the RTL8373 only if also the SDS