Hi,
I have implemented QEMU support for several of the peripherals found in the Kinetis KL-series of microcontrollers, to various degrees: the Bit Manipulation Engine (BME) addressing extension, LPUART, LPTMR, MCGLite, SIM, SMC, GPIO/PORT.
The BME, and GPIO/PORT are feature-complete. LPUART and LPTMR support most common modes of operation. Reads/writes to SIM/SMC/MCGLite are emulated correctly, but they don't interact with any other parts of the system (i.e. peripherals are always clocked, the core/bus frequency cannot be changed, regardless of the actual settings in SMC/MCGLite).
I am hosting the repository with these changes here: https://github.com/Wallacoloo/qemu-kinetis (it is the master branch).
Additionally, I will attach diffs in reference to commit 240a9b744 of the gnuarmeclipse branch of the repository hosted here ( git://git.code.sf.net/p/gnuarmeclipse/qemu ), created with git format-patch 240a9b744 --stdout > wallacoloo.patch.
Of the MCUs listed in hw/arm/kinetis_mcus.c, I have only added these new peripherals to the system bus for the mkl03z32vfk4, but one can easily add them to any other KL MCU.
Feedback is welcomed & apologies if I have not posted this in the correct location.
Colin
ok, great!
I'm not familiar with the KL peripherals, but in my oppinion the minimum that needs to be implemented are those peripherals used by CMSIS SystemInit & Co., possibly by the special initialisations used in KDS templates, if any.
the goal is to run a simple blinky application, similarly to those for STM32F4-Discovery.
are you considering adding the LED definitions to the boards?
could you also correctly update the internal system clock, so that SysTick runs at the correct speed?
also I'm curious why did you choose not to use the new register definitions, and implement everything by hand?
the idea is that in a future version I plan to read the vendor SVD files and generate all processor registers automatically, so I would not spend much time with manual definitions.
it looks like you based your work on a preliminary version of GNU ARM QEMU, perhaps it would be useful to check the latest version.
Some background on this PR: My intention was to use QEMU to perform automated testing on a project I designed around a KL03. So I searched for a fork of QEMU that had done the most work towards supporting the KL series (that is, this fork) & implemented all the peripherals my particular project needed in order to not hard fault ;-)
Looking through the SystemInit function in system_MKL03Z4.c, it reads/writes to registers under PMC, SIM, SMC, PORTA, MCG and OSC, though all under a net of #ifdefs. In my case, the init routine only wrote to SIM, SMC, MCGLite & PORT. So 67% of the work is done - only PMC and OSC need to be implemented for the default startup routines to work in all use cases.
I can make whatever small tweaks might be necessary to make these fit in with the GNUArmEclipse code base, but since this development has been sponsored by my employer & the project I was working on is now completed, I can't justifiably put in the time required to implement the remaining 2 peripherals.
I'm not totally sure what you mean by the LED definitions. My project controls some LEDs, but it just sets the appropriate GPIO pin high/low to turn on/off the LED, and that's handled correctly in my implementation of the GPIO/PORT peripheral. Whereas the UART can be interfaced with over stdio, I couldn't find any resources to access the GPIO pins externally, so the way that I verify the state of an output pin/LED in my tests is to attach a gdb process to the program being simulated &
p/x {uint32_t} 0x400FF000(i.e. inspect the Port Data Output Register). Inputs are achieved the same way, but by writing to the Port Data Input Register instead.I could look into this. At a glance, it looks like I can just write to the global
system_clock_scalevariable defined in hw/arm/arm.h? That one seems to be in units of 100 kHz (?), and I believe you can run many of these micros of the 32 kHz crystal, so I'm not sure how that would be reconcilable.Well I did much searching online and through the codebase for documentation on how to add new peripherals before beginning. The internals of the QEMU codebase seemed, from my point of view, extremely under-documented. In the end I just took an existing peripheral, cloned it and modified it to match the Kinetis implementation, then repeated with the rest. I looked through about a dozen peripheral implementations & this is how they all seemed to function.
if you have a few minutes, please update to the latest Eclipse plug-ins and the latest QEMU and follow the steps from:
http://gnuarmeclipse.livius.net/blog/blinky-project/
or at least please take a look at the picture from:
http://gnuarmeclipse.livius.net/blog/2015/08/02/gnu-arm-eclipse-qemu-2-3-50-20150801-dev-released/
the 4 LEDs are defined in:
https://github.com/gnuarmeclipse/qemu/blob/gnuarmeclipse-dev/hw/arm/stm32-boards.c
yes, but you just used my deprecated APIs, which will no longer be supported in future versions, and missed the point with the new mechanisms I added, which are not present in the original QEMU.
please take a look at the stm32-gpio implementation:
https://github.com/gnuarmeclipse/qemu/blob/gnuarmeclipse-dev/hw/gpio/stm32-gpio.c
there are two important points:
also the MCUs should be defined in terms of capabilities, and the actual peripherals should test these bits, to implement various families and subfamilies in the same file, otherwise code duplication creates a big maintenance problem.
Ah, I see. No, my interest is only in implementing the MCU - I added a board definition just because the examples I found were for launching FRDM-xxx boards rather than specific MCUs & I thought it'd be easiest to just follow that convention.
The APIs I used are the ones exposed in vanilla QEMU (i.e. MemoryRegionOps: https://github.com/gnuarmeclipse/qemu/blob/master/include/exec/memory.h). There is no deprecation note anywhere in that file regarding any functions I used & MemoryRegionOps is used extensively within QEMU and on non-arm architectures, so I don't think you have to worry about these APIs going anywhere.
Agreed. If there is an easy way to achieve this then I will modify my code to support that, provided that you think these peripherals are worth merging.
cortex_m0p_core_init() is not part of the vanilla QEMU and will no longer be available in future versions.
I see. I rebased my changes against your dev branch, and it looks as though all of the MCUs defined in
kinetis-mcus.care still using thiscortex_mxx_core_init()function, despite it currently being defined asreturn NULLand thus totally breaking everything. What is the intended replacement?Btw, the rebased fork can be found here: https://github.com/Wallacoloo/qemu-kinetis/tree/gae-rebase2
please take a look at how the STM32 families are implemented.
as I already mentioned, please keep in mind that the entire mechanism of defining cores and peripherals will be migrated to a generic engine that will read external json files, prepared off-line from the CMSIS SVD files.
I don't have a deadline for this, but the use of register tables validated the concept, the difference being that those tables (slightly trimmed to match the CMSIS definitions) will no longer be entered manually.