Raspberry Pi Pico Multi Core Kullanım

Merhaba Arkadaşlar;

Bu yazımda sizlere Pico yu nasıl multi core kullanacağımızı anlatacağım.

Bildiğiniz gibi Pico da 2 core bulunmaktadır. Biz aslında Core0 ı kullanıyoruz, diğer core1 uyku modunda çalışmaktadır. Çok karmaşık projelerinizde bazı işler diğer core a aktarılabilir. Örnek olarak Core0 sistemi yönetirken, Core1 ise sensörleri okur.

Çoğu uygulamalarda 2 core arasında data aktarımı ihtiyacı olacaktır. RP2040 da çekirdeklerden erişilebilen iki FIFO tamponu vardır. Biri FIFO tamponu ilk giren ilk çıkar arabelleğidir, basitçe arabelleğe yazılan ilk verinin okunan ilk veri olduğu anlamına gelir. Tamponlardan birine yalnızca bir çekirdek tarafından push adı verilen bir işlemle yazılabilir ve diğer çekirdek tarafından pop adı verilen bir işlemle okunabilir. Hiçbir çekirdeğin birden fazla arabelleğe yazamadığını veya okuyamadığını görebilirsiniz.

Veriler çekirdeklerden biri tarafından tampona yazıldığında, diğer çekirdekte bir kesinti oluşur.

Şimdi bir örnekle devam edelim, işlemci üzerindeki sıcaklık sensörünü core0 ile okuyup, core1 de print ile terminale yazdıracağız.

Temel olarak 3 fonksiyona ihtiyacımız var.

// Core 1 interrupt Handler
void core1_interrupt_handler()
{

}

// Core 1 Main Code
void core1_entry()
{

}

// Core 0 Main Code
int main(void)
{

}

Core 0 da led ve ADC ayarlarını yaptıktan sonra diğer core u çalıştırıyoruz ve 500ms aralıklarla okuyup core1 e ham adc datayı gönderiyoruz.

// Core 0 Main Code
int main()
{
    stdio_init_all();

    //led init
    gpio_init(BoardLED);
    gpio_set_dir(BoardLED, GPIO_OUT);

    //init multicore
    multicore_launch_core1(core1_entry); // Start core 1 - Do this before any interrupt configuration

    //init ADC
    adc_init();
    adc_set_temp_sensor_enabled(true); // Enable on board temp sensor
    adc_select_input(4);

    while (true)
    {
        uint16_t raw = adc_read();
        multicore_fifo_push_blocking(raw);

        //led toggle
        ledst = !ledst;
        gpio_put(BoardLED, ledst);

        sleep_ms(500);
    }

    return 0;
}

Daha sonra core1 de çalışacak kodu oluşturuyoruz ve core1 kesmesini ayarlıyoruz.

// Core 1 Main Code
void core1_entry()
{
    // Configure Core 1 Interrupt
    multicore_fifo_clear_irq();
    irq_set_exclusive_handler(SIO_IRQ_PROC1, core1_interrupt_handler);

    irq_set_enabled(SIO_IRQ_PROC1, true);

    // Infinte While Loop to wait for interrupt
    while (1)
    {
        tight_loop_contents();
    }
}

Son olarak kesme fonksiyonunda ham adc yi alıp hesapladıktan sonra terminale yazdırıyoruz.

// Core 1 interrupt Handler
void core1_interrupt_handler()
{
    //raw değerini al ve göster
    while (multicore_fifo_rvalid())
    {
        uint16_t raw = multicore_fifo_pop_blocking();

        //adc hesapla ve goster
        const float conversion_factor = 3.3f / (1 << 12);
        float result = raw * conversion_factor;
        float temp = 27 - (result - 0.706) / 0.001721;
        printf("Temp = %4.2f C\n", temp);
    }

    multicore_fifo_clear_irq(); // Clear interrupt
}

Programın son hali aşağıdaki gibidir.

#include <stdio.h>
#include <stdbool.h>
#include "pico/stdlib.h"
#include "pico/multicore.h"
#include "hardware/irq.h"
#include "hardware/adc.h"
#include "hardware/gpio.h"

#define BoardLED PICO_DEFAULT_LED_PIN
bool ledst = false;

void core1_interrupt_handler();
void core1_entry();

// Core 0 Main Code
int main()
{
    stdio_init_all();

    //led init
    gpio_init(BoardLED);
    gpio_set_dir(BoardLED, GPIO_OUT);

    //init multicore
    multicore_launch_core1(core1_entry); // Start core 1 - Do this before any interrupt configuration

    //init ADC
    adc_init();
    adc_set_temp_sensor_enabled(true); // Enable on board temp sensor
    adc_select_input(4);

    while (true)
    {
        uint16_t raw = adc_read();
        multicore_fifo_push_blocking(raw);

        //led toggle
        ledst = !ledst;
        gpio_put(BoardLED, ledst);

        sleep_ms(500);
    }

    return 0;
}


// Core 1 Main Code
void core1_entry()
{
    // Configure Core 1 Interrupt
    multicore_fifo_clear_irq();
    irq_set_exclusive_handler(SIO_IRQ_PROC1, core1_interrupt_handler);

    irq_set_enabled(SIO_IRQ_PROC1, true);

    // Infinte While Loop to wait for interrupt
    while (1)
    {
        tight_loop_contents();
    }
}


// Core 1 interrupt Handler
void core1_interrupt_handler()
{
    //raw değerini al ve göster
    while (multicore_fifo_rvalid())
    {
        uint16_t raw = multicore_fifo_pop_blocking();

        //adc hesapla ve goster
        const float conversion_factor = 3.3f / (1 << 12);
        float result = raw * conversion_factor;
        float temp = 27 - (result - 0.706) / 0.001721;
        printf("Temp = %4.2f C\n", temp);
    }

    multicore_fifo_clear_irq(); // Clear interrupt
}

Şimdi programı derleyip çalıştırdığımızda core0 adc yi okuyup ledi toggle yapacaktır, diğer core ise ham adc değerini hesaplayıp terminale yazdıracaktır.

VSC projesini indirmek için tıklayın multi_core

Bir sonraki projede görüşmek üzere,
Kolay Gelsin.

Bir cevap yazın

E-posta hesabınız yayımlanmayacak.