diff --git a/hw/arm/prusa/launch-xl.sh b/hw/arm/prusa/launch-xl.sh index 9e57066a11..5bc7f2499b 100755 --- a/hw/arm/prusa/launch-xl.sh +++ b/hw/arm/prusa/launch-xl.sh @@ -24,13 +24,19 @@ esac MAIN_FW="public.bin" MODBED_BL="newbl/bootloader-v296-prusa_modular_bed-1.0.elf" DWARF_BL="newbl/bootloader-v296-prusa_dwarf-1.0.elf" -ESP_SERIAL="-chardev serial,id=stm32uart7,path=/dev/ttyUSB0" -# ESP_SERIAL="-chardev pty,id=stm32uart7" +#ESP_SERIAL="-chardev serial,id=stm32uart7,path=/dev/ttyUSB1" +#ESP_SERIAL="-chardev socket,id=stm32uart7,path=/tmp/esp" +#ESP_SERIAL="-chardev pty,id=stm32uart7" +rm bed.log +rm e0.log +rm esp32.log clear && ./qemu-system-buddy -machine prusa-xl-${XL} -kernel ${MAIN_FW} ${ESP_SERIAL} -chardev stdio,id=stm32_itm -drive id=usbstick,file=fat:rw:sd2 -device usb-storage,drive=usbstick -icount 1 -S -s & sleep 1 && # screen -SDm dwarf5 ./qemu-system-buddy -machine prusa-xl-extruder-g0-4 -kernel newbl/bootloader-v296-prusa_dwarf-1.0.elf -icount 5 & # screen -SDm dwarf4 ./qemu-system-buddy -machine prusa-xl-extruder-g0-3 -kernel newbl/bootloader-v296-prusa_dwarf-1.0.elf -icount 5 & # screen -SDm dwarf3 ./qemu-system-buddy -machine prusa-xl-extruder-g0-2 -kernel newbl/bootloader-v296-prusa_dwarf-1.0.elf -icount 5 & # screen -SDm dwarf2 ./qemu-system-buddy -machine prusa-xl-extruder-g0-1 -kernel newbl/bootloader-v296-prusa_dwarf-1.0.elf -icount 5 & -screen -SDm dwarf ./qemu-system-buddy -machine prusa-xl-extruder-${DWARF}-0 -kernel ${DWARF_BL} -icount 2 & -sleep 2 && screen -SDm modbed ./qemu-system-buddy -machine prusa-xl-bed-${MODBED} -kernel ${MODBED_BL} -icount 6 +screen -L -Logfile e0.log -SDm dwarf ./qemu-system-buddy -machine prusa-xl-extruder-${DWARF}-0 -kernel ${DWARF_BL} -icount 5 & +sleep 2 && screen -L -Logfile bed.log -SDm bed ./qemu-system-buddy -machine prusa-xl-bed-${MODBED} -kernel ${MODBED_BL} -icount 4 \ +& sleep 1 && screen -L -Logfile esp32.log -SDm esp32 ./qemu-system-xtensa -machine prusa-xl-esp32 killall qemu-system-buddy +killall qemu-system-xtensa diff --git a/hw/arm/prusa/parts/xl_bridge.c b/hw/arm/prusa/parts/xl_bridge.c index f67cac50d0..07d69edcf6 100644 --- a/hw/arm/prusa/parts/xl_bridge.c +++ b/hw/arm/prusa/parts/xl_bridge.c @@ -48,7 +48,8 @@ static const char* shm_names[XL_BRIDGE_COUNT] = "PXL_E2", "PXL_E3", "PXL_E4", - "PXL_E5" + "PXL_E5", + "PXL_ESP32" }; // Messages are composed of some GPIO status bits @@ -82,7 +83,7 @@ struct XLBridgeState { CharBackend chr[XL_BRIDGE_COUNT]; CharBackend gpio[XL_BRIDGE_COUNT]; - qemu_irq byte_receive; + qemu_irq byte_receive[XLBRIDGE_UART_COUNT]; qemu_irq gpio_out[XLBRIDGE_PIN_COUNT]; @@ -160,8 +161,17 @@ static void xl_bridge_tx_assert(void *opaque, int n, int level) static void xl_bridge_byte_send(void *opaque, int n, int level) { - // TODO - construct the control byte. XLBridgeState *s = XLBRIDGE(opaque); + + // ESP uart isn't RS485, just forward on the data (this is from ESP to STM32)... + if (n == XLBRIDGE_UART_ESP32) + { + uint8_t data = level; + //printf("ESP32: %02x (%c)\n", data, data); + qemu_chr_fe_write_all(&s->chr[XL_DEV_ESP32], (uint8_t*)&data, 1); + return; + } + //uint16_t data = 0x00FF | (level & 0xFF)<<8; // swap the bytes here so they come in in the right order. // Buffer up the data for a single-shot transmit. s->buffer[s->buffer_level++] = level & 0xFF; @@ -198,7 +208,7 @@ static int xl_bridge_gpio_can_receive(void *opaque) return 1; // Currently only 1 byte increments. } -static void xl_bridge_receive(void *opaque, const uint8_t *buf, int size) +static void _xl_bridge_receive(void *opaque, const uint8_t *buf, int size, int destination) { XLBridgeState *s = XLBRIDGE(opaque); //#define FILTER size < 20 && s->id == XL_DEV_XBUDDY @@ -207,12 +217,28 @@ static void xl_bridge_receive(void *opaque, const uint8_t *buf, int size) if (FILTER) printf(" %u Received: ", s->id); for (const uint8_t* p = buf; pbyte_receive, *p); + qemu_set_irq(s->byte_receive[destination], *p); if (FILTER) printf("%02x ",*p); } if (FILTER) printf("\n"); } +static inline void xl_bridge_receive(void *opaque, const uint8_t *buf, int size) +{ + _xl_bridge_receive(opaque, buf, size, XLBRIDGE_UART_PUPPY); +} + +static int xl_bridge_esp_can_receive(void *opaque) +{ + return 1; // Currently only 1 byte increments. +} + +static inline void xl_bridge_esp_receive(void *opaque, const uint8_t *buf, int size) +{ + // printf("ESP32 said: %02x (%c)\n", buf[0], buf[0]); + _xl_bridge_receive(opaque, buf, size, XLBRIDGE_UART_ESP32); +} + #define PROCESS_BIT(pin, field) \ if (s->gpio_states[s->id].bits.field != state.bits.field) \ { \ @@ -340,7 +366,7 @@ static void xl_bridge_realize(DeviceState *dev, Error **errp) XLBridgeState *s = XLBRIDGE(dev); if (s->id == XL_DEV_XBUDDY) { - for (int i=XL_DEV_T4; i>=XL_DEV_BED; i--) // just two tools for now, because of the "server" wait. + for (int i=XL_DEV_ESP32; i>=XL_DEV_BED; i--) // just two tools for now, because of the "server" wait. { Chardev* d=qemu_chr_find(shm_names[i]); gchar* io_name = g_strdup_printf("%s-io",shm_names[i]); @@ -356,18 +382,19 @@ static void xl_bridge_realize(DeviceState *dev, Error **errp) printf("Socket ID %s - not found, creating it instead.\n", shm_names[i]); QemuOpts *opts; // Now create the IO (GPIO) channel. - opts = qemu_opts_create(qemu_find_opts("chardev"), g_strdup_printf("%s-io",shm_names[i]), 1, NULL); - qemu_opt_set(opts, "backend","socket", errp); - qemu_opt_set(opts, "path", g_strdup_printf("/tmp/%s-io", shm_names[i]), errp); - qemu_opt_set(opts, "server", "on", errp); - qemu_opt_set_bool(opts, "wait", false, errp); - d2 = qemu_chr_new_from_opts(opts, NULL, errp); - qemu_opts_del(opts); + opts = qemu_opts_create(qemu_find_opts("chardev"), g_strdup_printf("%s-io",shm_names[i]), 1, NULL); + qemu_opt_set(opts, "backend","socket", errp); + qemu_opt_set(opts, "path", g_strdup_printf("/tmp/%s-io", shm_names[i]), errp); + qemu_opt_set(opts, "server", "on", errp); + qemu_opt_set_bool(opts, "wait", false, errp); + d2 = qemu_chr_new_from_opts(opts, NULL, errp); + qemu_opts_del(opts); + opts = qemu_opts_create(qemu_find_opts("chardev"), g_strdup(shm_names[i]), 1, NULL); qemu_opt_set(opts, "backend","socket", errp); qemu_opt_set(opts, "path", g_strdup_printf("/tmp/%s", shm_names[i]), errp); qemu_opt_set(opts, "server", "on", errp); - if (i > XL_DEV_T0) // Only force wait for required items, namely tool 0 and the bed. + if (i > XL_DEV_T0 && i != XL_DEV_ESP32) // Only force wait for required items, namely tool 0 and the bed. { qemu_opt_set_bool(opts, "wait", false, errp); } @@ -376,8 +403,16 @@ static void xl_bridge_realize(DeviceState *dev, Error **errp) } qemu_chr_fe_init(&s->chr[i],d, errp); - qemu_chr_fe_set_handlers(&s->chr[i], xl_bridge_can_receive, xl_bridge_receive, NULL, - NULL,s,NULL,true); + if (i != XL_DEV_ESP32) + { + qemu_chr_fe_set_handlers(&s->chr[i], xl_bridge_can_receive, xl_bridge_receive, NULL, + NULL,s,NULL,true); + } + else + { + qemu_chr_fe_set_handlers(&s->chr[i], xl_bridge_esp_can_receive, xl_bridge_esp_receive, NULL, + NULL,s,NULL,true); + } qemu_chr_fe_accept_input(&s->chr[i]); qemu_chr_fe_init(&s->gpio[i],d2, errp); @@ -406,15 +441,28 @@ static void xl_bridge_realize(DeviceState *dev, Error **errp) qemu_opt_set(opts, "path", g_strdup_printf("/tmp/%s-io", shm_names[s->id]), errp); d2 = qemu_chr_new_from_opts(opts, NULL, errp); qemu_opts_del(opts); - opts = qemu_opts_create(qemu_find_opts("chardev"), g_strdup(shm_names[s->id]), 1, NULL); - qemu_opt_set(opts, "backend","socket", errp); - qemu_opt_set(opts, "path", g_strdup_printf("/tmp/%s", shm_names[s->id]), errp); - d = qemu_chr_new_from_opts(opts, NULL, errp); - qemu_opts_del(opts); + // ESP can't really use this mecahnism right now. Maybe in the future if it's cleaned up... + if (s->id != XL_DEV_ESP32) + { + opts = qemu_opts_create(qemu_find_opts("chardev"), g_strdup(shm_names[s->id]), 1, NULL); + qemu_opt_set(opts, "backend","socket", errp); + qemu_opt_set(opts, "path", g_strdup_printf("/tmp/%s", shm_names[s->id]), errp); + d = qemu_chr_new_from_opts(opts, NULL, errp); + qemu_opts_del(opts); + } } qemu_chr_fe_init(&s->chr[s->id],d, errp); - qemu_chr_fe_set_handlers(&s->chr[s->id], xl_bridge_can_receive, xl_bridge_receive, NULL, - NULL,s,NULL,true); + if (s->id != XL_DEV_ESP32) + { + qemu_chr_fe_set_handlers(&s->chr[s->id], xl_bridge_can_receive, xl_bridge_receive, NULL, + NULL,s,NULL,true); + } + else + { + qemu_chr_fe_set_handlers(&s->chr[s->id], xl_bridge_esp_can_receive, xl_bridge_esp_receive, NULL, + NULL,s,NULL,true); + } + qemu_chr_fe_accept_input(&s->chr[s->id]); qemu_chr_fe_init(&s->gpio[s->id],d2, errp); @@ -449,9 +497,9 @@ static void xl_bridge_init(Object *obj) XLBridgeState *s = XLBRIDGE(obj); // Serial I/O IRQs DeviceState* dev = DEVICE(obj); - qdev_init_gpio_in_named(dev, xl_bridge_byte_send, "byte-send", 1); + qdev_init_gpio_in_named(dev, xl_bridge_byte_send, "byte-send", XLBRIDGE_UART_COUNT); qdev_init_gpio_in_named(dev, xl_bridge_tx_assert, "tx-assert", 1); - qdev_init_gpio_out_named(dev, &s->byte_receive, "byte-receive", 1); + qdev_init_gpio_out_named(dev, s->byte_receive, "byte-receive", XLBRIDGE_UART_COUNT); qdev_init_gpio_in_named(dev, xl_bridge_gpio_in, "gpio-in",XLBRIDGE_PIN_COUNT); qdev_init_gpio_in_named(dev, xl_bridge_reset_in, "reset-in", XL_BRIDGE_COUNT); diff --git a/hw/arm/prusa/parts/xl_bridge.h b/hw/arm/prusa/parts/xl_bridge.h index de22d741b7..c20afbb049 100644 --- a/hw/arm/prusa/parts/xl_bridge.h +++ b/hw/arm/prusa/parts/xl_bridge.h @@ -1,7 +1,7 @@ /* xl_bridge.h - include with defines for bridge properties. - Copyright 2022-3 VintagePC + Copyright 2022-4 VintagePC This file is part of Mini404. @@ -30,6 +30,7 @@ enum { XL_DEV_T3, XL_DEV_T4, XL_DEV_T5, + XL_DEV_ESP32, XL_BRIDGE_COUNT }; @@ -47,5 +48,12 @@ enum { XLBRIDGE_PIN_nAC_FAULT, XLBRIDGE_PIN_RESET, XLBRIDGE_PIN_Z_UM, + XLBRIDGE_PIN_ESP_GPIO0, XLBRIDGE_PIN_COUNT }; + +enum { + XLBRIDGE_UART_PUPPY = 0, + XLBRIDGE_UART_ESP32, + XLBRIDGE_UART_COUNT +}; diff --git a/hw/arm/prusa/prusa-xl-esp32.c b/hw/arm/prusa/prusa-xl-esp32.c new file mode 100644 index 0000000000..98cbbf4e6e --- /dev/null +++ b/hw/arm/prusa/prusa-xl-esp32.c @@ -0,0 +1,148 @@ +/* + * Prusa XL embedded ESP32 machine model. + * + * Copyright 2024 VintagePC + * + * It's just a derived version that adds some convenience wrapping + * for the control lines and the automatic UART connection from xl-bridge + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "qemu/units.h" +#include "qapi/error.h" +#include "hw/boards.h" +#include "hw/sysbus.h" +#include "sysemu/block-backend.h" +#include "sysemu/sysemu.h" +#include "chardev/char.h" +#include "hw/qdev-properties.h" +#include "hw/core/split-irq.h" +#include "qemu/error-report.h" +#include "parts/xl_bridge.h" + +#define FLASH_FN "Prusa_XL_ESP32_flash.bin" +#define FLASH_ID "prusa-xl-esp32-flash" + +// Yes, I'm being really lazy about this right now. +// Long term, this shuold be consolidated with the version in stm32_common. + +static bool create_if_not_exist(const char* default_name, uint32_t file_size) +{ + bool exists = true; + if (access(default_name, R_OK | W_OK) == -1) + { +#ifndef CONFIG_GCOV + printf("%s not found - creating it.\n",default_name); +#endif + // Create it. + int fd = creat(default_name, S_IRUSR | S_IWUSR); + exists = (ftruncate(fd, file_size) != -1); + close(fd); + } + return exists; +} + +static BlockBackend* get_or_create_drive(BlockInterfaceType interface, int index, const char* default_name, const char* label, uint32_t file_size, Error** errp) +{ + BlockBackend *blk = blk_by_name(label); + if (blk) + { + return blk; + } + DriveInfo* dinfo = drive_get(interface, 0, index); + if (!dinfo) + { + if (create_if_not_exist(default_name, file_size)) + { +#ifndef CONFIG_GCOV + printf("No -%s drive specified, using default %s\n", + interface==IF_MTD? "mtdblock" : "pflash", + default_name); +#endif + QemuOpts* drive_opts = drive_add(interface, index, default_name, "format=raw"); + dinfo = drive_new(drive_opts, interface, errp); + } + } + return blk_by_legacy_dinfo(dinfo); +} + + +static void prusa_esp32_init(MachineState *machine) +{ + // Set strap mode so it's not needed on command line. + GlobalProperty *g; + g = g_malloc0(sizeof(*g)); + g->driver = "esp32.gpio"; + g->property = "strap_mode"; + g->value = "0x0f"; + qdev_prop_register_global(g); + + // Create chardev handler. We can't pipe bytes directly into the UART like the STM32 side, so it's a bit more complex. + if (!serial_hd(0)) + { + QemuOpts *opts; + opts = qemu_opts_create(qemu_find_opts("chardev"), "prusaxl-esp32", 1, NULL); + qemu_opt_set(opts, "backend","socket", &error_fatal); + qemu_opt_set(opts, "path", "/tmp/PXL_ESP32", &error_fatal); + qemu_chr_new_from_opts(opts, NULL, &error_fatal); + qemu_opts_del(opts); + } + + // Create flash storage: + get_or_create_drive(IF_MTD, 0, FLASH_FN, FLASH_ID, 4U*MiB, &error_fatal); + + DeviceState *dev = qdev_new("xl-bridge"); + qdev_prop_set_uint8(dev, "device", XL_DEV_ESP32); + + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + + // Invoke parent + ObjectClass *oc = object_class_by_name(MACHINE_TYPE_NAME("esp32")); + if (oc != NULL) + { + MachineClass *mc = MACHINE_CLASS(oc); + mc->init(machine); + } + + + // qdev_connect_gpio_out_named(stm32_soc_get_periph(dev_soc, STM32_P_UART1),"byte-out", 0, qdev_get_gpio_in_named(dev, "byte-send",0)); + // qdev_connect_gpio_out_named(dev, "byte-receive", 0, qdev_get_gpio_in_named(stm32_soc_get_periph(dev_soc, STM32_P_UART1),"byte-in", 0)); +}; + +static void xlbuddy_esp32_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + mc->desc = "Prusa XL embedded ESP32"; + mc->family = "xlbuddy-machine", + mc->no_parallel = true; + mc->no_serial = true; + mc->init = prusa_esp32_init; +} + +static const TypeInfo xlbuddy_esp32_machine_types[] = { + { + .name = MACHINE_TYPE_NAME("prusa-xl-esp32"), + .parent = MACHINE_TYPE_NAME("esp32"), + .class_init = xlbuddy_esp32_class_init, + } +}; + +DEFINE_TYPES(xlbuddy_esp32_machine_types) diff --git a/hw/arm/prusa/prusa-xl.c b/hw/arm/prusa/prusa-xl.c index d60530196a..510dbc7d28 100644 --- a/hw/arm/prusa/prusa-xl.c +++ b/hw/arm/prusa/prusa-xl.c @@ -680,8 +680,11 @@ static void xl_init(MachineState *machine, xl_cfg_t cfg) qdev_prop_set_uint8(dev, "device", XL_DEV_XBUDDY); sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); qdev_connect_gpio_out(stm32_soc_get_periph(dev_soc, STM32_P_GPIOG), 1, qdev_get_gpio_in_named(dev,"tx-assert",0)); - qdev_connect_gpio_out_named(stm32_soc_get_periph(dev_soc, STM32_P_UART3),"uart-byte-out", 0, qdev_get_gpio_in_named(dev, "byte-send",0)); - qdev_connect_gpio_out_named(dev, "byte-receive", 0, qdev_get_gpio_in_named(stm32_soc_get_periph(dev_soc, STM32_P_UART3),"uart-byte-in", 0)); + qdev_connect_gpio_out_named(stm32_soc_get_periph(dev_soc, STM32_P_UART3),"uart-byte-out", 0, qdev_get_gpio_in_named(dev, "byte-send", XLBRIDGE_UART_PUPPY)); + qdev_connect_gpio_out_named(dev, "byte-receive", 0, qdev_get_gpio_in_named(stm32_soc_get_periph(dev_soc, STM32_P_UART3),"uart-byte-in", XLBRIDGE_UART_PUPPY)); + + qdev_connect_gpio_out_named(stm32_soc_get_periph(dev_soc, STM32_P_UART8),"uart-byte-out", 0, qdev_get_gpio_in_named(dev, "byte-send", XLBRIDGE_UART_ESP32)); + qdev_connect_gpio_out_named(dev, "byte-receive", XLBRIDGE_UART_ESP32, qdev_get_gpio_in_named(stm32_soc_get_periph(dev_soc, STM32_P_UART8),"uart-byte-in", 0)); qdev_connect_gpio_out(stm32_soc_get_periph(dev_soc, BANK(cfg.m_step[AXIS_E])), PIN(cfg.m_step[AXIS_E]), qdev_get_gpio_in_named(dev,"gpio-in",XLBRIDGE_PIN_E_STEP)); qdev_connect_gpio_out(stm32_soc_get_periph(dev_soc, BANK(cfg.m_dir[AXIS_E])), PIN(cfg.m_dir[AXIS_E]), qdev_get_gpio_in_named(dev,"gpio-in",XLBRIDGE_PIN_E_DIR)); @@ -694,6 +697,7 @@ static void xl_init(MachineState *machine, xl_cfg_t cfg) qdev_connect_gpio_out(expander, 3, qdev_get_gpio_in_named(dev,"reset-in",XL_DEV_T2)); qdev_connect_gpio_out(expander, 4, qdev_get_gpio_in_named(dev,"reset-in",XL_DEV_T3)); qdev_connect_gpio_out(expander, 5, qdev_get_gpio_in_named(dev,"reset-in",XL_DEV_T4)); + qdev_connect_gpio_out(stm32_soc_get_periph(dev_soc, STM32_P_GPIOG), 4, qdev_get_gpio_in_named(dev,"reset-in",XL_DEV_ESP32)); } //qdev_connect_gpio_out(stm32_soc_get_periph(dev_soc, BANK(cfg.m_dir[AXIS_E])), PIN(cfg.m_dir[AXIS_E]), qdev_get_gpio_in_named(dev,"gpio-in",XLBRIDGE_PIN_nAC_FAULT)); diff --git a/hw/arm/prusa/stm32f407/stm32_uart.c b/hw/arm/prusa/stm32f407/stm32_uart.c index 68f0bd9992..4fb96defea 100644 --- a/hw/arm/prusa/stm32f407/stm32_uart.c +++ b/hw/arm/prusa/stm32f407/stm32_uart.c @@ -180,7 +180,14 @@ static void stm32_uart_start_tx(Stm32Uart *s, uint32_t value) stm32_uart_tx_complete(s); #else /* Otherwise, start the transmit delay timer. */ - timer_mod(s->tx_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + s->ns_per_char); + if (s->parent.periph == STM32_P_UART8) + { + timer_mod(s->tx_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + (s->ns_per_char)/10); + } + else + { + timer_mod(s->tx_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + s->ns_per_char); + } #endif } @@ -411,6 +418,9 @@ static void stm32_uart_reset(DeviceState *dev) s->curr_irq_level = 0; + // Empty the RX buffer... + s->rcv_char_bytes = 0; + // Do not initialize USART_DR - it is documented as undefined at reset // and does not behave like normal registers. //stm32_uart_USART_BRR_write(s, 0x00000000, true); diff --git a/hw/arm/prusa/stm32f407/stm32f2xx_tim.c b/hw/arm/prusa/stm32f407/stm32f2xx_tim.c index eb8cca7382..af78fbf89e 100644 --- a/hw/arm/prusa/stm32f407/stm32f2xx_tim.c +++ b/hw/arm/prusa/stm32f407/stm32f2xx_tim.c @@ -133,7 +133,10 @@ static void f2xx_tim_update_irqs(f2xx_tim *s) flags |= (s->regs[R_TIM_SR] & INT_CCOF_MASK) >> 8; flags &= s->regs[R_TIM_DIER]; qemu_set_irq(s->irq[IRQ_GLOBAL], flags > 0); - qemu_set_irq(s->public_irq, flags > 0); + if (flags & INT_UIF) + { + qemu_irq_raise(s->public_irq); + } if (!qemu_irq_is_connected(s->irq[IRQ_GLOBAL])) { qemu_set_irq(s->irq[IRQ_CC], (flags & INT_CC_MSK) > 0); diff --git a/hw/xtensa/esp32.c b/hw/xtensa/esp32.c index 28b360599b..f8fc316654 100644 --- a/hw/xtensa/esp32.c +++ b/hw/xtensa/esp32.c @@ -759,7 +759,19 @@ static void esp32_machine_init(MachineState *machine) if (blk) { ss->dport.flash_blk = blk; } - qdev_prop_set_chr(DEVICE(ss), "serial0", serial_hd(0)); + + // Probably an epic kludge, but I couldn't find a better way to do this by + // e.g. back-populating a -serial cmdline argument to get picked up by serial_hd() + // ~VintagePC + Chardev* cdev = qemu_chr_find("prusaxl-esp32"); + if (cdev) + { + qdev_prop_set_chr(DEVICE(ss), "serial0", cdev); + } + else + { + qdev_prop_set_chr(DEVICE(ss), "serial0", serial_hd(0)); + } qdev_prop_set_chr(DEVICE(ss), "serial1", serial_hd(1)); qdev_prop_set_chr(DEVICE(ss), "serial2", serial_hd(2)); if (machine->ram_size > 0) { diff --git a/hw/xtensa/meson.build b/hw/xtensa/meson.build index 695f15bd42..4124eb83bc 100644 --- a/hw/xtensa/meson.build +++ b/hw/xtensa/meson.build @@ -7,6 +7,6 @@ xtensa_ss.add(files( xtensa_ss.add(when: 'CONFIG_XTENSA_SIM', if_true: files('sim.c')) xtensa_ss.add(when: 'CONFIG_XTENSA_VIRT', if_true: files('virt.c')) xtensa_ss.add(when: 'CONFIG_XTENSA_XTFPGA', if_true: files('xtfpga.c')) -xtensa_ss.add(when: 'CONFIG_XTENSA_ESP32', if_true: files('esp32.c', 'esp32_intc.c')) +xtensa_ss.add(when: 'CONFIG_XTENSA_ESP32', if_true: files('esp32.c', 'esp32_intc.c', '../arm/prusa/prusa-xl-esp32.c', '../arm/prusa/parts/xl_bridge.c')) hw_arch += {'xtensa': xtensa_ss}