Wykład 5:
Budowa programu

Mariusz Chilmon
m.chilmon@amw.gdynia.pl
uc.vmario.org

Program bare-metal

Funkcja main


		int main() {
		}
	

Inicjalizacja


		void gpioInit() {
			// Inicjalizacja GPIO
		}

		int main() {
			gpioInit();
		}
	

Nieskończona pętla


		void gpioInit() {
			// Inicjalizacja GPIO
		}

		int main() {
			gpioInit();
			while (true) {
			}
		}
	

Funkcja główna


		void gpioInit() {
			// Inicjalizacja GPIO
		}

		void ledBlink() {
			// Mruganie diodą
		}

		int main()
		{
			gpioInit();
			while (true) {
				ledBlink();
			}
		}
	

Obsługa przerwań


		void gpioInit() {
			// Inicjalizacja GPIO
		}

		void ledBlink() {
			// Mruganie diodą
		}

		ISR(TIMER0_OVF_vect) {
			// Obsługa timera
		}

		int main()
		{
			gpioInit();
			while (true) {
				ledBlink();
			}
		}
	

Komunikacja przerwań z pętlą główną


		void gpioInit() {
			// Inicjalizacja GPIO
		}

		volatile bool timerFlag;

		void ledBlink() {
			// Mruganie diodą
			if (timerFlag) {
				// Reakcja na upływ czasu
				timerFlag = false;
			}
		}

		ISR(TIMER0_OVF_vect) {
			timerFlag = true;
		}

		int main()
		{
			gpioInit();
			while (true) {
				ledBlink();
			}
		}
	

Proces kompilacji i linkowania

Pliki nagłówkowe

Deklaracja i definicja funkcji

foo.h (deklaracja z dokumentacją)


			/** Robi coś ważnego.
			 *  @param argument Liczba wejściowa.
			 *  @return Kod błędu. */
			int foo(int argument);
		

foo.c (definicja)


			#include "foo.h"
			int foo(int argument) {
				// Bardzo mądra funkcja
			}
		

bar.c (wywołanie)


			#include "foo.h"
			void bar() {
				int result = foo(42);
			}
		

Deklaracja i definicja zmiennej

foo.h (deklaracja z dokumentacją)


			int foo; ///< Licznik dziwnych zdarzeń.
		

foo.c (definicja)


			#include "foo.h"

			int foo = 42;
		

bar.c (wywołanie)


			#include "foo.h"

			void bar() {
				printf("%d\n", foo);
			}
		

Kod maszynowy

Sekcje pamięci

Zarządzanie pamięcią

Dane statyczne

  • stałe, zmienne globalne i statyczne (static)
  • deterministyczne
  • praktycznie natychmiastowe
  • bardzo bezpieczne (safety-critical) 💪

Stos

  • deterministyczny
  • szybki
  • wspierany sprzętowo
  • możliwość przepełnienia np. przez rekurencję 🤯
  • zazwyczaj małe dane
  • dane lokalne
  • dane dostępne przez czas życia funkcji

Sterta

  • niedeterministyczna
  • realizacja programowa
  • fragmentacja
  • dane dostępne przez nieograniczony czas
  • wycieki pamięci
  • obsługa przez wskaźniki
  • C: malloc(), free()
  • C++: new, delete, unique_ptr<T>, shared_ptr<T>

Wektor przerwań

Listing


		00000000 <__vectors>:
		   0:	0c 94 46 00 	jmp	0x8c	; 0x8c <__ctors_end>
		   4:	0c 94 50 00 	jmp	0xa0	; 0xa0 <__bad_interrupt>
		   8:	0c 94 50 00 	jmp	0xa0	; 0xa0 <__bad_interrupt>
		   c:	0c 94 50 00 	jmp	0xa0	; 0xa4 <__vector_3>
		  10:	0c 94 50 00 	jmp	0xa0	; 0xa0 <__bad_interrupt>
	

Listing


		00000000 <__vectors>:
		   0:	0c 94 46 00 	jmp	0x8c	; 0x8c <__ctors_end>
		   4:	0c 94 50 00 	jmp	0xa0	; 0xa0 <__bad_interrupt>
		   8:	0c 94 50 00 	jmp	0xa0	; 0xa0 <__bad_interrupt>
		   c:	0c 94 50 00 	jmp	0xa0	; 0xa4 <__vector_3>
		  10:	0c 94 50 00 	jmp	0xa0	; 0xa0 <__bad_interrupt>

		0000008c <__ctors_end>:
		  8c:	11 24       	eor	r1, r1
		  8e:	1f be       	out	0x3f, r1	; 63
		  90:	cf ef       	ldi	r28, 0xFF	; 255
		  92:	d0 e4       	ldi	r29, 0x40	; 64
		  94:	de bf       	out	0x3e, r29	; 62
		  96:	cd bf       	out	0x3d, r28	; 61
		  98:	0e 94 5c 00 	call	0xb8	; 0xb8 <main>
		  9c:	0c 94 65 00 	jmp	0xca	; 0xca <_exit>
	

Listing


		00000000 <__vectors>:
		   0:	0c 94 46 00 	jmp	0x8c	; 0x8c <__ctors_end>
		   4:	0c 94 50 00 	jmp	0xa0	; 0xa0 <__bad_interrupt>
		   8:	0c 94 50 00 	jmp	0xa0	; 0xa0 <__bad_interrupt>
		   c:	0c 94 50 00 	jmp	0xa0	; 0xa4 <__vector_3>
		  10:	0c 94 50 00 	jmp	0xa0	; 0xa0 <__bad_interrupt>

		000000a0 <__bad_interrupt>:
		  a0:	0c 94 00 00 	jmp	0	; 0x0 <__vectors>
	

Listing


		00000000 <__vectors>:
		   0:	0c 94 46 00 	jmp	0x8c	; 0x8c <__ctors_end>
		   4:	0c 94 50 00 	jmp	0xa0	; 0xa0 <__bad_interrupt>
		   8:	0c 94 50 00 	jmp	0xa0	; 0xa0 <__bad_interrupt>
		   c:	0c 94 50 00 	jmp	0xa0	; 0xa4 <__vector_3>
		  10:	0c 94 50 00 	jmp	0xa0	; 0xa0 <__bad_interrupt>

		000000a4 <__vector_3>:
		  a4:	1f 92       	push	r1
		  a6:	0f 92       	push	r0
		  a8:	0f b6       	in	r0, 0x3f	; 63
		  aa:	0f 92       	push	r0
		  ac:	11 24       	eor	r1, r1
		  ae:	0f 90       	pop	r0
		  b0:	0f be       	out	0x3f, r0	; 63
		  b2:	0f 90       	pop	r0
		  b4:	1f 90       	pop	r1
		  b6:	18 95       	reti
	

Wskaźniki na zmienne i funkcje

Wskaźnik do zmiennej na stosie


		*d = 6; // a ← 0x0000 0006
		d = &b; // d ← 0x0080 421b
		*d = 6; // b ← 0x0000 0006
	

Wskaźnik do zmiennej na stercie

Wskaźnik na funkcję


		int increment(int number) {
			return number + 1;
		}

		void processArray(
				int* array,
				size_t size,
				int(*algorithm)(int)
		) {
			while (size-- > 0) {
				array[size] = algorithm(array[size]);
			}
		}

		int main() {
			const size_t SIZE = 8;
			int foo[SIZE] = {0, 1, 2, 3, 4, 5, 6, 7};
			processArray(foo, SIZE, increment);
			// foo == {1, 2, 3, 4, 5, 6, 7, 8}
		}