From a55c25ddca97a5f809ac26b17324e4315e299f7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Fri, 25 Mar 2016 22:31:19 +0100 Subject: [PATCH] quite reliable, fixed bugs in bulk --- Makefile | 2 +- esp_meas.pro | 9 +++-- esp_meas.pro.user | 2 +- sbmp | 2 +- user/ftoa.c | 83 +++++++++++++++++++++++++++++++++++++++++ user/ftoa.h | 10 +++++ user/sampling.c | 93 ++++++++++++++++++++++++++++++---------------- user/sbmp_config.h | 12 +++++- user/serial.c | 8 ++-- user/timeout.h | 2 +- 10 files changed, 180 insertions(+), 43 deletions(-) create mode 100644 user/ftoa.c create mode 100644 user/ftoa.h diff --git a/Makefile b/Makefile index 0808aba..258857e 100644 --- a/Makefile +++ b/Makefile @@ -66,7 +66,7 @@ LIBS += esphttpd # compiler flags using during compilation of source files CFLAGS = -Os -ggdb -std=gnu99 -Werror -Wpointer-arith -Wundef -Wall -Wl,-EL -fno-inline-functions \ -nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH \ - -Wno-address -ffunction-sections + -Wno-address -ffunction-sections -Wno-unused-value #-Wno-strict-aliasing # linker flags used to generate the main object file diff --git a/esp_meas.pro b/esp_meas.pro index 8aade0f..8857ce0 100644 --- a/esp_meas.pro +++ b/esp_meas.pro @@ -13,7 +13,8 @@ INCLUDEPATH = . \ libesphttpd/espfs \ libesphttpd/core \ libesphttpd/lib/heatshrink \ - sbmp/library + sbmp/library \ + /home/ondra/devel/esp/sdk/esp-open-sdk/xtensa-lx106-elf/xtensa-lx106-elf/include SOURCES += \ libesphttpd/core/auth.c \ @@ -55,7 +56,8 @@ SOURCES += \ user/uptime.c \ sbmp/library/payload_parser.c \ user/sampling.c \ - user/page_home.c + user/page_home.c \ + user/ftoa.c HEADERS += \ include/uart_hw.h \ @@ -134,7 +136,8 @@ HEADERS += \ user/page_home.h \ user/timeout.h \ user/sbmp_config.h \ - sbmp/library/sbmp_config.example.h + sbmp/library/sbmp_config.example.h \ + user/ftoa.h DISTFILES += \ style.astylerc \ diff --git a/esp_meas.pro.user b/esp_meas.pro.user index 71a43ea..95632ac 100644 --- a/esp_meas.pro.user +++ b/esp_meas.pro.user @@ -1,6 +1,6 @@ - + EnvironmentId diff --git a/sbmp b/sbmp index 6495ad6..8e7a1cb 160000 --- a/sbmp +++ b/sbmp @@ -1 +1 @@ -Subproject commit 6495ad6474dbd7a5e7198fbb998a247efed368a2 +Subproject commit 8e7a1cbff148745f2d9b21e3585606a7c2555f04 diff --git a/user/ftoa.c b/user/ftoa.c new file mode 100644 index 0000000..2c28a58 --- /dev/null +++ b/user/ftoa.c @@ -0,0 +1,83 @@ +#include + +/* reverse: reverse string s in place */ +static void str_reverse(char *s) +{ + for (int i = 0, j = (int)(strlen(s) - 1); i < j; i++, j--) { + char c = s[i]; + s[i] = s[j]; + s[j] = c; + } +} + +/* itoa: convert n to characters in s. returns length */ +int my_itoa(int n, char *s) +{ + int i, sign; + + if ((sign = n) < 0) /* record sign */ + n = -n; /* make n positive */ + i = 0; + do { /* generate digits in reverse order */ + s[i++] = n % 10 + '0'; /* get next digit */ + } while ((n /= 10) > 0); /* delete it */ + if (sign < 0) + s[i++] = '-'; + s[i] = '\0'; + + str_reverse(s); + + return i; +} + +int my_ftoa(char *buffer, float f, int precision) +{ + // add 0.5 * 10^-precision + float rounder = 0.5; + for (int i = 0; i < precision; i++) rounder *= 0.1; + f += rounder; + + int wholePart = (int) f; + + // Deposit the whole part of the number. + + int length = my_itoa(wholePart, buffer); + + // Now work on the faction if we need one. + if (precision > 0) { + // We do, so locate the end of the string and insert + // a decimal point. + char *endOfString = buffer + length; + //while (*endOfString != '\0') endOfString++; + *endOfString++ = '.'; + + length++; + + // Now work on the fraction, be sure to turn any negative + // values positive. + if (f < 0) { + f *= -1; + wholePart *= -1; + } + + float fraction = f - wholePart; + while (precision > 0) { + // Multiply by ten and pull out the digit. + fraction *= 10; + int dig = (int) fraction; + *endOfString++ = (char)('0' + dig); + + // Update the fraction and move on to the + // next digit. + fraction -= dig; + precision--; + + length++; + } + + // Terminate the string. + *endOfString = 0; + } + + return length; +} diff --git a/user/ftoa.h b/user/ftoa.h new file mode 100644 index 0000000..aac1574 --- /dev/null +++ b/user/ftoa.h @@ -0,0 +1,10 @@ +#ifndef FTOA_H +#define FTOA_H + +#include + +/* itoa: convert n to characters in s. returns length */ +int my_itoa(int n, char *s); +int my_ftoa(char *buffer, float f, int precision); + +#endif // FTOA_H diff --git a/user/sampling.c b/user/sampling.c index 7331456..b77c93a 100644 --- a/user/sampling.c +++ b/user/sampling.c @@ -14,20 +14,37 @@ #define CHUNK_LEN (CHUNK_LEN_32*4) -static bool acquire_pending = false; -static uint16_t acquire_session; +static volatile bool acquire_pending = false; +static volatile uint16_t acquire_session; static ETSTimer prSampleAbortTimer; -static void FLASH_FN prSampleAbortTimerCb(void *arg) { +static void FLASH_FN prSampleAbortTimerCb(void *arg) +{ warn("Sampling aborted due to timeout."); - acquire_pending = false; + + // try to abort the readout + sbmp_bulk_abort(dlnk_ep, acquire_session); // free the data obj if not NULL sbmp_ep_free_listener_obj(dlnk_ep, acquire_session); // release the slot sbmp_ep_remove_listener(dlnk_ep, acquire_session); + acquire_pending = false; +} + + +static void setReadoutTmeoTimer(int ms) +{ + os_timer_disarm(&prSampleAbortTimer); + os_timer_setfn(&prSampleAbortTimer, prSampleAbortTimerCb, NULL); + os_timer_arm(&prSampleAbortTimer, ms, 0); +} + +static void stopReadoutTmeoTimer(void) +{ + os_timer_disarm(&prSampleAbortTimer); } @@ -41,12 +58,12 @@ static void FLASH_FN request_data_sesn_listener(SBMP_Endpoint *ep, SBMP_Datagram bool suc = false; dbg("Received msg in session %d, dg type %d", dg->session, dg->type); - DataReadState *state = *obj; + DataReadState *readState = *obj; // allocate the state struct - if (state == NULL) { - state = malloc(sizeof(DataReadState)); - *obj = state; + if (readState == NULL) { + readState = malloc(sizeof(DataReadState)); + *obj = readState; } PayloadParser pp; @@ -57,39 +74,43 @@ static void FLASH_FN request_data_sesn_listener(SBMP_Endpoint *ep, SBMP_Datagram // data is ready to be read pp = pp_start(dg->payload, dg->length); - state->pos = 0; - state->total = pp_u32(&pp); + readState->pos = 0; + readState->total = pp_u32(&pp); - dbg("Total bytes: %d", state->total); + dbg("Total bytes: %d", readState->total); - retry_until_timeout(10, sbmp_bulk_request(ep, state->pos, CHUNK_LEN, dg->session)); + retry_TO(100, sbmp_bulk_request(ep, readState->pos, CHUNK_LEN, dg->session)); + + setReadoutTmeoTimer(500); break; case DG_BULK_DATA: // data received - info("--- Received a chunk ---"); + info("--- Received a chunk, length %d ---", dg->length); // Process the received data pp = pp_start(dg->payload, dg->length); - for (int i = 0; i < dg->length/4; i++) { - float f = pp_float(&pp); - dbg("Rx %.2f", f); + while(pp.ptr < pp.len) { + uint32_t x = pp_u32(&pp); + printf("%d,", x); } + printf("\n"); // and ask for more - state->pos += dg->length; + readState->pos += dg->length; - if (state->pos >= state->total) { + if (readState->pos >= readState->total) { dbg("Transfer is complete."); // transfer complete // make sure the peer has freed the buffer // (may be waiting for us if we wanted to re-read something) - retry_until_timeout(10, sbmp_bulk_abort(ep, dg->session)); + retry_TO(100, sbmp_bulk_abort(ep, dg->session)); goto cleanup; } else { // read next part - retry_until_timeout(10, sbmp_bulk_request(ep, state->pos, CHUNK_LEN, dg->session)); + retry_TO(100, sbmp_bulk_request(ep, readState->pos, CHUNK_LEN, dg->session)); + setReadoutTmeoTimer(500); } break; @@ -103,14 +124,20 @@ static void FLASH_FN request_data_sesn_listener(SBMP_Endpoint *ep, SBMP_Datagram cleanup: // free the obj - free(state); + free(readState); // remove the listener sbmp_ep_remove_listener(ep, dg->session); + stopReadoutTmeoTimer(); + acquire_pending = false; + + // In case the error was in SBMP (bad state) } static bool FLASH_FN meas_request_data(uint16_t count) { + bool suc = false; + info("Requesting data capture - %d samples.", count); if (acquire_pending) { @@ -123,32 +150,36 @@ static bool FLASH_FN meas_request_data(uint16_t count) return false; } - // start the abort timer - timeout - os_timer_disarm(&prSampleAbortTimer); - os_timer_setfn(&prSampleAbortTimer, prSampleAbortTimerCb, NULL); - os_timer_arm(&prSampleAbortTimer, 5000, 0); // 5 seconds, no repeat + acquire_pending = true; + // start the abort timer - timeout + setReadoutTmeoTimer(6000); // start a message - uint16_t sesn; - bool suc = sbmp_ep_start_message(dlnk_ep, DG_REQUEST_CAPTURE, sizeof(uint16_t), &sesn); + uint16_t sesn = 0; + retry_TO(100, sbmp_ep_start_message(dlnk_ep, DG_REQUEST_CAPTURE, sizeof(uint16_t), &sesn)); if (!suc) goto fail; // register the session listener suc = sbmp_ep_add_listener(dlnk_ep, sesn, request_data_sesn_listener, NULL); - if (!suc) goto fail; + if (!suc) { + // discard the unfinished outgoing packet + sbmp_frm_reset_tx(&dlnk_ep->frm); + goto fail; + } + + acquire_session = sesn; // request N values sbmp_ep_send_u16(dlnk_ep, count); dbg("Request sent, session nr %d", sesn); - acquire_session = sesn; - return true; fail: - os_timer_disarm(&prSampleAbortTimer); + stopReadoutTmeoTimer(); + acquire_pending = false; return false; } diff --git a/user/sbmp_config.h b/user/sbmp_config.h index 6207948..d63a69c 100644 --- a/user/sbmp_config.h +++ b/user/sbmp_config.h @@ -3,6 +3,7 @@ #include + /* ---------- CRC32 ---------------- */ /** @@ -54,7 +55,7 @@ /** * @brief Enable detailed logging (only for debugging, disable for better performance). */ -#define SBMP_DEBUG 1 +#define SBMP_DEBUG 0 // here are the actual logging functions #define sbmp_error(fmt, ...) (SBMP_DEBUG||SBMP_LOGGING ? os_printf("\x1b[31;1m[SBMP][E] "fmt"\x1b[0m\n", ##__VA_ARGS__) : 0) @@ -63,4 +64,13 @@ #define sbmp_dbg(fmt, ...) (SBMP_DEBUG ? os_printf("[SBMP][ ] "fmt"\n", ##__VA_ARGS__) : 0) +/* ---------- Fix formatting -------------- */ + +#define PRIu16 "u" +#define PRIu32 "u" +#define PRIu8 "u" +#define PRIi16 "d" +#define PRIi32 "d" +#define PRIi8 "d" + #endif // SBMP_CONFIG_H diff --git a/user/serial.c b/user/serial.c index a0bf95e..ea660e8 100644 --- a/user/serial.c +++ b/user/serial.c @@ -34,12 +34,12 @@ void FLASH_FN clear_rxtx(int uart_no) * @brief Configure UART 115200-8-N-1 * @param uart_no */ -static void FLASH_FN my_uart_init(UARTn uart_no) +static void FLASH_FN my_uart_init(UARTn uart_no, uint32 baud) { UART_SetParity(uart_no, PARITY_NONE); UART_SetStopBits(uart_no, ONE_STOP_BIT); UART_SetWordLength(uart_no, EIGHT_BITS); - UART_SetBaudrate(uart_no, BIT_RATE_115200); + UART_SetBaudrate(uart_no, baud); UART_ResetFifo(uart_no); } @@ -58,8 +58,8 @@ static void FLASH_FN conf_uart_pins(void) PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_U1TXD_BK); // Configure the UART peripherals - my_uart_init(UART0); // main - my_uart_init(UART1); // debug (output only) + my_uart_init(UART0, BIT_RATE_460800); // main + my_uart_init(UART1, BIT_RATE_115200); // debug (output only) // Select debug port UART_SetPrintPort(UART1); diff --git a/user/timeout.h b/user/timeout.h index ed09d1e..ecaebb0 100644 --- a/user/timeout.h +++ b/user/timeout.h @@ -6,7 +6,7 @@ #define until_timeout(to_ms) for(uint32_t _utmeo = system_get_time(); system_get_time() - _utmeo < ((to_ms)*1000);) /** Retry a call until a timeout. Variable 'suc' is set to the return value. Must be defined. */ -#define retry_until_timeout(to_ms, call) \ +#define retry_TO(to_ms, call) \ until_timeout(to_ms) { \ suc = call; \ if (suc) break; \