Bir ISR'ın veri yazıp ana döngünün okuduğu, kilitsiz (lock-free) bir circular buffer (ring buffer) yazın.
Cevap
Tek üretici (ISR) ve tek tüketici (main loop) olduğunda, head'i sadece üretici, tail'i sadece tüketici yazarsa kesmeleri kapatmadan güvenli bir ring buffer yazılabilir. Boyutu 2'nin kuvveti seçmek modulo yerine maske kullanmayı sağlar.
#include <stdint.h>
#include <stdbool.h>
#define RB_SIZE 64u /* 2'nin kuvveti olmalı */
#define RB_MASK (RB_SIZE - 1u)
typedef struct {
volatile uint32_t head; /* sadece üretici yazar */
volatile uint32_t tail; /* sadece tüketici yazar */
uint8_t data[RB_SIZE];
} ringbuf_t;
/* ISR içinden çağrılır (ör. UART RX) */
bool rb_put(ringbuf_t *rb, uint8_t byte)
{
uint32_t head = rb->head;
if ((head - rb->tail) == RB_SIZE) /* dolu */
return false;
rb->data[head & RB_MASK] = byte;
__DMB(); /* veri, head'den önce görünür olsun */
rb->head = head + 1u;
return true;
}
/* Ana döngüden çağrılır */
bool rb_get(ringbuf_t *rb, uint8_t *byte)
{
uint32_t tail = rb->tail;
if (rb->head == tail) /* boş */
return false;
*byte = rb->data[tail & RB_MASK];
__DMB();
rb->tail = tail + 1u;
return true;
}Neden çalışıyor?
headvetailserbestçe artan sayaçlardır;head - tailunsigned aritmetikle sarma (wrap) olsa bile doğru eleman sayısını verir, çünküRB_SIZE2^32'yi tam böler.- Bu yöntemle buffer'ın tüm
RB_SIZEhücresi kullanılır. Klasik "bir hücreyi boş bırak" yöntemine gerek kalmaz. - Cortex-M'de hizalı 32-bit okuma/yazma atomiktir. 8-bit bir MCU'da (AVR) 16/32-bit indeks atomik değildir; ya 8-bit indeks kullanın ya da kısa kritik bölge açın.
__DMB()(CMSIS) tek çekirdekli Cortex-M0/M3/M4'te çoğu zaman gerekmez ama M7 ve çok çekirdekli sistemlerde yeniden sıralamaya karşı korur. Taşınabilir kod için C11stdatomic.hilememory_order_release/acquirekullanılabilir.
Takip soruları
- Buffer dolunca ne yapılmalı? Yeni veriyi at, en eskinin üzerine yaz veya taşma sayacı tut; hangisi olduğu gereksinime bağlıdır.
- Birden çok üretici varsa bu tasarım yetmez; kritik bölge veya RTOS queue gerekir.
İlgili C Programlama soruları
- C dilinde volatile anahtar kelimesi ne işe yarar?
- Bir yazmaçtaki belirli bir biti set, clear ve toggle eden C kodunu yazın.
- Stack ile heap arasındaki fark nedir? Gömülü sistemlerde dinamik bellek kullanımından neden kaçınılır?
- Endianness nedir? Little-endian ile big-endian farkı nedir?
- Bit field nedir? Donanım register'larına erişimde bit field mi yoksa bit maskesi mi kullanılmalı?
- Fonksiyon pointer'ları ve callback tabloları gömülü sistemlerde nasıl kullanılır? Bir state machine örneği verin.
Bu konuda başka bir soru biliyor musun?
Mülakatta karşılaştığın soruları ekle, onaylandıktan sonra yayına alınsın.