mirror of
https://github.com/stnolting/neorv32.git
synced 2025-04-20 12:18:07 -04:00
87 lines
5.2 KiB
Text
87 lines
5.2 KiB
Text
<<<
|
|
:sectnums:
|
|
==== General Purpose Input and Output Port (GPIO)
|
|
|
|
[cols="<3,<3,<4"]
|
|
[grid="none"]
|
|
|=======================
|
|
| Hardware source files: | neorv32_gpio.vhd |
|
|
| Software driver files: | neorv32_gpio.c | link:https://stnolting.github.io/neorv32/sw/neorv32__gpio_8c.html[Online software reference (Doxygen)]
|
|
| | neorv32_gpio.h | link:https://stnolting.github.io/neorv32/sw/neorv32__gpio_8h.html[Online software reference (Doxygen)]
|
|
| Top entity ports: | `gpio_o` | 32-bit parallel output port
|
|
| | `gpio_i` | 32-bit parallel input port
|
|
| Configuration generics: | `IO_GPIO_NUM` | number of input/output pairs to implement (0..32)
|
|
| CPU interrupts: | fast IRQ channel 8 | GPIO (see <<_processor_interrupts>>)
|
|
|=======================
|
|
|
|
|
|
**Overview**
|
|
|
|
The general purpose IO unit provides simple uni-directional input and output port. These ports can be used
|
|
chip-externally (for example to drive status LEDs, connect buttons, etc.) or chip-internally to provide control
|
|
signals for other IP modules. The input port features programmable pin-individual level or edge interrupts
|
|
capabilities.
|
|
|
|
Data written to the `PORT_OUT` will appear on the processor's `gpio_o` port. Vice versa, the `PORT_IN` register
|
|
represents the current state of the processor's `gpio_i`.
|
|
|
|
The actual number of input/output pairs is defined by the `IO_GPIO_NUM` generic. When set to zero, the GPIO module
|
|
is excluded from synthesis and the output port `gpio_o` is tied to all-zero. If `IO_GPIO_NUM` is less than the
|
|
maximum value of 32, only the LSB-aligned bits in `gpio_o` and `gpio_i` are actually connected while the remaining
|
|
bits are tied to zero or are left unconnected, respectively. This also applies to all memory-mapped interface
|
|
registers of the GPIO module (i.e. the according most-significant bits are hardwired to zero).
|
|
|
|
|
|
**Input Pin Interrupts**
|
|
|
|
Each input pin (`gpio_i`) provides an individual programmable interrupt trigger. The actual interrupt trigger
|
|
type can be configured individually for each input pin using the `IRQ_TYPE` and `IRQ_POLARITY` registers.
|
|
`IRQ_TYPE` defines the actual trigger type (level-triggered or edge-triggered), while `IRQ_POLARITY` defines
|
|
the trigger's polarity (low-level/falling-edge or high-level/rising-edge). The position of each bit in these
|
|
registers corresponds the according `gpio_i` input pin.
|
|
|
|
Each pin interrupt channel can be enabled or disabled individually using the `IRQ_ENABLE` register. Each bit
|
|
in this register corresponds to the according input pin. If the programmed trigger of a disabled input
|
|
(`IRQ_ENABLE(i) = 0`) fires, the interrupt request is entirely ignored.
|
|
|
|
.GPIO Trigger Configuration for Pin _i_
|
|
[cols="^2,^2,^2,<4"]
|
|
[options="header",grid="all"]
|
|
|=======================
|
|
| `IRQ_ENABLE(i)` | `IRQ_TYPE(i)` | `IRQ_POLARITY(i)` | Resulting trigger of `gpio_i(i)`
|
|
| `1` | `0` | `0` | low-level (`GPIO_TRIG_LEVEL_LOW`)
|
|
| `1` | `0` | `1` | high-level (`GPIO_TRIG_LEVEL_HIGH`)
|
|
| `1` | `1` | `0` | falling-edge (`GPIO_TRIG_EDGE_FALLING`)
|
|
| `1` | `1` | `1` | rising-edge (`GPIO_TRIG_EDGE_RISING`)
|
|
| `0` | `-` | `-` | interrupt disabled
|
|
|=======================
|
|
|
|
If the configured trigger of an enabled input pin (`IRQ_ENABLE(i) = 1`) fires, the according interrupt request
|
|
is buffered internally in the `IRQ_PENDING` register. When this register contains a non-zero value (i.e. any
|
|
bit becomes set) an interrupt request is sent to the CPU via FIRQ channel 8 (see <<_processor_interrupts>>).
|
|
|
|
The CPU can determine the interrupt-triggering pins by reading the `IRQ_PENDING` register. Each set bit in this
|
|
register indicates that the according input pin's interrupt trigger has fired. Then, the CPU can clear those
|
|
pending interrupt pin by setting all set bits to zero.
|
|
|
|
.GPIO Interrupts Demo Program
|
|
[TIP]
|
|
A demo program for the GPIO input interrupts can be found in `sw/example/demo_gpio`.
|
|
|
|
|
|
**Register Map**
|
|
|
|
.GPIO unit register map (`struct NEORV32_GPIO`)
|
|
[cols="<2,<2,^1,^1,<6"]
|
|
[options="header",grid="rows"]
|
|
|=======================
|
|
| Address | Name [C] | Bit(s) | R/W | Function
|
|
| `0xfffc0000` | `PORT_IN` | 31:0 | r/- | Parallel input port; `PORT_IN(i)` corresponds to `gpio_i(i)`
|
|
| `0xfffc0004` | `PORT_OUT` | 31:0 | r/w | Parallel output port; `PORT_OUT(i)` corresponds to `gpio_o(i)`
|
|
| `0xfffc0008` | - | 31:0 | r/- | _reserved_, read as zero
|
|
| `0xfffc000c` | - | 31:0 | r/- | _reserved_, read as zero
|
|
| `0xfffc0010` | `IRQ_TYPE` | 31:0 | r/w | Trigger type select (`0` = level trigger, `1` = edge trigger); `IRQ_TYPE(i)` corresponds to `gpio_i(i)`
|
|
| `0xfffc0014` | `IRQ_POLARITY` | 31:0 | r/w | Trigger polarity select (`0` = low-level/falling-edge, `1` = high-level/rising-edge); `IRQ_POLARITY(i)` corresponds to `gpio_i(i)`
|
|
| `0xfffc0018` | `IRQ_ENABLE` | 31:0 | r/w | Per-pin interrupt enable; `IRQ_ENABLE(i)` corresponds to `gpio_i(i)`
|
|
| `0xfffc001c` | `IRQ_PENDING` | 31:0 | r/c | Per-pin interrupt pending, can be cleared by writing zero to the according bit(s); `IRQ_PENDING(i)` corresponds to `gpio_i(i)`
|
|
|=======================
|