Today I have added support for simulated buttons/switches/LEDs in U-Boot, so my students may also experiment with systems equipped with the button-selectable "rescue mode" (or "administrative mode"). The design is in the branch "gpio_uboot" of the https://github.com/wzab/BR_Internet_Radio repository.
The version of my emulated GPIO connected to the GUI is quite mature. It even simulates the bouncing effect in buttons and switches. You may find it in https://github.com/wzab/BR_Internet_Radio/tree/gpio
Regards,
Wojtek
Reply by ●March 22, 20202020-03-22
OK. It appeared that the problem was trivial. I have learned the solution from https://lxr.missinglinkelectronics.com/qemu/hw/misc/edu.c#L350
I simply had to call qemu_mutex_lock_iothread(); before calling qemu_set_irq() and qemu_mutex_unlock_iothread() after, when generating IRQs in my thread:
static void * remote_gpio_thread(void * arg)
{
//Here we receive the data from the queue
const int MSG_MAX = 8192;
char buf[MSG_MAX];
gpio_msg * mg = (gpio_msg *)&buf;
mqd_t mq = mq_open("/to_qemu",O_CREAT | O_RDONLY,0x660,NULL);
if(mq<0) {
perror("I can't open mq");
exit(1);
}
while(1) {
int res = mq_receive(mq,buf,8192,NULL);
if(res<0) {
perror("I can't receive");
exit(1);
}
if(res != sizeof(gpio_msg)) continue;
if((int) mg->magick[0]*256+mg->magick[1] != REMOTE_GPIO_MAGICK) {
printf("Wrong message received");
}
if(mg->pin < 32) {
qemu_mutex_lock_iothread();
mpc8xxx_gpio_set_irq(arg,mg->pin,mg->state);
qemu_mutex_unlock_iothread();
}
}
}
Reply by ●March 22, 20202020-03-22
My code handles input and output, but still has a problem with interrupts. When I enable interrupt for a pin, then I get error in QEMU:
buildroot-2020.02/output/build/host-qemu-4.2.0/accel/tcg/tcg-all.c:40:tcg_handle_interrupt: assertion failed: (qemu_mutex_iothread_locked())
Obviously I must modify handling of input so that interrupts are not triggered when mutex is locked.
Reply by ●March 21, 20202020-03-21
I have managed to modify the model of the MPC8XXX GPIO in QEMU so that it works together with the GUI written in Python. The communication is established via POSIX message queues. The code is available at alt.sources group https://groups.google.com/forum/#!topic/alt.sources/_EbOdnQKZ18
The full project that uses the modified MPC8XXX in an emulated Vexpress A9 board is available in in https://github.com/wzab/BR_Internet_Radio repository
in branch "gpio".
The code is just a "proof of the concept" so it lacks error checking, and probably is buggy, but it works for me.
I hope that somebody may find it useful and develop the concept further.
With best regards,
Wojtek
PS. The concept is inspired by the "remote port" solution introduced by Xilinx in their version of QEMU (see the files with names starting with "remote-port" in the https://github.com/Xilinx/qemu/tree/master/include/hw and https://github.com/Xilinx/qemu/tree/master/hw/core directories.)
I think that the application implementing the GUI could use msgpack ( https://msgpack.org/ ) protocol to communicate the QEMU.
So whenever the QEMU changes the state of the pin, it sends a message contining two fields:
Direction: (In, Out)
State: (High, Low, High Impedance)
Whenever somebody changes the state of the pin in the GUI, similar message is sent to QEMU, but it should contain only one field:
State: (High, Low)
I assume that the logic that resolves collisions and generates the random state when somebody tries to read the not connected input should be implemented in the GUI application.
What do you think about it?