بِسْمِ اللَّهِ الرَّحْمَنِ الرَّحِيم

Di bagian 5 sudah dijelaskan bagaimana memori manajemen di aplikasi yang menggunakan FreeRTOS. Terlepas dari metode yang digunakan, Statik atau dinamik, setiap task tetap harus ditentukan berapa memori yang diperlukan. Telah dijelaskan juga bahwa memori stack setiap task tidak hanya untuk menyimpan variabel lokal yang digunakan oleh task tersebut tetapi juga menyimpan apa yang dinamakan dengan TCB (Task Control Block) yang menyimpan informasi tentang task yang bersangkutan, seperti alamat stack (awal dan akhir), nama task, prioritas dan lain-lain. TCB ini berukuran 112 byte.

Ukuran Stack Minimal

Setiap kali kernel FreeRTOS dijalankan, maka secara otomatis akan membuat sebuah task yang dinamakan idle task. FreeRTOS mengharuskan minimal ada satu task dalam status running dan task idle dibuat untuk tujuan itu, ketika task-task berada di status blok, task idle akan selalu siap untuk dijalankan. Walaupun demikian, task idle akan dibuat dengan dengan prioritas paling renda, sehingga task ini tidak akan menghalangi task-task yang lain dengan prioritas lebih tinggi untuk dijalankan oleh kernel (scheduler). Jadi pada dasarnya, task idle ini tidak akan pernah dijalankan oleh scheduler, dengan catatan task-task yang kita buat harus mempunyai prioritas lebih tinggi dari pada task idle. Mengenai prioritas task, Insya Allah akan dibahas di artikel selanjutnya.

Oleh karena kita tidak bisa mengatur ukuran stack untuk task idle, FreeRTOS menyediakan configMINIMAL_STACK_SIZE sebagai ukuran stack minimal yang akan digunakan oleh task idle. Saya belum menemukan sampai seminimal apa ukuran stack bisa dibuat. Kalau melihat ukuran TCB (112 byte), mungkin ini ukuran stack minimum plus beberapa byte agar context switch bisa terjadi dengan benar. Dalam STM32CubeMX, configMINIMAL_STACK_SIZE ini ditetapkan minimal 64 Words. Dan ukuran configMINIMAL_STACK_SIZE ini akan menjadi ukuran stack minimal ketika membuat task. Dalam FreeRTOS ukuran stack dinyatakan dalam words atau 32 bit (4 byte). 64 Word artinya 64 x 4 byte (256 byte).

Ukuran Stack Minimum

Parameter configMINIMAL_STACK_SIZE ini juga ditetapkan sebagai ukuran stack minimal ketika kita membuat task. Di STM32CubeMX bisa kita lihat bahwa ukuran memori stack yang sebenarnya adalah ukuran stack yang ditetapkan ditambah dengan ukuran TCB. Sehingga ukuran minimal stack sebuah task adalah

configMINIMAL_STACK_SIZE + Ukuran TCB
Dengan configMINIMAL_STACK_SIZE = 64 x 4( 256 byte)
Ukuran Minimal = 256 + 112 (TCB) = 368 byte

Penghitungan Aktual Memori Stack

Berapa Ukuran Stack Seharusnya?

Dalam FreeRTOS, memori stack tiap task akan berfungsi sama dengan memori stack yang didefinisikan di file linker. Ketika terjadi context switch (pindah ke task yang lain), kernel FreeRTOS akan menyimpan kondisi terakhir dari task yang sedang berjalan ke memori stack. Data yang disimpan berupa register internal, Program Counter (PC) dan lokal variabel yang digunakan. Ketika task memanggil fungsi yang lain, variabel lokal yang digunakan oleh fungsi tersebut juga harus diperhitungkan. Semakin banyak fungsi yang dipanggil, dan semakin banyak variabel lokal yang digunakan, maka semakin banyak memori stack yang dibutuhkan.

Jadi ukuran stack yang dibutuhkan ditentukan oleh

  • Banyaknya variabel lokal yang digunakan
  • Banyaknya fungsi-fungsi yang dipanggil oleh task tersebut.
  • dan kedalaman dari fungsi-fungsi tersebut, artinya ketika sebuah fungsi memanggil fungsi yang lain, kemudian fungsi tersebut memanggil fungsi yang lainnya lagi, dan seterusnya, maka stack yang dibutuhkan akan semakin besar. Karena tiap kali memanggil fungsi, maka informasi setiap fungsi yang memanggil tersebut harus disimpan ke stack, agar ketika kembali, program bisa kembali berjalan sesuai dengan urutannya.

Agak susah memang untuk menghitung kebutuhan stack secara persis. Tapi minimal kita menghitung variabel lokal yang digunakan, tentu saja memori stack harus dilebihkan dengan jumlah tersebut. Dan perlu diingat bahwa, dalam fungsi FreeRTOS jumlah memori stack ditentukan dalam word (32 bit) atau 4 byte. Ukuran memori mikrokontroler yang digunakan juga harus dilihat. Mikrokontroler dengan RAM kecil mungkin sebaiknya tidak menggunakan RTOS.

Permasalahan-Permasalahan Terkait Memori Stack

Permasalahan utama di memori stack, tentu saja Stack overflow. Di mana memori yang dialokasikan untuk stack tidak cukup.Hal ini tentu saja akan menyebabkan program crash atau hang. Misal sebuah task menggunakan 512 byre variabel lokal, tetapi alokasi stack untuk task tersebut hanya 256 byte. Saat dijalankan, program dipastikan akan hang/crash. Mungkin akan menimbulkan Memory Management Fault atau Hardfault.

Selain itu, ketika digunakan alokasi stack secara dinamis, penentuan ukuran memori heap tidak mencukupi untuk memori stack setiap task. Sebagai contoh, sebuah aplikasi mempunyai 4 task dengan stack 128 (word). Sehingga masing-masing task akan membutuhkan 624 byte. Jadi total stack yang dibutuhkan adalah 2496 byte. Ukuran heap misal di 2048 byte. Tentu saja ukuran heap tidak mencukupi untuk total memori stack yang dibutuhkan. Ketika fungsi membuat task dipanggil, maka hanya akan ada 3 task yang bisa dibuat. Pada saat pembuatan task yang keempat, memori heap sudah tdak cukup, maka task ke-4 tidak akan terbentuk. Kernel FreeRTOS pun hanya akan bisa menjalankan 3 task. Dalam kasus ini, program tidak sampai hang/crash, tetapi hanya task 1-3 yang berjalan, task 4 tidak.

Kalau pembuatan task dilakukan melalui STM32CubeMX, maka penggunaan memori heap ini bisa diketahui. Dan akan menampilkan error jika memori heap kurang.

Penggunaan Memori Heap

Kesalahan alokasi heap atau stack tidak akan menimbulkan error di compiler, hanya bisa diketahui setalah program berjalan. FreeRTOS menyediakan fungsi mengetahui memori heap yang digunakan. Fungsi xPortGetFreeHeapSize() digunakan untuk mengetahui sisa memori heap. Selain itu ada juga fungsi vPortGetHeapStats() yang berfungsi untuk struktur dari memori heap.

/* Prototype of the vPortGetHeapStats() function. */
void vPortGetHeapStats( HeapStats_t *xHeapStats );

/* Definition of the Heap_stats_t structure. */
typedef struct xHeapStats
{
	size_t xAvailableHeapSpaceInBytes;      /* The total heap size currently available - this is the sum of all the free blocks, not the largest block that can be allocated. */
	size_t xSizeOfLargestFreeBlockInBytes; 	/* The maximum size, in bytes, of all the free blocks within the heap at the time vPortGetHeapStats() is called. */
	size_t xSizeOfSmallestFreeBlockInBytes; /* The minimum size, in bytes, of all the free blocks within the heap at the time vPortGetHeapStats() is called. */
	size_t xNumberOfFreeBlocks;		/* The number of free memory blocks within the heap at the time vPortGetHeapStats() is called. */
	size_t xMinimumEverFreeBytesRemaining;	/* The minimum amount of total free memory (sum of all free blocks) there has been in the heap since the system booted. */
	size_t xNumberOfSuccessfulAllocations;	/* The number of calls to pvPortMalloc() that have returned a valid memory block. */
	size_t xNumberOfSuccessfulFrees;	/* The number of calls to vPortFree() that has successfully freed a block of memory. */
} HeapStats_t;

Semoga bermanfaat

Leave a Reply

Your email address will not be published.