Skip to content
This repository has been archived by the owner on Nov 5, 2019. It is now read-only.

Commit

Permalink
bring extra GME files back, from build.git
Browse files Browse the repository at this point in the history
  • Loading branch information
ilg-ul committed May 16, 2018
1 parent 2c04740 commit 813cf97
Show file tree
Hide file tree
Showing 555 changed files with 674,847 additions and 0 deletions.
5 changes: 5 additions & 0 deletions gnu-mcu-eclipse/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
These are additional files added to **GNU MCU Eclipse QEMU**.

- devices: JSON definitions of device peripherals
- graphics: board images
- develop: development notes & misc files
23 changes: 23 additions & 0 deletions gnu-mcu-eclipse/develop/CortexM.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
The main purpose of the GNU ARM Eclipse QEMU was to improve Cortex-M support and provide a framework for adding new Cortex-M MCUs.

The current Cortex-M support includes:

## ARMv7-M

The current emulation supports only Cortex-M3, with Cortex-M4 support to be added soon. FPU support will be added to a later date.

## NVIC

NVIC support is currently via the more generic GIC implementation. It is fully functional but it is not very accurate and in the future will probably require a rewrite.

## SysTick

SysTick is full functional. Currently it is included in the NVIC source file ad in the future will probably be moved to a separate file.

## ITM

The ITM currently implements only the stimulus port 0, used by trace streams.

To simplify things, now the port starts as enabled, but a separate mechanism will be added in the future.


167 changes: 167 additions & 0 deletions gnu-mcu-eclipse/develop/Eclipse-formatter.xml

Large diffs are not rendered by default.

38 changes: 38 additions & 0 deletions gnu-mcu-eclipse/develop/STM32.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
STM32 is the main Cortex-M family emulated by **GNU ARM Eclipse QEMU**, and as such, provides the most accurate emulation.

Currently only the F1 family is implemented, but support for F4 and other families is provisioned, there are some switch case branches to be added.

## RCC

All RCC registers are present in the emulator, although some provide only limited functionality.

The peripheral clock enable bits are not yet made available to peripherals.

## GPIO

Setting the Set/Reset bits is reflected in the ODR bits, so using the GPIO for output operations is functional, but the input bits are not linked to the output bits, nor interrupts are triggered.

## FLASH

The FLASH device is used during the CMSIS initialisation to configure some wait states, and as such is mandatory for the emulator.

Using this device to reprogram the flash will be implemented at a later date, since it will require the flash region to be persistent.

## PWR

The PWR device is used during the CMSIS initialisation and as such it is mandatory for the emulator.

## EXTI

The EXTI device is used to route external interrupts to NVIC, and was added when support for the push buttons was needed.

Support for events is currently not provided.

## SYSCFG

The SYSCFG device is used for devices rom the F4 family, among other things, to configure which GPIO bits are connected to EXTI interrupts.

## USART

Support for USART is currently experimental, and incomplete.

45 changes: 45 additions & 0 deletions gnu-mcu-eclipse/develop/STYLE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@

## C

[QEMU Coding Style](http://git.qemu-project.org/?p=qemu.git;a=blob_plain;f=CODING_STYLE;hb=HEAD)

- indents are four spaces
- tabs are never used
- lines are 80 characters
- variables are **lower\_case\_with\_underscores**
- structured type names are in **CamelCase**
- sScalar type names are **lower\_case\_with\_underscores\_ending\_with\_a\_t**
- declarations should be at the beginning of blocks (?!)

Block structure:

if (a == 5) {
printf("a was 5.\n");
} else if (a == 6) {
printf("a was 6.\n");
} else {
printf("a was something else entirely.\n");
}

void a_function(void)
{
do_something();
}

- suffix interrupt handlers with **\_irq\_handler**
- stm32\_gpio\_in\_irq\_handler
- suffix all other callback functions with **_callback**
- .class\_init = stm32\_gpio\_class\_init\_callback,
- .instance\_init = stm32\_gpio\_instance\_init\_callback,
- dc->reset = stm32\_gpio\_reset\_callback;
- dc->realize = stm32\_gpio\_realize\_callback;
- .read = stm32\_gpio\_read\_callback,
- .write = stm32\_gpio\_write\_callback,


## QOM (QEMU Object Model)

[QOM Conventions](http://wiki.qemu.org/QOMConventions)

- DO use names-separated-by-dashes

41 changes: 41 additions & 0 deletions gnu-mcu-eclipse/develop/TODO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# All

- make the flash persistent (use a file to save at the end, if it was written)

## System memory
- add flash size
- F1: 0x1FFFF7E0
- F1: 0x1FFF7A22
- add device ID
- F1: 1FFFF7E8 (12 bytes)
- F4: 1FFF7A10 (12 bytes)
- add content for System Memory
- F1: 0x1FFFF000-0x1FFFF7FF (2K)
- F4: 0x1FFF0000-0x1FFF77FF
- add Option bytes

## NVIC

Reimplement NVIC as a separate object

## SysTick

Move the SysTick code outside the NVIC source file.

## ITM configuration

Add a configuration mechanism to enable/disable ITM externally, and to configure the stimulus port enable bits.

## ARMv6-M

Add separate code to implement the simplified M0/M0+ (armv6m) excetion specifics.


# STM32

## RCC
- add an API to get access to the clock tree

## GPIO
- check the peripheral clocks from RCC

139 changes: 139 additions & 0 deletions gnu-mcu-eclipse/develop/irqs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
# Interrupts

QEMU uses a custom notification mechanism not only to emulate interrupts, but also to pass values from one object to another.

This mechanism uses `TYPE_IRQ` objects to store the pointer of the interrupt handler. Arrays of such objects are allocated in the incoming end (like NVIC, for actual interrupts, but also other objects that are driven by values set in other parts, like LEDs, etc).

The outgoing end of this mechanism uses plain pointers to `TYPE_IRQ` objects.

This simple implementation has limitations, as oposed to usual observer pattern implementations, it is not possible to register any number of listeners to a single notifier; the application must keep separate pointers to different `TYPE_IRQ` objects and explicitly notify them all.

## Interrupts as named properties of devices

Althoug interrupts can be created and initialised separately, the recommended way is to create them as named properties associated to `TYPE_DEVICE` objects. The device DeviceState structure includes a list (sugestively named `gpios`) which includes elements of type NamedGPIOList, that basically have a name and a pointer to an array of `TYPE_IRQ` objects.


## Incoming

Incoming interrupts are objects that process raise/lower actions invoked by other objects.

To create an array of incoming interrupts in a device use `cm_irq_init_in()` in the instance init callback:

```
cm_irq_init_in(DEVICE(obj), xxx_irq_handler, "xxx-in", size);
```

The names are arbitrary, but it is recommended to suffix incoming interrupts with `-in`.

The handler function should have the following prototype:

```
static void gpio_led_irq_handler(void *opaque, int index, int level)
{
// GPIOLEDState *state = GPIO_LED_STATE(opaque);
// ...
}
```


## Outgoing

Outgoing interrupts are not separate objects, but links to incoming interrupts. Multiple outgoing interrupts can point to the same incoming interrupt.

Arrays of pointers to `TYPE_DEVICE` objects must be defined in the object state.

```
typedef struct {
qemu_irq out_irq[N];
} XxxState;
```

To be able to conveniently address these arrays at global level, use `cm_irq_init_out()` in the instance init callback:

```
cm_irq_init_out(DEVICE(obj), &state->irq_out, "xxx-out", N);
```

## Connect

Each output interrupt must be individually and explicitly connected to its corresponding incoming interrupt.

For example to connect the button to one GPIO pin, use something like this in the realize callback:

```
cm_irq_connect(DEVICE(button), IRQ_BUTTON_GPIO_OUT, 0,
DEVICE(gpio), IRQ_GPIO_IDR_IN, gpio_bit);
```

## Use

Interrupts can be raised or lowered:

```
cm_irq_set(state->out_irq[i], condition ? 1 : 0);
cm_irq_raise(state->out_irq[i]);
cm_irq_lower(state->out_irq[i]);
```

Generally each outgoing interrupt should be connected to one and only one incoming interrupt, with multiple outgoing interrupts being allowed to connect to the same incoming interrupt.

For NVIC exception, each outgoing interrupt should be connected to one NVIC exception, and multiple outgoing interrupt can be connected to the same NVIC exception:

```
cm_irq_connect(dev, IRQ_EXTI_OUT, 5, nvic, IRQ_NVIC_IN, STM32F10X_MD_EXTI9_5_IRQn);
cm_irq_connect(dev, IRQ_EXTI_OUT, 6, nvic, IRQ_NVIC_IN, STM32F10X_MD_EXTI9_5_IRQn);
// ...
```

## Reset

The entire outgoing array can be reset during the reset callback:

```
static void xxx_reset_callback(DeviceState *dev)
{
int i;
XxxxState *state = XXX_STATE(dev);
for (i = 0; i < N; i++) {
cm_irq_lower(state->out_irq[i]);
}
}
```

For regular devices this might be redundant, but for some devices, like active low buttons, the inactive value is 1, and must be explicitly set.

```
cm_irq_raise(button->out_irq);
```

Note: for this to be effective, the button must be reset **after** the GPIO port.


## Core interrupt processing

In `cpu-exec.c`, `cpu_exec()` prepares a `sigsetjmp()` context for exception handling. The context is restored by `cpu_loop_exit()`, called generally from from `raise_exception()`.

Then checks `cpu_handle_exception()` and possibly `cpu_handle_interrupt()`.

`cpu_handle_exception()` uses `cpu->exception_index` and possibly calls `cc->do_interrupt(cpu)`.

`cpu_handle_interrupt()` calls `cc->cpu_exec_interrupt(cpu, interrupt_request)`, which is pointing to `arm_v7m_cpu_exec_interrupt()`.


## Pending an exception

`cortexm_nvic_set_pending_exception()`

`gic_set_pending_private()` checks if pending, and, if not sets it (`s->irq_state[irq].pending |= (cm)`), then calls `gic_update()`.

`gic_update()` enumerates all `s->num_irq`, identifies the highest pending and calls `qemu_set_irq(s->parent_irq[cpu], irq_level)` which calls `arm_cpu_set_irq()`.

## Pending an interrupt

`cortexm_nvic_set_pending_interrupt()`

32 changes: 32 additions & 0 deletions gnu-mcu-eclipse/develop/repos.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
## Repository URLs

- the GNU ARM Eclipse git remote URL to clone from is
- `https://github.com/gnuarmeclipse/qemu.git` (remote *origin*)
- the QEMU git remote URL is
- `git://git.qemu-project.org/qemu.git` (remote *qemu*)

From the remote *qemu*, pull its master → master, then push it to *origin*.

## Update procedures

### The gnuarmeclipse-dev branch

To keep the development repository in sync with the original QEMU repository:

- checkout `master`
- pull from `qemu/master`
- checkout `gnuarmeclipse-dev`
- merge `master`
- add a tag like `gae-2.3.0-201403261500-dev` after each public release

### The gnuarmeclipse branch

To keep the stable development in sync with the development branch:

- checkout `gnuarmeclipse`
- merge `gnuarmeclipse-dev`
- add a tag like `gae-2.3.0-201403261500` after each public release




Loading

0 comments on commit 813cf97

Please sign in to comment.