moved all third-party lib to separate folder

This commit is contained in:
2021-02-27 19:32:58 +01:00
committed by Robin Mueller
parent 264191415f
commit fa81b06bea
138 changed files with 22 additions and 2 deletions

123
thirdparty/libcsp/doc/example.rst vendored Normal file
View File

@ -0,0 +1,123 @@
Client and server example
=========================
The following examples show the initialization of the protocol stack and examples of client/server code.
Initialization Sequence
-----------------------
This code initializes the CSP buffer system, device drivers and router core. The example uses the CAN interface function csp_can_tx but the initialization is similar for other interfaces. The loopback interface does not require any explicit initialization.
.. code-block:: c
#include <csp/csp.h>
#include <csp/interfaces/csp_if_can.h>
/* CAN configuration struct for SocketCAN interface "can0" */
struct csp_can_config can_conf = {.ifc = "can0"};
/* Init buffer system with 10 packets of maximum 320 bytes each */
csp_buffer_init(10, 320);
/* Init CSP with address 1 */
csp_init(1);
/* Init the CAN interface with hardware filtering */
csp_can_init(CSP_CAN_MASKED, &can_conf)
/* Setup default route to CAN interface */
csp_route_set(CSP_DEFAULT_ROUTE, &csp_can_tx, CSP_HOST_MAC);
/* Start router task with 500 word stack, OS task priority 1 */
csp_route_start_task(500, 1);
Server
------
This example shows how to create a server task that listens for incoming connections. CSP should be initialized before starting this task. Note the use of `csp_service_handler()` as the default branch in the port switch case. The service handler will automatically reply to ICMP-like requests, such as pings and buffer status requests.
.. code-block:: c
void csp_task(void *parameters) {
/* Create socket without any socket options */
csp_socket_t *sock = csp_socket(CSP_SO_NONE);
/* Bind all ports to socket */
csp_bind(sock, CSP_ANY);
/* Create 10 connections backlog queue */
csp_listen(sock, 10);
/* Pointer to current connection and packet */
csp_conn_t *conn;
csp_packet_t *packet;
/* Process incoming connections */
while (1) {
/* Wait for connection, 10000 ms timeout */
if ((conn = csp_accept(sock, 10000)) == NULL)
continue;
/* Read packets. Timout is 1000 ms */
while ((packet = csp_read(conn, 1000)) != NULL) {
switch (csp_conn_dport(conn)) {
case MY_PORT:
/* Process packet here */
default:
/* Let the service handler reply pings, buffer use, etc. */
csp_service_handler(conn, packet);
break;
}
}
/* Close current connection, and handle next */
csp_close(conn);
}
}
Client
------
This example shows how to allocate a packet buffer, connect to another host and send the packet. CSP should be initialized before calling this function. RDP, XTEA, HMAC and CRC checksums can be enabled per connection, by setting the connection option to a bitwise OR of any combination of `CSP_O_RDP`, `CSP_O_XTEA`, `CSP_O_HMAC` and `CSP_O_CRC`.
.. code-block:: c
int send_packet(void) {
/* Get packet buffer for data */
csp_packet_t *packet = csp_buffer_get(data_size);
if (packet == NULL) {
/* Could not get buffer element */
printf("Failed to get buffer element\\n");
return -1;
}
/* Connect to host HOST, port PORT with regular UDP-like protocol and 1000 ms timeout */
csp_conn_t *conn = csp_connect(CSP_PRIO_NORM, HOST, PORT, 1000, CSP_O_NONE);
if (conn == NULL) {
/* Connect failed */
printf("Connection failed\\n");
/* Remember to free packet buffer */
csp_buffer_free(packet);
return -1;
}
/* Copy message to packet */
char *msg = "HELLO";
strcpy(packet->data, msg);
/* Set packet length */
packet->length = strlen(msg);
/* Send packet */
if (!csp_send(conn, packet, 1000)) {
/* Send failed */
printf("Send failed\\n");
csp_buffer_free(packet);
}
/* Close connection */
csp_close(conn);
return 0
}

17
thirdparty/libcsp/doc/history.rst vendored Normal file
View File

@ -0,0 +1,17 @@
History
=======
The idea was developed by a group of students from Aalborg University in 2008. In 2009 the main developer started working for GomSpace, and CSP became integrated into the GomSpace products. The protocol is based on a 32-bit header containing both transport, network and MAC-layer information. It's implementation is designed for, but not limited to, embedded systems such as the 8-bit AVR microprocessor and the 32-bit ARM and AVR from Atmel. The implementation is written in C and is currently ported to run on FreeRTOS and POSIX and pthreads based operating systems like Linux and BSD. The three letter acronym CSP was originally an abbreviation for CAN Space Protocol because the first MAC-layer driver was written for CAN-bus. Now the physical layer has extended to include spacelink, I2C and RS232, the name was therefore extended to the more general CubeSat Space Protocol without changing the abbreviation.
Satellites using CSP
--------------------
This is the known list of satellites or organisations that uses CSP.
* GomSpace GATOSS GOMX-1
* AAUSAT-3
* EgyCubeSat
* EuroLuna
* NUTS
* Hawaiian Space Flight Laboratory
* GomSpace GOMX-3

95
thirdparty/libcsp/doc/interfaces.rst vendored Normal file
View File

@ -0,0 +1,95 @@
CSP Interfaces
==============
This is an example of how to implement a new layer-2 interface in CSP. The example is going to show how to create a `csp_if_fifo`, using a set of [named pipes](http://en.wikipedia.org/wiki/Named_pipe). The complete interface example code can be found in `examples/fifo.c`. For an example of a fragmenting interface, see the CAN interface in `src/interfaces/csp_if_can.c`.
CSP interfaces are declared in a `csp_iface_t` structure, which sets the interface nexthop function and name. A maximum transmission unit can also be set, which forces CSP to drop outgoing packets above a certain size. The fifo interface is defined as:
.. code-block:: c
#include <csp/csp.h>
#include <csp/csp_interface.h>
csp_iface_t csp_if_fifo = {
.name = "fifo",
.nexthop = csp_fifo_tx,
.mtu = BUF_SIZE,
};
Outgoing traffic
----------------
The nexthop function takes a pointer to a CSP packet and a timeout as parameters. All outgoing packets that are routed to the interface are passed to this function:
.. code-block:: c
int csp_fifo_tx(csp_packet_t *packet, uint32_t timeout) {
write(tx_channel, &packet->length, packet->length + sizeof(uint32_t) + sizeof(uint16_t));
csp_buffer_free(packet);
return 1;
}
In the fifo interface, we simply transmit the header, length field and data using a write to the fifo. CSP does not dictate the wire format, so other interfaces may decide to e.g. ignore the length field if the physical layer provides start/stop flags.
_Important notice: If the transmission succeeds, the interface must free the packet and return 1. If transmission fails, the nexthop function should return 0 and not free the packet, to allow retransmissions by the caller._
Incoming traffic
----------------
The interface also needs to receive incoming packets and pass it to the CSP protocol stack. In the fifo interface, this is handled by a thread that blocks on the incoming fifo and waits for packets:
.. code-block:: c
void * fifo_rx(void * parameters) {
csp_packet_t *buf = csp_buffer_get(BUF_SIZE);
/* Wait for packet on fifo */
while (read(rx_channel, &buf->length, BUF_SIZE) > 0) {
csp_qfifo_write(buf, &csp_if_fifo, NULL);
buf = csp_buffer_get(BUF_SIZE);
}
}
A new CSP buffer is preallocated with csp_buffer_get(). When data is received, the packet is passed to CSP using `csp_qfifo_write()` and a new buffer is allocated for the next packet. In addition to the received packet, `csp_qfifo_write()` takes two additional arguments:
.. code-block:: c
void csp_qfifo_write(csp_packet_t *packet, csp_iface_t *interface, CSP_BASE_TYPE *pxTaskWoken);
The calling interface must be passed in `interface` to avoid routing loops. Furthermore, `pxTaskWoken` must be set to a non-NULL value if the packet is received in an interrupt service routine. If the packet is received in task context, NULL must be passed. 'pxTaskWoken' only applies to FreeRTOS systems, and POSIX system should always set the value to NULL.
`csp_qfifo_write` will either accept the packet or free the packet buffer, so the interface must never free the packet after passing it to CSP.
Initialization
--------------
In order to initialize the interface, and make it available to the router, use the following function found in `csp/csp_interface.h`:
.. code-block:: c
csp_route_add_if(&csp_if_fifo);
This actually happens automatically if you try to call `csp_route_add()` with an interface that is unknown to the router. This may however be removed in the future, in order to ensure that all interfaces are initialised before configuring the routing table. The reason is, that some products released in the future may ship with an empty routing table, which is then configured by a routing protocol rather than a static configuration.
In order to setup a manual static route, use the following example where the default route is set to the fifo interface:
.. code-block:: c
csp_route_set(CSP_DEFAULT_ROUTE, &csp_if_fifo, CSP_NODE_MAC);
All outgoing traffic except loopback, is now passed to the fifo interface's nexthop function.
Building the example
--------------------
The fifo examples can be compiled with:
.. code-block:: bash
% gcc csp_if_fifo.c -o csp_if_fifo -I<CSP PATH>/include -L<CSP PATH>/build -lcsp -lpthread -lrt
The two named pipes are created with:
.. code-block:: bash
% mkfifo server_to_client client_to_server

21
thirdparty/libcsp/doc/libcsp.rst vendored Normal file
View File

@ -0,0 +1,21 @@
.. CSP Documentation master file.
.. _libcsp:
**********************
CubeSat Space Protocol
**********************
.. toctree::
:maxdepth: 3
../README
history
structure
interfaces
memory
protocolstack
topology
mtu
example

28
thirdparty/libcsp/doc/memory.rst vendored Normal file
View File

@ -0,0 +1,28 @@
How CSP uses memory
===================
CSP has been written for small microprocessor systems. The way memory is handled is therefore a tradeoff between the amount used and the code efficiency. This section tries to give some answers to what the memory is used for and how it it used. The primary memory blocks in use by CSP is:
* Routing table
* Ports table
* Connection table
* Buffer pool
* Interface list
Tables
------
The reason for using tables for the routes, ports and connections is speed. When a new packet arrives the core of CSP needs to do a quick lookup in the connection so see if it can find an existing connection to which the packet matches. If this is not found, it will take a lookup in the ports table to see if there are any applications listening on the incoming port number. Another argument of using tables are pre-allocation. The linker will reserve an area of the memory for which the routes and connections can be stored. This avoid an expensive `malloc()` call during initialization of CSP, and practically costs zero CPU instructions. The downside of using tables are the wasted memory used by unallocated ports and connections. For the routing table the argumentation is the same, pre-allocation is better than calling `malloc()`.
Buffer Pool
-----------
The buffer handling system can be compiled for either static allocation or a one-time dynamic allocation of the main memory block. After this, the buffer system is entirely self-contained. All allocated elements are of the same size, so the buffer size must be chosen to be able to handle the maximum possible packet length. The buffer pool uses a queue to store pointers to free buffer elements. First of all, this gives a very quick method to get the next free element since the dequeue is an O(1) operation. Furthermore, since the queue is a protected operating system primitive, it can be accessed from both task-context and interrupt-context. The `csp_buffer_get` version is for task-context and `csp_buffer_get_isr` is for interrupt-context. Using fixed size buffer elements that are preallocated is again a question of speed and safety.
A basic concept of the buffer system is called Zero-Copy. This means that from userspace to the kernel-driver, the buffer is never copied from one buffer to another. This is a big deal for a small microprocessor, where a call to `memcpy()` can be very expensive. In practice when data is inserted into a packet, it is shifted a certain number of bytes in order to allow for a packet header to be prepended at the lower layers. This also means that there is a strict contract between the layers, which data can be modified and where. The buffer object is normally casted to a `csp_packet_t`, but when its given to an interface on the MAC layer it's casted to a `csp_i2c_frame_t` for example.
Interface list
--------------
The interface list is a simple single-ended linked list of references to the interface specification structures. These structures are static const and allocated by the linker. The pointer to this data is inserted into the list one time during setup of the interface. Each entry in the routing table has a direct pointer to the interface element, thereby avoiding list lookup, but the list is needed in order for the dynamic route configuration to know which interfaces are available.

19
thirdparty/libcsp/doc/mtu.rst vendored Normal file
View File

@ -0,0 +1,19 @@
Maximum Transfer Unit
=====================
There are two things limiting the MTU of CSP.
1. The pre-allocated buffer pools allocation size
2. The link layer protocol.
So lets assume that you have made a protocol called KISS with a MTU of 256. The 256 is the total amount of data that you can put into the CSP-packet. However, you need to take the overhead of the link layer into account. Typically this could consist of a length field and/or a start/stop flag. So the actual frame size on the link layer would for example be 256 bytes of data + 2 bytes sync flag + 2 bytes length field.
This requires a buffer allocation of at lest 256 + 2 + 2. However, the CSP packet itself has some reserved bytes in the beginning of the packet (which you can see in csp.h) - so the recommended buffer allocation size is MAX MTU + 16 bytes. In this case the max MTU would be 256.
If you try to pass data which is longer than the MTU, the chance is that you will also make a buffer overflow in the CSP buffer pool. However, lets assume that you have two interfaces one with an MTU of 200 bytes and another with an MTU of 100 bytes. In this case you might successfully transfer 150 bytes over the first interface, but the packet will be rejected once it comes to the second interface.
If you want to increase your MTU of a specific link layer, it is up to the link layer protocol to implement its own fragmentation protocol. A good example is CAN-bus which only allows a frame size of 8 bytes. libcsp have a small protocol for this called the “CAN fragmentation protocol" or CFP for short. This allows data of much larger size to be transferred over the CAN bus.
Okay, but what if you want to transfer 1000 bytes, and the network maximum MTU is 256? Well, since CSP does not include streaming sockets, only packets. Somebody will have to split that data up into chunks. It might be that you application have special knowledge about the datatype you are transmitting, and that it makes sense to split the 1000 byte content into 10 chunks of 100 byte status messages. This, application layer delimitation might be good if you have a situation with packet loss, because your receiver could still make good usage of the partially delivered chunks.
But, what if you just want 1000 bytes transmitted, and you dont care about the fragmentation unit, and also dont want the hassle of writing the fragmentation code yourself? - In this case, libcsp now features a new (still experimental) feature called SFP (small fragmentation protocol) designed to work on the application layer. For this purpose you will not use csp_send and csp_recv, but csp_sfp_send and csp_sfp_recv. This will split your data into chunks of a certain size, enumerate them and transfer over a given connection. If a chunk is missing the SFP client will abort the reception, because SFP does not provide retransmission. If you wish to also have retransmission and orderly delivery you will have to open an RDP connection and send your SFP message to that connection.

54
thirdparty/libcsp/doc/protocolstack.rst vendored Normal file
View File

@ -0,0 +1,54 @@
The Protocol Stack
==================
The CSP protocol stack includes functionality on all layers of the TCP/IP model:
Layer 1: Drivers
----------------
Lib CSP is not designed for any specific processor or hardware peripheral, but yet these drivers are required in order to work. The intention of LibCSP is not to provide CAN, I2C or UART drivers for all platforms, however some drivers has been included for some platforms. If you do not find your platform supported, it is quite simple to add a driver that conforms to the CSP interfaces. For example the I2C driver just requires three functions: `init`, `send` and `recv`. For good stability and performance interrupt driven drivers are preferred in favor of polled drivers. Where applicable also DMA usage is recommended.
Layer 2: MAC interfaces
-----------------------
CSP has interfaces for I2C, CAN, RS232 (KISS) and Loopback. The layer 2 protocol software defines a frame-format that is suitable for the media. CSP can be easily extended with implementations for even more links. For example a radio-link and IP-networks. The file `csp_interface.h` declares the rx and tx functions needed in order to define a network interface in CSP. During initialisation of CSP each interface will be inserted into a linked list of interfaces that is available to the router. In cases where link-layer addresses are required, such as I2C, the routing table supports specifying next-hop link-layer address directly. This avoids the need to implement an address resolution protocol to translate CSP addresses to I2C addresses.
Layer 3: Network Router
-----------------------
The router core is the backbone of the CSP implementation. The router works by looking at a 32-bit CSP header which contains the delivery and source address together with port numbers for the connection. Each router supports both local delivery and forwarding of frames to another destination. Frames will never exit the router on the same interface that they arrives at, this concept is called split horizon, and helps prevent routing loops.
The main purpose of the router is to accept incoming packets and deliver them to the right message queue. Therefore, in order to listen on a port-number on the network, a task must create a socket and call the accept() call. This will make the task block and wait for incoming traffic, just like a web-server or similar. When an incoming connection is opened, the task is woken. Depending on the task-priority, the task can even preempt another task and start execution immediately.
There is no routing protocol for automatic route discovery, all routing tables are pre-programmed into the subsystems. The table itself contains a separate route to each of the possible 32 nodes in the network and the additional default route. This means that the overall topology must be decided before putting sub-systems together, as explained in the `topology.md` file. However CSP has an extension on port zero CMP (CSP management protocol), which allows for over-the-network routing table configuration. This has the advantage that default routes could be changed if for example the primary radio fails, and the secondary should be used instead.
Layer 4: Transport Layer
------------------------
LibCSP implements two different Transport Layer protocols, they are called UDP (unreliable datagram protocol) and RDP (reliable datagram protocol). The name UDP has not been chosen to be an exact replica of the UDP (user datagram protocol) known from the TCP/IP model, but they have certain similarities.
The most important thing to notice is that CSP is entirely a datagram service. There is no stream based service like TCP. A datagram is defined a block of data with a specified size and structure. This block enters the transport layer as a single datagram and exits the transport layer in the other end as a single datagram. CSP preserves this structure all the way to the physical layer for I2C, KISS and Loopback interfaces are used. The CAN-bus interface has to fragment the datagram into CAN-frames of 8 bytes, however only a fully completed datagram will arrive at the receiver.
UDP
^^^
UDP uses a simple transmission model without implicit hand-shaking dialogues for guaranteeing reliability, ordering, or data integrity. Thus, UDP provides an unreliable service and datagrams may arrive out of order, appear duplicated, or go missing without notice. UDP assumes that error checking and correction is either not necessary or performed in the application, avoiding the overhead of such processing at the network interface level. Time-sensitive applications often use UDP because dropping packets is preferable to waiting for delayed packets, which may not be an option in a real-time system.
UDP is very practical to implement request/reply based communication where a single packet forms the request and a single packet forms the reply. In this case a typical request and wait protocol is used between the client and server, which will simply return an error if a reply is not received within a specified time limit. An error would normally lead to a retransmission of the request from the user or operator which sent the request.
While UDP is very simple, it also has some limitations. Normally a human in the loop is a good thing when operating the satellite over UDP. But when it comes to larger file transfers, the human becomes the bottleneck. When a high-speed file transfer is initiated data acknowledgment should be done automatically in order to speed up the transfer. This is where the RDP protocol can help.
RDP
^^^
CSP provides a transport layer extension called RDP (reliable datagram protocol) which is an implementation of RFC908 and RFC1151. RDP provides a few additional features:
* Three-way handshake
* Flow Control
* Data-buffering
* Packet re-ordering
* Retransmission
* Windowing
* Extended Acknowledgment
For more information on this, please refer to RFC908.

27
thirdparty/libcsp/doc/structure.rst vendored Normal file
View File

@ -0,0 +1,27 @@
Structure
=========
The Cubesat Space Protocol library is structured as shown in the following table:
============================= =========================================================================
**Folder** **Description**
============================= =========================================================================
libcsp/include/csp Main include files
libcsp/include/csp/arch Architecture include files
libcsp/include/csp/interfaces Interface include files
libcsp/include/csp/drivers Drivers include files
libcsp/src Main modules for CSP: io, router, connections, services
libcsp/src/interfaces Interface modules for CAN, I2C, KISS, LOOP and ZMQHUB
libcsp/src/drivers/can Driver for CAN
libcsp/src/drivers/usart Driver for USART
libcsp/src/arch/freertos FreeRTOS architecture module
libcsp/src/arch/macosx Mac OS X architecture module
libcsp/src/arch/posix Posix architecture module
libcsp/src/arch/windows Windows architecture module
libcsp/src/rtable Routing table module
libcsp/transport Transport module, UDP and RDP
libcsp/crypto Crypto module
libcsp/utils Utilities
libcsp/bindings/python Python wrapper for libcsp
libcsp/examples CSP examples (source code)
libasf/doc The doc folder contains the source code for this documentation
============================= =========================================================================

26
thirdparty/libcsp/doc/topology.rst vendored Normal file
View File

@ -0,0 +1,26 @@
Network Topology
================
CSP uses a network oriented terminology similar to what is known from the Internet and the TCP/IP model. A CSP network can be configured for several different topologies. The most common topology is to create two segments, one for the Satellite and one for the Ground-Station.
.. code-block:: none
I2C BUS
_______________________________
/ | | | \
+---+ +---+ +---+ +---+ +---+
|OBC| |COM| |EPS| |PL1| |PL2| Nodes 0 - 7 (Space segment)
+---+ +---+ +---+ +---+ +---+
^
| Radio
v
+---+ +----+
|TNC| ------- | PC | Nodes 8 - 15 (Ground segment)
+---+ USB +----+
Node 9 Node 10
The address range, from 0 to 15, has been segmented into two equal size segments. This allows for easy routing in the network. All addresses starting with binary 1 is on the ground-segment, and all addresses starting with 0 is on the space segment. From CSP v1.0 the address space has been increased to 32 addresses, 0 to 31. But for legacy purposes, the old 0 to 15 is still used in most products.
The network is configured using static routes initialised at boot-up of each sub-system. This means that the basic routing table must be assigned compile-time of each subsystem. However each node supports assigning an individual route to every single node in the network and can be changed run-time. This means that the network topology can be easily reconfigured after startup.