RT-Thread RTOS
An open source embedded real-time operating system
PIC core framework

Core framework (<tt>pic.c</tt>, <tt>pic_rthw.c</tt>)

Registration, ISR attach, trap dispatch, and global IRQ control wrappers.


<tt>struct rt_pic</tt> / <tt>struct rt_pic_ops</tt>

rt_pic_ops Role
**irq_init / irq_finit** Controller-wide setup (called from **rt_pic_irq_init**)
**irq_enable / irq_disable** Optional gate
**irq_mask / irq_unmask** Mask line at hardware
**irq_ack / irq_eoi** Acknowledge / end of interrupt
**irq_map** Allocate virtual IRQ from hwirq + mode (required for OFW)
**irq_parse** Decode **#interrupt-cells** into **out_pirq** (required for OFW)
**irq_set_priority / irq_set_affinity / irq_set_triger_mode** Configuration
**irq_send_ipi** SMP IPI
MSI: **irq_alloc_msi**, **irq_compose_msi_msg**, … PIC and PCI MSI
**flags** **RT_PIC_F_IRQ_ROUTING** — parent dispatches children in **rt_pic_handle_isr**

Trap path (root PIC)

Root PIC (CPU-facing) registers a trap handler:

rt_pic_add_traps(my_root_handler, pic);

CPU exception → **rt_pic_do_traps()** → first handler returning **RT_TRUE**:

  1. Read hwirq from hardware (e.g. GIC IAR in pic-gicv2.c)
  2. Map to **pirq** (IPI vs SPI)
  3. **irq_ack** → **rt_pic_handle_isr(pirq)** → **irq_eoi**

Child PICs without traps are reached via cascade or dedicated parent ISR (PIC cascade and routing).


<tt>rt_pic_handle_isr</tt>

  1. If **children_nodes** non-empty: for each child, **irq_ack**, recursive **rt_pic_handle_isr(child)**, **irq_eoi**
  2. Call primary **pirq->isr.action.handler(irq, param)**
  3. Call chained ISRs on **pirq->isr.list**

Used by root trap and by software demux (e.g. Rockchip PCIe legacy ISR).


Attach / detach

rt_err_t rt_pic_attach_irq(int irq, rt_isr_handler_t handler, void *uid,
const char *name, int flags);
rt_err_t rt_pic_detach_irq(int irq, void *uid);
  • **irq**: virtual global number
  • First handler uses embedded **pirq->isr**; additional handlers malloc **struct rt_pic_isr** nodes
  • **rt_hw_interrupt_install** in **pic_rthw.c** wraps **rt_pic_attach_irq**

Global IRQ API

Thin wrappers: **irq2pirq(irq)** → **pirq->pic->ops->…**

void rt_pic_irq_mask(int irq);
void rt_pic_irq_unmask(int irq);
void rt_pic_irq_eoi(int irq);
/* … priority, affinity, trigger mode, IPI … */

**rt_hw_interrupt_mask / umask** in arch code call these.


Init refcount (<tt>phye</tt>-style pattern in phye.c — here init/power on PIC is per-op at device level)

For **rt_phye**-like refcount see phye; PIC uses per-pirq ISR and init_count only inside individual drivers.

PIC core **rt_phye_init** N/A — use **irq_map** once per DT line.


<tt>rt_pic_register</tt> pattern (provider)

There is no single **rt_pic_register** — providers:

  1. Embed **struct rt_pic** in driver private data
  2. Set **ops**, **priv_data**
  3. **rt_pic_linear_irq**
  4. **rt_ofw_data(np) = &pic** (or **rt_dm_dev_bind_fwdata**)
  5. Optional **rt_pic_user_extends**, **rt_pic_add_traps**

See also