Commit 0548e324 authored by Michael Zehrer's avatar Michael Zehrer
Browse files

Initial commit

parent 5db93b5a
# ignore python cache
**/__pycache__
# ignore visual studio code settings
**/.vscode
cmake_minimum_required(VERSION 3.13)
get_directory_property(hasParent PARENT_DIRECTORY)
if(NOT hasParent)
message(FATAL_ERROR "This isn't a standalone project")
elseif(NOT DEFINED ARCTOS_CURRENT_TUNING)
message(FATAL_ERROR "You must specify a tuning")
endif()
project(
arctos
VERSION 0.0.2
LANGUAGES C CXX ASM
)
set(ARCTOS_DIR_BASE "${CMAKE_CURRENT_LIST_DIR}" )
set(ARCTOS_DIR_API "${ARCTOS_DIR_BASE}/api" )
set(ARCTOS_DIR_CORE "${ARCTOS_DIR_BASE}/core" )
set(ARCTOS_DIR_MODULES "${ARCTOS_DIR_BASE}/modules" )
set(ARCTOS_DIR_PORTS "${ARCTOS_DIR_BASE}/ports" )
set(ARCTOS_DIR_TUNINGS "${ARCTOS_DIR_BASE}/tunings" )
set(ARCTOS_LIB_TARGET "${PROJECT_NAME}" )
set(ARCTOS_INTERFACE "${ARCTOS_LIB_TARGET}_interface" )
message("-- Use arctos tuning '${ARCTOS_CURRENT_TUNING}'")
string(TOLOWER "${ARCTOS_CURRENT_TUNING}" ARCTOS_CURRENT_TUNING_LOWER)
if(NOT EXISTS "${ARCTOS_DIR_TUNINGS}/${ARCTOS_CURRENT_TUNING_LOWER}/tuning.cmake")
message(FATAL_ERROR "You must compile the tuning '${ARCTOS_CURRENT_TUNING}' first!")
endif()
add_library(${ARCTOS_INTERFACE} INTERFACE)
target_include_directories(${ARCTOS_INTERFACE} INTERFACE
"${ARCTOS_DIR_API}"
"${ARCTOS_DIR_TUNINGS}/${ARCTOS_CURRENT_TUNING_LOWER}"
)
target_compile_features(${ARCTOS_INTERFACE} INTERFACE
c_std_99
cxx_std_11
cxx_constexpr
cxx_nullptr
)
target_compile_definitions(${ARCTOS_INTERFACE} INTERFACE
ARCTOS_VERSION=\"${PROJECT_VERSION}\"
$<$<COMPILE_LANGUAGE:ASM>:__ASSEMBLY__>
)
include("${ARCTOS_DIR_TUNINGS}/${ARCTOS_CURRENT_TUNING_LOWER}/tuning.cmake")
set(ARCTOS_DIR_BASE ${ARCTOS_DIR_BASE} PARENT_SCOPE)
set(ARCTOS_DIR_API ${ARCTOS_DIR_API} PARENT_SCOPE)
set(ARCTOS_DIR_CORE ${ARCTOS_DIR_CORE} PARENT_SCOPE)
set(ARCTOS_DIR_MODULES ${ARCTOS_DIR_MODULES} PARENT_SCOPE)
set(ARCTOS_DIR_PORTS ${ARCTOS_DIR_PORTS} PARENT_SCOPE)
set(ARCTOS_DIR_TUNINGS ${ARCTOS_DIR_TUNINGS} PARENT_SCOPE)
set(ARCTOS_LIB_TARGET ${ARCTOS_LIB_TARGET} PARENT_SCOPE)
arctos is released under the BSD license, which is included in this
document. Unless otherwise noted, the BSD license applies to all
files in this directory and its subdirectories.
Copyright (c) 2018-2019, Michael Zehrer
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
Original licence text from RODOS:
Copyright (c) 2008, German Aerospace Center (DLR)
Copyright (c) 2011, University of Wuerzburg
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
* Neither the name of the German Aerospace Center or the University of
Würzburg nor the names of its contributors may be used to endorse or
promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/**
* Copyright (c) 2018, Michael Zehrer
* All rights reserved.
*
* @licence BSD
* @brief Debug functions
* @author Michael Zehrer
*/
#ifndef ARCTOS_DEBUG_H
#define ARCTOS_DEBUG_H
#ifdef __cplusplus
extern "C" {
#endif
// TODO Comment!!
void PRINTF(const char* fmt, ...) __attribute__((__format__(__printf__,1,2)));
void SPRINTF(char* dest, const char* fmt, ...) __attribute__((__format__(__printf__,2,3)));
void PANIC(const char* error_msg, ...) __attribute__((__format__(__printf__,1,2)));
#ifdef __cplusplus
} // end extern "C"
#endif
#endif /* ARCTOS_DEBUG_H */
/**
* Copyright (c) 2008, DLR
* Copyright (c) 2018, Michael Zehrer
* All rights reserved.
*
* @licence BSD
* @brief FIFO (first in first out) communication (header)
* @author Michael Zehrer
* (based on code from Sergio Montenegro and Lutz Dittrich)
*/
#ifndef ARCTOS_FIFO_HPP
#define ARCTOS_FIFO_HPP
#include <stdbool.h>
#include <stddef.h>
namespace arctos {
// TODO
class Putter {
size_t unused;
};
// TODO Thread-safe
/**
* @class Fifo
* @brief simple FIFO (realized as ring buffer)
*
* A fifo where both sides (reader & writer) can work asynchronously.
* If one side has more than one owner, the fifo has to be
* protected using semaphores.
*
* @param T data type of fifo entries
* @param size maximal number of entries
*/
template<typename T, size_t size>
class Fifo : public Putter {
protected:
T buffer[size + 1];
volatile size_t idx_write;
volatile size_t idx_read;
/**
* @brief Advance index to the next position with
* an overflow to 0 to implement a ring
*/
size_t advanceIndex(size_t index) const {
return ((index < size) ? (index + 1) : 0);
}
public:
Fifo() : idx_write(0), idx_read(0) { }
// TODO putGeneric??
/**
* @brief Insert one element into the buffer
* @return true on success, false otherwise (fifo full)
*/
bool put(const T &val) {
size_t index = this->advanceIndex(this->idx_write);
if (index == this->idx_read)
return false;
this->buffer[idx_write] = val;
this->idx_write = index;
return true;
}
/**
* @brief Extract one element from the buffer
* @return true on success, false otherwise (fifo empty)
*/
bool get(T &val) {
if (this->idx_read == this->idx_write)
return false;
val = this->buffer[this->idx_read];
this->idx_read = advanceIndex(this->idx_read);
return true;
}
/**
* @brief Retrieve the size of this fifo
* @return Size of fifo
*/
size_t getSize() const { return size; }
/**
* @brief Determines the number of elements inside this fifo
* @return Number of elements in the fifo
*/
size_t getElementCount() const {
size_t r = this->idx_read;
size_t w = this->idx_write;
return (r <= w) ? (w - r) : (size + 1 - r + w);
}
/**
* @brief Determines the amount of free entries
* @return Number of free entries
*/
size_t getFreeSpaceCount() const {
return size - getElementCount();
}
/**
* @brief Checks if the list is full
* @return true if the list is full, false otherwise
*/
bool isFull() const { return advanceIndex(this->idx_write) == this->idx_read; }
/**
* @brief Checks if the list is empty
* @return true if the list is empty, false otherwise
*/
bool isEmpty() const { return this->idx_read == this->idx_write;}
/**
* @brief Deletes all entries
*/
void clear() { this->idx_read = this->idx_write = 0; }
};
/**
* @class BlockFifo
* @brief Simple FIFO with direct block transfers
*
* A Fifo that lets you write or read continius Blocks of the stored type.
* Gives out pointers to the internal space, so you can copy data directly from/to there.
* Useful for DMA transfers.
*
* @param T data type of fifo entries
* @param size maximal number of entries
*/
template<class T, size_t size>
class BlockFifo : public Fifo<T, size> {
protected:
size_t advanceIndexByNumber(size_t index, size_t count) const {
size_t nindex = index + count;
while (nindex > size)
nindex = nindex - size - 1;
return nindex;
}
public:
BlockFifo() : Fifo<T, size>() { }
/**
* @brief Retrieve a pointer to the internal buffer
* @param max_size Maximal number of entries to be written.
* (IMPORTANT: max_size may be updated to match internal constraints)
* @return Pointer to internal buffer or 'nullptr' if the buffer is full
*/
T* getBufferToWrite(size_t &max_size) {
size_t r = this->idx_read;
size_t w = this->idx_write;
// if the buffer is full
if (r == this->advanceIndex(w)) {
max_size = 0;
return nullptr;
}
if (r > w) // until r-1 possible
max_size = r - w - 1;
else { // until end possible
max_size = size + 1 - w;
if (r == 0) { --max_size; }
}
return this->buffer + w;
}
/**
* @brief Retrieve a pointer to the internal buffer
* @param max_size Maximal number of entries to be read.
* (IMPORTANT: max_size may be updated to match internal constraints)
* @return Pointer to internal buffer or 'nullptr' if the buffer is empty
*/
T* getBufferToRead(size_t &max_size) {
size_t r = this->idx_read;
size_t w = this->idx_write;
// if the buffer is empty
if (r == w) {
max_size = 0;
return nullptr;
}
if (r < w) // until w-1 possible
max_size = w - r;
else // until end possible
max_size = size + 1 - r;
return this->buffer + r;
}
/**
* @brief Call this function after you have written into the buffer
* you got from 'getBufferToWrite(...)'
*/
void writeConcluded(size_t size_written) {
this->idx_write = this->advanceIndexByNumber(this->idx_write, size_written);
}
/**
* @brief Call this function after you have read from the buffer
* you got from 'getBufferToRead(...)'
*/
void readConcluded(size_t size_read) {
this->idx_read = this->advanceIndexByNumber(this->idx_read, size_read);
}
};
} /* namespace arctos */
#endif /* ARCTOS_FIFO_HPP */
/**
* Copyright (c) 2018, Michael Zehrer
* All rights reserved.
*
* @licence BSD
* @brief Simple implementation of a (linked) list
* @author Michael Zehrer
*/
#ifndef ARCTOS_LIST_HPP
#define ARCTOS_LIST_HPP
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
/**
* @brief List iterate macro
* @param __type Data type of list nodes.
* @param __list The list.
*/
#define ITERATE_LIST(__type,__list) \
for (ListItem<__type> *item = __list.getHead(); \
item != nullptr; \
item = item->getNextItem())
namespace arctos {
// TODO Thread-safe
template<typename T>
class LinkedList;
/**
* @class ListItem
* @brief a item which could be inserted into a list
* @param T data type of the content
*/
template<typename T>
class ListItem {
friend class LinkedList<T>;
protected:
ListItem<T> *p_next = nullptr;
T *p_content = nullptr;
uint32_t rank = 0;
public:
ListItem() {}
ListItem(T *content, uint32_t rank = 0)
: p_content(content), rank(rank) {}
ListItem<T>* getNextItem() const { return this->p_next; }
uint32_t getRank() const { return this->rank; }
T* getContent() const { return this->p_content; }
void setContent(T *cnt) { this->p_content = cnt; }
};
/**
* @class LinkedList
* @brief (single) ordered linked list
*
* This is a simple implementation of a (single) linked list
* with all items ordered downwards by there 'rank'.
*
* To perform a walk-through, simply call 'getHead()' on this
* list and afterwards 'getNextItem()' on each individual item.
*
* @param T data type of ListItem content
*/
template<typename T>
class LinkedList {
protected:
ListItem<T> *p_head = nullptr;
size_t size = 0;
public:
LinkedList() {}
size_t getSize() const { return this->size; }
ListItem<T>*getHead() const { return this->p_head; }
/**
* @brief Inserts the given 'item' into the linked list
* @return true on success, false otherwise
*/
bool insert(ListItem<T> *item) {
if (item == nullptr || item->p_next != nullptr)
return false;
if (this->p_head == nullptr) {
this->p_head = item;
++size;
return true;
}
else if (this->p_head->rank < item->rank) {
item->p_next = this->p_head;
this->p_head = item;
++size;
return true;
}
ListItem<T> *cur = this->p_head;
do {
ListItem<T> *next = cur->p_next;
if (next == nullptr) {
cur->p_next = item;
break;
}
else if (next->rank < item->rank) {
item->p_next = next;
cur->p_next = item;
break;
}
cur = next;
} while (true);
++size;
return true;
}
/**
* @brief Removes the given 'item' from the linked list.
* @return true on success, false otherwise
*/
bool remove(ListItem<T> *item) {
if (item == nullptr)
return false;
ListItem<T> *cur = this->p_head;
if (cur == item) {
this->p_head = cur->p_next;
--size;
return true;
}
while (cur != nullptr) {
ListItem<T> *next = cur->p_next;
if (item == next) {
cur->p_next = next->p_next;
--size;
return true;
}
cur = next;
}
return false;
}
};
} /* namespace arctos */
#endif /* ARCTOS_LIST_HPP */
/**
* Copyright (c) 2018, Michael Zehrer
* All rights reserved.
*
* @licence BSD
* @brief Memory partitioning for (semi) dynamic memory allocation
* @author Michael Zehrer
*/
#ifndef ARCTOS_MEMORY_PARTITIONING_HPP
#define ARCTOS_MEMORY_PARTITIONING_HPP
#include <stdint.h>
#include <stdbool.h>
namespace arctos {
namespace memmory {
// TODO Comment
// TODO Thread-safe
class Partitioning {
private:
uint32_t full_size;
uint32_t item_size;
uintptr_t start_addr;
uint8_t *p_bm_start;
Partitioning();
public:
uint32_t getItemSize() { return this->item_size; }
uint32_t getFullSize() { return this->full_size; }
// TODO suspend if full??
void *allocateItem();
void deallocateItem(void *);
// TODO allocateArray(size_t size) ???
static Partitioning *create(uint32_t full_size, uint32_t item_size);
};
} /* namespace memmory */
} /* namespace arctos */
#endif /* ARCTOS_MEMORY_PARTITIONING_HPP */
/**
* Copyright (c) 2018, Michael Zehrer
* All rights reserved.
*
* @licence BSD
* @brief Simple Mutex-Implementation
* @author Michael Zehrer
*/
#ifndef ARCTOS_MUTEX_HPP
#define ARCTOS_MUTEX_HPP
#include <stdint.h>
#include <stdbool.h>
namespace arctos {
// TODO comment and implement
class Mutex {
protected:
uint32_t holder_priority;
public:
Mutex() : holder_priority(0) { }
void lock(void);
void unlock(void);
bool tryLock(void);
};
} /* namespace arctos */
#endif /* ARCTOS_MUTEX_HPP */
/**
* Copyright (c) 2018, Michael Zehrer
* All rights reserved.
*
* @licence BSD
* @brief A Task is an active schedulable object with own context and stack
* @author Michael Zehrer
*/
#ifndef ARCTOS_TASK_HPP
#define ARCTOS_TASK_HPP
#include <stdbool.h>
#include <stdint.h>
#include <arctos/params.h>
#include "list.hpp"
namespace arctos {
class Task {
friend class Scheduler;
friend void _initSystem(void);
private:
ListItem<Task> self;
void *volatile p_context;