From 540dc9643efc866af6e7040634c9d7a17ca6c5b0 Mon Sep 17 00:00:00 2001 From: Jan Breuer <jan.breuer@jaybee.cz> Date: 周六, 05 12月 2015 21:40:52 +0800 Subject: [PATCH] Fix error queue and resolve #67 --- libscpi/inc/scpi/error.h | 2 libscpi/src/fifo_private.h | 3 libscpi/src/error.c | 37 +-------- libscpi/src/fifo.c | 57 ++++++++++++-- libscpi/test/test_parser.c | 43 +++++++++- libscpi/test/test_fifo.c | 77 ++++++++++++++++-- 6 files changed, 162 insertions(+), 57 deletions(-) diff --git a/libscpi/inc/scpi/error.h b/libscpi/inc/scpi/error.h index 539ebae..c8f9679 100644 --- a/libscpi/inc/scpi/error.h +++ b/libscpi/inc/scpi/error.h @@ -164,7 +164,7 @@ XE(SCPI_ERROR_OUT_OF_DEVICE_MEMORY, -321, "Out of memory") \ XE(SCPI_ERROR_SELF_TEST_FAILED, -330, "Self-test failed") \ XE(SCPI_ERROR_CALIBRATION_FAILED, -340, "Calibration failed") \ - XE(SCPI_ERROR_QUEUE_OVERFLOW, -350, "Queue overflow") \ + X(SCPI_ERROR_QUEUE_OVERFLOW, -350, "Queue overflow") \ XE(SCPI_ERROR_COMMUNICATION_ERROR, -360, "Communication error") \ XE(SCPI_ERROR_PARITY_ERROR_IN_CMD_MSG, -361, "Parity error in program message") \ XE(SCPI_ERROR_FRAMING_ERROR_IN_CMD_MSG, -362, "Framing error in program message") \ diff --git a/libscpi/src/error.c b/libscpi/src/error.c index df3db2c..c0ef488 100644 --- a/libscpi/src/error.c +++ b/libscpi/src/error.c @@ -49,12 +49,6 @@ * @param context - scpi context */ void SCPI_ErrorInit(scpi_t * context) { - /* - * // FreeRTOS - * context->error_queue = (scpi_error_queue_t)xQueueCreate(100, sizeof(int16_t)); - */ - - /* basic FIFO */ context->error_queue = (scpi_error_queue_t) & local_error_queue; fifo_init((scpi_fifo_t *) context->error_queue); } @@ -91,12 +85,6 @@ * @param context - scpi context */ void SCPI_ErrorClear(scpi_t * context) { - /* - * // FreeRTOS - * xQueueReset((xQueueHandle)context->error_queue); - */ - - /* basic FIFO */ fifo_clear((scpi_fifo_t *) context->error_queue); SCPI_ErrorEmitEmpty(context); @@ -110,14 +98,6 @@ int16_t SCPI_ErrorPop(scpi_t * context) { int16_t result = 0; - /* - * // FreeRTOS - * if (pdFALSE == xQueueReceive((xQueueHandle)context->error_queue, &result, 0)) { - * result = 0; - * } - */ - - /* basic FIFO */ fifo_remove((scpi_fifo_t *) context->error_queue, &result); SCPI_ErrorEmitEmpty(context); @@ -133,25 +113,16 @@ int32_t SCPI_ErrorCount(scpi_t * context) { int16_t result = 0; - /* - * // FreeRTOS - * result = uxQueueMessagesWaiting((xQueueHandle)context->error_queue); - */ - - /* basic FIFO */ fifo_count((scpi_fifo_t *) context->error_queue, &result); return result; } static void SCPI_ErrorAddInternal(scpi_t * context, int16_t err) { - /* - * // FreeRTOS - * xQueueSend((xQueueHandle)context->error_queue, &err, 0); - */ - - /* basic FIFO */ - fifo_add((scpi_fifo_t *) context->error_queue, err); + if (!fifo_add((scpi_fifo_t *) context->error_queue, err)) { + fifo_remove_last((scpi_fifo_t *) context->error_queue, NULL); + fifo_add((scpi_fifo_t *) context->error_queue, SCPI_ERROR_QUEUE_OVERFLOW); + } } struct error_reg { diff --git a/libscpi/src/fifo.c b/libscpi/src/fifo.c index a69cf85..a64d351 100644 --- a/libscpi/src/fifo.c +++ b/libscpi/src/fifo.c @@ -21,19 +21,37 @@ } /** - * Add element to fifo. If fifo is full, remove last element. + * Test if fifo is empty + * @param fifo + * @return + */ +scpi_bool_t fifo_is_empty(scpi_fifo_t * fifo) { + return fifo->wr == fifo->rd; +} + +/** + * Test if fifo is full + * @param fifo + * @return + */ +scpi_bool_t fifo_is_full(scpi_fifo_t * fifo) { + return fifo->wr == ((fifo->rd + fifo->size - 1) % (fifo->size)); +} + +/** + * Add element to fifo. If fifo is full, return FALSE. * @param fifo * @param value - * @return + * @return */ scpi_bool_t fifo_add(scpi_fifo_t * fifo, int16_t value) { /* FIFO full? */ - if (fifo->wr == ((fifo->rd + fifo->size) % (fifo->size + 1))) { - fifo_remove(fifo, NULL); + if (fifo_is_full(fifo)) { + return FALSE; } fifo->data[fifo->wr] = value; - fifo->wr = (fifo->wr + 1) % (fifo->size + 1); + fifo->wr = (fifo->wr + 1) % (fifo->size); return TRUE; } @@ -46,7 +64,7 @@ */ scpi_bool_t fifo_remove(scpi_fifo_t * fifo, int16_t * value) { /* FIFO empty? */ - if (fifo->wr == fifo->rd) { + if (fifo_is_empty(fifo)) { return FALSE; } @@ -54,7 +72,28 @@ *value = fifo->data[fifo->rd]; } - fifo->rd = (fifo->rd + 1) % (fifo->size + 1); + fifo->rd = (fifo->rd + 1) % (fifo->size); + + return TRUE; +} + +/** + * Remove last element from fifo + * @param fifo + * @param value + * @return FALSE - fifo is empty + */ +scpi_bool_t fifo_remove_last(scpi_fifo_t * fifo, int16_t * value) { + /* FIFO empty? */ + if (fifo_is_empty(fifo)) { + return FALSE; + } + + fifo->wr = (fifo->wr + fifo->size - 1) % (fifo->size); + + if (value) { + *value = fifo->data[fifo->wr]; + } return TRUE; } @@ -63,12 +102,12 @@ * Retrive number of elements in fifo * @param fifo * @param value - * @return + * @return */ scpi_bool_t fifo_count(scpi_fifo_t * fifo, int16_t * value) { *value = fifo->wr - fifo->rd; if (*value < 0) { - *value += (fifo->size + 1); + *value += (fifo->size); } return TRUE; } diff --git a/libscpi/src/fifo_private.h b/libscpi/src/fifo_private.h index 20dff74..d04da84 100644 --- a/libscpi/src/fifo_private.h +++ b/libscpi/src/fifo_private.h @@ -57,8 +57,11 @@ void fifo_init(scpi_fifo_t * fifo) LOCAL; void fifo_clear(scpi_fifo_t * fifo) LOCAL; + scpi_bool_t fifo_is_empty(scpi_fifo_t * fifo) LOCAL; + scpi_bool_t fifo_is_full(scpi_fifo_t * fifo) LOCAL; scpi_bool_t fifo_add(scpi_fifo_t * fifo, int16_t value) LOCAL; scpi_bool_t fifo_remove(scpi_fifo_t * fifo, int16_t * value) LOCAL; + scpi_bool_t fifo_remove_last(scpi_fifo_t * fifo, int16_t * value) LOCAL; scpi_bool_t fifo_count(scpi_fifo_t * fifo, int16_t * value) LOCAL; #ifdef __cplusplus diff --git a/libscpi/test/test_fifo.c b/libscpi/test/test_fifo.c index c31cc26..f99a467 100644 --- a/libscpi/test/test_fifo.c +++ b/libscpi/test/test_fifo.c @@ -28,57 +28,114 @@ fifo_init(&fifo); int16_t value; - fifo.size = 4; + fifo.size = 5; #define TEST_FIFO_COUNT(n) \ do { \ fifo_count(&fifo, &value); \ CU_ASSERT_EQUAL(value, n); \ } while(0) \ - + TEST_FIFO_COUNT(0); + CU_ASSERT_TRUE(fifo_is_empty(&fifo)); + CU_ASSERT_FALSE(fifo_is_full(&fifo)); + CU_ASSERT_TRUE(fifo_add(&fifo, 1)); TEST_FIFO_COUNT(1); + CU_ASSERT_FALSE(fifo_is_empty(&fifo)); + CU_ASSERT_FALSE(fifo_is_full(&fifo)); + CU_ASSERT_TRUE(fifo_add(&fifo, 2)); TEST_FIFO_COUNT(2); + CU_ASSERT_FALSE(fifo_is_empty(&fifo)); + CU_ASSERT_FALSE(fifo_is_full(&fifo)); + CU_ASSERT_TRUE(fifo_add(&fifo, 3)); TEST_FIFO_COUNT(3); + CU_ASSERT_FALSE(fifo_is_empty(&fifo)); + CU_ASSERT_FALSE(fifo_is_full(&fifo)); + CU_ASSERT_TRUE(fifo_add(&fifo, 4)); TEST_FIFO_COUNT(4); - CU_ASSERT_TRUE(fifo_add(&fifo, 1)); - TEST_FIFO_COUNT(4); + CU_ASSERT_FALSE(fifo_is_empty(&fifo)); + CU_ASSERT_TRUE(fifo_is_full(&fifo)); CU_ASSERT_EQUAL(fifo.data[0], 1); CU_ASSERT_EQUAL(fifo.data[1], 2); CU_ASSERT_EQUAL(fifo.data[2], 3); CU_ASSERT_EQUAL(fifo.data[3], 4); + + CU_ASSERT_FALSE(fifo_add(&fifo, 5)); + TEST_FIFO_COUNT(4); + CU_ASSERT_FALSE(fifo_is_empty(&fifo)); + CU_ASSERT_TRUE(fifo_is_full(&fifo)); + + CU_ASSERT_EQUAL(fifo.data[0], 1); + CU_ASSERT_EQUAL(fifo.data[1], 2); + CU_ASSERT_EQUAL(fifo.data[2], 3); + CU_ASSERT_EQUAL(fifo.data[3], 4); + + CU_ASSERT_TRUE(fifo_remove_last(&fifo, &value)); + CU_ASSERT_EQUAL(value, 4); + TEST_FIFO_COUNT(3); + CU_ASSERT_FALSE(fifo_is_empty(&fifo)); + CU_ASSERT_FALSE(fifo_is_full(&fifo)); + + CU_ASSERT_TRUE(fifo_add(&fifo, 6)); + TEST_FIFO_COUNT(4); + CU_ASSERT_FALSE(fifo_is_empty(&fifo)); + CU_ASSERT_TRUE(fifo_is_full(&fifo)); + + CU_ASSERT_EQUAL(fifo.data[0], 1); + CU_ASSERT_EQUAL(fifo.data[1], 2); + CU_ASSERT_EQUAL(fifo.data[2], 3); + CU_ASSERT_EQUAL(fifo.data[3], 6); + + CU_ASSERT_TRUE(fifo_remove(&fifo, &value)); + CU_ASSERT_EQUAL(value, 1); + TEST_FIFO_COUNT(3); + CU_ASSERT_FALSE(fifo_is_empty(&fifo)); + CU_ASSERT_FALSE(fifo_is_full(&fifo)); + + CU_ASSERT_TRUE(fifo_add(&fifo, 7)); + TEST_FIFO_COUNT(4); + CU_ASSERT_TRUE(fifo_remove(&fifo, &value)); CU_ASSERT_EQUAL(value, 2); TEST_FIFO_COUNT(3); - CU_ASSERT_TRUE(fifo_add(&fifo, 5)); + CU_ASSERT_TRUE(fifo_remove(&fifo, &value)); + CU_ASSERT_EQUAL(value, 3); + TEST_FIFO_COUNT(2); + + CU_ASSERT_TRUE(fifo_add(&fifo, 10)); + TEST_FIFO_COUNT(3); + + CU_ASSERT_TRUE(fifo_add(&fifo, 11)); TEST_FIFO_COUNT(4); CU_ASSERT_TRUE(fifo_remove(&fifo, &value)); - CU_ASSERT_EQUAL(value, 3); + CU_ASSERT_EQUAL(value, 6); TEST_FIFO_COUNT(3); CU_ASSERT_TRUE(fifo_remove(&fifo, &value)); - CU_ASSERT_EQUAL(value, 4); + CU_ASSERT_EQUAL(value, 7); TEST_FIFO_COUNT(2); - CU_ASSERT_TRUE(fifo_remove(&fifo, &value)); - CU_ASSERT_EQUAL(value, 1); + CU_ASSERT_TRUE(fifo_remove_last(&fifo, &value)); + CU_ASSERT_EQUAL(value, 11); TEST_FIFO_COUNT(1); CU_ASSERT_TRUE(fifo_remove(&fifo, &value)); - CU_ASSERT_EQUAL(value, 5); + CU_ASSERT_EQUAL(value, 10); TEST_FIFO_COUNT(0); CU_ASSERT_FALSE(fifo_remove(&fifo, &value)); TEST_FIFO_COUNT(0); + + CU_ASSERT_FALSE(fifo_remove_last(&fifo, NULL)); } int main() { diff --git a/libscpi/test/test_parser.c b/libscpi/test/test_parser.c index 0c59bfa..b3c1463 100644 --- a/libscpi/test/test_parser.c +++ b/libscpi/test/test_parser.c @@ -8,6 +8,7 @@ #include "CUnit/Basic.h" #include "scpi/scpi.h" +#include "../src/fifo_private.h" /* * CUnit Test Suite @@ -316,7 +317,7 @@ TEST_IEEE4882("ABCD\r\n", ""); /* "Undefined header" cause command error */ CU_ASSERT_EQUAL(srq_val, (STB_ESR | STB_SRQ | STB_QMA)); /* value of STB as service request */ TEST_IEEE4882("*STB?\r\n", "100\r\n"); /* Event status register + Service request */ - TEST_IEEE4882("*ESR?\r\n", "32\r\n"); /* Command error */ + TEST_IEEE4882("*ESR?\r\n", "32\r\n"); /* Command error */ TEST_IEEE4882("*STB?\r\n", "68\r\n"); /* Error queue is still not empty */ TEST_IEEE4882("*ESR?\r\n", "0\r\n"); @@ -332,10 +333,10 @@ TEST_IEEE4882("ABCD\r\n", ""); /* "Undefined header" cause command error */ CU_ASSERT_EQUAL(srq_val, 0); /* no control callback */ TEST_IEEE4882("*STB?\r\n", "100\r\n"); /* Event status register + Service request */ - TEST_IEEE4882("*ESR?\r\n", "32\r\n"); /* Command error */ + TEST_IEEE4882("*ESR?\r\n", "32\r\n"); /* Command error */ TEST_IEEE4882("SYST:ERR:NEXT?\r\n", "-113,\"Undefined header\"\r\n"); scpi_context.interface->control = SCPI_Control; - + RST_executed = FALSE; TEST_IEEE4882("*RST\r\n", ""); CU_ASSERT_EQUAL(RST_executed, TRUE); @@ -372,7 +373,7 @@ TEST_IEEE4882("STUB\r\n", ""); TEST_IEEE4882("STUB?\r\n", "0\r\n"); - + TEST_IEEE4882_REG(SCPI_REG_COUNT + 1, 0); TEST_IEEE4882_REG_SET(SCPI_REG_OPERE, 1); TEST_IEEE4882_REG(SCPI_REG_OPERE, 1); @@ -1180,6 +1181,39 @@ TEST_SCPI_NumberToStr(TRUE, SCPI_NUM_DEF, SCPI_UNIT_NONE, "DEFault"); } +static void testErrorQueue(void) { + ((scpi_fifo_t *) (scpi_context.error_queue))->size = 5; + + SCPI_ErrorClear(&scpi_context); + CU_ASSERT_EQUAL(SCPI_ErrorCount(&scpi_context), 0); + SCPI_ErrorPush(&scpi_context, -1); + CU_ASSERT_EQUAL(SCPI_ErrorCount(&scpi_context), 1); + SCPI_ErrorPush(&scpi_context, -2); + CU_ASSERT_EQUAL(SCPI_ErrorCount(&scpi_context), 2); + SCPI_ErrorPush(&scpi_context, -3); + CU_ASSERT_EQUAL(SCPI_ErrorCount(&scpi_context), 3); + SCPI_ErrorPush(&scpi_context, -4); + CU_ASSERT_EQUAL(SCPI_ErrorCount(&scpi_context), 4); + SCPI_ErrorPush(&scpi_context, -5); + CU_ASSERT_EQUAL(SCPI_ErrorCount(&scpi_context), 4); + SCPI_ErrorPush(&scpi_context, -6); + CU_ASSERT_EQUAL(SCPI_ErrorCount(&scpi_context), 4); + + CU_ASSERT_EQUAL(SCPI_ErrorPop(&scpi_context), -1); + CU_ASSERT_EQUAL(SCPI_ErrorCount(&scpi_context), 3); + CU_ASSERT_EQUAL(SCPI_ErrorPop(&scpi_context), -2); + CU_ASSERT_EQUAL(SCPI_ErrorCount(&scpi_context), 2); + CU_ASSERT_EQUAL(SCPI_ErrorPop(&scpi_context), -3); + CU_ASSERT_EQUAL(SCPI_ErrorCount(&scpi_context), 1); + CU_ASSERT_EQUAL(SCPI_ErrorPop(&scpi_context), SCPI_ERROR_QUEUE_OVERFLOW); + CU_ASSERT_EQUAL(SCPI_ErrorCount(&scpi_context), 0); + CU_ASSERT_EQUAL(SCPI_ErrorPop(&scpi_context), 0); + CU_ASSERT_EQUAL(SCPI_ErrorCount(&scpi_context), 0); + + SCPI_ErrorClear(&scpi_context); + ((scpi_fifo_t *) (scpi_context.error_queue))->size = FIFO_SIZE; +} + int main() { unsigned int result; CU_pSuite pSuite = NULL; @@ -1226,6 +1260,7 @@ || (NULL == CU_add_test(pSuite, "SCPI_ResultArbitraryBlock", testResultArbitraryBlock)) || (NULL == CU_add_test(pSuite, "SCPI_ResultArray", testResultArray)) || (NULL == CU_add_test(pSuite, "SCPI_NumberToStr", testNumberToStr)) + || (NULL == CU_add_test(pSuite, "SCPI_ErrorQueue", testErrorQueue)) ) { CU_cleanup_registry(); return CU_get_error(); -- Gitblit v1.9.1