File indexing completed on 2025-05-11 08:24:46
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifdef HAVE_CONFIG_H
0010 #include "config.h"
0011 #endif
0012
0013 #include <sys/param.h>
0014 #include <sys/stat.h>
0015 #include <fcntl.h>
0016 #include <math.h>
0017 #include <string.h>
0018 #include <termios.h>
0019 #include <unistd.h>
0020
0021 #include <rtems.h>
0022 #include <rtems/console.h>
0023
0024 #include "tmacros.h"
0025
0026 const char rtems_test_name[] = "SPCONSOLE 1";
0027
0028 #define LINE_LEN 79
0029
0030 static const char n_line[LINE_LEN + 1] =
0031 "nNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNnNn";
0032
0033 static const char b_line[LINE_LEN + 1] =
0034 "bBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBb";
0035
0036 static const char e_line[LINE_LEN + 1] =
0037 "eEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEe";
0038
0039 typedef struct {
0040 speed_t speed;
0041 uint32_t value;
0042 const char *msg;
0043 } speed_desc;
0044
0045 static const speed_desc speeds[] = {
0046 { .speed = B9600, .value = 9600, .msg = "9600 8N1" },
0047 { .speed = B19200, .value = 19200, .msg = "19200 8N1" },
0048 { .speed = B38400, .value = 38400, .msg = "38400 8N1" },
0049 { .speed = B57600, .value = 57600, .msg = "57600 8N1" },
0050 { .speed = B115200, .value = 115200, .msg = "115200 8N1" }
0051 };
0052
0053 #define BITS_PER_CHAR 10
0054
0055 typedef struct {
0056 int fd;
0057 struct termios saved_term;
0058 struct termios term;
0059 char buf[9600 / BITS_PER_CHAR];
0060 rtems_id done;
0061 } test_context;
0062
0063 static test_context test_instance;
0064
0065 static void drain(test_context *ctx)
0066 {
0067 int rv;
0068
0069 rv = tcdrain(ctx->fd);
0070 rtems_test_assert(rv == 0);
0071
0072
0073 rv = usleep(200000);
0074 rtems_test_assert(rv == 0);
0075 }
0076
0077 static void do_begin(test_context *ctx, const char *msg)
0078 {
0079 puts(n_line);
0080 puts(msg);
0081 puts(b_line);
0082 drain(ctx);
0083 }
0084
0085 static void do_end(test_context *ctx)
0086 {
0087 int rv;
0088
0089 drain(ctx);
0090
0091 rv = cfsetspeed(&ctx->term, cfgetospeed(&ctx->saved_term));
0092 rtems_test_assert(rv == 0);
0093
0094 rv = tcsetattr(ctx->fd, TCSANOW, &ctx->term);
0095 rtems_test_assert(rv == 0);
0096
0097 puts("");
0098 puts(e_line);
0099 }
0100
0101 static void test_steps_one_task(test_context *ctx, char c)
0102 {
0103 char buf[128];
0104 size_t i;
0105
0106 for (i = 0; i < RTEMS_ARRAY_SIZE(buf); ++i) {
0107 size_t r;
0108 char *p;
0109
0110 buf[i] = '\n';
0111
0112 r = i;
0113 p = buf;
0114 while (r > 0) {
0115 ssize_t m;
0116
0117 m = write(ctx->fd, p, r);
0118 rtems_test_assert(m > 0);
0119
0120 r -= (size_t) m;
0121 p += (size_t) m;
0122 }
0123
0124 if (i > 1) {
0125 buf[i - 2] = c;
0126 }
0127
0128 if (i > 0) {
0129 buf[i - 1] = '\r';
0130 }
0131 }
0132 }
0133
0134 static void test_speeds(test_context *ctx)
0135 {
0136 size_t i;
0137
0138 for (i = 0; i < RTEMS_ARRAY_SIZE(speeds); ++i) {
0139 uint64_t t0;
0140 uint64_t t1;
0141 size_t n;
0142 size_t r;
0143 int rv;
0144
0145 do_begin(ctx, speeds[i].msg);
0146
0147 rv = cfsetspeed(&ctx->term, speeds[i].speed);
0148 rtems_test_assert(rv == 0);
0149
0150 rv = tcsetattr(ctx->fd, TCSANOW, &ctx->term);
0151 rtems_test_assert(rv == 0);
0152
0153 n = speeds[i].value / BITS_PER_CHAR;
0154 r = n;
0155 t0 = rtems_clock_get_uptime_nanoseconds();
0156
0157 while (r > 0) {
0158 ssize_t m;
0159
0160 m = write(ctx->fd, ctx->buf, MIN(sizeof(ctx->buf), r));
0161 rtems_test_assert(m > 0);
0162
0163 r -= (size_t) m;
0164 }
0165
0166 rv = tcdrain(ctx->fd);
0167 rtems_test_assert(rv == 0);
0168
0169 t1 = rtems_clock_get_uptime_nanoseconds();
0170
0171 do_end(ctx);
0172
0173 printf("transmitted chars: %zu\n", n);
0174 printf(
0175 "transmitted bits (1 start, 8 data, 1 stop): %zu\n",
0176 n * BITS_PER_CHAR
0177 );
0178
0179 printf("actual transmit time: %10" PRIu64 "ns\n", t1 - t0);
0180 printf("expected transmit time: 1000000000ns\n");
0181 }
0182 }
0183
0184 static void task(test_context *ctx, char c)
0185 {
0186 rtems_status_code sc;
0187
0188 test_steps_one_task(ctx, c);
0189
0190 sc = rtems_semaphore_release(ctx->done);
0191 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0192
0193 rtems_task_suspend(RTEMS_SELF);
0194 }
0195
0196 static void task_y(rtems_task_argument arg)
0197 {
0198 test_context *ctx;
0199
0200 ctx = (test_context *) arg;
0201 task(ctx, 'Y');
0202 }
0203
0204 static void task_z(rtems_task_argument arg)
0205 {
0206 test_context *ctx;
0207
0208 ctx = (test_context *) arg;
0209 task(ctx, 'z');
0210 }
0211
0212 static void test(test_context *ctx)
0213 {
0214 int rv;
0215 rtems_status_code sc;
0216 rtems_id y;
0217 rtems_id z;
0218
0219 sc = rtems_semaphore_create(
0220 rtems_build_name('D', 'O', 'N', 'E'),
0221 0,
0222 RTEMS_COUNTING_SEMAPHORE,
0223 0,
0224 &ctx->done
0225 );
0226 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0227
0228 ctx->fd = open(CONSOLE_DEVICE_NAME, O_RDWR);
0229 rtems_test_assert(ctx->fd >= 0);
0230
0231 rv = tcgetattr(ctx->fd, &ctx->saved_term);
0232 rtems_test_assert(rv == 0);
0233
0234 ctx->term = ctx->saved_term;
0235 cfmakeraw(&ctx->term);
0236
0237 rv = tcsetattr(ctx->fd, TCSANOW, &ctx->term);
0238 rtems_test_assert(rv == 0);
0239
0240 memset(&ctx->buf, 'd', sizeof(ctx->buf));
0241
0242 do_begin(ctx, "steps one task");
0243 test_steps_one_task(ctx, 'x');
0244 do_end(ctx);
0245
0246 do_begin(ctx, "steps three tasks");
0247
0248 sc = rtems_task_create(
0249 rtems_build_name(' ', ' ', ' ', 'Y'),
0250 1,
0251 RTEMS_MINIMUM_STACK_SIZE,
0252 RTEMS_DEFAULT_MODES,
0253 RTEMS_DEFAULT_ATTRIBUTES,
0254 &y
0255 );
0256 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0257
0258 sc = rtems_task_start(y, task_y, (rtems_task_argument) ctx);
0259 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0260
0261 sc = rtems_task_create(
0262 rtems_build_name(' ', ' ', ' ', 'Z'),
0263 1,
0264 RTEMS_MINIMUM_STACK_SIZE,
0265 RTEMS_DEFAULT_MODES,
0266 RTEMS_DEFAULT_ATTRIBUTES,
0267 &z
0268 );
0269 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0270
0271 sc = rtems_task_start(z, task_z, (rtems_task_argument) ctx);
0272 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0273
0274 test_steps_one_task(ctx, 'x');
0275
0276 sc = rtems_semaphore_obtain(ctx->done, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
0277 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0278
0279 sc = rtems_semaphore_obtain(ctx->done, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
0280 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0281
0282 do_end(ctx);
0283
0284 test_speeds(ctx);
0285
0286 rv = close(ctx->fd);
0287 rtems_test_assert(rv == 0);
0288
0289 sc = rtems_task_delete(y);
0290 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0291
0292 sc = rtems_task_delete(z);
0293 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0294
0295 sc = rtems_semaphore_delete(ctx->done);
0296 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0297 }
0298
0299 static void Init(rtems_task_argument arg)
0300 {
0301 TEST_BEGIN();
0302
0303 rtems_print_printer_fprintf_putc(&rtems_test_printer);
0304 test(&test_instance);
0305
0306 TEST_END();
0307 rtems_test_exit(0);
0308 }
0309
0310 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
0311 #define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
0312
0313 #define CONFIGURE_MAXIMUM_FILE_DESCRIPTORS 4
0314
0315 #define CONFIGURE_MAXIMUM_TASKS 3
0316 #define CONFIGURE_MAXIMUM_SEMAPHORES 1
0317
0318 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
0319
0320 #define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES
0321 #define CONFIGURE_INIT_TASK_ATTRIBUTES RTEMS_FLOATING_POINT
0322
0323 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
0324
0325 #define CONFIGURE_INIT
0326
0327 #include <rtems/confdefs.h>