## page was renamed from Loesungstipps_es2_a4 ## page was renamed from Loesungstipps #format rst #language de **Tipps zur Loesung der "retarget" Aufgabe vom 13.11.2019** URL der Aufgabe: https://r-n-d.informatik.hs-augsburg.de:8080/es2/es2-nucl476/retarget Folgendes gilt fuer das Beispiel "a1" (bare-metal). Die minimalen Stack und Heap-Groessen habe ich je auf 4K vergroessert: Dazu in STM32L476RG_FLASH.ld die Zeilen aendern: :: _Min_Heap_Size = 0x1000;; /* required amount of heap */ _Min_Stack_Size = 0x1000;; /* required amount of stack */ Im Makefile waren meine Linker-Flags: :: PRO_LDFLAGS = -TSTM32L476RG_FLASH.ld -Wl,-Map,main.map -nostartfiles -mcpu=cortex-m4 -mthumb -mfloat -abi=hard -mfpu=fpv4-sp-d16 --specs=nano.specs --specs=nosys.specs -u _printf_float -u _scanf_float -lm -ffast-math In ``Src/usart.c`` muss man noch folgende Funktion einbauen: :: __attribute__((weak)) char __io_getchar() { char c; c = usart_receive_char(); return c; } Die Empfangsfunktion ``usart_receive_char()`` sieht so aus: :: char usart_receive_char() { USART2_CR1 |= (1 << 2); while(!(USART2_ISR & (1 << 5))) ; return (char) USART2_RDR; } Die ``_read()`` Funktion sieht so aus: :: /* works with gets and scanf() -- int, string, float * works with getchar() * tested with picocom terminal emulator on Linux */ int _read(int file, char *ptr, int len) { int idx; char c; for (idx = 0; idx < len; idx++) { c = __io_getchar(); if (c == 0x0d) { /* 0x0d is the ENTER key */ *ptr++ = 0x0a; /* 0x0a is the newline character (line ending) */ return idx+1; } else { *ptr++ = c; } } } Die _read() Funktion wird von allen Standardbibliotheksfunktionen aufgerufen, die ein oder mehrere Zeichen einlesen wollen. Da die Anzahl variabel ist, muss die Anzahl der tatsaechlich gelesenen Zeichen als Rueckgabewert zurueckliefert werden. Die Eingabe wird auf der Tastatur immer durch ENTER (ASCII 0x0d) abgeschlossen. Intern wertet aber __read() das Newline-Zeichen (0x0a) aus. Mit der obigen Funktion haben scanf(), gets() und getchar() funktioniert. ---- Die Ausgabe von Zeichen auf dem Terminal ist einfacher. Ohne grosse Schwierigkeiten haben ``printf()`` und ``snprintf()`` (zunächst in String, dann String über USART ausgeben) funktioniert. ---- Hier ist noch eine Anweisung zum Einschalten des numerischen Koprozessors (FPU). Ich bin mir nicht sicher, ob man das braucht. Wollte es nur mal ausprobieren. :: #define SCB_CPACR REGISTER_32(0xE000ED88) SCB_CPACR |= ((3UL << 10*2) | /* set CP10 Full Access */ (3UL << 11*2) ); /* set CP11 Full Access */