Kompilasi oleh : Reza Ervani bin Asmanu
Dalam artikel sebelumnya tentang [Peta Alamat Fisik BCM2835], kita telah membahas bahwa untuk mengatur mode GPIO, kita harus mengakses register tertentu. Secara spesifik, kita menggunakan alamat offset 0x04 (GPFSEL1) untuk mengatur GPIO 16 (Lampu LED Internal) sebagai Output.
Mungkin Anda bertanya: “Mengapa harus offset 0x04? Mengapa tidak di 0x00? Dan dari mana datangnya angka pergeseran 18 bit (<< 18) dalam kode kita?”
Artikel ini akan membedah matematika di balik manajemen register GPIO pada arsitektur ARM 32-bit.
1. Tantangan Arsitektur: 32 Bit vs 54 Jalur GPIO
Prosesor BCM2835 yang menjadi otak Raspberry Pi 1 adalah mesin 32-bit. Artinya, setiap “laci” penyimpanan (register) di dalamnya hanya memiliki lebar data 32 bit (dari bit 0 hingga bit 31).
Di sisi lain, chip BCM2835 memiliki total 54 Jalur GPIO (GPIO 0 hingga GPIO 53).
Jika setiap GPIO hanya butuh logika sederhana (1 bit untuk Input, 0 bit untuk Output), mungkin 32 GPIO bisa muat dalam satu register. Namun, GPIO pada BCM2835 sangat canggih. Setiap satu jalur GPIO memiliki 8 kemungkinan mode fungsi:
- Input
- Output
- Alternative Function 0 (misal: I2C SDA)
- Alternative Function 1 (misal: UART TX)
- Alternative Function 2
- Alternative Function 3
- Alternative Function 4
- Alternative Function 5
Secara matematika biner, untuk membedakan 8 pilihan ($2^3 = 8$), kita membutuhkan 3 bit data untuk konfigurasi setiap satu GPIO.
2. Kalkulasi “Kamar” Register
Jika satu GPIO “memakan” tempat sebanyak 3 bit, berapa banyak GPIO yang bisa ditampung dalam satu register 32-bit?
Sisa pembagian:
Dua bit terakhir (bit 30 dan 31) tidak digunakan (Reserved), dan 30 bit pertama digunakan untuk mengatur 10 GPIO.
Karena satu register hanya muat 10 GPIO, maka Broadcom memecah pengaturan 54 GPIO tersebut ke dalam 6 register berurutan (GPFSEL0 hingga GPFSEL5):
| Nama Register | Offset | Rentang GPIO | Keterangan |
| GPFSEL0 | 0x00 | GPIO 0 – 9 | Mengatur 10 GPIO pertama |
| GPFSEL1 | 0x04 | GPIO 10 – 19 | Mengatur 10 GPIO kedua (Termasuk GPIO 16) |
| GPFSEL2 | 0x08 | GPIO 20 – 29 | Mengatur 10 GPIO ketiga |
| GPFSEL3 | 0x0C | GPIO 30 – 39 | … |
| GPFSEL4 | 0x10 | GPIO 40 – 49 | … |
| GPFSEL5 | 0x14 | GPIO 50 – 53 | Hanya mengatur sisa 4 GPIO |
3. Studi Kasus: Melacak GPIO 16
Sekarang kita paham mengapa kita menggunakan GPFSEL1 (Offset 0x04) untuk GPIO 16. Alasannya sederhana: karena angka 16 berada dalam rentang 10-19.
Langkah selanjutnya adalah menentukan posisi bit yang tepat di dalam register tersebut.
- Indeks Lokal: Di dalam “kamar” GPFSEL1, GPIO 10 adalah penghuni pertama (urutan ke-0). Maka, GPIO 16 adalah penghuni ke-6.
- Posisi Bit: Karena setiap penghuni memakan 3 bit, kita kalikan indeks tersebut dengan 3.
Jadi, pengaturan untuk GPIO 16 terletak pada Bit 18, 19, dan 20 di dalam register GPFSEL1.
4. Implementasi dalam Kode C
Pemahaman ini menjelaskan logika di balik baris kode inisialisasi yang kita tulis:
/* 1. Reset Bit (Pembersihan) */
*GPFSEL1 &= ~(7 << 18);
/* 2. Set Output (Pengaturan) */
*GPFSEL1 |= (1 << 18);
Mari kita bedah operasinya:
Langkah 1: Pembersihan (Reset)
Sebelum mengatur mode, kita wajib membersihkan konfigurasi lama agar tidak tercampur.
- Angka 7 dalam biner adalah
111(merepresentasikan 3 bit penuh). (7 << 18)menggeser angka111ke posisi bit 18-20.- Operator
~(NOT) membalikkan semua bit, membuat “lubang nol” di posisi 18-20, dan angka 1 di tempat lain. - Operator
&=(AND) akan memaksa bit 18-20 menjadi000(Input Mode/Reset), sementara bit milik GPIO lain tidak berubah.
Langkah 2: Pengaturan (Set)
Menurut datasheet, kode biner untuk Output adalah 001.
- Angka 1 dalam biner adalah
001. (1 << 18)menempatkan angka001tepat di posisi bit 18-20.- Operator
|=(OR) menuliskan nilai tersebut ke register.
Kesimpulan
Satu baris kode *GPFSEL1 |= (1 << 18); yang terlihat sederhana, sebenarnya mengandung logika aritmatika sistem yang presisi:
- Memilih register yang tepat berdasarkan kelipatan 10 GPIO (GPFSEL1).
- Menghitung offset bit berdasarkan kelipatan 3 bit per GPIO (Bit 18).
- Menerapkan nilai fungsi yang sesuai (Output = 1).
Dengan memahami struktur ini, Anda kini bisa dengan mudah menulis driver untuk GPIO mana pun (misalnya GPIO 23 di Pin Fisik 16) tanpa harus menebak-nebak angka “ajaib” di dalam kode Anda.
