RFC: Low power "Halt" ARM seimhosting call

Executing OBCSW on top of the HAL clone in the QEMU emulator uses 100% of a CPU core, so I decided to investigate if there was any way to improve this. I looked into if there was any hidden FreeRTOS tasks in ISIS's libraries that were not yielding very often, but found nothing. I also looked into the QEMU emulator itself, but QEMU doesn't usually use 100% CPU usage when it runs other guests, so I dropped that idea.

I finally found out that the cause is likely FreeRTOS itself. By default, FreeRTOS does busy waiting when all tasks are suspended or blocked. I confirmed this by looking at the FreeRTOS idle task in the OBCSW ELF file in ghidra. I'm pretty sure there is no hardware support in the iOBC to actually go into a low power mode, so this makes sense.

However, for the hardware that does support it, FreeRTOS provides a Tickless Low Power mode. This mode allows FreeRTOS to halt for as predicted max amount of time, and then, using an external source of time, calculate the number of ticks that has passed and adjust the tick counter accordingly. This made me think, would it not be possible to compile a version of ISIS distribution that has Tickless Low Power enabled, and leverage QEMU to actually support it? FreeRTOS is GPL licensed, so ISIS should have no problems with us making our modification of their FreeRTOS port public in the future.

I looked into the options for ARM semihosting syscalls to make QEMU go to sleep, but the only option I found was to call SYS_SYSTEM with an argument of "sleep 0.003" or somthing like that. Then the "external time source" could be emulated using SYS_ELAPSED or SYS_CLOCK. The problem with this however is that invoking a sleep command in QEMU is going to introduce an overhead, and most importantly, it's going to make QEMU unable to read input from stdin, causing a severe performance hit.

Therefore, a suggestion could be to add a custom semihosting call, say SYS_HALT, that will take the maximum number of ticks or milliseconds or whatever to halt for, and return the number of milliseconds or ticks that it actually halted for. As for how to implement it, it could be done using the pthread_cond_timedwait POSIX call. When at91-dbgu.c gets a character from the QEMU character front-end, it will signal the condition and make the guest thread wake up if it is sleeping.

Edited by William Stackenäs