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:

1 #include <csp/csp.h>
2 #include <csp/csp_interface.h>
3 
4 csp_iface_t csp_if_fifo = {
5  .name = "fifo",
6  .nexthop = csp_fifo_tx,
7  .mtu = BUF_SIZE,
8 };

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:

1 int csp_fifo_tx(csp_packet_t *packet, uint32_t timeout) {
2  write(tx_channel, &packet->length, packet->length + sizeof(uint32_t) + sizeof(uint16_t));
3  csp_buffer_free(packet);
4  return 1;
5 }

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:

1 void * fifo_rx(void * parameters) {
2  csp_packet_t *buf = csp_buffer_get(BUF_SIZE);
3  /* Wait for packet on fifo */
4  while (read(rx_channel, &buf->length, BUF_SIZE) > 0) {
5  csp_new_packet(buf, &csp_if_fifo, NULL);
6  buf = csp_buffer_get(BUF_SIZE);
7  }
8 }

A new CSP buffer is preallocated with csp_buffer_get(). When data is received, the packet is passed to CSP using csp_new_packet() and a new buffer is allocated for the next packet. In addition to the received packet, csp_new_packet() takes two additional arguments:

1 void csp_new_packet(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