Add re-entrancy support / multiple instances (#9)

* done with changes but now segfaulting

* fixed the bug

* fix some bad indents

* some cleanings

* updated readme
pull/14/head 2.0.0
Ondřej Hruška 7 years ago committed by GitHub
parent 77f60e1876
commit db0ae30f41
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      README.md
  2. 6
      TF_Integration.example.c
  3. 1300
      TinyFrame.c
  4. 247
      TinyFrame.h
  5. 261
      demo/demo.c
  6. 2
      demo/demo.h
  7. 7
      demo/multipart_tx/Makefile
  8. 545
      demo/multipart_tx/test.c
  9. 2
      demo/simple/Makefile
  10. 71
      demo/simple/test.c
  11. 2
      demo/socket_demo/Makefile
  12. 30
      demo/socket_demo/master.c
  13. 45
      demo/socket_demo/slave.c
  14. 35
      demo/utils.c

@ -19,6 +19,10 @@ The library lets you register listeners (callback functions) to wait for (1) any
a particular frame Type, or (3) a specific message ID. This high-level API lets you a particular frame Type, or (3) a specific message ID. This high-level API lets you
easily implement various async communication patterns. easily implement various async communication patterns.
TinyFrame is re-entrant and supports creating multiple instances with the limitation
that their structure (field sizes and checksum type) must be the same. There is a support
for adding multi-threaded access to a shared instance using a mutex (via a callback stub).
## Frame structure ## Frame structure
All fields in the message frame have a configurable size (see the top of the header file). All fields in the message frame have a configurable size (see the top of the header file).
@ -49,7 +53,9 @@ DATA_CKSUM .. checksum, implemented as XOR of all preceding bytes in the message
- All TinyFrame functions, typedefs and macros start with the `TF_` prefix. - All TinyFrame functions, typedefs and macros start with the `TF_` prefix.
- Both peers must include the library with the same parameters (configured at the top of the header file) - Both peers must include the library with the same parameters (configured at the top of the header file)
- Start by calling `TF_Init()` with `TF_MASTER` or `TF_SLAVE` as the argument - Start by calling `TF_Init()` with `TF_MASTER` or `TF_SLAVE` as the argument. This creates a handle.
Use `TF_InitStatic()` to avoid the use of malloc(). If multiple instances are used, you can tag them
using the `tf.userdata` / `tf.usertag` field.
- Implement `TF_WriteImpl()` - declared at the bottom of the header file as `extern`. - Implement `TF_WriteImpl()` - declared at the bottom of the header file as `extern`.
This function is used by `TF_Send()` and others to write bytes to your UART (or other physical layer). This function is used by `TF_Send()` and others to write bytes to your UART (or other physical layer).
A frame can be sent in it's entirety, or in multiple parts, depending on its size. A frame can be sent in it's entirety, or in multiple parts, depending on its size.

@ -10,19 +10,19 @@
* listener timeout feature. * listener timeout feature.
*/ */
void TF_WriteImpl(const uint8_t *buff, size_t len) void TF_WriteImpl(TinyFrame *tf, const uint8_t *buff, size_t len)
{ {
// send to UART // send to UART
} }
/** Claim the TX interface before composing and sending a frame */ /** Claim the TX interface before composing and sending a frame */
void TF_ClaimTx(void) void TF_ClaimTx(TinyFrame *tf)
{ {
// take mutex // take mutex
} }
/** Free the TX interface after composing and sending a frame */ /** Free the TX interface after composing and sending a frame */
void TF_ReleaseTx(void) void TF_ReleaseTx(TinyFrame *tf)
{ {
// release mutex // release mutex
} }

File diff suppressed because it is too large Load Diff

@ -10,12 +10,13 @@
* Upstream URL: https://github.com/MightyPork/TinyFrame * Upstream URL: https://github.com/MightyPork/TinyFrame
*/ */
#define TF_VERSION "1.2.0" #define TF_VERSION "2.0.0"
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
#include <stdint.h> // for uint8_t etc #include <stdint.h> // for uint8_t etc
#include <stdbool.h> // for bool #include <stdbool.h> // for bool
#include <stdlib.h> // for NULL #include <stddef.h> // for NULL
#include <string.h> // for memset()
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Select checksum type (0 = none, 8 = ~XOR, 16 = CRC16 0x8005, 32 = CRC32) // Select checksum type (0 = none, 8 = ~XOR, 16 = CRC16 0x8005, 32 = CRC32)
@ -24,54 +25,54 @@
#define TF_CKSUM_CRC16 16 #define TF_CKSUM_CRC16 16
#define TF_CKSUM_CRC32 32 #define TF_CKSUM_CRC32 32
#include <TF_Config.h> #include "TF_Config.h"
//region Resolve data types //region Resolve data types
#if TF_LEN_BYTES == 1 #if TF_LEN_BYTES == 1
typedef uint8_t TF_LEN; typedef uint8_t TF_LEN;
#elif TF_LEN_BYTES == 2 #elif TF_LEN_BYTES == 2
typedef uint16_t TF_LEN; typedef uint16_t TF_LEN;
#elif TF_LEN_BYTES == 4 #elif TF_LEN_BYTES == 4
typedef uint32_t TF_LEN; typedef uint32_t TF_LEN;
#else #else
#error Bad value of TF_LEN_BYTES, must be 1, 2 or 4 #error Bad value of TF_LEN_BYTES, must be 1, 2 or 4
#endif #endif
#if TF_TYPE_BYTES == 1 #if TF_TYPE_BYTES == 1
typedef uint8_t TF_TYPE; typedef uint8_t TF_TYPE;
#elif TF_TYPE_BYTES == 2 #elif TF_TYPE_BYTES == 2
typedef uint16_t TF_TYPE; typedef uint16_t TF_TYPE;
#elif TF_TYPE_BYTES == 4 #elif TF_TYPE_BYTES == 4
typedef uint32_t TF_TYPE; typedef uint32_t TF_TYPE;
#else #else
#error Bad value of TF_TYPE_BYTES, must be 1, 2 or 4 #error Bad value of TF_TYPE_BYTES, must be 1, 2 or 4
#endif #endif
#if TF_ID_BYTES == 1 #if TF_ID_BYTES == 1
typedef uint8_t TF_ID; typedef uint8_t TF_ID;
#elif TF_ID_BYTES == 2 #elif TF_ID_BYTES == 2
typedef uint16_t TF_ID; typedef uint16_t TF_ID;
#elif TF_ID_BYTES == 4 #elif TF_ID_BYTES == 4
typedef uint32_t TF_ID; typedef uint32_t TF_ID;
#else #else
#error Bad value of TF_ID_BYTES, must be 1, 2 or 4 #error Bad value of TF_ID_BYTES, must be 1, 2 or 4
#endif #endif
#if TF_CKSUM_TYPE == TF_CKSUM_XOR || TF_CKSUM_TYPE == TF_CKSUM_NONE #if TF_CKSUM_TYPE == TF_CKSUM_XOR || TF_CKSUM_TYPE == TF_CKSUM_NONE
// ~XOR (if 0, still use 1 byte - it won't be used) // ~XOR (if 0, still use 1 byte - it won't be used)
typedef uint8_t TF_CKSUM; typedef uint8_t TF_CKSUM;
#elif TF_CKSUM_TYPE == TF_CKSUM_CRC16 #elif TF_CKSUM_TYPE == TF_CKSUM_CRC16
// CRC16 // CRC16
typedef uint16_t TF_CKSUM; typedef uint16_t TF_CKSUM;
#elif TF_CKSUM_TYPE == TF_CKSUM_CRC32 #elif TF_CKSUM_TYPE == TF_CKSUM_CRC32
// CRC32 // CRC32
typedef uint32_t TF_CKSUM; typedef uint32_t TF_CKSUM;
#else #else
#error Bad value for TF_CKSUM_TYPE, must be 8, 16 or 32 #error Bad value for TF_CKSUM_TYPE, must be 8, 16 or 32
#endif #endif
//endregion //endregion
@ -86,26 +87,27 @@
/** Peer bit enum (used for init) */ /** Peer bit enum (used for init) */
typedef enum { typedef enum {
TF_SLAVE = 0, TF_SLAVE = 0,
TF_MASTER, TF_MASTER = 1,
} TF_Peer; } TF_Peer;
/** Response from listeners */
typedef enum { typedef enum {
TF_NEXT = 0, //!< Not handled, let other listeners handle it TF_NEXT = 0, //!< Not handled, let other listeners handle it
TF_STAY = 1, //!< Handled, stay TF_STAY = 1, //!< Handled, stay
TF_RENEW = 2, //!< Handled, stay, renew - useful only with listener timeout TF_RENEW = 2, //!< Handled, stay, renew - useful only with listener timeout
TF_CLOSE = 3, //!< Handled, remove self TF_CLOSE = 3, //!< Handled, remove self
} TF_Result; } TF_Result;
/** Data structure for sending / receiving messages */ /** Data structure for sending / receiving messages */
typedef struct _TF_MSG_STRUCT_ { typedef struct _TF_MSG_STRUCT_ {
TF_ID frame_id; //!< message ID TF_ID frame_id; //!< message ID
bool is_response; //!< internal flag, set when using the Respond function. frame_id is then kept unchanged. bool is_response; //!< internal flag, set when using the Respond function. frame_id is then kept unchanged.
TF_TYPE type; //!< received or sent message type TF_TYPE type; //!< received or sent message type
const uint8_t *data; //!< buffer of received data or data to send. NULL = listener timed out, free userdata! const uint8_t *data; //!< buffer of received data or data to send. NULL = listener timed out, free userdata!
TF_LEN len; //!< length of the buffer TF_LEN len; //!< length of the buffer
void *userdata; //!< here's a place for custom data; this data will be stored with the listener void *userdata; //!< here's a place for custom data; this data will be stored with the listener
void *userdata2; void *userdata2;
} TF_Msg; } TF_Msg;
/** /**
@ -113,15 +115,11 @@ typedef struct _TF_MSG_STRUCT_ {
*/ */
static inline void TF_ClearMsg(TF_Msg *msg) static inline void TF_ClearMsg(TF_Msg *msg)
{ {
msg->frame_id = 0; memset(msg, 0, sizeof(TF_Msg));
msg->is_response = false;
msg->type = 0;
msg->data = NULL;
msg->len = 0;
msg->userdata = NULL;
msg->userdata2 = NULL;
} }
typedef struct TinyFrame_ TinyFrame;
/** /**
* TinyFrame Type Listener callback * TinyFrame Type Listener callback
* *
@ -131,21 +129,117 @@ static inline void TF_ClearMsg(TF_Msg *msg)
* @param len - number of bytes in the buffer * @param len - number of bytes in the buffer
* @return listener result * @return listener result
*/ */
typedef TF_Result (*TF_Listener)(TF_Msg *msg); typedef TF_Result (*TF_Listener)(TinyFrame *tf, TF_Msg *msg);
// -------------------------------------------------------------------
// region Internal
enum TFState_ {
TFState_SOF = 0, //!< Wait for SOF
TFState_LEN, //!< Wait for Number Of Bytes
TFState_HEAD_CKSUM, //!< Wait for header Checksum
TFState_ID, //!< Wait for ID
TFState_TYPE, //!< Wait for message type
TFState_DATA, //!< Receive payload
TFState_DATA_CKSUM //!< Wait for Checksum
};
struct TF_IdListener_ {
TF_ID id;
TF_Listener fn;
TF_TICKS timeout; // nr of ticks remaining to disable this listener
TF_TICKS timeout_max; // the original timeout is stored here
void *userdata;
void *userdata2;
};
struct TF_TypeListener_ {
TF_TYPE type;
TF_Listener fn;
};
struct TF_GenericListener_ {
TF_Listener fn;
};
/**
* Frame parser internal state.
*/
struct TinyFrame_ {
/* Public user data */
void *userdata;
uint32_t usertag;
// --- the rest of the struct is internal, do not access directly ---
/* Own state */
TF_Peer peer_bit; //!< Own peer bit (unqiue to avoid msg ID clash)
TF_ID next_id; //!< Next frame / frame chain ID
/* Parser state */
enum TFState_ state;
TF_TICKS parser_timeout_ticks;
TF_ID id; //!< Incoming packet ID
TF_LEN len; //!< Payload length
uint8_t data[TF_MAX_PAYLOAD_RX]; //!< Data byte buffer
TF_LEN rxi; //!< Field size byte counter
TF_CKSUM cksum; //!< Checksum calculated of the data stream
TF_CKSUM ref_cksum; //!< Reference checksum read from the message
TF_TYPE type; //!< Collected message type number
bool discard_data; //!< Set if (len > TF_MAX_PAYLOAD) to read the frame, but ignore the data.
/* --- Callbacks --- */
/* Transaction callbacks */
struct TF_IdListener_ id_listeners[TF_MAX_ID_LST];
struct TF_TypeListener_ type_listeners[TF_MAX_TYPE_LST];
struct TF_GenericListener_ generic_listeners[TF_MAX_GEN_LST];
// Those counters are used to optimize look-up times.
// They point to the highest used slot number,
// or close to it, depending on the removal order.
TF_COUNT count_id_lst;
TF_COUNT count_type_lst;
TF_COUNT count_generic_lst;
// Buffer for building frames
uint8_t sendbuf[TF_SENDBUF_LEN];
};
// endregion
// -------------------------------------------------------------------
/** /**
* Initialize the TinyFrame engine. * Initialize the TinyFrame engine.
* This can also be used to completely reset it (removing all listeners etc) * This can also be used to completely reset it (removing all listeners etc).
*
* The field .userdata (or .usertag) can be used to identify different instances
* in the TF_WriteImpl() function etc. Set this field after the init.
*
* This function is a wrapper around TF_InitStatic that calls malloc() to obtain
* the instance.
* *
* @param peer_bit - peer bit to use for self * @param peer_bit - peer bit to use for self
*/ */
void TF_Init(TF_Peer peer_bit); TinyFrame *TF_Init(TF_Peer peer_bit);
/**
* Initialize the TinyFrame engine using a statically allocated instance struct.
*
* The .userdata / .usertag field is preserved when TF_InitStatic is called.
*
* @param peer_bit - peer bit to use for self
*/
void TF_InitStatic(TinyFrame *tf, TF_Peer peer_bit);
/** /**
* Reset the frame parser state machine. * Reset the frame parser state machine.
* This does not affect registered listeners. * This does not affect registered listeners.
*/ */
void TF_ResetParser(void); void TF_ResetParser(TinyFrame *tf);
/** /**
* Register a frame type listener. * Register a frame type listener.
@ -155,14 +249,14 @@ void TF_ResetParser(void);
* @param timeout - timeout in ticks to auto-remove the listener (0 = keep forever) * @param timeout - timeout in ticks to auto-remove the listener (0 = keep forever)
* @return slot index (for removing), or TF_ERROR (-1) * @return slot index (for removing), or TF_ERROR (-1)
*/ */
bool TF_AddIdListener(TF_Msg *msg, TF_Listener cb, TF_TICKS timeout); bool TF_AddIdListener(TinyFrame *tf, TF_Msg *msg, TF_Listener cb, TF_TICKS timeout);
/** /**
* Remove a listener by the message ID it's registered for * Remove a listener by the message ID it's registered for
* *
* @param frame_id - the frame we're listening for * @param frame_id - the frame we're listening for
*/ */
bool TF_RemoveIdListener(TF_ID frame_id); bool TF_RemoveIdListener(TinyFrame *tf, TF_ID frame_id);
/** /**
* Register a frame type listener. * Register a frame type listener.
@ -171,14 +265,14 @@ bool TF_RemoveIdListener(TF_ID frame_id);
* @param cb - callback * @param cb - callback
* @return slot index (for removing), or TF_ERROR (-1) * @return slot index (for removing), or TF_ERROR (-1)
*/ */
bool TF_AddTypeListener(TF_TYPE frame_type, TF_Listener cb); bool TF_AddTypeListener(TinyFrame *tf, TF_TYPE frame_type, TF_Listener cb);
/** /**
* Remove a listener by type. * Remove a listener by type.
* *
* @param type - the type it's registered for * @param type - the type it's registered for
*/ */
bool TF_RemoveTypeListener(TF_TYPE type); bool TF_RemoveTypeListener(TinyFrame *tf, TF_TYPE type);
/** /**
* Register a generic listener. * Register a generic listener.
@ -186,14 +280,14 @@ bool TF_RemoveTypeListener(TF_TYPE type);
* @param cb - callback * @param cb - callback
* @return slot index (for removing), or TF_ERROR (-1) * @return slot index (for removing), or TF_ERROR (-1)
*/ */
bool TF_AddGenericListener(TF_Listener cb); bool TF_AddGenericListener(TinyFrame *tf, TF_Listener cb);
/** /**
* Remove a generic listener by function pointer * Remove a generic listener by function pointer
* *
* @param cb - callback function to remove * @param cb - callback function to remove
*/ */
bool TF_RemoveGenericListener(TF_Listener cb); bool TF_RemoveGenericListener(TinyFrame *tf, TF_Listener cb);
/** /**
* Send a frame, no listener * Send a frame, no listener
@ -201,17 +295,12 @@ bool TF_RemoveGenericListener(TF_Listener cb);
* @param msg - message struct. ID is stored in the frame_id field * @param msg - message struct. ID is stored in the frame_id field
* @return success * @return success
*/ */
bool TF_Send(TF_Msg *msg); bool TF_Send(TinyFrame *tf, TF_Msg *msg);
/** /**
* Like TF_Send, but without the struct * Like TF_Send, but without the struct
*/ */
bool TF_SendSimple(TF_TYPE type, const uint8_t *data, TF_LEN len); bool TF_SendSimple(TinyFrame *tf, TF_TYPE type, const uint8_t *data, TF_LEN len);
/**
* Like TF_Query, but without the struct
*/
bool TF_QuerySimple(TF_TYPE type, const uint8_t *data, TF_LEN len, TF_Listener listener, TF_TICKS timeout, void *userdata);
/** /**
* Send a frame, and optionally attach an ID listener. * Send a frame, and optionally attach an ID listener.
@ -221,7 +310,13 @@ bool TF_QuerySimple(TF_TYPE type, const uint8_t *data, TF_LEN len, TF_Listener l
* @param timeout - listener expiry time in ticks * @param timeout - listener expiry time in ticks
* @return success * @return success
*/ */
bool TF_Query(TF_Msg *msg, TF_Listener listener, TF_TICKS timeout); bool TF_Query(TinyFrame *tf, TF_Msg *msg, TF_Listener listener, TF_TICKS timeout);
/**
* Like TF_Query, but without the struct
*/
bool TF_QuerySimple(TinyFrame *tf, TF_TYPE type, const uint8_t *data, TF_LEN len,
TF_Listener listener, TF_TICKS timeout);
/** /**
* Send a response to a received message. * Send a response to a received message.
@ -229,15 +324,15 @@ bool TF_Query(TF_Msg *msg, TF_Listener listener, TF_TICKS timeout);
* @param msg - message struct. ID is read from frame_id. set ->renew to reset listener timeout * @param msg - message struct. ID is read from frame_id. set ->renew to reset listener timeout
* @return success * @return success
*/ */
bool TF_Respond(TF_Msg *msg); bool TF_Respond(TinyFrame *tf, TF_Msg *msg);
/** /**
* Renew ID listener timeout * Renew an ID listener timeout externally (as opposed to by returning TF_RENEW from the ID listener)
* *
* @param id - listener ID to renew * @param id - listener ID to renew
* @return true if listener was found and renewed * @return true if listener was found and renewed
*/ */
bool TF_RenewIdListener(TF_ID id); bool TF_RenewIdListener(TinyFrame *tf, TF_ID id);
/** /**
* Accept incoming bytes & parse frames * Accept incoming bytes & parse frames
@ -245,21 +340,14 @@ bool TF_RenewIdListener(TF_ID id);
* @param buffer - byte buffer to process * @param buffer - byte buffer to process
* @param count - nr of bytes in the buffer * @param count - nr of bytes in the buffer
*/ */
void TF_Accept(const uint8_t *buffer, size_t count); void TF_Accept(TinyFrame *tf, const uint8_t *buffer, size_t count);
/** /**
* Accept a single incoming byte * Accept a single incoming byte
* *
* @param c - a received char * @param c - a received char
*/ */
void TF_AcceptChar(uint8_t c); void TF_AcceptChar(TinyFrame *tf, uint8_t c);
/**
* 'Write bytes' function that sends data to UART
*
* ! Implement this in your application code !
*/
extern void TF_WriteImpl(const uint8_t *buff, size_t len);
/** /**
* This function should be called periodically. * This function should be called periodically.
@ -269,12 +357,21 @@ extern void TF_WriteImpl(const uint8_t *buff, size_t len);
* *
* (suggestion - call this in a SysTick handler) * (suggestion - call this in a SysTick handler)
*/ */
void TF_Tick(void); void TF_Tick(TinyFrame *tf);
// --- TO BE IMPLEMENTED BY USER ---
/**
* 'Write bytes' function that sends data to UART
*
* ! Implement this in your application code !
*/
extern void TF_WriteImpl(TinyFrame *tf, const uint8_t *buff, size_t len);
/** Claim the TX interface before composing and sending a frame */ /** Claim the TX interface before composing and sending a frame */
extern void TF_ClaimTx(void); extern void TF_ClaimTx(TinyFrame *tf);
/** Free the TX interface after composing and sending a frame */ /** Free the TX interface after composing and sending a frame */
extern void TF_ReleaseTx(void); extern void TF_ReleaseTx(TinyFrame *tf);
#endif #endif

@ -7,6 +7,7 @@
// those magic defines are needed so we can use clone() // those magic defines are needed so we can use clone()
#define _GNU_SOURCE #define _GNU_SOURCE
#define __USE_GNU #define __USE_GNU
#include <sched.h> #include <sched.h>
#include <unistd.h> #include <unistd.h>
@ -15,17 +16,21 @@
#include <string.h> #include <string.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <signal.h> #include <signal.h>
#include <malloc.h>
#include <stdlib.h>
volatile int sockfd = -1; volatile int sockfd = -1;
volatile bool conn_disband = false; volatile bool conn_disband = false;
TinyFrame *demo_tf;
/** /**
* Close socket * Close socket
*/ */
void demo_disconn(void) void demo_disconn(void)
{ {
conn_disband = true; conn_disband = true;
if (sockfd >= 0) close(sockfd); if (sockfd >= 0) close(sockfd);
} }
/** /**
@ -34,17 +39,18 @@ void demo_disconn(void)
* @param buff * @param buff
* @param len * @param len
*/ */
void TF_WriteImpl(const uint8_t *buff, size_t len) void TF_WriteImpl(TinyFrame *tf, const uint8_t *buff, size_t len)
{ {
printf("\033[32mTF_WriteImpl - sending frame:\033[0m\n"); printf("\033[32mTF_WriteImpl - sending frame:\033[0m\n");
dumpFrame(buff, len); dumpFrame(buff, len);
usleep(1000); usleep(1000);
if (sockfd != -1) { if (sockfd != -1) {
write(sockfd, buff, len); write(sockfd, buff, len);
} else { }
printf("\nNo peer!\n"); else {
} printf("\nNo peer!\n");
}
} }
@ -54,46 +60,46 @@ void TF_WriteImpl(const uint8_t *buff, size_t len)
* @param unused * @param unused
* @return unused * @return unused
*/ */
static int demo_client(void* unused) static int demo_client(void *unused)
{ {
(void)unused; (void) unused;
ssize_t n = 0; ssize_t n = 0;
uint8_t recvBuff[1024]; uint8_t recvBuff[1024];
struct sockaddr_in serv_addr; struct sockaddr_in serv_addr;
printf("\n--- STARTING CLIENT! ---\n"); printf("\n--- STARTING CLIENT! ---\n");
memset(recvBuff, '0', sizeof(recvBuff)); memset(recvBuff, '0', sizeof(recvBuff));
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
printf("\n Error : Could not create socket \n"); printf("\n Error : Could not create socket \n");
return false; return false;
} }
memset(&serv_addr, '0', sizeof(serv_addr)); memset(&serv_addr, '0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET; serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT); serv_addr.sin_port = htons(PORT);
if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) { if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) {
printf("\n inet_pton error occured\n"); printf("\n inet_pton error occured\n");
return false; return false;
} }
if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) { if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
printf("\n Error : Connect Failed \n"); printf("\n Error : Connect Failed \n");
perror("PERROR "); perror("PERROR ");
return false; return false;
} }
printf("\n Child Process \n"); printf("\n Child Process \n");
while ((n = read(sockfd, recvBuff, sizeof(recvBuff) - 1)) > 0) { while ((n = read(sockfd, recvBuff, sizeof(recvBuff) - 1)) > 0) {
printf("\033[36m--- RX %ld bytes ---\033[0m\n", n); printf("\033[36m--- RX %ld bytes ---\033[0m\n", n);
dumpFrame(recvBuff, (size_t) n); dumpFrame(recvBuff, (size_t) n);
TF_Accept(recvBuff, (size_t) n); TF_Accept(demo_tf, recvBuff, (size_t) n);
} }
return 0; return 0;
} }
/** /**
@ -102,59 +108,59 @@ static int demo_client(void* unused)
* @param unused * @param unused
* @return unused * @return unused
*/ */
static int demo_server(void* unused) static int demo_server(void *unused)
{ {
(void)unused; (void) unused;
ssize_t n; ssize_t n;
int listenfd = 0; int listenfd = 0;
uint8_t recvBuff[1024]; uint8_t recvBuff[1024];
struct sockaddr_in serv_addr; struct sockaddr_in serv_addr;
int option; int option;
printf("\n--- STARTING SERVER! ---\n"); printf("\n--- STARTING SERVER! ---\n");
listenfd = socket(AF_INET, SOCK_STREAM, 0); listenfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&serv_addr, '0', sizeof(serv_addr)); memset(&serv_addr, '0', sizeof(serv_addr));
option = 1; option = 1;
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (char*)&option, sizeof(option)); setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (char *) &option, sizeof(option));
serv_addr.sin_family = AF_INET; serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(PORT); serv_addr.sin_port = htons(PORT);
if (bind(listenfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) { if (bind(listenfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
perror("Failed to bind"); perror("Failed to bind");
return 1; return 1;
} }
if (listen(listenfd, 10) < 0) { if (listen(listenfd, 10) < 0) {
perror("Failed to listen"); perror("Failed to listen");
return 1; return 1;
} }
while (1) { while (1) {
printf("\nWaiting for client...\n"); printf("\nWaiting for client...\n");
sockfd = accept(listenfd, (struct sockaddr *) NULL, NULL); sockfd = accept(listenfd, (struct sockaddr *) NULL, NULL);
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char*)&option, sizeof(option)); setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *) &option, sizeof(option));
printf("\nClient connected\n"); printf("\nClient connected\n");
conn_disband = false; conn_disband = false;
while ((n = read(sockfd, recvBuff, sizeof(recvBuff) - 1)) > 0 && !conn_disband) { while ((n = read(sockfd, recvBuff, sizeof(recvBuff) - 1)) > 0 && !conn_disband) {
printf("\033[36m--- RX %ld bytes ---\033[0m\n", n); printf("\033[36m--- RX %ld bytes ---\033[0m\n", n);
dumpFrame(recvBuff, n); dumpFrame(recvBuff, n);
TF_Accept(recvBuff, (size_t) n); TF_Accept(demo_tf, recvBuff, (size_t) n);
} }
if (n < 0) { if (n < 0) {
printf("\n Read error \n"); printf("\n Read error \n");
} }
printf("Closing socket\n"); printf("Closing socket\n");
close(sockfd); close(sockfd);
sockfd = -1; sockfd = -1;
} }
return 0; return 0;
} }
/** /**
@ -164,11 +170,11 @@ static int demo_server(void* unused)
*/ */
static void signal_handler(int sig) static void signal_handler(int sig)
{ {
(void)sig; (void) sig;
printf("Shutting down..."); printf("Shutting down...");
demo_disconn(); demo_disconn();
exit(sig); // pass the signal through - this is nonstandard behavior but useful for debugging exit(sig); // pass the signal through - this is nonstandard behavior but useful for debugging
} }
/** /**
@ -176,7 +182,7 @@ static void signal_handler(int sig)
*/ */
void demo_sleep(void) void demo_sleep(void)
{ {
while(1) usleep(10); while (1) usleep(10);
} }
/** /**
@ -188,32 +194,33 @@ void demo_sleep(void)
*/ */
void demo_init(TF_Peer peer) void demo_init(TF_Peer peer)
{ {
signal(SIGTERM, signal_handler); signal(SIGTERM, signal_handler);
signal(SIGINT, signal_handler); signal(SIGINT, signal_handler);
int retc; int retc;
void *stack = malloc(8192); void *stack = malloc(8192);
if (stack == NULL) { if (stack == NULL) {
perror("Oh fuck"); perror("Oh fuck");
signal_handler(9); signal_handler(9);
return; return;
} }
printf("Starting %s...\n", peer == TF_MASTER ? "MASTER" : "SLAVE"); printf("Starting %s...\n", peer == TF_MASTER ? "MASTER" : "SLAVE");
// CLONE_VM --- share heap // CLONE_VM --- share heap
// CLONE_FILES --- share stdout and stderr // CLONE_FILES --- share stdout and stderr
if (peer == TF_MASTER) { if (peer == TF_MASTER) {
retc = clone(&demo_client, (char *)stack+8192, CLONE_VM|CLONE_FILES, 0); retc = clone(&demo_client, (char *) stack + 8192, CLONE_VM | CLONE_FILES, 0);
} else { }
retc = clone(&demo_server, (char *)stack+8192, CLONE_VM|CLONE_FILES, 0); else {
} retc = clone(&demo_server, (char *) stack + 8192, CLONE_VM | CLONE_FILES, 0);
}
if (retc == 0) {
perror("Clone fail"); if (retc == 0) {
signal_handler(9); perror("Clone fail");
return; signal_handler(9);
} return;
}
printf("Thread started\n");
printf("Thread started\n");
} }

@ -11,6 +11,8 @@
#define PORT 9798 #define PORT 9798
extern TinyFrame *demo_tf;
/** Sleep and wait for ^C */ /** Sleep and wait for ^C */
void demo_sleep(void); void demo_sleep(void);

@ -1,11 +1,12 @@
CFILES=../utils.c ../../TinyFrame.c CFILES=../utils.c ../../TinyFrame.c
INCLDIRS=-I. -I.. -I../.. INCLDIRS=-I. -I.. -I../..
CFLAGS=-O0 -ggdb --std=gnu99 -Wno-main -Wall -Wextra $(CFILES) $(INCLDIRS) CFLAGS=-O0 -ggdb --std=gnu99 -Wno-main -Wall -Wno-unused -Wextra $(CFILES) $(INCLDIRS)
run: test.bin
./test.bin
build: test.bin build: test.bin
run: test.bin
./test.bin
test.bin: test.c $(CFILES) test.bin: test.c $(CFILES)
gcc test.c $(CFLAGS) -o test.bin gcc test.c $(CFLAGS) -o test.bin

@ -3,295 +3,298 @@
#include "../../TinyFrame.h" #include "../../TinyFrame.h"
#include "../utils.h" #include "../utils.h"
TinyFrame *demo_tf;
extern const char *romeo; extern const char *romeo;
/** /**
* This function should be defined in the application code. * This function should be defined in the application code.
* It implements the lowest layer - sending bytes to UART (or other) * It implements the lowest layer - sending bytes to UART (or other)
*/ */
void TF_WriteImpl(const uint8_t *buff, size_t len) void TF_WriteImpl(TinyFrame *tf, const uint8_t *buff, size_t len)
{ {
printf("--------------------\n"); printf("--------------------\n");
printf("\033[32mTF_WriteImpl - sending frame:\033[0m\n"); printf("\033[32mTF_WriteImpl - sending frame:\033[0m\n");
dumpFrame(buff, len); dumpFrame(buff, len);
// Send it back as if we received it // Send it back as if we received it
TF_Accept(buff, len); TF_Accept(tf, buff, len);
} }
/** An example listener function */ /** An example listener function */
TF_Result myListener(TF_Msg *msg) TF_Result myListener(TinyFrame *tf, TF_Msg *msg)
{ {
dumpFrameInfo(msg); dumpFrameInfo(msg);
if (strcmp(msg->data, romeo) == 0) { if (strcmp((const char *) msg->data, romeo) == 0) {
printf("FILE TRANSFERRED OK!\r\n"); printf("FILE TRANSFERRED OK!\r\n");
} else { }
printf("FAIL!!!!\r\n"); else {
} printf("FAIL!!!!\r\n");
return TF_STAY; }
return TF_STAY;
} }
void main(void) void main(void)
{ {
TF_Msg msg; TF_Msg msg;
// Set up the TinyFrame library // Set up the TinyFrame library
TF_Init(TF_MASTER); // 1 = master, 0 = slave demo_tf = TF_Init(TF_MASTER); // 1 = master, 0 = slave
TF_AddGenericListener(myListener); TF_AddGenericListener(demo_tf, myListener);
printf("------ Simulate sending a LOOONG message --------\n"); printf("------ Simulate sending a LOOONG message --------\n");
TF_ClearMsg(&msg); TF_ClearMsg(&msg);
msg.type = 0x22; msg.type = 0x22;
msg.data = (pu8)romeo; msg.data = (pu8) romeo;
msg.len = strlen(romeo); msg.len = (TF_LEN) strlen(romeo);
TF_Send(&msg); TF_Send(demo_tf, &msg);
} }
const char *romeo ="THE TRAGEDY OF ROMEO AND JULIET\n" const char *romeo = "THE TRAGEDY OF ROMEO AND JULIET\n"
"\n" "\n"
"by William Shakespeare\n" "by William Shakespeare\n"
"\n" "\n"
"\n" "\n"
"\n" "\n"
"Dramatis Personae\n" "Dramatis Personae\n"
"\n" "\n"
" Chorus.\n" " Chorus.\n"
"\n" "\n"
"\n" "\n"
" Escalus, Prince of Verona.\n" " Escalus, Prince of Verona.\n"
"\n" "\n"
" Paris, a young Count, kinsman to the Prince.\n" " Paris, a young Count, kinsman to the Prince.\n"
"\n" "\n"
" Montague, heads of two houses at variance with each other.\n" " Montague, heads of two houses at variance with each other.\n"
"\n" "\n"
" Capulet, heads of two houses at variance with each other.\n" " Capulet, heads of two houses at variance with each other.\n"
"\n" "\n"
" An old Man, of the Capulet family.\n" " An old Man, of the Capulet family.\n"
"\n" "\n"
" Romeo, son to Montague.\n" " Romeo, son to Montague.\n"
"\n" "\n"
" Tybalt, nephew to Lady Capulet.\n" " Tybalt, nephew to Lady Capulet.\n"
"\n" "\n"
" Mercutio, kinsman to the Prince and friend to Romeo.\n" " Mercutio, kinsman to the Prince and friend to Romeo.\n"
"\n" "\n"
" Benvolio, nephew to Montague, and friend to Romeo\n" " Benvolio, nephew to Montague, and friend to Romeo\n"
"\n" "\n"
" Tybalt, nephew to Lady Capulet.\n" " Tybalt, nephew to Lady Capulet.\n"
"\n" "\n"
" Friar Laurence, Franciscan.\n" " Friar Laurence, Franciscan.\n"
"\n" "\n"
" Friar John, Franciscan.\n" " Friar John, Franciscan.\n"
"\n" "\n"
" Balthasar, servant to Romeo.\n" " Balthasar, servant to Romeo.\n"
"\n" "\n"
" Abram, servant to Montague.\n" " Abram, servant to Montague.\n"
"\n" "\n"
" Sampson, servant to Capulet.\n" " Sampson, servant to Capulet.\n"
"\n" "\n"
" Gregory, servant to Capulet.\n" " Gregory, servant to Capulet.\n"
"\n" "\n"
" Peter, servant to Juliet's nurse.\n" " Peter, servant to Juliet's nurse.\n"
"\n" "\n"
" An Apothecary.\n" " An Apothecary.\n"
"\n" "\n"
" Three Musicians.\n" " Three Musicians.\n"
"\n" "\n"
" An Officer.\n" " An Officer.\n"
"\n" "\n"
"\n" "\n"
" Lady Montague, wife to Montague.\n" " Lady Montague, wife to Montague.\n"
"\n" "\n"
" Lady Capulet, wife to Capulet.\n" " Lady Capulet, wife to Capulet.\n"
"\n" "\n"
" Juliet, daughter to Capulet.\n" " Juliet, daughter to Capulet.\n"
"\n" "\n"
" Nurse to Juliet.\n" " Nurse to Juliet.\n"
"\n" "\n"
"\n" "\n"
" Citizens of Verona; Gentlemen and Gentlewomen of both houses;\n" " Citizens of Verona; Gentlemen and Gentlewomen of both houses;\n"
" Maskers, Torchbearers, Pages, Guards, Watchmen, Servants, and\n" " Maskers, Torchbearers, Pages, Guards, Watchmen, Servants, and\n"
" Attendants.\n" " Attendants.\n"
"\n" "\n"
" SCENE.--Verona; Mantua.\n" " SCENE.--Verona; Mantua.\n"
"\n" "\n"
"\n" "\n"
"\n" "\n"
" THE PROLOGUE\n" " THE PROLOGUE\n"
"\n" "\n"
" Enter Chorus.\n" " Enter Chorus.\n"
"\n" "\n"
"\n" "\n"
" Chor. Two households, both alike in dignity,\n" " Chor. Two households, both alike in dignity,\n"
" In fair Verona, where we lay our scene,\n" " In fair Verona, where we lay our scene,\n"
" From ancient grudge break to new mutiny,\n" " From ancient grudge break to new mutiny,\n"
" Where civil blood makes civil hands unclean.\n" " Where civil blood makes civil hands unclean.\n"
" From forth the fatal loins of these two foes\n" " From forth the fatal loins of these two foes\n"
" A pair of star-cross'd lovers take their life;\n" " A pair of star-cross'd lovers take their life;\n"
" Whose misadventur'd piteous overthrows\n" " Whose misadventur'd piteous overthrows\n"
" Doth with their death bury their parents' strife.\n" " Doth with their death bury their parents' strife.\n"
" The fearful passage of their death-mark'd love,\n" " The fearful passage of their death-mark'd love,\n"
" And the continuance of their parents' rage,\n" " And the continuance of their parents' rage,\n"
" Which, but their children's end, naught could remove,\n" " Which, but their children's end, naught could remove,\n"
" Is now the two hours' traffic of our stage;\n" " Is now the two hours' traffic of our stage;\n"
" The which if you with patient ears attend,\n" " The which if you with patient ears attend,\n"
" What here shall miss, our toil shall strive to mend.\n" " What here shall miss, our toil shall strive to mend.\n"
" [Exit.]\n" " [Exit.]\n"
"\n" "\n"
"\n" "\n"
"\n" "\n"
"\n" "\n"
"ACT I. Scene I.\n" "ACT I. Scene I.\n"
"Verona. A public place.\n" "Verona. A public place.\n"
"\n" "\n"
"Enter Sampson and Gregory (with swords and bucklers) of the house\n" "Enter Sampson and Gregory (with swords and bucklers) of the house\n"
"of Capulet.\n" "of Capulet.\n"
"\n" "\n"
"\n" "\n"
" Samp. Gregory, on my word, we'll not carry coals.\n" " Samp. Gregory, on my word, we'll not carry coals.\n"
"\n" "\n"
" Greg. No, for then we should be colliers.\n" " Greg. No, for then we should be colliers.\n"
"\n" "\n"
" Samp. I mean, an we be in choler, we'll draw.\n" " Samp. I mean, an we be in choler, we'll draw.\n"
"\n" "\n"
" Greg. Ay, while you live, draw your neck out of collar.\n" " Greg. Ay, while you live, draw your neck out of collar.\n"
"\n" "\n"
" Samp. I strike quickly, being moved.\n" " Samp. I strike quickly, being moved.\n"
"\n" "\n"
" Greg. But thou art not quickly moved to strike.\n" " Greg. But thou art not quickly moved to strike.\n"
"\n" "\n"
" Samp. A dog of the house of Montague moves me.\n" " Samp. A dog of the house of Montague moves me.\n"
"\n" "\n"
" Greg. To move is to stir, and to be valiant is to stand.\n" " Greg. To move is to stir, and to be valiant is to stand.\n"
" Therefore, if thou art moved, thou runn'st away.\n" " Therefore, if thou art moved, thou runn'st away.\n"
"\n" "\n"
" Samp. A dog of that house shall move me to stand. I will take\n" " Samp. A dog of that house shall move me to stand. I will take\n"
" the wall of any man or maid of Montague's.\n" " the wall of any man or maid of Montague's.\n"
"\n" "\n"
" Greg. That shows thee a weak slave; for the weakest goes to the\n" " Greg. That shows thee a weak slave; for the weakest goes to the\n"
" wall.\n" " wall.\n"
"\n" "\n"
" Samp. 'Tis true; and therefore women, being the weaker vessels,\n" " Samp. 'Tis true; and therefore women, being the weaker vessels,\n"
" are ever thrust to the wall. Therefore I will push Montague's men\n" " are ever thrust to the wall. Therefore I will push Montague's men\n"
" from the wall and thrust his maids to the wall.\n" " from the wall and thrust his maids to the wall.\n"
"\n" "\n"
" Greg. The quarrel is between our masters and us their men.\n" " Greg. The quarrel is between our masters and us their men.\n"
"\n" "\n"
" Samp. 'Tis all one. I will show myself a tyrant. When I have\n" " Samp. 'Tis all one. I will show myself a tyrant. When I have\n"
" fought with the men, I will be cruel with the maids- I will cut off\n" " fought with the men, I will be cruel with the maids- I will cut off\n"
" their heads.\n" " their heads.\n"
"\n" "\n"
" Greg. The heads of the maids?\n" " Greg. The heads of the maids?\n"
"\n" "\n"
" Samp. Ay, the heads of the maids, or their maidenheads.\n" " Samp. Ay, the heads of the maids, or their maidenheads.\n"
" Take it in what sense thou wilt.\n" " Take it in what sense thou wilt.\n"
"\n" "\n"
" Greg. They must take it in sense that feel it.\n" " Greg. They must take it in sense that feel it.\n"
"\n" "\n"
" Samp. Me they shall feel while I am able to stand; and 'tis known I\n" " Samp. Me they shall feel while I am able to stand; and 'tis known I\n"
" am a pretty piece of flesh.\n" " am a pretty piece of flesh.\n"
"\n" "\n"
" Greg. 'Tis well thou art not fish; if thou hadst, thou hadst\n" " Greg. 'Tis well thou art not fish; if thou hadst, thou hadst\n"
" been poor-John. Draw thy tool! Here comes two of the house of\n" " been poor-John. Draw thy tool! Here comes two of the house of\n"
" Montagues.\n" " Montagues.\n"
"\n" "\n"
" Enter two other Servingmen [Abram and Balthasar].\n" " Enter two other Servingmen [Abram and Balthasar].\n"
"\n" "\n"
"\n" "\n"
" Samp. My naked weapon is out. Quarrel! I will back thee.\n" " Samp. My naked weapon is out. Quarrel! I will back thee.\n"
"\n" "\n"
" Greg. How? turn thy back and run?\n" " Greg. How? turn thy back and run?\n"
"\n" "\n"
" Samp. Fear me not.\n" " Samp. Fear me not.\n"
"\n" "\n"
" Greg. No, marry. I fear thee!\n" " Greg. No, marry. I fear thee!\n"
"\n" "\n"
" Samp. Let us take the law of our sides; let them begin.\n" " Samp. Let us take the law of our sides; let them begin.\n"
"\n" "\n"
" Greg. I will frown as I pass by, and let them take it as they list.\n" " Greg. I will frown as I pass by, and let them take it as they list.\n"
"\n" "\n"
" Samp. Nay, as they dare. I will bite my thumb at them; which is\n" " Samp. Nay, as they dare. I will bite my thumb at them; which is\n"
" disgrace to them, if they bear it.\n" " disgrace to them, if they bear it.\n"
"\n" "\n"
" Abr. Do you bite your thumb at us, sir?\n" " Abr. Do you bite your thumb at us, sir?\n"
"\n" "\n"
" Samp. I do bite my thumb, sir.\n" " Samp. I do bite my thumb, sir.\n"
"\n" "\n"
" Abr. Do you bite your thumb at us, sir?\n" " Abr. Do you bite your thumb at us, sir?\n"
"\n" "\n"
" Samp. [aside to Gregory] Is the law of our side if I say ay?\n" " Samp. [aside to Gregory] Is the law of our side if I say ay?\n"
"\n" "\n"
" Greg. [aside to Sampson] No.\n" " Greg. [aside to Sampson] No.\n"
"\n" "\n"
" Samp. No, sir, I do not bite my thumb at you, sir; but I bite my\n" " Samp. No, sir, I do not bite my thumb at you, sir; but I bite my\n"
" thumb, sir.\n" " thumb, sir.\n"
"\n" "\n"
" Greg. Do you quarrel, sir?\n" " Greg. Do you quarrel, sir?\n"
"\n" "\n"
" Abr. Quarrel, sir? No, sir.\n" " Abr. Quarrel, sir? No, sir.\n"
"\n" "\n"
" Samp. But if you do, sir, am for you. I serve as good a man as\n" " Samp. But if you do, sir, am for you. I serve as good a man as\n"
" you.\n" " you.\n"
"\n" "\n"
" Abr. No better.\n" " Abr. No better.\n"
"\n" "\n"
" Samp. Well, sir.\n" " Samp. Well, sir.\n"
"\n" "\n"
" Enter Benvolio.\n" " Enter Benvolio.\n"
"\n" "\n"
"\n" "\n"
" Greg. [aside to Sampson] Say 'better.' Here comes one of my\n" " Greg. [aside to Sampson] Say 'better.' Here comes one of my\n"
" master's kinsmen.\n" " master's kinsmen.\n"
"\n" "\n"
" Samp. Yes, better, sir.\n" " Samp. Yes, better, sir.\n"
"\n" "\n"
" Abr. You lie.\n" " Abr. You lie.\n"
"\n" "\n"
" Samp. Draw, if you be men. Gregory, remember thy swashing blow.\n" " Samp. Draw, if you be men. Gregory, remember thy swashing blow.\n"
" They fight.\n" " They fight.\n"
"\n" "\n"
" Ben. Part, fools! [Beats down their swords.]\n" " Ben. Part, fools! [Beats down their swords.]\n"
" Put up your swords. You know not what you do.\n" " Put up your swords. You know not what you do.\n"
"\n" "\n"
" Enter Tybalt.\n" " Enter Tybalt.\n"
"\n" "\n"
"\n" "\n"
" Tyb. What, art thou drawn among these heartless hinds?\n" " Tyb. What, art thou drawn among these heartless hinds?\n"
" Turn thee Benvolio! look upon thy death.\n" " Turn thee Benvolio! look upon thy death.\n"
"\n" "\n"
" Ben. I do but keep the peace. Put up thy sword,\n" " Ben. I do but keep the peace. Put up thy sword,\n"
" Or manage it to part these men with me.\n" " Or manage it to part these men with me.\n"
"\n" "\n"
" Tyb. What, drawn, and talk of peace? I hate the word\n" " Tyb. What, drawn, and talk of peace? I hate the word\n"
" As I hate hell, all Montagues, and thee.\n" " As I hate hell, all Montagues, and thee.\n"
" Have at thee, coward! They fight.\n" " Have at thee, coward! They fight.\n"
"\n" "\n"
" Enter an officer, and three or four Citizens with clubs or\n" " Enter an officer, and three or four Citizens with clubs or\n"
" partisans.\n" " partisans.\n"
"\n" "\n"
"\n" "\n"
" Officer. Clubs, bills, and partisans! Strike! beat them down!\n" " Officer. Clubs, bills, and partisans! Strike! beat them down!\n"
"\n" "\n"
" Citizens. Down with the Capulets! Down with the Montagues!\n" " Citizens. Down with the Capulets! Down with the Montagues!\n"
"\n" "\n"
" Enter Old Capulet in his gown, and his Wife.\n" " Enter Old Capulet in his gown, and his Wife.\n"
"\n" "\n"
"\n" "\n"
" Cap. What noise is this? Give me my long sword, ho!\n" " Cap. What noise is this? Give me my long sword, ho!\n"
"\n" "\n"
" Wife. A crutch, a crutch! Why call you for a sword?\n" " Wife. A crutch, a crutch! Why call you for a sword?\n"
"\n" "\n"
" Cap. My sword, I say! Old Montague is come\n" " Cap. My sword, I say! Old Montague is come\n"
" And flourishes his blade in spite of me.\n" " And flourishes his blade in spite of me.\n"
"\n" "\n"
" Enter Old Montague and his Wife.\n" " Enter Old Montague and his Wife.\n"
"\n" "\n"
"\n" "\n"
" Mon. Thou villain Capulet!- Hold me not, let me go.\n" " Mon. Thou villain Capulet!- Hold me not, let me go.\n"
"\n" "\n"
" M. Wife. Thou shalt not stir one foot to seek a foe.\n" " M. Wife. Thou shalt not stir one foot to seek a foe.\n"
"\n" "\n"
" Enter Prince Escalus, with his Train.\n" " Enter Prince Escalus, with his Train.\n"
"\n" "\n"
"\n" "\n"
"END OF FILE\n"; "END OF FILE\n";

@ -1,6 +1,6 @@
CFILES=../utils.c ../../TinyFrame.c CFILES=../utils.c ../../TinyFrame.c
INCLDIRS=-I. -I.. -I../.. INCLDIRS=-I. -I.. -I../..
CFLAGS=-O0 -ggdb --std=gnu99 -Wno-main -Wall -Wextra $(CFILES) $(INCLDIRS) CFLAGS=-O0 -ggdb --std=gnu99 -Wno-main -Wno-unused -Wall -Wextra $(CFILES) $(INCLDIRS)
run: test.bin run: test.bin
./test.bin ./test.bin

@ -3,63 +3,64 @@
#include "../../TinyFrame.h" #include "../../TinyFrame.h"
#include "../utils.h" #include "../utils.h"
TinyFrame *demo_tf;
/** /**
* This function should be defined in the application code. * This function should be defined in the application code.
* It implements the lowest layer - sending bytes to UART (or other) * It implements the lowest layer - sending bytes to UART (or other)
*/ */
void TF_WriteImpl(const uint8_t *buff, size_t len) void TF_WriteImpl(TinyFrame *tf, const uint8_t *buff, size_t len)
{ {
printf("--------------------\n"); printf("--------------------\n");
printf("\033[32mTF_WriteImpl - sending frame:\033[0m\n"); printf("\033[32mTF_WriteImpl - sending frame:\033[0m\n");
dumpFrame(buff, len); dumpFrame(buff, len);
// Send it back as if we received it // Send it back as if we received it
TF_Accept(buff, len); TF_Accept(tf, buff, len);
} }
/** An example listener function */ /** An example listener function */
TF_Result myListener(TF_Msg *msg) TF_Result myListener(TinyFrame *tf, TF_Msg *msg)
{ {
dumpFrameInfo(msg); dumpFrameInfo(msg);
return TF_STAY; return TF_STAY;
} }
TF_Result testIdListener(TF_Msg *msg) TF_Result testIdListener(TinyFrame *tf, TF_Msg *msg)
{ {
printf("OK - ID Listener triggered for msg!\n"); printf("OK - ID Listener triggered for msg!\n");
dumpFrameInfo(msg); dumpFrameInfo(msg);
return TF_CLOSE; return TF_CLOSE;
} }
void main(void) void main(void)
{ {
TF_Msg msg; TF_Msg msg;
const char *longstr = "Lorem ipsum dolor sit amet."; const char *longstr = "Lorem ipsum dolor sit amet.";
// Set up the TinyFrame library // Set up the TinyFrame library
TF_Init(TF_MASTER); // 1 = master, 0 = slave demo_tf = TF_Init(TF_MASTER); // 1 = master, 0 = slave
TF_AddGenericListener(myListener); TF_AddGenericListener(demo_tf, myListener);
printf("------ Simulate sending a message --------\n"); printf("------ Simulate sending a message --------\n");
TF_ClearMsg(&msg); TF_ClearMsg(&msg);
msg.type = 0x22; msg.type = 0x22;
msg.data = (pu8)"Hello TinyFrame"; msg.data = (pu8) "Hello TinyFrame";
msg.len = 16; msg.len = 16;
TF_Send(&msg); TF_Send(demo_tf, &msg);
msg.type = 0x33; msg.type = 0x33;
msg.data = (pu8)longstr; msg.data = (pu8) longstr;
msg.len = (TF_LEN) (strlen(longstr)+1); // add the null byte msg.len = (TF_LEN) (strlen(longstr) + 1); // add the null byte
TF_Send(&msg); TF_Send(demo_tf, &msg);
msg.type = 0x44; msg.type = 0x44;
msg.data = (pu8)"Hello2"; msg.data = (pu8) "Hello2";
msg.len = 7; msg.len = 7;
TF_Send(&msg); TF_Send(demo_tf, &msg);
msg.len = 0; msg.len = 0;
msg.type = 0x77; msg.type = 0x77;
TF_Query(&msg, testIdListener, 0); TF_Query(demo_tf, &msg, testIdListener, 0);
} }

@ -1,6 +1,6 @@
CFILES=../demo.c ../utils.c ../../TinyFrame.c CFILES=../demo.c ../utils.c ../../TinyFrame.c
INCLDIRS=-I. -I.. -I../.. INCLDIRS=-I. -I.. -I../..
CFLAGS=-O0 -ggdb --std=gnu99 -Wno-main -Wall -Wextra $(CFILES) $(INCLDIRS) CFLAGS=-O0 -ggdb --std=gnu99 -Wno-main -Wall -Wno-unused -Wextra $(CFILES) $(INCLDIRS)
build: master.bin slave.bin build: master.bin slave.bin

@ -5,31 +5,31 @@
#include <stdio.h> #include <stdio.h>
#include "../demo.h" #include "../demo.h"
TF_Result testIdListener(TF_Msg *msg) TF_Result testIdListener(TinyFrame *tf, TF_Msg *msg)
{ {
printf("testIdListener()\n"); printf("testIdListener()\n");
dumpFrameInfo(msg); dumpFrameInfo(msg);
return TF_CLOSE; return TF_CLOSE;
} }
TF_Result testGenericListener(TF_Msg *msg) TF_Result testGenericListener(TinyFrame *tf, TF_Msg *msg)
{ {
printf("testGenericListener()\n"); printf("testGenericListener()\n");
dumpFrameInfo(msg); dumpFrameInfo(msg);
return TF_STAY; return TF_STAY;
} }
int main(void) int main(void)
{ {
TF_Init(TF_MASTER); demo_tf = TF_Init(TF_MASTER);
TF_AddGenericListener(testGenericListener); TF_AddGenericListener(demo_tf, testGenericListener);
demo_init(TF_MASTER); demo_init(TF_MASTER);
TF_SendSimple(1, (pu8)"Ahoj", 5); TF_SendSimple(demo_tf, 1, (pu8) "Ahoj", 5);
TF_SendSimple(1, (pu8)"Hello", 6); TF_SendSimple(demo_tf, 1, (pu8) "Hello", 6);
TF_QuerySimple(2, (pu8)"Query!", 6, testIdListener, 0, NULL); TF_QuerySimple(demo_tf, 2, (pu8) "Query!", 6, testIdListener, 0);
demo_sleep(); demo_sleep();
} }

@ -4,39 +4,38 @@
#include <stdio.h> #include <stdio.h>
#include "../demo.h" #include "../demo.h"
#include <memory.h>
TF_Result helloListener(TF_Msg *msg) TF_Result helloListener(TinyFrame *tf, TF_Msg *msg)
{ {
printf("helloListener()\n"); printf("helloListener()\n");
dumpFrameInfo(msg); dumpFrameInfo(msg);
return TF_STAY; return TF_STAY;
} }
TF_Result replyListener(TF_Msg *msg) TF_Result replyListener(TinyFrame *tf, TF_Msg *msg)
{ {
printf("replyListener()\n"); printf("replyListener()\n");
dumpFrameInfo(msg); dumpFrameInfo(msg);
msg->data = (const uint8_t *) "response to query"; msg->data = (const uint8_t *) "response to query";
msg->len = (TF_LEN) strlen((const char *) msg->data); msg->len = (TF_LEN) strlen((const char *) msg->data);
TF_Respond(msg); TF_Respond(tf, msg);
// unsolicited reply - will not be handled by the ID listener, which is already gone // unsolicited reply - will not be handled by the ID listener, which is already gone
msg->data = (const uint8_t *) "SPAM"; msg->data = (const uint8_t *) "SPAM";
msg->len = 5; msg->len = 5;
TF_Respond(msg); TF_Respond(tf, msg);
// unrelated message // unrelated message
TF_SendSimple(77, (const uint8_t *) "NAZDAR", 7); TF_SendSimple(tf, 77, (const uint8_t *) "NAZDAR", 7);
return TF_STAY; return TF_STAY;
} }
int main(void) int main(void)
{ {
TF_Init(TF_SLAVE); demo_tf = TF_Init(TF_SLAVE);
TF_AddTypeListener(1, helloListener); TF_AddTypeListener(demo_tf, 1, helloListener);
TF_AddTypeListener(2, replyListener); TF_AddTypeListener(demo_tf, 2, replyListener);
demo_init(TF_SLAVE); demo_init(TF_SLAVE);
demo_sleep(); demo_sleep();
} }

@ -8,25 +8,26 @@
// helper func for testing // helper func for testing
void dumpFrame(const uint8_t *buff, size_t len) void dumpFrame(const uint8_t *buff, size_t len)
{ {
size_t i; size_t i;
for(i = 0; i < len; i++) { for (i = 0; i < len; i++) {
printf("%3u \033[94m%02X\033[0m", buff[i], buff[i]); printf("%3u \033[94m%02X\033[0m", buff[i], buff[i]);
if (buff[i] >= 0x20 && buff[i] < 127) { if (buff[i] >= 0x20 && buff[i] < 127) {
printf(" %c", buff[i]); printf(" %c", buff[i]);
} else { }
printf(" \033[31m.\033[0m"); else {
} printf(" \033[31m.\033[0m");
printf("\n"); }
} printf("\n");
printf("--- end of frame ---\n\n"); }
printf("--- end of frame ---\n\n");
} }
void dumpFrameInfo(TF_Msg *msg) void dumpFrameInfo(TF_Msg *msg)
{ {
printf("\033[33mFrame info\n" printf("\033[33mFrame info\n"
" type: %02Xh\n" " type: %02Xh\n"
" data: \"%.*s\"\n" " data: \"%.*s\"\n"
" len: %u\n" " len: %u\n"
" id: %Xh\033[0m\n\n", " id: %Xh\033[0m\n\n",
msg->type, msg->len, msg->data, msg->len, msg->frame_id); msg->type, msg->len, msg->data, msg->len, msg->frame_id);
} }

Loading…
Cancel
Save