10 Commits
3 changed files with 81 additions and 38 deletions
+4
View File
@@ -23,6 +23,10 @@ TinyFrame is re-entrant and supports creating multiple instances with the limita
that their structure (field sizes and checksum type) must be the same. There is a support 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). for adding multi-threaded access to a shared instance using a mutex (via a callback stub).
## Ports
A partial port to Python can be found at [MightyPork/PonyFrame](https://github.com/MightyPork/PonyFrame)
## 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).
+47 -15
View File
@@ -169,6 +169,13 @@ TinyFrame * _TF_FN TF_Init(TF_Peer peer_bit)
return tf; return tf;
} }
/** Release the struct */
void TF_DeInit(TinyFrame *tf)
{
if (tf == NULL) return;
free(tf);
}
//region Listeners //region Listeners
/** Reset ID listener's timeout to the original value */ /** Reset ID listener's timeout to the original value */
@@ -365,6 +372,12 @@ static void _TF_FN TF_HandleReceivedMessage(TinyFrame *tf)
if (res == TF_RENEW) { if (res == TF_RENEW) {
renew_id_listener(ilst); renew_id_listener(ilst);
} }
else if (res == TF_CLOSE) {
// Set userdata to NULL to avoid calling user for cleanup
ilst->userdata = NULL;
ilst->userdata2 = NULL;
cleanup_id_listener(tf, i, ilst);
}
return; return;
} }
} }
@@ -382,8 +395,12 @@ static void _TF_FN TF_HandleReceivedMessage(TinyFrame *tf)
res = tlst->fn(tf, &msg); res = tlst->fn(tf, &msg);
if (res != TF_NEXT) { if (res != TF_NEXT) {
// if it's TF_CLOSE, we assume user already cleaned up userdata // type listeners don't have userdata.
// TF_RENEW doesn't make sense here because type listeners don't expire // TF_RENEW doesn't make sense here because type listeners don't expire = same as TF_STAY
if (res == TF_CLOSE) {
cleanup_type_listener(tf, i, tlst);
}
return; return;
} }
} }
@@ -397,8 +414,16 @@ static void _TF_FN TF_HandleReceivedMessage(TinyFrame *tf)
res = glst->fn(tf, &msg); res = glst->fn(tf, &msg);
if (res != TF_NEXT) { if (res != TF_NEXT) {
// if it's TF_CLOSE, we assume user already cleaned up userdata // generic listeners don't have userdata.
// TF_RENEW doesn't make sense here because generic listeners don't expire // TF_RENEW doesn't make sense here because generic listeners don't expire = same as TF_STAY
// note: It's not expected that user will have multiple generic listeners, or
// ever actually remove them. They're most useful as default callbacks if no other listener
// handled the message.
if (res == TF_CLOSE) {
cleanup_generic_listener(tf, i, glst);
}
return; return;
} }
} }
@@ -456,10 +481,11 @@ void _TF_FN TF_AcceptChar(TinyFrame *tf, unsigned char c)
#if !TF_USE_SOF_BYTE #if !TF_USE_SOF_BYTE
if (tf->state == TFState_SOF) { if (tf->state == TFState_SOF) {
TF_ParsBeginFrame(); pars_begin_frame();
} }
#endif #endif
//@formatter:off
switch (tf->state) { switch (tf->state) {
case TFState_SOF: case TFState_SOF:
if (c == TF_SOF_BYTE) { if (c == TF_SOF_BYTE) {
@@ -488,15 +514,15 @@ void _TF_FN TF_AcceptChar(TinyFrame *tf, unsigned char c)
case TFState_TYPE: case TFState_TYPE:
CKSUM_ADD(tf->cksum, c); CKSUM_ADD(tf->cksum, c);
COLLECT_NUMBER(tf->type, TF_TYPE) { COLLECT_NUMBER(tf->type, TF_TYPE) {
#if TF_CKSUM_TYPE == TF_CKSUM_NONE #if TF_CKSUM_TYPE == TF_CKSUM_NONE
tf->state = TFState_DATA; tf->state = TFState_DATA;
tf->rxi = 0; tf->rxi = 0;
#else #else
// enter HEAD_CKSUM state // enter HEAD_CKSUM state
tf->state = TFState_HEAD_CKSUM; tf->state = TFState_HEAD_CKSUM;
tf->rxi = 0; tf->rxi = 0;
tf->ref_cksum = 0; tf->ref_cksum = 0;
#endif #endif
} }
break; break;
@@ -511,6 +537,7 @@ void _TF_FN TF_AcceptChar(TinyFrame *tf, unsigned char c)
} }
if (tf->len == 0) { if (tf->len == 0) {
// if the message has no body, we're done.
TF_HandleReceivedMessage(tf); TF_HandleReceivedMessage(tf);
TF_ResetParser(tf); TF_ResetParser(tf);
break; break;
@@ -522,7 +549,7 @@ void _TF_FN TF_AcceptChar(TinyFrame *tf, unsigned char c)
CKSUM_RESET(tf->cksum); // Start collecting the payload CKSUM_RESET(tf->cksum); // Start collecting the payload
if (tf->len >= TF_MAX_PAYLOAD_RX) { if (tf->len > TF_MAX_PAYLOAD_RX) {
// ERROR - frame too long. Consume, but do not store. // ERROR - frame too long. Consume, but do not store.
tf->discard_data = true; tf->discard_data = true;
} }
@@ -538,16 +565,16 @@ void _TF_FN TF_AcceptChar(TinyFrame *tf, unsigned char c)
} }
if (tf->rxi == tf->len) { if (tf->rxi == tf->len) {
#if TF_CKSUM_TYPE == TF_CKSUM_NONE #if TF_CKSUM_TYPE == TF_CKSUM_NONE
// All done // All done
TF_HandleReceivedMessage(); TF_HandleReceivedMessage();
TF_ResetParser(); TF_ResetParser();
#else #else
// Enter DATA_CKSUM state // Enter DATA_CKSUM state
tf->state = TFState_DATA_CKSUM; tf->state = TFState_DATA_CKSUM;
tf->rxi = 0; tf->rxi = 0;
tf->ref_cksum = 0; tf->ref_cksum = 0;
#endif #endif
} }
break; break;
@@ -563,8 +590,10 @@ void _TF_FN TF_AcceptChar(TinyFrame *tf, unsigned char c)
} }
break; break;
} }
//@formatter:on
// we get here after finishing HEAD, if no data are to be received - handle and clear // we get here after finishing HEAD, if no data are to be received - handle and clear
// TODO verify - this seems unreachable under normal circumstances
if (tf->len == 0 && tf->state == TFState_DATA) { if (tf->len == 0 && tf->state == TFState_DATA) {
TF_HandleReceivedMessage(tf); TF_HandleReceivedMessage(tf);
TF_ResetParser(tf); TF_ResetParser(tf);
@@ -696,7 +725,7 @@ static size_t _TF_FN TF_ComposeBody(uint8_t *outbuff,
* @param cksum - checksum variable used for the body * @param cksum - checksum variable used for the body
* @return nr of bytes in outbuff used * @return nr of bytes in outbuff used
*/ */
static size_t _TF_FN TF_ComposeTail(uint8_t *outbuff, const TF_CKSUM *cksum) static size_t _TF_FN TF_ComposeTail(uint8_t *outbuff, TF_CKSUM *cksum)
{ {
int8_t si = 0; // signed small int int8_t si = 0; // signed small int
uint8_t b = 0; uint8_t b = 0;
@@ -746,6 +775,8 @@ static bool _TF_FN TF_SendFrame(TinyFrame *tf, TF_Msg *msg, TF_Listener listener
} }
} }
// Checksum only if message had a body
if (msg->len > 0) {
// Flush if checksum wouldn't fit in the buffer // Flush if checksum wouldn't fit in the buffer
if (TF_SENDBUF_LEN - len < sizeof(TF_CKSUM)) { if (TF_SENDBUF_LEN - len < sizeof(TF_CKSUM)) {
TF_WriteImpl(tf, (const uint8_t *) tf->sendbuf, len); TF_WriteImpl(tf, (const uint8_t *) tf->sendbuf, len);
@@ -753,9 +784,10 @@ static bool _TF_FN TF_SendFrame(TinyFrame *tf, TF_Msg *msg, TF_Listener listener
} }
// Add checksum, flush what remains to be sent // Add checksum, flush what remains to be sent
len += TF_ComposeTail(tf->sendbuf+len, &cksum); len += TF_ComposeTail(tf->sendbuf + len, &cksum);
TF_WriteImpl(tf, (const uint8_t *) tf->sendbuf, len); }
TF_WriteImpl(tf, (const uint8_t *) tf->sendbuf, len);
TF_ReleaseTx(tf); TF_ReleaseTx(tf);
return true; return true;
+8 -1
View File
@@ -10,7 +10,7 @@
* Upstream URL: https://github.com/MightyPork/TinyFrame * Upstream URL: https://github.com/MightyPork/TinyFrame
*/ */
#define TF_VERSION "2.0.0" #define TF_VERSION "2.0.5"
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
#include <stdint.h> // for uint8_t etc #include <stdint.h> // for uint8_t etc
@@ -235,6 +235,13 @@ TinyFrame *TF_Init(TF_Peer peer_bit);
*/ */
void TF_InitStatic(TinyFrame *tf, TF_Peer peer_bit); void TF_InitStatic(TinyFrame *tf, TF_Peer peer_bit);
/**
* De-init the dynamically allocated TF instance
*
* @param tf
*/
void TF_DeInit(TinyFrame *tf);
/** /**
* Reset the frame parser state machine. * Reset the frame parser state machine.
* This does not affect registered listeners. * This does not affect registered listeners.