diff --git a/bacnet-stack/include/ringbuf.h b/bacnet-stack/include/ringbuf.h index 6e6a0a46..6091a28b 100644 --- a/bacnet-stack/include/ringbuf.h +++ b/bacnet-stack/include/ringbuf.h @@ -49,13 +49,17 @@ extern "C" { RING_BUFFER const *b); bool Ringbuf_Empty( RING_BUFFER const *b); - volatile uint8_t *Ringbuf_Get_Front( + volatile uint8_t *Ringbuf_Peek( RING_BUFFER const *b); - volatile uint8_t *Ringbuf_Pop_Front( - RING_BUFFER * b); + bool Ringbuf_Pop( + RING_BUFFER * b, + uint8_t *data_element); bool Ringbuf_Put( RING_BUFFER * b, /* ring buffer structure */ - volatile uint8_t * data_element); /* one element to add to the ring */ + uint8_t *data_element); /* one element to add to the ring */ + bool Ringbuf_Put_Front( + RING_BUFFER * b, /* ring buffer structure */ + uint8_t *data_element); volatile uint8_t *Ringbuf_Alloc( RING_BUFFER * b); /* Note: element_count must be a power of two */ @@ -65,6 +69,14 @@ extern "C" { unsigned element_size, /* size of one element in the data block */ unsigned element_count); /* number of elements in the data block */ +#ifdef TEST +#include "ctest.h" +void testRingBufSize16( + Test * pTest); +void testRingBufSize32( + Test * pTest); +#endif + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/bacnet-stack/ports/at91sam7s/dlmstp.c b/bacnet-stack/ports/at91sam7s/dlmstp.c index e5cfb9a6..e7a96cea 100644 --- a/bacnet-stack/ports/at91sam7s/dlmstp.c +++ b/bacnet-stack/ports/at91sam7s/dlmstp.c @@ -763,7 +763,7 @@ static bool MSTP_Master_Node_FSM( transition_now = true; } else { uint8_t frame_type; - pkt = (struct mstp_pdu_packet *) Ringbuf_Pop_Front(&PDU_Queue); + pkt = (struct mstp_pdu_packet *) Ringbuf_Peek(&PDU_Queue); if (pkt->data_expecting_reply) { frame_type = FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY; } else { @@ -790,6 +790,7 @@ static bool MSTP_Master_Node_FSM( Master_State = MSTP_MASTER_STATE_DONE_WITH_TOKEN; break; } + (void) Ringbuf_Pop(&PDU_Queue, NULL); } break; case MSTP_MASTER_STATE_WAIT_FOR_REPLY: @@ -1091,7 +1092,7 @@ static bool MSTP_Master_Node_FSM( /* BACnet Data Expecting Reply, a Test_Request, or */ /* a proprietary frame that expects a reply is received. */ case MSTP_MASTER_STATE_ANSWER_DATA_REQUEST: - pkt = (struct mstp_pdu_packet *) Ringbuf_Get_Front(&PDU_Queue); + pkt = (struct mstp_pdu_packet *) Ringbuf_Peek(&PDU_Queue); if (pkt != NULL) { matched = dlmstp_compare_data_expecting_reply(&InputBuffer[0], @@ -1109,7 +1110,6 @@ static bool MSTP_Master_Node_FSM( /* then call MSTP_Send_Frame to transmit the reply frame */ /* and enter the IDLE state to wait for the next frame. */ uint8_t frame_type; - pkt = (struct mstp_pdu_packet *) Ringbuf_Pop_Front(&PDU_Queue); if (pkt->data_expecting_reply) { frame_type = FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY; } else { @@ -1117,6 +1117,7 @@ static bool MSTP_Master_Node_FSM( } MSTP_Send_Frame(frame_type, pkt->destination_mac, This_Station, (uint8_t *) & pkt->buffer[0], pkt->length); + (void) Ringbuf_Pop(&PDU_Queue, NULL); Master_State = MSTP_MASTER_STATE_IDLE; /* clear our flag we were holding for comparison */ MSTP_Flag.ReceivedValidFrame = false; @@ -1180,7 +1181,7 @@ static void MSTP_Slave_Node_FSM( } } else if (MSTP_Flag.ReceivePacketPending) { if (!Ringbuf_Empty(&PDU_Queue)) { - pkt = (struct mstp_pdu_packet *) Ringbuf_Pop_Front(&PDU_Queue); + pkt = (struct mstp_pdu_packet *) Ringbuf_Peek(&PDU_Queue); matched = dlmstp_compare_data_expecting_reply(&InputBuffer[0], DataLength, SourceAddress, &pkt->buffer[0], pkt->length, @@ -1194,7 +1195,6 @@ static void MSTP_Slave_Node_FSM( /* then call MSTP_Send_Frame to transmit the reply frame */ /* and enter the IDLE state to wait for the next frame. */ uint8_t frame_type; - pkt = (struct mstp_pdu_packet *) Ringbuf_Pop_Front(&PDU_Queue); if (pkt->data_expecting_reply) { frame_type = FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY; } else { @@ -1202,6 +1202,7 @@ static void MSTP_Slave_Node_FSM( } MSTP_Send_Frame(frame_type, pkt->destination_mac, This_Station, (uint8_t *) & pkt->buffer[0], pkt->length); + (void) Ringbuf_Pop(&PDU_Queue, NULL); } /* clear our flag we were holding for comparison */ MSTP_Flag.ReceivePacketPending = false; diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/dlmstp.c b/bacnet-stack/ports/bdk-atxx4-mstp/dlmstp.c index 5c8094f3..67d4f2d1 100644 --- a/bacnet-stack/ports/bdk-atxx4-mstp/dlmstp.c +++ b/bacnet-stack/ports/bdk-atxx4-mstp/dlmstp.c @@ -785,7 +785,7 @@ static bool MSTP_Master_Node_FSM( transition_now = true; } else { uint8_t frame_type; - pkt = (struct mstp_pdu_packet *) Ringbuf_Pop_Front(&PDU_Queue); + pkt = (struct mstp_pdu_packet *) Ringbuf_Peek(&PDU_Queue); if (pkt->data_expecting_reply) { frame_type = FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY; } else { @@ -812,6 +812,7 @@ static bool MSTP_Master_Node_FSM( Master_State = MSTP_MASTER_STATE_DONE_WITH_TOKEN; break; } + (void) Ringbuf_Pop(&PDU_Queue, NULL); } break; case MSTP_MASTER_STATE_WAIT_FOR_REPLY: @@ -1123,7 +1124,7 @@ static bool MSTP_Master_Node_FSM( /* clear our flag we were holding for comparison */ MSTP_Flag.ReceivedValidFrame = false; } else { - pkt = (struct mstp_pdu_packet *) Ringbuf_Get_Front(&PDU_Queue); + pkt = (struct mstp_pdu_packet *) Ringbuf_Peek(&PDU_Queue); if (pkt != NULL) { matched = dlmstp_compare_data_expecting_reply(&InputBuffer[0], @@ -1141,7 +1142,6 @@ static bool MSTP_Master_Node_FSM( /* then call MSTP_Send_Frame to transmit the reply frame */ /* and enter the IDLE state to wait for the next frame. */ uint8_t frame_type; - pkt = (struct mstp_pdu_packet *) Ringbuf_Pop_Front(&PDU_Queue); if (pkt->data_expecting_reply) { frame_type = FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY; } else { @@ -1152,6 +1152,8 @@ static bool MSTP_Master_Node_FSM( Master_State = MSTP_MASTER_STATE_IDLE; /* clear our flag we were holding for comparison */ MSTP_Flag.ReceivedValidFrame = false; + /* clear the queue */ + (void) Ringbuf_Pop(&PDU_Queue, NULL); } else if (pkt != NULL) { /* DeferredReply */ /* If no reply will be available from the higher layers */ diff --git a/bacnet-stack/ports/linux/dlmstp.c b/bacnet-stack/ports/linux/dlmstp.c index 5e37d08f..beb9ec24 100644 --- a/bacnet-stack/ports/linux/dlmstp.c +++ b/bacnet-stack/ports/linux/dlmstp.c @@ -316,7 +316,7 @@ uint16_t MSTP_Get_Send( if (Ringbuf_Empty(&PDU_Queue)) { return 0; } - pkt = (struct mstp_pdu_packet *) Ringbuf_Pop_Front(&PDU_Queue); + pkt = (struct mstp_pdu_packet *) Ringbuf_Peek(&PDU_Queue); if (pkt->data_expecting_reply) { frame_type = FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY; } else { @@ -326,6 +326,7 @@ uint16_t MSTP_Get_Send( pdu_len = MSTP_Create_Frame(&mstp_port->OutputBuffer[0], /* <-- loading this */ mstp_port->OutputBufferSize, frame_type, pkt->destination_mac, mstp_port->This_Station, (uint8_t *) & pkt->buffer[0], pkt->length); + (void) Ringbuf_Pop(&PDU_Queue, NULL); return pdu_len; } @@ -498,7 +499,7 @@ uint16_t MSTP_Get_Reply( if (Ringbuf_Empty(&PDU_Queue)) { return 0; } - pkt = (struct mstp_pdu_packet *) Ringbuf_Get_Front(&PDU_Queue); + pkt = (struct mstp_pdu_packet *) Ringbuf_Peek(&PDU_Queue); /* is this the reply to the DER? */ matched = dlmstp_compare_data_expecting_reply(&mstp_port->InputBuffer[0], @@ -507,7 +508,6 @@ uint16_t MSTP_Get_Reply( if (!matched) { return 0; } - pkt = (struct mstp_pdu_packet *) Ringbuf_Pop_Front(&PDU_Queue); if (pkt->data_expecting_reply) { frame_type = FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY; } else { @@ -517,6 +517,7 @@ uint16_t MSTP_Get_Reply( pdu_len = MSTP_Create_Frame(&mstp_port->OutputBuffer[0], /* <-- loading this */ mstp_port->OutputBufferSize, frame_type, pkt->destination_mac, mstp_port->This_Station, (uint8_t *) & pkt->buffer[0], pkt->length); + (void) Ringbuf_Pop(&PDU_Queue, NULL); return pdu_len; } diff --git a/bacnet-stack/ports/linux/dlmstp_linux.c b/bacnet-stack/ports/linux/dlmstp_linux.c index a79e26a0..58a699ac 100644 --- a/bacnet-stack/ports/linux/dlmstp_linux.c +++ b/bacnet-stack/ports/linux/dlmstp_linux.c @@ -387,7 +387,7 @@ uint16_t MSTP_Get_Send( if (Ringbuf_Empty(&poSharedData->PDU_Queue)) { return 0; } - pkt = (struct mstp_pdu_packet *) Ringbuf_Pop_Front(&poSharedData->PDU_Queue); + pkt = (struct mstp_pdu_packet *) Ringbuf_Peek(&poSharedData->PDU_Queue); if (pkt->data_expecting_reply) { frame_type = FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY; } else { @@ -397,6 +397,7 @@ uint16_t MSTP_Get_Send( pdu_len = MSTP_Create_Frame(&mstp_port->OutputBuffer[0], /* <-- loading this */ mstp_port->OutputBufferSize, frame_type, pkt->destination_mac, mstp_port->This_Station, (uint8_t *) & pkt->buffer[0], pkt->length); + (void) Ringbuf_Pop(&poSharedData->PDU_Queue, NULL); return pdu_len; } @@ -574,7 +575,7 @@ uint16_t MSTP_Get_Reply( if (Ringbuf_Empty(&poSharedData->PDU_Queue)) { return 0; } - pkt = (struct mstp_pdu_packet *) Ringbuf_Get_Front(&poSharedData->PDU_Queue); + pkt = (struct mstp_pdu_packet *) Ringbuf_Peek(&poSharedData->PDU_Queue); /* is this the reply to the DER? */ matched = dlmstp_compare_data_expecting_reply(&mstp_port->InputBuffer[0], @@ -583,7 +584,6 @@ uint16_t MSTP_Get_Reply( if (!matched) { return 0; } - pkt = (struct mstp_pdu_packet *) Ringbuf_Pop_Front(&poSharedData->PDU_Queue); if (pkt->data_expecting_reply) { frame_type = FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY; } else { @@ -593,6 +593,7 @@ uint16_t MSTP_Get_Reply( pdu_len = MSTP_Create_Frame(&mstp_port->OutputBuffer[0], /* <-- loading this */ mstp_port->OutputBufferSize, frame_type, pkt->destination_mac, mstp_port->This_Station, (uint8_t *) & pkt->buffer[0], pkt->length); + (void) Ringbuf_Pop(&poSharedData->PDU_Queue, NULL); return pdu_len; } diff --git a/bacnet-stack/ports/stm32f10x/dlmstp.c b/bacnet-stack/ports/stm32f10x/dlmstp.c index 86416f11..5cfe54ad 100644 --- a/bacnet-stack/ports/stm32f10x/dlmstp.c +++ b/bacnet-stack/ports/stm32f10x/dlmstp.c @@ -379,7 +379,7 @@ static bool MSTP_Transmit_FSM( if (!Ringbuf_Empty(&Transmit_Queue)) { /* get the packet - but don't remove it from queue */ pkt = (struct mstp_tx_packet *) - Ringbuf_Get_Front(&Transmit_Queue); + Ringbuf_Peek(&Transmit_Queue); state = MSTP_TX_STATE_SILENCE_WAIT; } break; @@ -410,7 +410,7 @@ static bool MSTP_Transmit_FSM( if (rs485_byte_sent() && rs485_frame_sent()) { rs485_rts_enable(false); /* remove the packet from the queue */ - (void) Ringbuf_Pop_Front(&Transmit_Queue); + (void) Ringbuf_Pop(&Transmit_Queue, NULL); state = MSTP_TX_STATE_IDLE; } break; @@ -873,7 +873,7 @@ static bool MSTP_Master_Node_FSM( transition_now = true; } else { uint8_t frame_type; - pkt = (struct mstp_pdu_packet *) Ringbuf_Pop_Front(&PDU_Queue); + pkt = (struct mstp_pdu_packet *) Ringbuf_Peek(&PDU_Queue); if (pkt->data_expecting_reply) { frame_type = FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY; } else { @@ -900,6 +900,7 @@ static bool MSTP_Master_Node_FSM( Master_State = MSTP_MASTER_STATE_DONE_WITH_TOKEN; break; } + (void) Ringbuf_Pop(&PDU_Queue, NULL); } break; case MSTP_MASTER_STATE_WAIT_FOR_REPLY: @@ -1206,7 +1207,7 @@ static bool MSTP_Master_Node_FSM( /* BACnet Data Expecting Reply, a Test_Request, or */ /* a proprietary frame that expects a reply is received. */ case MSTP_MASTER_STATE_ANSWER_DATA_REQUEST: - pkt = (struct mstp_pdu_packet *) Ringbuf_Get_Front(&PDU_Queue); + pkt = (struct mstp_pdu_packet *) Ringbuf_Peek(&PDU_Queue); if (pkt != NULL) { matched = dlmstp_compare_data_expecting_reply(&InputBuffer[0], @@ -1224,7 +1225,6 @@ static bool MSTP_Master_Node_FSM( /* then call MSTP_Send_Frame to transmit the reply frame */ /* and enter the IDLE state to wait for the next frame. */ uint8_t frame_type; - pkt = (struct mstp_pdu_packet *) Ringbuf_Pop_Front(&PDU_Queue); if (pkt->data_expecting_reply) { frame_type = FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY; } else { diff --git a/bacnet-stack/src/mstp.c b/bacnet-stack/src/mstp.c index b2be65dc..10234056 100644 --- a/bacnet-stack/src/mstp.c +++ b/bacnet-stack/src/mstp.c @@ -1239,7 +1239,7 @@ static void Load_Input_Buffer( } /* empty any the existing data */ while (!Ringbuf_Empty(&Test_Buffer)) { - (void) Ringbuf_Pop_Front(&Test_Buffer); + (void) Ringbuf_Pop(&Test_Buffer, NULL); } if (buffer) { @@ -1257,11 +1257,12 @@ void RS485_Check_UART_Data( char *data; if (!Ringbuf_Empty(&Test_Buffer) && mstp_port && (mstp_port->DataAvailable == false)) { - data = Ringbuf_Pop_Front(&Test_Buffer); + data = Ringbuf_Peek(&Test_Buffer); if (data) { mstp_port->DataRegister = *data; mstp_port->DataAvailable = true; } + (void)Ringbuf_Pop(&Test_Buffer, NULL); } } diff --git a/bacnet-stack/src/ringbuf.c b/bacnet-stack/src/ringbuf.c index b8500fef..42b3d88c 100644 --- a/bacnet-stack/src/ringbuf.c +++ b/bacnet-stack/src/ringbuf.c @@ -91,7 +91,7 @@ bool Ringbuf_Empty( * ALGORITHM: none * NOTES: none *****************************************************************************/ -volatile uint8_t *Ringbuf_Get_Front( +volatile uint8_t *Ringbuf_Peek( RING_BUFFER const *b) { volatile uint8_t *data_element = NULL; /* return value */ @@ -105,23 +105,32 @@ volatile uint8_t *Ringbuf_Get_Front( } /**************************************************************************** -* DESCRIPTION: Gets the data from the front of the list, and removes it -* RETURN: pointer to the data, or NULL if nothing in the list +* DESCRIPTION: Copy the data from the front of the list, and removes it +* RETURN: true if data was copied, false if list is empty * ALGORITHM: none * NOTES: none *****************************************************************************/ -volatile uint8_t *Ringbuf_Pop_Front( - RING_BUFFER * b) +bool Ringbuf_Pop( + RING_BUFFER * b, + uint8_t *data_element) { - volatile uint8_t *data_element = NULL; + bool status = false; /* return value */ + volatile uint8_t *ring_data = NULL; /* used to help point ring data */ + unsigned i; /* loop counter */ if (!Ringbuf_Empty(b)) { - data_element = b->buffer; - data_element += ((b->tail % b->element_count) * b->element_size); + ring_data = b->buffer; + ring_data += ((b->tail % b->element_count) * b->element_size); + if (data_element) { + for (i = 0; i < b->element_size; i++) { + data_element[i] = ring_data[i]; + } + } b->tail++; + status = true; } - return data_element; + return status; } /**************************************************************************** @@ -132,7 +141,7 @@ volatile uint8_t *Ringbuf_Pop_Front( *****************************************************************************/ bool Ringbuf_Put( RING_BUFFER * b, /* ring buffer structure */ - volatile uint8_t * data_element) + uint8_t *data_element) { /* one element to add to the ring */ bool status = false; /* return value */ volatile uint8_t *ring_data = NULL; /* used to help point ring data */ @@ -154,6 +163,39 @@ bool Ringbuf_Put( return status; } +/**************************************************************************** +* DESCRIPTION: Adds an element of data to the front of the ring buffer +* RETURN: true on succesful add, false if not added +* ALGORITHM: none +* NOTES: moves the tail on add instead of head, so this function +* can't be used if keeping producer and consumer +* as separate processes (i.e. interrupts) +*****************************************************************************/ +bool Ringbuf_Put_Front( + RING_BUFFER * b, /* ring buffer structure */ + uint8_t *data_element) +{ /* one element to add to the front of the ring */ + bool status = false; /* return value */ + volatile uint8_t *ring_data = NULL; /* used to help point ring data */ + unsigned i = 0; /* loop counter */ + + if (b && data_element) { + /* limit the amount of elements that we accept */ + if (!Ringbuf_Full(b)) { + b->tail--; + ring_data = b->buffer; + ring_data += ((b->tail % b->element_count) * b->element_size); + /* copy the data to the ring data element */ + for (i = 0; i < b->element_size; i++) { + ring_data[i] = data_element[i]; + } + status = true; + } + } + + return status; +} + /**************************************************************************** * DESCRIPTION: Reserves and gets the next data portion of the buffer. * RETURN: pointer to the data, or NULL if the list is full @@ -208,14 +250,14 @@ void Ringbuf_Init( #include "ctest.h" /* test the ring buffer */ -void testRingAroundBuffer( +static void testRingAroundBuffer( Test * pTest, RING_BUFFER * test_buffer, uint8_t * data_element, unsigned element_size, unsigned element_count) { - uint8_t *test_data; + volatile uint8_t *test_data; unsigned index; unsigned data_index; unsigned count; @@ -236,28 +278,21 @@ void testRingAroundBuffer( for (count = 1; count < 4; count++) { dummy = index * count; - test_data = Ringbuf_Get_Front(test_buffer); - ct_test(pTest, test_data); - if (test_data) { - for (data_index = 0; data_index < element_size; data_index++) { - ct_test(pTest, test_data[data_index] == dummy); - } - } - - test_data = Ringbuf_Pop_Front(test_buffer); + test_data = Ringbuf_Peek(test_buffer); ct_test(pTest, test_data); if (test_data) { for (data_index = 0; data_index < element_size; data_index++) { ct_test(pTest, test_data[data_index] == dummy); } } + (void)Ringbuf_Pop(test_buffer, NULL); } } ct_test(pTest, Ringbuf_Empty(test_buffer)); } /* test the ring buffer */ -void testRingBuf( +static void testRingBuf( Test * pTest, uint8_t * data_store, uint8_t * data_element, @@ -265,7 +300,7 @@ void testRingBuf( unsigned element_count) { RING_BUFFER test_buffer; - uint8_t *test_data; + volatile uint8_t *test_data; unsigned index; unsigned data_index; bool status; @@ -280,16 +315,12 @@ void testRingBuf( ct_test(pTest, status == true); ct_test(pTest, !Ringbuf_Empty(&test_buffer)); - test_data = Ringbuf_Get_Front(&test_buffer); + test_data = Ringbuf_Peek(&test_buffer); for (data_index = 0; data_index < element_size; data_index++) { ct_test(pTest, test_data[data_index] == data_element[data_index]); } ct_test(pTest, !Ringbuf_Empty(&test_buffer)); - - test_data = Ringbuf_Pop_Front(&test_buffer); - for (data_index = 0; data_index < element_size; data_index++) { - ct_test(pTest, test_data[data_index] == data_element[data_index]); - } + (void)Ringbuf_Pop(&test_buffer, NULL); ct_test(pTest, Ringbuf_Empty(&test_buffer)); /* fill to max */ @@ -313,21 +344,14 @@ void testRingBuf( /* check buffer full */ for (index = 0; index < element_count; index++) { - test_data = Ringbuf_Get_Front(&test_buffer); - ct_test(pTest, test_data); - if (test_data) { - for (data_index = 0; data_index < element_size; data_index++) { - ct_test(pTest, test_data[data_index] == index); - } - } - - test_data = Ringbuf_Pop_Front(&test_buffer); + test_data = Ringbuf_Peek(&test_buffer); ct_test(pTest, test_data); if (test_data) { for (data_index = 0; data_index < element_size; data_index++) { ct_test(pTest, test_data[data_index] == index); } } + (void)Ringbuf_Pop(&test_buffer, NULL); } ct_test(pTest, Ringbuf_Empty(&test_buffer)); @@ -365,14 +389,14 @@ void testRingBufSize32( } -#ifdef TEST_RINGBUF +#ifdef TEST_RING_BUFFER int main( void) { Test *pTest; bool rc; - pTest = ct_create("ringbuf", NULL); + pTest = ct_create("Ring Buffer", NULL); /* individual tests */ rc = ct_addTestFunction(pTest, testRingBufSize16);