diff --git a/ESP32/console_esp32.cpp b/ESP32/console_esp32.cpp index d4efeb0..787733f 100644 --- a/ESP32/console_esp32.cpp +++ b/ESP32/console_esp32.cpp @@ -72,7 +72,6 @@ void console_esp32::panel_update_thread() pixels.begin(); pixels.clear(); - pixels.show(); constexpr uint8_t brightness = 16; @@ -103,7 +102,7 @@ void console_esp32::panel_update_thread() pixels.clear(); pixels.show(); - for(;;) { + while(!stop_panel) { vTaskDelay(20 / portTICK_PERIOD_MS); try { @@ -141,5 +140,10 @@ void console_esp32::panel_update_thread() put_string_lf("Unknown exception in panel thread"); } } + + pixels.clear(); + pixels.show(); + + Serial.println(F("panel task terminating")); #endif } diff --git a/ESP32/main.ino b/ESP32/main.ino index bb29dd8..1d581cd 100644 --- a/ESP32/main.ino +++ b/ESP32/main.ino @@ -18,6 +18,9 @@ #include #include #endif +#if defined(ESP32) +#include "esp_heap_caps.h" +#endif #if defined(SHA2017) #include "console_shabadge.h" @@ -70,14 +73,13 @@ std::atomic_bool *running { nullptr }; bool trace_output { false }; -std::vector rk05_files; -std::vector rl02_files; - void console_thread_wrapper_panel(void *const c) { console *const cnsl = reinterpret_cast(c); cnsl->panel_update_thread(); + + vTaskSuspend(nullptr); } uint32_t load_serial_speed_configuration() @@ -208,6 +210,14 @@ void set_tty_serial_speed(console *const c, const uint32_t bps) c->put_string_lf("Failed to store configuration file with serial settings"); } +#if defined(ESP32) +void heap_caps_alloc_failed_hook(size_t requested_size, uint32_t caps, const char *function_name) +{ + printf("%s was called but failed to allocate %d bytes with 0x%X capabilities\r\n", function_name, requested_size, caps); +} + +#endif + void setup() { Serial.begin(115200); @@ -222,6 +232,10 @@ void setup() { Serial.print(F("Size of int: ")); Serial.println(sizeof(int)); +#if defined(ESP32) + heap_caps_register_failed_alloc_callback(heap_caps_alloc_failed_hook); +#endif + #if !defined(BUILD_FOR_RP2040) Serial.print(F("CPU clock frequency (MHz): ")); Serial.println(getCpuFrequencyMhz()); @@ -295,9 +309,9 @@ void setup() { running = cnsl->get_running_flag(); Serial.println(F("Connect RK05 and RL02 to BUS")); - b->add_rk05(new rk05(rk05_files, b, cnsl->get_disk_read_activity_flag(), cnsl->get_disk_write_activity_flag())); + b->add_rk05(new rk05(b, cnsl->get_disk_read_activity_flag(), cnsl->get_disk_write_activity_flag())); - b->add_rl02(new rl02(rl02_files, b, cnsl->get_disk_read_activity_flag(), cnsl->get_disk_write_activity_flag())); + b->add_rl02(new rl02(b, cnsl->get_disk_read_activity_flag(), cnsl->get_disk_write_activity_flag())); Serial.println(F("Init TTY")); tty_ = new tty(cnsl, b); diff --git a/ESP32/platformio.ini b/ESP32/platformio.ini index c085fdd..903dbdf 100644 --- a/ESP32/platformio.ini +++ b/ESP32/platformio.ini @@ -35,3 +35,18 @@ lib_deps = greiman/SdFat@^2.1.2 build_flags = -std=gnu++2a -DESP32=1 -DSHA2017 -ggdb3 -D_GLIBCXX_USE_C99 -ISHAdisplay/Arduino/libraries/epd2in9-badge -ISHAdisplay/Arduino/libraries/epdpaint -ISHAdisplay/components/epaper-29-dke build_unflags = -std=gnu++11 -std=gnu++17 upload_protocol = esptool + +[env:ESP32-ttgo-t-beam] +build_src_filter = +<*> -<.git/> -<.svn/> - - - - - - - - +platform = espressif32 +board = ttgo-t-beam +framework = arduino +monitor_speed = 115200 +upload_speed = 1000000 +board_build.filesystem = littlefs +lib_deps = greiman/SdFat@^2.1.2 + adafruit/Adafruit NeoPixel + bblanchon/ArduinoJson@^6.19.4 +build_flags = -std=gnu++17 -DESP32=1 -ggdb3 -D_GLIBCXX_USE_C99 +build_unflags = -std=gnu++11 +extra_scripts = pre:prepare.py diff --git a/ESP32/win32.cpp b/ESP32/win32.cpp deleted file mode 120000 index caccb16..0000000 --- a/ESP32/win32.cpp +++ /dev/null @@ -1 +0,0 @@ -../win32.cpp \ No newline at end of file diff --git a/ESP32/win32.h b/ESP32/win32.h deleted file mode 120000 index fba5da8..0000000 --- a/ESP32/win32.h +++ /dev/null @@ -1 +0,0 @@ -../win32.h \ No newline at end of file diff --git a/bus.cpp b/bus.cpp index 5d73884..232d82d 100644 --- a/bus.cpp +++ b/bus.cpp @@ -120,8 +120,6 @@ bus *bus::deserialize(const json_t *const j, console *const cnsl, std::atomic_ui void bus::set_memory_size(const int n_pages) { - this->n_pages = n_pages; - uint32_t n_bytes = n_pages * 8192l; delete m; @@ -474,7 +472,7 @@ uint16_t bus::read(const uint16_t addr_in, const word_mode_t word_mode, const rm } // LO size register field must be all 1s, so subtract 1 - uint32_t system_size = n_pages * 8192l / 64 - 1; + uint32_t system_size = m->get_memory_size() / 64 - 1; if (a == ADDR_SYSSIZE + 2) { // system size HI uint16_t temp = system_size >> 16; @@ -505,7 +503,7 @@ uint16_t bus::read(const uint16_t addr_in, const word_mode_t word_mode, const rm return 0; } - if (m_offset >= uint32_t(n_pages * 8192)) { + if (m_offset >= m->get_memory_size()) { if (peek_only) { DOLOG(debug, false, "READ from %06o - out of range!", addr_in); return 0; @@ -696,8 +694,8 @@ uint32_t bus::calculate_physical_address(const int run_mode, const uint16_t a, c } } - if (m_offset >= n_pages * 8192l && !is_io) [[unlikely]] { - DOLOG(debug, !peek_only, "bus::calculate_physical_address %o >= %o", m_offset, n_pages * 8192l); + if (m_offset >= m->get_memory_size() && !is_io) [[unlikely]] { + DOLOG(debug, !peek_only, "bus::calculate_physical_address %o >= %o", m_offset, m->get_memory_size()); DOLOG(debug, false, "TRAP(04) (throw 6) on address %06o", a); if (mmu_->is_locked() == false) { @@ -1025,7 +1023,7 @@ write_rc_t bus::write(const uint16_t addr_in, const word_mode_t word_mode, uint1 DOLOG(debug, false, "WRITE to %06o/%07o %c %c: %06o", addr_in, m_offset, space == d_space ? 'D' : 'I', word_mode == wm_byte ? 'B' : 'W', value); - if (m_offset >= uint32_t(n_pages * 8192)) { + if (m_offset >= m->get_memory_size()) { c->trap(004); // no such RAM throw 1; } @@ -1042,7 +1040,7 @@ void bus::writePhysical(const uint32_t a, const uint16_t value) { DOLOG(debug, false, "physicalWRITE %06o to %o", value, a); - if (a >= n_pages * 8192l) { + if (a >= m->get_memory_size()) { DOLOG(debug, false, "physicalWRITE to %o: trap 004", a); c->trap(004); throw 12; @@ -1054,7 +1052,7 @@ void bus::writePhysical(const uint32_t a, const uint16_t value) uint16_t bus::readPhysical(const uint32_t a) { - if (a >= n_pages * 8192l) { + if (a >= m->get_memory_size()) { DOLOG(debug, false, "physicalREAD from %o: trap 004", a); c->trap(004); throw 13; diff --git a/bus.h b/bus.h index 1e8db64..800e926 100644 --- a/bus.h +++ b/bus.h @@ -75,10 +75,7 @@ private: rl02 *rl02_ { nullptr }; tty *tty_ { nullptr }; kw11_l *kw11_l_ { nullptr }; - mmu *mmu_ { nullptr }; - - int n_pages { DEFAULT_N_PAGES }; memory *m { nullptr }; uint16_t microprogram_break_register { 0 }; @@ -104,7 +101,6 @@ public: void set_debug_mode() { console_switches |= 128; } uint16_t get_console_leds() { return console_leds; } - int get_memory_size() const { return n_pages; } void set_memory_size(const int n_pages); void mmudebug(const uint16_t a); diff --git a/console.h b/console.h index 5cb932f..6101602 100644 --- a/console.h +++ b/console.h @@ -29,7 +29,8 @@ private: #endif protected: - std::atomic_uint32_t *const stop_event { nullptr }; + std::atomic_uint32_t *const stop_event { nullptr }; + std::atomic_bool stop_panel { false }; bus *b { nullptr }; #if !defined(BUILD_FOR_RP2040) @@ -88,5 +89,6 @@ public: std::atomic_bool * get_disk_read_activity_flag() { return &disk_read_activity_flag; } std::atomic_bool * get_disk_write_activity_flag() { return &disk_write_activity_flag; } + void stop_panel_thread() { stop_panel = true; } virtual void panel_update_thread() = 0; }; diff --git a/console_ncurses.cpp b/console_ncurses.cpp index 2a9c76c..c8803db 100644 --- a/console_ncurses.cpp +++ b/console_ncurses.cpp @@ -133,7 +133,7 @@ void console_ncurses::panel_update_thread() constexpr int refresh_rate = 50; - while(*stop_event != EVENT_TERMINATE) { + while(*stop_event != EVENT_TERMINATE && stop_panel == false) { myusleep(1000000 / refresh_rate); // note that these are approximately as there's no mutex on the emulation diff --git a/debugger.cpp b/debugger.cpp index 8eb6212..2087c19 100644 --- a/debugger.cpp +++ b/debugger.cpp @@ -26,6 +26,7 @@ #include "disk_backend_nbd.h" #include "loaders.h" #include "log.h" +#include "memory.h" #include "tty.h" #include "utils.h" @@ -37,13 +38,9 @@ #include "rp2040.h" #endif -void set_boot_loader(bus *const b); - -void configure_disk(console *const c); - -void configure_network(console *const c); -void check_network(console *const c); -void start_network(console *const c); +void configure_network(console *const cnsl); +void check_network(console *const cnsl); +void start_network(console *const cnsl); void set_tty_serial_speed(console *const c, const uint32_t bps); #endif @@ -825,6 +822,12 @@ void debugger(console *const cnsl, bus *const b, std::atomic_uint32_t *const sto continue; } #if defined(ESP32) + else if (cmd == "debug") { + if (heap_caps_check_integrity_all(true) == false) + cnsl->put_string_lf("HEAP corruption!"); + + continue; + } else if (cmd == "cfgnet") { configure_network(cnsl); @@ -863,7 +866,7 @@ void debugger(console *const cnsl, bus *const b, std::atomic_uint32_t *const sto if (parts.size() == 2) b->set_memory_size(std::stoi(parts.at(1))); else { - int n_pages = b->get_memory_size(); + int n_pages = b->getRAM()->get_memory_size(); cnsl->put_string_lf(format("Memory size: %u pages or %u kB (decimal)", n_pages, n_pages * 8192 / 1024)); } @@ -942,7 +945,10 @@ void debugger(console *const cnsl, bus *const b, std::atomic_uint32_t *const sto } #endif else if (parts[0] == "setsl" && parts.size() == 3) { - setloghost(parts.at(1).c_str(), parse_ll(parts[2])); + if (setloghost(parts.at(1).c_str(), parse_ll(parts[2])) == false) + cnsl->put_string_lf("Failed parsing IP address"); + else + send_syslog(info, "Hello, world!"); continue; } @@ -951,6 +957,11 @@ void debugger(console *const cnsl, bus *const b, std::atomic_uint32_t *const sto continue; } + else if (cmd == "dp") { + cnsl->stop_panel_thread(); + + continue; + } else if (cmd == "bt") { if (c->get_debug() == false) cnsl->put_string_lf("Debug mode is disabled!"); @@ -1006,11 +1017,13 @@ void debugger(console *const cnsl, bus *const b, std::atomic_uint32_t *const sto "ser - serialize state to a file", // "dser - deserialize state from a file", #endif + "dp - disable panel", #if defined(ESP32) "cfgnet - configure network (e.g. WiFi)", "startnet - start network", "chknet - check network status", "serspd - set serial speed in bps (8N1 are default)", + "debug - debugging info", #endif "cfgdisk - configure disk", nullptr diff --git a/disk_backend.cpp b/disk_backend.cpp index 488ee94..a3e087b 100644 --- a/disk_backend.cpp +++ b/disk_backend.cpp @@ -4,6 +4,7 @@ #include #include "disk_backend.h" +#include "gen.h" #if IS_POSIX #include "disk_backend_file.h" #include "disk_backend_nbd.h" diff --git a/disk_backend_nbd.cpp b/disk_backend_nbd.cpp index 310e31c..031aede 100644 --- a/disk_backend_nbd.cpp +++ b/disk_backend_nbd.cpp @@ -91,10 +91,10 @@ bool disk_backend_nbd::connect(const bool retry) { do { // LOOP until connected, logging message, exponential backoff? - addrinfo *res = nullptr; + addrinfo *res = nullptr; addrinfo hints { 0 }; - hints.ai_family = AF_INET; + hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; char port_str[8] { 0 }; @@ -137,7 +137,7 @@ bool disk_backend_nbd::connect(const bool retry) uint64_t size; uint32_t flags; uint8_t padding[124]; - } nbd_hello; + } nbd_hello { }; if (fd != -1) { if (READ(fd, reinterpret_cast(&nbd_hello), sizeof nbd_hello) != sizeof nbd_hello) { @@ -194,7 +194,7 @@ bool disk_backend_nbd::read(const off_t offset_in, const size_t n, uint8_t *cons uint64_t handle; uint64_t offset; uint32_t length; - } nbd_request { 0 }; + } nbd_request { }; nbd_request.magic = ntohl(0x25609513); nbd_request.type = 0; // READ diff --git a/loaders.cpp b/loaders.cpp index 5a809a2..849048b 100644 --- a/loaders.cpp +++ b/loaders.cpp @@ -30,7 +30,7 @@ void loadbin(bus *const b, uint16_t base, const char *const file) void set_boot_loader(bus *const b, const bootloader_t which) { - cpu *const c = b->getCpu(); + cpu *const c = b->getCpu(); uint16_t offset = 0; uint16_t start = 0; @@ -40,7 +40,7 @@ void set_boot_loader(bus *const b, const bootloader_t which) if (which == BL_RK05) { start = offset = 01000; - static uint16_t rk05_code[] = { + constexpr const uint16_t rk05_code[] = { 0012700, 0177406, 0012710, @@ -92,7 +92,7 @@ void set_boot_loader(bus *const b, const bootloader_t which) start = offset = 01000; /* from https://www.pdp-11.nl/peripherals/disk/rl-info.html - static uint16_t rl02_code[] = { + constexpr const uint16_t rl02_code[] = { 0012701, 0174400, 0012761, @@ -120,7 +120,7 @@ void set_boot_loader(bus *const b, const bootloader_t which) */ // from http://gunkies.org/wiki/RL11_disk_controller - static uint16_t rl02_code[] = { + constexpr const uint16_t rl02_code[] = { 0012700, 0174400, 0012760, diff --git a/log.cpp b/log.cpp index 62ae93f..d3374db 100644 --- a/log.cpp +++ b/log.cpp @@ -15,7 +15,9 @@ #include "error.h" #include "log.h" #include "utils.h" +#if defined(_WIN32) #include "win32.h" +#endif static const char *logfile = strdup("/tmp/kek.log"); @@ -54,16 +56,19 @@ void setlogfile(const char *const lf, const log_level_t ll_file, const log_level atexit(closelog); } -void setloghost(const char *const host, const log_level_t ll) +bool setloghost(const char *const host, const log_level_t ll) { - inet_aton(host, &syslog_ip_addr.sin_addr); - syslog_ip_addr.sin_port = htons(514); + syslog_ip_addr.sin_family = AF_INET; + bool ok = inet_aton(host, &syslog_ip_addr.sin_addr) == 1; + syslog_ip_addr.sin_port = htons(514); is_file = false; log_level_file = ll; l_timestamp = false; + + return ok; } void setll(const log_level_t ll_screen, const log_level_t ll_file) diff --git a/log.h b/log.h index 50b6ce5..668cf33 100644 --- a/log.h +++ b/log.h @@ -12,9 +12,10 @@ typedef enum { ll_emerg = 0, ll_alert, ll_critical, ll_error, warning, notice, i log_level_t parse_ll(const std::string & str); void setlogfile(const char *const lf, const log_level_t ll_file, const log_level_t ll_screen, const bool l_timestamp); -void setloghost(const char *const host, const log_level_t ll); +bool setloghost(const char *const host, const log_level_t ll); void setll(const log_level_t ll_screen, const log_level_t ll_file); void setloguid(const int uid, const int gid); +void send_syslog(const int ll, const std::string & what); void closelog(); void dolog(const log_level_t ll, const char *fmt, ...); diff --git a/main.cpp b/main.cpp index 7426408..c816370 100644 --- a/main.cpp +++ b/main.cpp @@ -534,9 +534,9 @@ int main(int argc, char *argv[]) if (enable_bootloader) set_boot_loader(b, bootloader); - b->add_rk05(new rk05(rk05_files, b, cnsl->get_disk_read_activity_flag(), cnsl->get_disk_write_activity_flag())); + b->add_rk05(new rk05(b, cnsl->get_disk_read_activity_flag(), cnsl->get_disk_write_activity_flag())); - b->add_rl02(new rl02(rl02_files, b, cnsl->get_disk_read_activity_flag(), cnsl->get_disk_write_activity_flag())); + b->add_rl02(new rl02(b, cnsl->get_disk_read_activity_flag(), cnsl->get_disk_write_activity_flag())); } else { FILE *fh = fopen(deserialize.c_str(), "r"); diff --git a/memory.h b/memory.h index 1a5dcbc..8ec1c14 100644 --- a/memory.h +++ b/memory.h @@ -18,6 +18,8 @@ public: memory(const uint32_t size); ~memory(); + uint32_t get_memory_size() const { return size; } + void reset(); #if IS_POSIX json_t *serialize() const; diff --git a/mmu.cpp b/mmu.cpp index 17abfe5..dddacca 100644 --- a/mmu.cpp +++ b/mmu.cpp @@ -53,8 +53,6 @@ void mmu::setMMR0(uint16_t value) value &= 254; // bits 7...1 are protected } -// TODO if bit 15/14/13 are set (either of them), then do not modify bit 1...7 - MMR0 = value; } @@ -103,17 +101,6 @@ void mmu::addToMMR1(const int8_t delta, const uint8_t reg) assert((getMMR0() & 0160000) == 0); // MMR1 should not be locked -#if defined(ESP32) -// if (MMR1 > 255) -// esp_backtrace_print(32); -#else - if (MMR1 > 255) { - extern FILE *lfh; - fflush(lfh); - } - assert(MMR1 < 256); -#endif - MMR1 <<= 8; MMR1 |= (delta & 31) << 3; diff --git a/rk05.cpp b/rk05.cpp index 34d0c37..2398e54 100644 --- a/rk05.cpp +++ b/rk05.cpp @@ -23,13 +23,11 @@ static const char * const regnames[] = { "RK05_DATABUF " }; -rk05::rk05(const std::vector & files, bus *const b, std::atomic_bool *const disk_read_acitivity, std::atomic_bool *const disk_write_acitivity) : +rk05::rk05(bus *const b, std::atomic_bool *const disk_read_acitivity, std::atomic_bool *const disk_write_acitivity) : b(b), disk_read_acitivity(disk_read_acitivity), disk_write_acitivity(disk_write_acitivity) { - fhs = files; - reset(); } diff --git a/rk05.h b/rk05.h index 5189011..e9b1d3d 100644 --- a/rk05.h +++ b/rk05.h @@ -39,7 +39,7 @@ private: void update_bus_address(const uint16_t v); public: - rk05(const std::vector & files, bus *const b, std::atomic_bool *const disk_read_acitivity, std::atomic_bool *const disk_write_acitivity); + rk05(bus *const b, std::atomic_bool *const disk_read_acitivity, std::atomic_bool *const disk_write_acitivity); virtual ~rk05(); void reset() override; diff --git a/rl02.cpp b/rl02.cpp index 6974218..3b56cce 100644 --- a/rl02.cpp +++ b/rl02.cpp @@ -31,13 +31,11 @@ static const char * const commands[] = { "read data w/o header check" }; -rl02::rl02(const std::vector & files, bus *const b, std::atomic_bool *const disk_read_activity, std::atomic_bool *const disk_write_activity) : +rl02::rl02(bus *const b, std::atomic_bool *const disk_read_activity, std::atomic_bool *const disk_write_activity) : b(b), disk_read_activity (disk_read_activity ), disk_write_activity(disk_write_activity) { - fhs = files; - reset(); } @@ -86,11 +84,11 @@ rl02 *rl02::deserialize(const json_t *const j, bus *const b) { std::vector backends; + rl02 *r = new rl02(b, nullptr, nullptr); + json_t *j_backends = json_object_get(j, "backends"); for(size_t i=0; iaccess_disk_backends()->push_back(disk_backend::deserialize(json_array_get(j_backends, i))); for(int regnr=0; regnr<4; regnr++) r->registers[regnr] = json_integer_value(json_object_get(j, format("register-%d", regnr).c_str())); diff --git a/rl02.h b/rl02.h index be8a96d..966cd14 100644 --- a/rl02.h +++ b/rl02.h @@ -47,7 +47,7 @@ private: uint32_t calc_offset() const; public: - rl02(const std::vector & files, bus *const b, std::atomic_bool *const disk_read_activity, std::atomic_bool *const disk_write_activity); + rl02(bus *const b, std::atomic_bool *const disk_read_activity, std::atomic_bool *const disk_write_activity); virtual ~rl02(); void reset() override; diff --git a/utils.cpp b/utils.cpp index b273316..f5c5d99 100644 --- a/utils.cpp +++ b/utils.cpp @@ -19,7 +19,9 @@ #include #include +#if defined(_WIN32) #include "win32.h" +#endif void setBit(uint16_t & v, const int bit, const bool vb)