User manual¶
LwPKT protocol library is a simple state-machine parser and raw data generator to allow 2 or more devices in a network to communicate in a structure way.
It is perfectly suitable for communication in embedded systems, suchs as RS-485, where multiple devices could be easily connected to one big network.
LwPKT library uses well known and easy implementation of LwRB library for data read and data write. It expects 2 different buffer instances.
Parser is simple state machine that reads and processes every received character from read buffer. When application wants to transmit data, LwPKT library generates raw data and writes them to TX buffer.
Combination of both gives embedded applications freedom to implement communication protocols for TX and RX.
Packet structure¶
Packet structure consists of several fields, where some are optional and some are mandatory.
START
: Byte with fixed value to represent start of packetFROM
: Byte from where this packet is coming from. Optional field, can be disabled withLWPKT_CFG_USE_ADDR
TO
: Byte to where this packet is targeting. Optional field, can be disabled withLWPKT_CFG_USE_ADDR
CMD
: Byte with optional command field to better align with multiple packets. Optional field, can be disabled withLWPKT_CFG_USE_CMD
LEN
: Length of data part field. This is variable multi-byte length to support data length>= 256
bytes. Always presentDATA
: Optional data field. Number of bytes is as inLEN
fieldCRC
: 8-bit CRC of all enabled fields except START and STOP bytes. Optional field, can be disabled withLWPKT_CFG_USE_CRC
STOP
: Byte with fixed value to represent stop of packet
Tip
If only 2
devices are communicating and are in the network, considering disabling LWPKT_CFG_USE_ADDR
to improve
data bandwidth and remove unnecessary packet overhead
Data input output¶
LwPKT library only reads and writes to 2
ringbuffers used for read and write operations.
It is up to application to implement how buffers are actually later written for read operation and sent out on the network for write operation.
Warning
LwPKT is platform independant and requires final application to actually take care of data being read/written from/to ringbuffers and transferred further over the network
Event management¶
LwPKT may operate in event mode, meaning that application receives notifications on different events:
New packet has been received
Timeout during packet receive
Timeout function is used when network doesn’t transmit all bytes or if data got lost in the middle of transmission. This is to make sure that packet protocol library easily recovers to be able to receive more packets in the future
Warning
To use this feature, application must provide accurate timing in units of milliseconds to be able to properly handle timeout function.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | #include <stdio.h>
#include "lwpkt/lwpkt.h"
/* LwPKT data */
static lwpkt_t pkt;
static lwrb_t pkt_tx_rb, pkt_rx_rb;
static uint8_t pkt_tx_rb_data[64], pkt_rx_rb_data[64];
/* Data to read and write */
static const char* data = "Hello World\r\n";
/**
* \brief LwPKT application callback
*/
static void
my_lwpkt_evt_fn(lwpkt_t* pkt, lwpkt_evt_type_t type) {
switch (type) {
case LWPKT_EVT_PKT: {
size_t len;
printf("Valid packet received..\r\n");
/* Packet is valid */
printf("Packet is valid!\r\n");
/* Print debug messages for packet */
#if LWPKT_CFG_USE_ADDR
printf("Packet from: 0x%02X\r\n", (unsigned)lwpkt_get_from_addr(pkt));
printf("Packet to: 0x%02X\r\n", (unsigned)lwpkt_get_to_addr(pkt));
#endif /* LWPKT_CFG_USE_ADDR */
#if LWPKT_CFG_USE_CMD
printf("Packet cmd: 0x%02X\r\n", (unsigned)lwpkt_get_cmd(pkt));
#endif /* LWPKT_CFG_USE_CMD */
printf("Packet data length: 0x%02X\r\n", (unsigned)lwpkt_get_data_len(pkt));
/* Do other thins... */
break;
}
case LWPKT_EVT_TIMEOUT: {
printf("Timeout detected during read operation..\r\n");
break;
}
}
}
/**
* \brief LwPKT example code with event feature
*/
void
example_lwpkt_evt(void) {
lwpktr_t res;
uint32_t time;
uint8_t b;
printf("---\r\nLwPKT event type..\r\n\r\n");
/*
* Initialize both ring buffers, for TX and RX operations
*
* Initialize LwPKT and link buffers together
*/
lwrb_init(&pkt_tx_rb, pkt_tx_rb_data, sizeof(pkt_tx_rb_data));
lwrb_init(&pkt_rx_rb, pkt_rx_rb_data, sizeof(pkt_rx_rb_data));
lwpkt_init(&pkt, &pkt_tx_rb, &pkt_rx_rb);
#if LWPKT_CFG_USE_ADDR
/* Set device address (if feature enabled) */
lwpkt_set_addr(&pkt, 0x12);
#endif /* LWPKT_CFG_USE_ADDR */
/*
* Write packet to the TX ringbuffer,
* act as device wants to send some data
*/
res = lwpkt_write(&pkt,
#if LWPKT_CFG_USE_ADDR
0x11, /* End address to whom to send */
#endif /* LWPKT_CFG_USE_ADDR */
#if LWPKT_CFG_USE_CMD
0x85, /* Command type */
#endif /* LWPKT_CFG_USE_CMD */
data, strlen(data)); /* Length of data and actual data */
/*
* LwPKT wrote data to pkt_tx_rb ringbuffer
* Now actually transmit data over your interface
* (USART for example, ...)
*/
/*
* For the purpose of this example, application will
* fake data transmission by doing reading from TX buffer
* and writing it to RX buffer
*/
while (lwrb_read(&pkt_tx_rb, &b, 1) == 1) {
lwrb_write(&pkt_rx_rb, &b, 1);
}
/*
* Here we have our data in RX buffer
* means we received data over network interface
*/
/* Now call process function instead */
time = 100; /* Get_current_time_in_milliseconds */
lwpkt_process(&pkt, time, my_lwpkt_evt_fn);
}
|