Tüm eğitimler
TEKNİK REHBER GÖMÜLÜ LİNUX ÇOK ÇEKİRDEK 2026

OpenAMP
Heterojen Çok Çekirdek İletişimi

remoteproc, RPMsg ve virtio katmanlarıyla Cortex-A Linux + Cortex-M RTOS aynı SoC üzerinde — STM32MP1, i.MX8M ve AM62x uygulamaları.

00 Heterojen SoC mimarisi

Modern SoC'lar aynı silikon üzerinde farklı mimarilere sahip işlemcileri bir araya getirir: güçlü Cortex-A uygulama işlemcisi yanında gerçek zamanlı görevler için Cortex-M mikrodenetleyici.

Neden heterojen tasarım

Güç verimliliğiCortex-M tipik olarak mW mertebesinde çalışırken Cortex-A W mertebesinde güç tüketir. Sensör okuma gibi sürekli görevler için M çekirdeği A çekirdeğini uyandırmaktan çok daha verimlidir.
Gerçek zamanlı deterministlikLinux çekirdeği öncelik tersine çevrilmesi, IRQ gecikmesi ve bellek yönetimi nedeniyle kesin zaman garantisi vermez. Cortex-M + RTOS mikrosaniye mertebesinde gecikme sunar.
Güvenlik izolasyonuM çekirdeği güvenli firmware çalıştırırken A çekirdeği kullanıcı uygulamalarını koşturabilir. TrustZone ile kriptografik işlemler izole edilebilir.
Görev ayrımıMotor kontrol, ADC örnekleme, PWM gibi donanım yakın görevler M'de; ağ yığını, kullanıcı arayüzü, OTA güncellemesi A'da çalışır.

Yaygın heterojen SoC'lar

SoCA çekirdeğiM çekirdeğiBellekTipik kullanım
STM32MP157Cortex-A7 (2 çekirdek, 650 MHz)Cortex-M4 (209 MHz)DDR3 + SRAMEndüstriyel kontrol, tıbbi
STM32MP135Cortex-A7 (1 çekirdek, 1 GHz)DDR3LHMI, IoT gateway
i.MX8M PlusCortex-A53 (4 çekirdek)Cortex-M7 (800 MHz)LPDDR4ML + gerçek zamanlı kontrol
i.MX8M MiniCortex-A53 (4 çekirdek)Cortex-M4 (400 MHz)LPDDR4Ses, enerji yönetimi
AM62x (AM6254)Cortex-A53 (4 çekirdek)Cortex-M4F (x2)LPDDR4Endüstriyel HMI, otomotiv
AM64xCortex-A53 (2 çekirdek)Cortex-M4F + R5FDDR4EtherCAT, CAN, motor kontrol

İki çekirdek arasındaki iletişim seçenekleri

Cortex-A (Linux)                    Cortex-M (RTOS / bare-metal)
     │                                      │
     │  ┌─────────────────────────┐         │
     ├──│  Shared Memory (DDR)    │─────────┤
     │  └─────────────────────────┘         │
     │  ┌─────────────────────────┐         │
     ├──│  Mailbox / IPC HW       │─────────┤  ← IRQ tetikler
     │  └─────────────────────────┘         │
     │  ┌─────────────────────────┐         │
     ├──│  OpenAMP (RPMsg/virtio) │─────────┤  ← Bu rehberin konusu
     │  └─────────────────────────┘         │
     │  ┌─────────────────────────┐         │
     └──│  RPMSG char / tty       │─────────┘  ← Kullanıcı alanı arayüzü

Bu bölümde

  • Heterojen SoC: aynı çipte A (Linux) + M (RTOS) — güç, deterministlik, izolasyon
  • Popüler SoC'lar: STM32MP1, i.MX8M, AM62x — her birinde Cortex-M yan işlemci
  • OpenAMP: shared memory + mailbox üzerine inşa edilen standart iletişim katmanı

01 OpenAMP bileşenleri

OpenAMP (Open Asymmetric Multi-Processing), üç temel katmandan oluşur: remoteproc (yaşam döngüsü), virtio/vring (aktarım), RPMsg (mesajlaşma).

Katman mimarisi

Kullanıcı alanı
┌────────────────────────────────────────────┐
│  /dev/rpmsg0  /dev/ttyRPMSG0              │
│  rpmsg_char driver   rpmsg_tty driver     │
└────────────────────────────────────────────┘
        │
Kernel alanı
┌────────────────────────────────────────────┐
│  RPMsg çerçevesi  (mesaj yönlendirme)      │
│  ┌──────────────────────────────────────┐  │
│  │  virtio + vring  (ring buffer DMA)   │  │
│  └──────────────────────────────────────┘  │
│  ┌──────────────────────────────────────┐  │
│  │  remoteproc  (firmware lifecycle)    │  │
│  └──────────────────────────────────────┘  │
│  ┌──────────────────────────────────────┐  │
│  │  mailbox driver  (IPC interrupt)     │  │
│  └──────────────────────────────────────┘  │
│  ┌──────────────────────────────────────┐  │
│  │  libmetal  (shared memory, I/O)      │  │
│  └──────────────────────────────────────┘  │
└────────────────────────────────────────────┘
        │ Shared DDR + HW Mailbox
Cortex-M tarafı (bare-metal / FreeRTOS)
┌────────────────────────────────────────────┐
│  OpenAMP lib: remoteproc_virtio + rpmsg    │
│  libmetal: bellek/IRQ soyutlama            │
│  RTOS: FreeRTOS / Zephyr / ThreadX         │
└────────────────────────────────────────────┘

Bileşen görevleri

libmetalDüşük seviyeli donanım soyutlama: bellek eşleme, önbellek yönetimi, I/O port erişimi, kesme yönetimi. Hem A hem M tarafında kullanılır.
remoteprocLinux tarafında M çekirdeğinin yaşam döngüsünü yönetir: firmware yükleme, başlatma, durdurma, crash recovery. /sys/class/remoteproc/ arayüzü sunar.
virtioSanallaştırma dünyasından alınan standart cihaz arayüzü. M tarafı bir virtio cihaz, A tarafı virtio sürücü görevi görür. vring halka tamponları veri taşır.
RPMsgvirtio üzerinde çalışan hafif mesajlaşma protokolü. Her channel için kaynak/hedef adres (endpoint) tanımlanır; 512 byte'a kadar mesaj gönderilir.

OpenAMP proje bileşenleri

BileşenKonumAçıklama
openampgithub.com/OpenAMP/open-ampÇekirdek kütüphane: remoteproc, rpmsg, virtio
libmetalgithub.com/OpenAMP/libmetalDonanım soyutlama katmanı
openamp-system-referencegithub.com/OpenAMP/openamp-system-referenceDemo uygulamalar ve BSP örnekleri
Kernel remoteprocdrivers/remoteproc/Linux kernel remoteproc sürücüleri
Kernel rpmsgdrivers/rpmsg/Linux kernel RPMsg çerçevesi

Bu bölümde

  • OpenAMP = libmetal + remoteproc + virtio/vring + RPMsg
  • libmetal: donanım soyutlama (her iki tarafta)
  • remoteproc: M çekirdeği yaşam döngüsü (Linux kernel sürücüsü)
  • RPMsg: virtio tabanlı 512B mesajlaşma — endpoint adresleme

02 remoteproc

remoteproc alt sistemi, Linux'un kardeş işlemciyi (remote processor) yönetmesini sağlar: ELF firmware yükleme, başlatma, durdurma ve güvenli yeniden başlatma.

remoteproc sysfs arayüzü

sysfs düğümüOkumaYazma
/sys/class/remoteproc/remoteproc0/stateoffline / running / suspended / crashedstart / stop
/sys/class/remoteproc/remoteproc0/firmwareFirmware adıFirmware adını değiştir
/sys/class/remoteproc/remoteproc0/coredumpcrash sonrası dump etkinleştirdisabled / enabled / inline
/sys/class/remoteproc/remoteproc0/recoveryOtomatik yeniden başlatma durumuenabled / disabled
/sys/class/remoteproc/remoteproc0/nameRemoteproc adı

Firmware yükleme ve başlatma

bash
# Firmware dosyasının yerini kontrol et (/lib/firmware/ altında olmalı)
ls /lib/firmware/stm32mp157c-rproc.elf

# Hangi firmware yüklenecek?
cat /sys/class/remoteproc/remoteproc0/firmware
# stm32mp157c-rproc.elf

# Firmware adını değiştir (çalışmıyorken)
echo "myfirmware.elf" > /sys/class/remoteproc/remoteproc0/firmware

# Cortex-M çekirdeğini başlat
echo "start" > /sys/class/remoteproc/remoteproc0/state

# Durum kontrolü
cat /sys/class/remoteproc/remoteproc0/state
# running

# Cortex-M çekirdeğini durdur
echo "stop" > /sys/class/remoteproc/remoteproc0/state

# Kernel log'unda remoteproc mesajlarını izle
dmesg | grep remoteproc

remoteproc sürücü zinciri

Platform device tree: &m4_rproc { ... }
        │
        ▼
SoC özgü remoteproc sürücüsü
  (stm32_rproc.c / imx_rproc.c / ti_k3_r5_remoteproc.c)
        │  firmware yükleme isteği
        ▼
request_firmware("stm32mp157c-rproc.elf")
        │  /lib/firmware/ üzerinden
        ▼
ELF ayrıştırma + resource table okuma
        │
        ├─ Bellek bölgelerini eşle (carveout)
        ├─ vdev'leri başlat (virtio)
        ├─ Mailbox kanallarını aç
        │
        ▼
M çekirdeği PC/SP değerlerini yaz → reset kaldır
        │
        ▼
M çekirdeği çalışıyor → virtio handshake

Kernel konfigürasyonu

Kconfig
CONFIG_REMOTEPROC=y
CONFIG_STM32_RPROC=y          # STM32MP için
# CONFIG_IMX_REMOTEPROC=y     # i.MX için
# CONFIG_TI_K3_R5_REMOTEPROC=y  # AM62x/AM64x için
CONFIG_RPMSG=y
CONFIG_RPMSG_VIRTIO=y
CONFIG_RPMSG_CHAR=y           # /dev/rpmsgX karakter aygıtları
CONFIG_RPMSG_TTY=y            # /dev/ttyRPMSGX sanal seri port
CONFIG_VIRTIO=y
CONFIG_VIRTIO_MMIO=y          # Bellek eşlemeli virtio
CONFIG_MAILBOX=y
# STM32 için:
CONFIG_STM32_IPCC=y           # STM32 IPCC mailbox

Bu bölümde

  • /sys/class/remoteproc/remoteproc0/: state, firmware, coredump, recovery
  • echo start/stop ile M çekirdeği kontrolü
  • ELF firmware: /lib/firmware/ altında, resource table içermeli
  • SoC özgü sürücü: stm32_rproc, imx_rproc, ti_k3_r5_remoteproc

03 RPMsg

RPMsg (Remote Processor Messaging), virtio vring halka tamponları üzerine inşa edilmiş hafif bir mesajlaşma çerçevesidir. Her endpoint bir adres-port çiftine sahiptir; mesajlar 512 bayta kadardır.

RPMsg mesaj yapısı

C
/* Kernel kaynak: include/linux/rpmsg.h */

struct rpmsg_hdr {
    __u32 src;    /* Kaynak endpoint adresi */
    __u32 dst;    /* Hedef endpoint adresi */
    __u32 reserved;
    __u16 len;    /* Yük uzunluğu (maks 512 byte) */
    __u16 flags;
    __u8  data[]; /* Mesaj verisi */
} __packed;

Linux tarafında RPMsg sürücüsü yazma

C
#include <linux/module.h>
#include <linux/rpmsg.h>

/* Mesaj geldiğinde çağrılır */
static int mydrv_cb(struct rpmsg_device *rpdev,
                    void *data, int len,
                    void *priv, u32 src)
{
    dev_info(&rpdev->dev, "M4'ten mesaj (src=%u, len=%d): %.*s\n",
             src, len, len, (char *)data);

    /* M4'e yanıt gönder */
    rpmsg_send(rpdev->ept, "ACK", 3);
    return 0;
}

static int mydrv_probe(struct rpmsg_device *rpdev)
{
    dev_info(&rpdev->dev, "RPMsg kanalı açıldı (src=%u dst=%u)\n",
             rpdev->src, rpdev->dst);

    /* Karşı tarafa tanışma mesajı gönder */
    rpmsg_send(rpdev->ept, "HELLO", 5);
    return 0;
}

static void mydrv_remove(struct rpmsg_device *rpdev)
{
    dev_info(&rpdev->dev, "RPMsg kanalı kapandı\n");
}

/* Bu isim, M4 tarafındaki endpoint adıyla eşleşmeli */
static struct rpmsg_device_id mydrv_id_table[] = {
    { .name = "my-rpmsg-channel" },
    { },
};
MODULE_DEVICE_TABLE(rpmsg, mydrv_id_table);

static struct rpmsg_driver mydrv = {
    .drv.name = "my_rpmsg_driver",
    .id_table = mydrv_id_table,
    .probe    = mydrv_probe,
    .remove   = mydrv_remove,
    .callback = mydrv_cb,
};
module_rpmsg_driver(mydrv);

Kullanıcı alanından RPMsg erişimi

bash
# rpmsg_char modülü yüklü olmalı
modprobe rpmsg_char

# RPMsg karakter aygıtları oluştur
ls /dev/rpmsg*
# /dev/rpmsg0   /dev/rpmsg_ctrl0

# rpmsg_ctrl üzerinden yeni endpoint aç
# (rpmsg_create_ept ioctl)

# Doğrudan okuma/yazma:
echo "Merhaba M4" > /dev/rpmsg0
cat /dev/rpmsg0   # M4'ten gelen veriyi oku

# ttyRPMSG sanal seri port ile (rpmsg_tty modülü)
modprobe rpmsg_tty
ls /dev/ttyRPMSG*
# /dev/ttyRPMSG0
minicom -D /dev/ttyRPMSG0 -b 115200

RPMsg endpoint adresleme

Adres 0x35 (53)name service endpoint — kanal keşfi için ayrılmış
Dinamik adresLinux tarafı, rpmsg_create_ept() ile dinamik olarak adres alır
M4 sabit adresM4 tarafı genellikle sabit adres kullanır; Linux name service üzerinden eşleşir
RPMSG_ADDR_ANYKaynak adres olarak kullanılırsa kernel uygun boş adresi atar

Bu bölümde

  • RPMsg: src/dst endpoint adresi + maks 512B mesaj
  • Kernel sürücüsü: rpmsg_driver + callback — name ile otomatik eşleşme
  • Kullanıcı alanı: /dev/rpmsg0 (char) veya /dev/ttyRPMSG0 (tty)
  • Name service (0x35): kanal adı üzerinden otomatik keşif ve eşleşme

04 Cortex-M tarafı

M çekirdeği, OpenAMP kütüphanesini doğrudan kullanarak RPMsg endpoint oluşturur, mesaj alır ve gönderir. FreeRTOS ile entegrasyon en yaygın yaklaşımdır.

OpenAMP bare-metal kurulumu

C
/* M4 tarafı: OpenAMP + FreeRTOS ile RPMsg endpoint */
#include "openamp/open_amp.h"
#include "metal/alloc.h"
#include "metal/sys.h"

/* Virtio cihaz ve vring yapıları (resource table'dan gelir) */
static struct virtio_device vdev;
static struct rpmsg_virtio_device rvdev;
static struct metal_io_region shm_io;

/* RPMsg endpoint */
static struct rpmsg_endpoint my_ept;

/* Mesaj alındığında çağrılır (ISR veya task context'ten) */
static int rpmsg_recv_callback(struct rpmsg_endpoint *ept,
                               void *data, size_t len,
                               uint32_t src, void *priv)
{
    /* Gelen veriyi işle */
    uint8_t *msg = (uint8_t *)data;

    /* Yanıt gönder */
    rpmsg_send(ept, "ACK", 3);
    return 0;
}

/* OpenAMP başlatma */
void openamp_init(void) {
    struct metal_init_params metal_params = METAL_INIT_DEFAULTS;

    /* libmetal başlat */
    metal_init(&metal_params);

    /* Shared memory I/O bölgesini kaydet */
    metal_io_init(&shm_io,
                  (void *)SHARED_MEM_BASE,   /* Fiziksel adres */
                  &(uint64_t){SHARED_MEM_BASE},
                  SHARED_MEM_SIZE,
                  (unsigned int)-1,          /* page_shift: sayfa yok */
                  0,                         /* flags */
                  NULL);                     /* ops */

    /* Resource table'dan virtio cihaz oluştur */
    rproc_virtio_init_vdev(&vdev,
                           &rsc_table->vdev,
                           VDEV_NOTIFY_ID,
                           notify_callback, NULL);

    /* RPMsg virtio cihaz başlat */
    rpmsg_init_vdev(&rvdev, &vdev,
                    rpmsg_ns_callback,   /* name service callback */
                    &shm_io,
                    &rpmsg_vring_rx,
                    &rpmsg_vring_tx,
                    RPMSG_ROLE_REMOTE);  /* M4 = remote, A7 = host */
}

/* Endpoint oluştur ve kaydet */
void create_endpoint(void) {
    struct rpmsg_device *rdev = rpmsg_virtio_get_rpmsg_device(&rvdev);

    rpmsg_create_ept(&my_ept,
                     rdev,
                     "my-rpmsg-channel",   /* Kanal adı (Linux sürücüsüyle eşleşmeli) */
                     RPMSG_ADDR_ANY,       /* Yerel adres: dinamik ata */
                     RPMSG_ADDR_ANY,       /* Uzak adres: name service'den öğren */
                     rpmsg_recv_callback,
                     NULL);
}

Mailbox (IPC) kesme işleme

C
/* STM32MP1 IPCC kesme işleyici (M4 tarafı) */
void IPCC_C1_RX_IRQHandler(void)
{
    /* A7'den M4'e gelen bildirim */
    /* virtio vring'de yeni mesaj var */
    rproc_virtio_notified(&vdev, VRING0_ID);

    /* Kesme bayrağını temizle */
    HAL_IPCC_RxCallback(&hipcc, IPCC_CHANNEL_1, IPCC_CHANNEL_DIR_TX);
}

/* M4'ten A7'ye bildirim gönder */
static void notify_callback(struct virtio_device *vdev,
                            uint32_t notifyid)
{
    /* A7 tarafına IRQ gönder (IPCC üzerinden) */
    HAL_IPCC_NotifyCPU2(&hipcc, IPCC_CHANNEL_1, IPCC_CHANNEL_DIR_RX);
}

FreeRTOS task ile RPMsg döngüsü

C
/* FreeRTOS task: RPMsg mesaj işleme döngüsü */
void rpmsg_task(void *pvParameters)
{
    openamp_init();
    create_endpoint();

    /* Bağlantı kurulana kadar bekle */
    while (!rpmsg_endpoint_is_bound(&my_ept)) {
        taskYIELD();
    }

    /* Ana döngü: mesaj gönder ve bekle */
    for (;;) {
        /* Sensör verisi örneği gönder */
        sensor_data_t sensor = read_sensor();
        rpmsg_send(&my_ept, &sensor, sizeof(sensor));

        /* 100ms bekle */
        vTaskDelay(pdMS_TO_TICKS(100));
    }
}

/* FreeRTOS task oluşturma (main veya scheduler başlatılmadan önce) */
xTaskCreate(rpmsg_task, "RPMsg", 512, NULL, tskIDLE_PRIORITY + 1, NULL);

Bu bölümde

  • M4 tarafı: metal_init + rpmsg_init_vdev + rpmsg_create_ept
  • Rol: M4 = RPMSG_ROLE_REMOTE, A7/Linux = host
  • Mailbox IRQ: A7'den bildirim geldiğinde rproc_virtio_notified() çağır
  • FreeRTOS: ayrı task ile RPMsg döngüsü, endpoint_is_bound() ile bağlantı kontrolü

05 Shared memory ve resource table

Resource table, M4 ELF firmware içinde gömülü bir veri yapısıdır. Linux remoteproc bu tabloyu okuyarak paylaşımlı bellek bölgelerini, vdev'leri ve trace buffer'ı yapılandırır.

Resource table yapısı

C
/* M4 ELF firmware içindeki resource_table bölümü */
/* Linker script'te: .resource_table bölümü tanımlanmalı */

#include "openamp/remoteproc.h"

/* Resource table yapısı — SoC'a göre değişir */
struct __resource_table {
    struct resource_table base;

    /* Kaynak sayısı kadar offset */
    uint32_t offset[2];

    /* 1. Kaynak: Paylaşımlı bellek carveout */
    struct fw_rsc_carveout shm_carveout;

    /* 2. Kaynak: virtio cihaz (RPMsg için) */
    struct fw_rsc_vdev     vdev;
    struct fw_rsc_vdev_vring vring0;  /* TX vring (M4 -> A7) */
    struct fw_rsc_vdev_vring vring1;  /* RX vring (A7 -> M4) */
    uint8_t vdev_features[RSC_VDEV_FEATURE_SIZE];

    /* 3. Kaynak: Trace buffer */
    struct fw_rsc_trace trace;
} __packed;

/* ELF içinde .resource_table bölümüne yerleştir */
__attribute__((section(".resource_table")))
struct __resource_table rsc_table = {
    .base = {
        .ver = 1,           /* Resource table versiyon */
        .num = 2,           /* Kaynak sayısı */
    },
    .offset = { offsetof(struct __resource_table, shm_carveout),
                offsetof(struct __resource_table, vdev) },

    .shm_carveout = {
        .type    = RSC_CARVEOUT,
        .da      = 0x10040000,   /* M4 görüş adresi */
        .pa      = 0x10040000,   /* Fiziksel adres */
        .len     = 0x10000,      /* 64 KB */
        .flags   = 0,
        .name    = "OPENAMP_SHM",
    },

    .vdev = {
        .type        = RSC_VDEV,
        .id          = VIRTIO_ID_RPMSG,  /* 7 */
        .notifyid    = 0,
        .dfeatures   = 1,       /* VIRTIO_RPMSG_F_NS */
        .gfeatures   = 0,
        .config_len  = 0,
        .status      = 0,
        .num_of_vrings = 2,
    },

    .vring0 = {
        .da     = FW_RSC_ADDR_ANY,  /* Linux tarafından atanır */
        .align  = 4096,
        .num    = 16,               /* Descriptor sayısı */
        .notifyid = 0,
    },
    .vring1 = {
        .da     = FW_RSC_ADDR_ANY,
        .align  = 4096,
        .num    = 16,
        .notifyid = 1,
    },

    .trace = {
        .type = RSC_TRACE,
        .da   = 0x10050000,   /* Trace buffer adresi */
        .len  = 0x1000,       /* 4 KB */
        .name = "M4_TRACE",
    },
};

Bellek haritası planlaması

DDR Bellek Haritası (STM32MP157 örneği)
┌──────────────────┬──────────────┬─────────────────────────┐
│  Adres           │  Boyut       │  Kullanım               │
├──────────────────┼──────────────┼─────────────────────────┤
│  0xC0000000      │  512 MB      │  Linux DDR (DT reserved) │
│  0xDD000000      │  1 MB        │  M4 DDR firmware        │
│  0xDD100000      │  64 KB       │  Carveout: vring + IPC  │
│  0xDD110000      │  4 KB        │  Trace buffer           │
│  0x10000000      │  64 KB       │  M4 SRAM (yerel)        │
└──────────────────┴──────────────┴─────────────────────────┘

Device tree'de carveout bölge tanımlama

dts
/* arch/arm/boot/dts/stm32mp157c-myboard.dts */

/ {
    reserved-memory {
        #address-cells = <1>;
        #size-cells = <1>;
        ranges;

        /* M4 firmware için ayrılmış DDR bölgesi */
        mcuram: mcuram@dd000000 {
            compatible = "shared-dma-pool";
            reg = <0xdd000000 0x100000>;   /* 1 MB */
            no-map;
        };

        /* OpenAMP paylaşımlı bellek */
        openamp_shmem: openamp-shmem@dd100000 {
            compatible = "shared-dma-pool";
            reg = <0xdd100000 0x10000>;    /* 64 KB */
            no-map;
        };
    };

    /* remoteproc düğümü */
    &m4_rproc {
        memory-region = <&mcuram>, <&openamp_shmem>;
        mboxes = <&ipcc 0>, <&ipcc 1>;
        mbox-names = "vq0", "vq1";
        status = "okay";
    };
};

Bu bölümde

  • Resource table: ELF içindeki .resource_table bölümü — carveout + vdev + trace
  • vring: iki yönlü halka tampon — TX (M4→A7) ve RX (A7→M4)
  • Device tree: reserved-memory ile carveout bölge no-map olarak ayrılır
  • FW_RSC_ADDR_ANY: vring adresini Linux dinamik olarak atar

06 STM32MP1 üzerinde OpenAMP

STM32MP157, Cortex-A7 ve Cortex-M4'ü aynı çipte barındırır. ST, Linux tarafı için OpenSTLinux dağıtımını ve M4 tarafı için STM32CubeMP1 HAL + FreeRTOS referans paketini sağlar.

Gerekli yazılım bileşenleri

OpenSTLinux (A7 tarafı)ST'nin Yocto tabanlı Linux dağıtımı; stm32_rproc.ko, rpmsg.ko ve IPCC sürücülerini içerir
STM32CubeMP1 (M4 tarafı)HAL kütüphanesi + OpenAMP + FreeRTOS referans projesi; CubeIDE ile derlenir
OpenAMP kütüphanesigithub.com/STMicroelectronics/openamp — ST yamaları içeren özel dal
IPCC (Inter-Processor Communication Controller)STM32MP1 dahili donanım mailbox; iki çekirdek arası kesme kanalları sağlar

Yocto ile OpenAMP etkinleştirme

bash
# meta-st-stm32mp layer'ı içeren Yocto projesi
# local.conf veya image recipe:

IMAGE_INSTALL:append = " \
    kernel-modules \
    rpmsg-utils \
    copro-utils \
"

# Firmware dosyasını rootfs'e koy
# meta-mylayer/recipes-firmware/m4-firmware/m4-firmware.bb
bash
# Hedef üzerinde M4 firmware başlatma

# 1. Firmware dosyasını /lib/firmware/ altına koy
cp stm32mp157c-rproc.elf /lib/firmware/

# 2. remoteproc sysfs üzerinden başlat
echo "stm32mp157c-rproc.elf" > /sys/class/remoteproc/remoteproc0/firmware
echo start > /sys/class/remoteproc/remoteproc0/state

# 3. Durum kontrolü
cat /sys/class/remoteproc/remoteproc0/state    # running

# 4. RPMsg kanalının açılıp açılmadığını kontrol et
dmesg | grep rpmsg
# rpmsg_virtio0: creating channel my-rpmsg-channel addr 0x400

# 5. Kullanıcı alanından test
ls /dev/rpmsg*
echo "test" > /dev/rpmsg0
cat /dev/rpmsg0

M4 trace buffer okuma

bash
# M4 firmware'in yazdığı trace buffer'ı oku
cat /sys/kernel/debug/remoteproc/remoteproc0/trace0

# Örnek M4 çıktısı:
# [M4] OpenAMP baslatiliyor...
# [M4] RPMsg endpoint olusturuldu: addr=1024
# [M4] A7 baglantisi kuruldu
# [M4] Sensor: temp=25.3C, humidity=65%

Copro (coprocessor) servis birimi

systemd unit
[Unit]
Description=STM32MP1 M4 Coprocessor
After=multi-user.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/copro-utils start stm32mp157c-rproc.elf
ExecStop=/usr/bin/copro-utils stop
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

Bu bölümde

  • STM32MP157: A7 Linux + M4 FreeRTOS, IPCC donanım mailbox üzerinden haberleşir
  • Firmware: /lib/firmware/ altında ELF; copro-utils veya sysfs ile başlatılır
  • Trace buffer: /sys/kernel/debug/remoteproc/remoteproc0/trace0 — M4 log çıktısı
  • Yocto: meta-st-stm32mp layer + rpmsg-utils + copro-utils

07 i.MX8M ve AM62x üzerinde OpenAMP

i.MX8M ve AM62x, STM32MP1'den farklı SoC mimarisine sahiptir; remoteproc sürücüleri ve device tree yapısı değişir ancak OpenAMP kullanım modeli aynı kalır.

i.MX8M Plus — Cortex-M7

dts — i.MX8M Plus
/* arch/arm64/boot/dts/freescale/imx8mp-myboard.dts */

/ {
    reserved-memory {
        #address-cells = <2>;
        #size-cells = <2>;
        ranges;

        /* M7 için ayrılmış bellek */
        m7_reserved: m7-reserved@55000000 {
            no-map;
            reg = <0 0x55000000 0 0x1000000>;  /* 16 MB */
        };

        /* vdev ring buffers */
        vdev0vring0: vdev0vring0@55000000 {
            no-map;
            reg = <0 0x55000000 0 0x8000>;
        };
        vdev0vring1: vdev0vring1@55008000 {
            no-map;
            reg = <0 0x55008000 0 0x8000>;
        };
        vdev0buffer: vdev0buffer@55400000 {
            compatible = "shared-dma-pool";
            no-map;
            reg = <0 0x55400000 0 0x100000>;
        };
    };

    &rpmsg {
        memory-region = <&vdev0buffer>;
        status = "okay";
    };
};

/* Kernel: CONFIG_IMX_REMOTEPROC=y */
bash — i.MX8M
# i.MX8M M7 firmware başlatma
# NXP MCUXpresso SDK veya Zephyr ile derlenen ELF kullanılır

# Firmware konumu
ls /lib/firmware/imx8mp-cm7-*

# remoteproc0 = M7 çekirdeği
echo "imx8mp-cm7-rpmsg.elf" > /sys/class/remoteproc/remoteproc0/firmware
echo start > /sys/class/remoteproc/remoteproc0/state

# i.MX8M MU (Messaging Unit) — mailbox mekanizması
# IPCC yerine MU kullanılır: drivers/mailbox/imx-mailbox.c
# Kernel: CONFIG_IMX_MBOX=y

AM62x (TI) — Cortex-M4F

BileşenAM62x'te karşılığı
remoteproc sürücüsüti_k3_r5_remoteproc.c (R5F) / ti_k3_m4_remoteproc.c (M4F)
MailboxOMAP mailbox: mailbox-j721e.c
sysfs/sys/class/remoteproc/remoteproc0/ (aynı arayüz)
Firmware konumu/lib/firmware/ti-ipc/am62xx/ipc_echo_testb_mcu1_0_release_strip.xer5f
IPC çerçevesiTI IPC (eski) veya OpenAMP (yeni, önerilen)
SDKMCU+ SDK, Processor SDK Linux
dts — AM62x
/* arch/arm64/boot/dts/ti/k3-am625-sk.dts */

&mcu_m4fss {
    mboxes = <&mailbox0_cluster0 &mbox_m4_0>,
             <&mailbox0_cluster0 &mbox_r5_0>;
    mbox-names = "txacq", "rxacq";
    memory-region = <&mcu_m4fss0_dma_memory_region>,
                    <&mcu_m4fss0_memory_region>;
    status = "okay";
};
bash — AM62x
# AM62x M4F başlatma (TI Processor SDK Linux)

# remoteproc sayısını kontrol et
ls /sys/class/remoteproc/
# remoteproc0  remoteproc1  (M4F-0 ve M4F-1)

# Firmware adı ve durumu
cat /sys/class/remoteproc/remoteproc0/firmware
# ti-ipc/am62xx/ipc_echo_testb_mcu1_0_release_strip.xer5f

echo start > /sys/class/remoteproc/remoteproc0/state

# TI IPC test aracı
# apt install ti-rpmsg-char (veya Yocto'da rpmsg-utils)
rpmsg_char_simple -d /dev/rpmsg0 -n 10 -m "Merhaba AM62x"

SoC karşılaştırması

ÖzellikSTM32MP157i.MX8M PlusAM62x
M çekirdeğiCortex-M4 @ 209 MHzCortex-M7 @ 800 MHzCortex-M4F @ 400 MHz
Mailbox HWIPCCMU (Messaging Unit)OMAP Mailbox
remoteproc sürücüsüstm32_rproc.cimx_rproc.cti_k3_m4_remoteproc.c
Yocto layermeta-st-stm32mpmeta-imxmeta-ti
M tarafı SDKSTM32CubeMP1MCUXpresso SDKMCU+ SDK
Trace okuma/debug/remoteproc/trace0/debug/remoteproc/trace0/debug/remoteproc/trace0

Bu bölümde

  • i.MX8M: IMX_REMOTEPROC sürücüsü, MU mailbox, MCUXpresso firmware
  • AM62x: ti_k3_m4_remoteproc, OMAP mailbox, MCU+ SDK
  • Tüm SoC'larda sysfs arayüzü aynı: state/firmware/coredump
  • Device tree: reserved-memory + vring bölgeleri SoC'a özgü adreslenmeli

08 Hata ayıklama

OpenAMP sorunları firmware yükleme hatalarından RPMsg mesaj kayıplarına kadar geniş bir yelpazede görülür. debugfs, dmesg ve donanım izleme araçları temel tanı araçlardır.

remoteproc debugfs arayüzü

bash
# debugfs bağla (genellikle zaten bağlı)
mount -t debugfs debugfs /sys/kernel/debug

# remoteproc debugfs dizini
ls /sys/kernel/debug/remoteproc/remoteproc0/
# carveout_memories  name  recovery  regs  trace0  version

# M4/M7 trace buffer çıktısı
cat /sys/kernel/debug/remoteproc/remoteproc0/trace0
# Çıktı yoksa: M4 firmware trace buffer başlatmamış olabilir
# Resource table'da fw_rsc_trace girişi kontrol et

# Carveout bellek bölgelerini listele
cat /sys/kernel/debug/remoteproc/remoteproc0/carveout_memories
# Name: OPENAMP_SHM PA: 0xdd100000 DA: 0xdd100000 Len: 0x10000

# Firmware versiyonunu göster
cat /sys/kernel/debug/remoteproc/remoteproc0/version

virtio-mmio ve vring durumu

bash
# virtio cihaz listesi
ls /sys/bus/virtio/devices/
# virtio0

# virtio cihaz bilgisi
cat /sys/bus/virtio/devices/virtio0/device
# 0x0007  (VIRTIO_ID_RPMSG)

cat /sys/bus/virtio/devices/virtio0/vendor
# 0x0000

# RPMsg kanal listesi
ls /sys/bus/rpmsg/devices/
# virtio0.my-rpmsg-channel.-1.1024
# Biçim: vdevNAME.channel.src.dst

# Virtio mmio aygıt bilgisi (debugfs)
ls /sys/kernel/debug/virtio-mmio/
cat /sys/kernel/debug/virtio-mmio/virtio0

Yaygın hata senaryoları

HataBelirtiÇözüm
Firmware bulunamadıdmesg: "failed to load firmware"/lib/firmware/ altında doğru isimde ELF var mı kontrol et
Resource table geçersizdmesg: "bad resource table"resource_table sürümü ve offset'leri kontrol et
State offline kalıyorecho start sonrası hâlâ offlinemailbox sürücüsü yüklü mü (dmesg | grep ipcc/mu/mbox)
RPMsg kanalı açılmıyordmesg'de rpmsg mesajı yokM4 firmware endpoint oluşturuyor mu (trace0 oku)
Mesaj kaybıUygulama veri kaybediyorvring descriptor sayısını artır (num=32), flow control ekle
M4 crash sonrası recoverystate: crashedcoredump okuma + recovery: enabled ile otomatik yeniden başlat

M4 crash dump okuma

bash
# Coredump etkinleştir
echo "enabled" > /sys/class/remoteproc/remoteproc0/coredump

# M4 crash olursa state "crashed" olur
cat /sys/class/remoteproc/remoteproc0/state
# crashed

# Coredump dosyasını kaydet (inline mode — debugfs üzerinden)
echo "inline" > /sys/class/remoteproc/remoteproc0/coredump
cat /sys/kernel/debug/remoteproc/remoteproc0/core_dump > m4_crash.elf

# GDB ile analiz
arm-none-eabi-gdb firmware.elf -c m4_crash.elf
# (gdb) bt   — backtrace
# (gdb) info registers

# Otomatik recovery etkinleştir
echo enabled > /sys/class/remoteproc/remoteproc0/recovery
# Crash sonrası firmware otomatik yeniden yüklenir ve başlatılır

Kernel log filtreleme

bash
# OpenAMP ile ilgili tüm kernel mesajları
dmesg | grep -E "remoteproc|rpmsg|virtio|ipcc|mailbox" | tail -50

# Dinamik debug etkinleştirme (çalışma zamanında)
echo "file drivers/remoteproc/stm32_rproc.c +p" > \
    /sys/kernel/debug/dynamic_debug/control

echo "file drivers/rpmsg/*.c +p" > \
    /sys/kernel/debug/dynamic_debug/control

# Etkinleştirilmiş dynamic debug kurallarını listele
grep "=p" /sys/kernel/debug/dynamic_debug/control | grep -E "remoteproc|rpmsg"

# ftrace ile remoteproc fonksiyon izleme
echo function > /sys/kernel/debug/tracing/current_tracer
echo "stm32_rproc*" > /sys/kernel/debug/tracing/set_ftrace_filter
echo 1 > /sys/kernel/debug/tracing/tracing_on
echo start > /sys/class/remoteproc/remoteproc0/state
cat /sys/kernel/debug/tracing/trace | head -50
echo 0 > /sys/kernel/debug/tracing/tracing_on

Bu bölümde

  • /sys/kernel/debug/remoteproc/remoteproc0/trace0: M4 firmware log çıktısı
  • carveout_memories: bellek bölgelerinin düzgün eşlenip eşlenmediğini kontrol et
  • coredump=inline: M4 crash ELF dump, GDB ile analiz edilebilir
  • dynamic_debug: çalışma zamanında remoteproc/rpmsg sürücü loglarını etkinleştir