Starting Point
This commit is contained in:
1
include/arch/bsp/.gitignore
vendored
Normal file
1
include/arch/bsp/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
# empty gitignore
|
||||
8
include/arch/bsp/yellow_led.h
Normal file
8
include/arch/bsp/yellow_led.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef YELLOW_LED_H
|
||||
#define YELLOW_LED_H
|
||||
|
||||
void init_yellow(void);
|
||||
void yellow_on(void);
|
||||
void yellow_off(void);
|
||||
|
||||
#endif
|
||||
1
include/arch/cpu/.gitignore
vendored
Normal file
1
include/arch/cpu/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
# empty gitignore
|
||||
48
include/config.h
Normal file
48
include/config.h
Normal file
@@ -0,0 +1,48 @@
|
||||
#ifndef CONFIG_H_
|
||||
#define CONFIG_H_
|
||||
|
||||
/* Falls auf den Boards gearbeitet wird am besten
|
||||
* die nächste Zeile auskommentieren
|
||||
*/
|
||||
#define BUILD_FOR_QEMU
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
/**
|
||||
* \file config.h
|
||||
*
|
||||
* Enthält defines und static Funktionen zum testen der
|
||||
* Implementierung. Wir tauschen diese Werte/Funktionen beim
|
||||
* Korrigieren zum Testen aus. Bitte fügt hier KEINE weiteren
|
||||
* defines oÄ ein. Ihr könnt diese Werte zum Testen natürlich
|
||||
* auch gerne selbst verändern.
|
||||
*/
|
||||
|
||||
void test_kernel [[gnu::weak]] (void);
|
||||
void test_user [[gnu::weak]] (void *args);
|
||||
void test_user_main [[gnu::weak]] (void);
|
||||
|
||||
/**
|
||||
* Erst ab Aufgabenblatt 2 relevant
|
||||
*/
|
||||
|
||||
#ifdef BUILD_FOR_QEMU
|
||||
/* Werte zum testen unter QEMU */
|
||||
static constexpr unsigned int BUSY_WAIT_COUNTER = 10000000;
|
||||
#else
|
||||
/* Werte zum testen auf der Hardware */
|
||||
static constexpr unsigned int BUSY_WAIT_COUNTER = 30000;
|
||||
#endif // BUILD_FOR_QEMU
|
||||
|
||||
static constexpr unsigned int PRINT_COUNT = 5;
|
||||
|
||||
// Wir testen nur mit Werten die durch 2^n darstellbar sind
|
||||
static constexpr unsigned int UART_INPUT_BUFFER_SIZE = 128;
|
||||
|
||||
// Timer Interrupt Interval zum testen in Mikrosekunden
|
||||
// Systimer taktet mit 1MHz
|
||||
// 1000000 -> 1 Sekunde
|
||||
static constexpr unsigned int TIMER_INTERVAL = 1000000;
|
||||
|
||||
#endif // __ASSEMBLER__
|
||||
#endif // CONFIG_H_
|
||||
1
include/kernel/.gitignore
vendored
Normal file
1
include/kernel/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
# empty gitignore
|
||||
1
include/lib/.gitignore
vendored
Normal file
1
include/lib/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
# empty gitignore
|
||||
110
include/lib/list.h
Normal file
110
include/lib/list.h
Normal file
@@ -0,0 +1,110 @@
|
||||
#ifndef LIB_LIST_H_
|
||||
#define LIB_LIST_H_
|
||||
/*
|
||||
* \file list.h
|
||||
* \brief Doppelt verkettete List Datenstruktur
|
||||
*
|
||||
* Diese Datei ist eine Hilfestellung für Aufgabe 3.
|
||||
* Sie erspart euch den Aufwand, selber eine doppelt verkettete Liste zu implementieren.
|
||||
*/
|
||||
|
||||
// List Node struct
|
||||
typedef struct list_node {
|
||||
struct list_node *next;
|
||||
struct list_node *prev;
|
||||
} list_node;
|
||||
|
||||
// Makro zum initialisieren einer Liste
|
||||
#define list_create(N) \
|
||||
static list_node head__##N = { &(head__##N), &(head__##N) }; \
|
||||
static list_node *N = &(head__##N)
|
||||
|
||||
//checks if list is empty
|
||||
[[nodiscard]] static inline bool list_is_empty(list_node *head)
|
||||
{
|
||||
return head == head->next;
|
||||
}
|
||||
|
||||
// Gibt das erste Elemnt der Liste zurück
|
||||
[[nodiscard, maybe_unused]] static inline list_node *list_get_first(list_node *head)
|
||||
{
|
||||
if (list_is_empty(head)) {
|
||||
return nullptr;
|
||||
}
|
||||
return head->next;
|
||||
}
|
||||
|
||||
// Gibt das letzte Element der Liste zurück
|
||||
[[nodiscard, maybe_unused]] static inline list_node *list_get_last(list_node *head)
|
||||
{
|
||||
if (list_is_empty(head)) {
|
||||
return nullptr;
|
||||
}
|
||||
return head->prev;
|
||||
}
|
||||
|
||||
// Füge Elemente hinzu (Hilfsfunktion)
|
||||
static inline void list_add_(list_node *node, list_node *prev)
|
||||
{
|
||||
node->prev = prev;
|
||||
node->next = prev->next;
|
||||
|
||||
prev->next->prev = node;
|
||||
prev->next = node;
|
||||
}
|
||||
|
||||
// Füge Element am Anfang der Liste hinzu
|
||||
[[maybe_unused]] static inline void list_add_first(list_node *head, list_node *new)
|
||||
{
|
||||
list_add_(new, head);
|
||||
}
|
||||
|
||||
// Füge Element am Ende der Liste hinzu
|
||||
[[maybe_unused]] static inline void list_add_last(list_node *head, list_node *new)
|
||||
{
|
||||
list_add_(new, head->prev);
|
||||
}
|
||||
|
||||
// Entferne Element (Hilfsfunktion)
|
||||
static inline void list_remove_(list_node *node)
|
||||
{
|
||||
node->prev->next = node->next;
|
||||
node->next->prev = node->prev;
|
||||
}
|
||||
|
||||
// Entfernt das erste Element aus der Liste und gibt es zurück
|
||||
[[maybe_unused]] static inline list_node *list_remove_first(list_node *head)
|
||||
{
|
||||
if (list_is_empty(head)) {
|
||||
return nullptr;
|
||||
}
|
||||
list_node *del = head->next;
|
||||
list_remove_(del);
|
||||
return del;
|
||||
}
|
||||
|
||||
// Entferne das letzte Element aus der Liste und gibt es zurück
|
||||
[[maybe_unused]] static inline list_node *list_remove_last(list_node *head)
|
||||
{
|
||||
if (list_is_empty(head)) {
|
||||
return nullptr;
|
||||
}
|
||||
list_node *del = head->prev;
|
||||
list_remove_(del);
|
||||
return del;
|
||||
}
|
||||
|
||||
// Entfernt das spezielle Element aus der Liste
|
||||
[[maybe_unused]] static inline list_node *list_remove(list_node *head, list_node *rem)
|
||||
{
|
||||
list_node *curr;
|
||||
for (curr = head->next; curr != head; curr = curr->next) {
|
||||
if (curr == rem) {
|
||||
list_remove_(curr);
|
||||
return curr;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#endif // LIB_LIST_H_
|
||||
89
include/lib/ringbuffer.h
Normal file
89
include/lib/ringbuffer.h
Normal file
@@ -0,0 +1,89 @@
|
||||
#ifndef RINGBUFFER_H_
|
||||
#define RINGBUFFER_H_
|
||||
|
||||
/**
|
||||
* \brief Ringbuffer Datenstruktur
|
||||
* \file ringbuffer.h
|
||||
*
|
||||
* Diese Datei ist eine Hilfestellung für Aufgabe 2.
|
||||
* Sie erspart euch den Aufwand, selber einen Ringbuffer zu implementieren.
|
||||
*/
|
||||
|
||||
struct ring_buff {
|
||||
unsigned int head;
|
||||
unsigned int tail;
|
||||
unsigned int size;
|
||||
unsigned int mask;
|
||||
char *buffer;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Überprüft ob eine positive Zahl eine Zweierpotenz ist
|
||||
*
|
||||
* Beispiel: (0b100 & 0b011) == 0b000.
|
||||
*/
|
||||
#define is_power_of_two(val) (((val) & ((val) - 1)) == 0)
|
||||
|
||||
/**
|
||||
* \brief Macro um einen Ringbuffer zu erstellen
|
||||
* \param name Bezeichnung des Buffers
|
||||
* \param size Größe des Buffers
|
||||
*
|
||||
*/
|
||||
#define create_ringbuffer(name, size) \
|
||||
static_assert((size) >= 1, "Size of Ringbuffer has to be at least 1"); \
|
||||
static_assert(is_power_of_two(size), "Size of Ringbuffer has to be a power of 2"); \
|
||||
static char _b_##name[size]; \
|
||||
static struct ring_buff _##name = { 0, 0, (size), (size) - 1, _b_##name }; \
|
||||
static volatile struct ring_buff *name = &_##name
|
||||
|
||||
[[nodiscard]] static bool buff_is_empty(volatile struct ring_buff *b)
|
||||
{
|
||||
return b->head == b->tail;
|
||||
}
|
||||
|
||||
[[nodiscard]] static bool buff_is_full(volatile struct ring_buff *b)
|
||||
{
|
||||
return ((b->tail & b->mask) == (b->head & b->mask)) && !buff_is_empty(b);
|
||||
}
|
||||
|
||||
static bool buff_putc(volatile struct ring_buff *b, char c)
|
||||
{
|
||||
if (buff_is_full(b)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
b->buffer[b->head & b->mask] = c;
|
||||
b->head++;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static char buff_getc(volatile struct ring_buff *b)
|
||||
{
|
||||
while (buff_is_empty(b)) {
|
||||
}
|
||||
|
||||
char c = b->buffer[b->tail & b->mask];
|
||||
b->tail++;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
[[nodiscard, maybe_unused]] static char buff_peekc(volatile struct ring_buff *b)
|
||||
{
|
||||
while (buff_is_empty(b)) {
|
||||
}
|
||||
|
||||
return b->buffer[b->tail & b->mask];
|
||||
}
|
||||
|
||||
[[nodiscard, maybe_unused]] static char buff_peekc_last(volatile struct ring_buff *b)
|
||||
{
|
||||
while (buff_is_empty(b)) {
|
||||
}
|
||||
|
||||
return b->buffer[(b->head - 1) & b->mask];
|
||||
}
|
||||
|
||||
#endif
|
||||
5
include/user/main.h
Normal file
5
include/user/main.h
Normal file
@@ -0,0 +1,5 @@
|
||||
#ifndef MAIN_H
|
||||
#define MAIN_H
|
||||
|
||||
void main(void *args);
|
||||
#endif
|
||||
Reference in New Issue
Block a user