diff options
Diffstat (limited to 'testsuites/sptests/spconsole01/init.c')
-rw-r--r-- | testsuites/sptests/spconsole01/init.c | 333 |
1 files changed, 333 insertions, 0 deletions
diff --git a/testsuites/sptests/spconsole01/init.c b/testsuites/sptests/spconsole01/init.c new file mode 100644 index 0000000000..99cd7c6f0e --- /dev/null +++ b/testsuites/sptests/spconsole01/init.c @@ -0,0 +1,333 @@ +/* + * Copyright (c) 2017 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <sys/param.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <math.h> +#include <string.h> +#include <termios.h> +#include <unistd.h> + +#include <rtems.h> +#include <rtems/console.h> + +#include "tmacros.h" + +const char rtems_test_name[] = "SPCONSOLE 1"; + +#define LINE_LEN 79 + +static const char n_line[LINE_LEN + 1] = +"nNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNn"; + +static const char b_line[LINE_LEN + 1] = +"bBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBb"; + +static const char e_line[LINE_LEN + 1] = +"eEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEe"; + +typedef struct { + speed_t speed; + uint32_t value; + const char *msg; +} speed_desc; + +static const speed_desc speeds[] = { + { .speed = B9600, .value = 9600, .msg = "9600 8N1" }, + { .speed = B19200, .value = 19200, .msg = "19200 8N1" }, + { .speed = B38400, .value = 38400, .msg = "38400 8N1" }, + { .speed = B57600, .value = 57600, .msg = "57600 8N1" }, + { .speed = B115200, .value = 115200, .msg = "115200 8N1" } +}; + +#define BITS_PER_CHAR 10 + +typedef struct { + int fd; + struct termios saved_term; + struct termios term; + char buf[9600 / BITS_PER_CHAR]; + rtems_id done; +} test_context; + +static test_context test_instance; + +static void drain(test_context *ctx) +{ + int rv; + + rv = tcdrain(ctx->fd); + rtems_test_assert(rv == 0); + + /* Ensure that a hardware transmit FIFO of reasonable size is empty */ + rv = usleep(200000); + rtems_test_assert(rv == 0); +} + +static void do_begin(test_context *ctx, const char *msg) +{ + puts(n_line); + puts(msg); + puts(b_line); + drain(ctx); +} + +static void do_end(test_context *ctx) +{ + int rv; + + drain(ctx); + + rv = cfsetspeed(&ctx->term, cfgetospeed(&ctx->saved_term)); + rtems_test_assert(rv == 0); + + rv = tcsetattr(ctx->fd, TCSANOW, &ctx->term); + rtems_test_assert(rv == 0); + + puts(""); + puts(e_line); +} + +static void test_steps_one_task(test_context *ctx, char c) +{ + char buf[128]; + size_t i; + + for (i = 0; i < RTEMS_ARRAY_SIZE(buf); ++i) { + size_t r; + char *p; + + buf[i] = '\n'; + + r = i; + p = buf; + while (r > 0) { + ssize_t m; + + m = write(ctx->fd, p, r); + rtems_test_assert(m > 0); + + r -= (size_t) m; + p += (size_t) m; + } + + if (i > 1) { + buf[i - 2] = c; + } + + if (i > 0) { + buf[i - 1] = '\r'; + } + } +} + +static void test_speeds(test_context *ctx) +{ + size_t i; + + for (i = 0; i < RTEMS_ARRAY_SIZE(speeds); ++i) { + uint64_t t0; + uint64_t t1; + size_t n; + size_t r; + int rv; + + do_begin(ctx, speeds[i].msg); + + rv = cfsetspeed(&ctx->term, speeds[i].speed); + rtems_test_assert(rv == 0); + + rv = tcsetattr(ctx->fd, TCSANOW, &ctx->term); + rtems_test_assert(rv == 0); + + n = speeds[i].value / BITS_PER_CHAR; + r = n; + t0 = rtems_clock_get_uptime_nanoseconds(); + + while (r > 0) { + ssize_t m; + + m = write(ctx->fd, ctx->buf, MIN(sizeof(ctx->buf), r)); + rtems_test_assert(m > 0); + + r -= (size_t) m; + } + + rv = tcdrain(ctx->fd); + rtems_test_assert(rv == 0); + + t1 = rtems_clock_get_uptime_nanoseconds(); + + do_end(ctx); + + printf("transmitted chars: %zu\n", n); + printf( + "transmitted bits (1 start, 8 data, 1 stop): %zu\n", + n * BITS_PER_CHAR + ); + + printf("actual transmit time: %10" PRIu64 "ns\n", t1 - t0); + printf("expected transmit time: 1000000000ns\n"); + } +} + +static void task(test_context *ctx, char c) +{ + rtems_status_code sc; + + test_steps_one_task(ctx, c); + + sc = rtems_semaphore_release(ctx->done); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + rtems_task_suspend(RTEMS_SELF); +} + +static void task_y(rtems_task_argument arg) +{ + test_context *ctx; + + ctx = (test_context *) arg; + task(ctx, 'Y'); +} + +static void task_z(rtems_task_argument arg) +{ + test_context *ctx; + + ctx = (test_context *) arg; + task(ctx, 'z'); +} + +static void test(test_context *ctx) +{ + int rv; + rtems_status_code sc; + rtems_id y; + rtems_id z; + + sc = rtems_semaphore_create( + rtems_build_name('D', 'O', 'N', 'E'), + 0, + RTEMS_COUNTING_SEMAPHORE, + 0, + &ctx->done + ); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + ctx->fd = open(CONSOLE_DEVICE_NAME, O_RDWR); + rtems_test_assert(ctx->fd >= 0); + + rv = tcgetattr(ctx->fd, &ctx->saved_term); + rtems_test_assert(rv == 0); + + ctx->term = ctx->saved_term; + cfmakeraw(&ctx->term); + + rv = tcsetattr(ctx->fd, TCSANOW, &ctx->term); + rtems_test_assert(rv == 0); + + memset(&ctx->buf, 'd', sizeof(ctx->buf)); + + do_begin(ctx, "steps one task"); + test_steps_one_task(ctx, 'x'); + do_end(ctx); + + do_begin(ctx, "steps three tasks"); + + sc = rtems_task_create( + rtems_build_name(' ', ' ', ' ', 'Y'), + 1, + RTEMS_MINIMUM_STACK_SIZE, + RTEMS_DEFAULT_MODES, + RTEMS_DEFAULT_ATTRIBUTES, + &y + ); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_start(y, task_y, (rtems_task_argument) ctx); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_create( + rtems_build_name(' ', ' ', ' ', 'Z'), + 1, + RTEMS_MINIMUM_STACK_SIZE, + RTEMS_DEFAULT_MODES, + RTEMS_DEFAULT_ATTRIBUTES, + &z + ); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_start(z, task_z, (rtems_task_argument) ctx); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + test_steps_one_task(ctx, 'x'); + + sc = rtems_semaphore_obtain(ctx->done, RTEMS_WAIT, RTEMS_NO_TIMEOUT); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_semaphore_obtain(ctx->done, RTEMS_WAIT, RTEMS_NO_TIMEOUT); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + do_end(ctx); + + test_speeds(ctx); + + rv = close(ctx->fd); + rtems_test_assert(rv == 0); + + sc = rtems_task_delete(y); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_delete(z); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_semaphore_delete(ctx->done); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); +} + +static void Init(rtems_task_argument arg) +{ + TEST_BEGIN(); + + rtems_print_printer_fprintf_putc(&rtems_test_printer); + test(&test_instance); + + TEST_END(); + rtems_test_exit(0); +} + +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER + +#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 4 + +#define CONFIGURE_MAXIMUM_TASKS 3 +#define CONFIGURE_MAXIMUM_SEMAPHORES 1 + +#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION + +#define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES +#define CONFIGURE_INIT_TASK_ATTRIBUTES RTEMS_FLOATING_POINT + +#define CONFIGURE_RTEMS_INIT_TASKS_TABLE + +#define CONFIGURE_INIT + +#include <rtems/confdefs.h> |