Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:57

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSBSPsPowerPCQorIQUartBridge
0007  *
0008  * @brief UART bridge master implementation.
0009  */
0010 
0011 /*
0012  * Copyright (C) 2011, 2015 embedded brains GmbH & Co. KG
0013  *
0014  * Redistribution and use in source and binary forms, with or without
0015  * modification, are permitted provided that the following conditions
0016  * are met:
0017  * 1. Redistributions of source code must retain the above copyright
0018  *    notice, this list of conditions and the following disclaimer.
0019  * 2. Redistributions in binary form must reproduce the above copyright
0020  *    notice, this list of conditions and the following disclaimer in the
0021  *    documentation and/or other materials provided with the distribution.
0022  *
0023  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0024  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0025  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0026  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0027  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0028  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0029  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0030  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0031  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0032  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0033  * POSSIBILITY OF SUCH DAMAGE.
0034  */
0035 
0036 #include <sys/stat.h>
0037 #include <assert.h>
0038 #include <fcntl.h>
0039 #include <unistd.h>
0040 #include <termios.h>
0041 
0042 #include <bspopts.h>
0043 #include <bsp/uart-bridge.h>
0044 #include <rtems/termiostypes.h>
0045 
0046 #define TRANSMIT_EVENT RTEMS_EVENT_13
0047 
0048 static void serial_settings(int fd)
0049 {
0050   struct termios term;
0051   int rv = tcgetattr(fd, &term);
0052   assert(rv == 0);
0053 
0054   term.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
0055   term.c_oflag &= ~OPOST;
0056   term.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
0057   term.c_cflag &= ~(CSIZE | PARENB);
0058   term.c_cflag |= CS8;
0059 
0060   term.c_cc [VMIN] = 1;
0061   term.c_cc [VTIME] = 1;
0062 
0063   rv = tcsetattr(fd, TCSANOW, &term);
0064   assert(rv == 0);
0065 }
0066 
0067 static void uart_bridge_master_service(intercom_packet *packet, void *arg)
0068 {
0069   rtems_status_code sc = RTEMS_SUCCESSFUL;
0070   uart_bridge_master_context *ctx = arg;
0071 
0072   sc = rtems_chain_append_with_notification(
0073     &ctx->transmit_fifo,
0074     &packet->glue.node,
0075     ctx->transmit_task,
0076     TRANSMIT_EVENT
0077   );
0078   assert(sc == RTEMS_SUCCESSFUL);
0079 }
0080 
0081 static void receive_task(rtems_task_argument arg)
0082 {
0083   uart_bridge_master_context *ctx = (uart_bridge_master_context *) arg;
0084   intercom_type type = ctx->type;
0085 
0086   int fd = open(ctx->device_path, O_RDONLY);
0087   assert(fd >= 0);
0088 
0089   serial_settings(fd);
0090 
0091   while (true) {
0092     intercom_packet *packet = qoriq_intercom_allocate_packet(
0093       type,
0094       INTERCOM_SIZE_64
0095     );
0096     ssize_t in = read(fd, packet->data, packet->size - 1);
0097     if (in > 0) {
0098       packet->size = (size_t) in;
0099       qoriq_intercom_send_packet(QORIQ_UART_BRIDGE_SLAVE_CORE, packet);
0100     } else {
0101       qoriq_intercom_free_packet(packet);
0102     }
0103   }
0104 }
0105 
0106 static void transmit_task(rtems_task_argument arg)
0107 {
0108   rtems_status_code sc = RTEMS_SUCCESSFUL;
0109   uart_bridge_master_context *ctx = (uart_bridge_master_context *) arg;
0110   rtems_chain_control *fifo = &ctx->transmit_fifo;
0111 
0112   int fd = open(ctx->device_path, O_WRONLY);
0113   assert(fd >= 0);
0114 
0115   serial_settings(fd);
0116 
0117   while (true) {
0118     intercom_packet *packet = NULL;
0119     sc = rtems_chain_get_with_wait(
0120       fifo,
0121       TRANSMIT_EVENT,
0122       RTEMS_NO_TIMEOUT,
0123       (rtems_chain_node **) &packet
0124     );
0125     assert(sc == RTEMS_SUCCESSFUL);
0126     write(fd, packet->data, packet->size);
0127     qoriq_intercom_free_packet(packet);
0128   }
0129 }
0130 
0131 static rtems_id create_task(
0132   char name,
0133   rtems_task_entry entry,
0134   uart_bridge_master_context *ctx
0135 )
0136 {
0137   rtems_status_code sc = RTEMS_SUCCESSFUL;
0138   rtems_id task = RTEMS_ID_NONE;
0139   char index = (char) ('0' + ctx->type - INTERCOM_TYPE_UART_0);
0140 
0141   sc = rtems_task_create(
0142     rtems_build_name('U', 'B', name, index),
0143     QORIQ_UART_BRIDGE_TASK_PRIORITY,
0144     0,
0145     RTEMS_DEFAULT_MODES,
0146     RTEMS_DEFAULT_ATTRIBUTES,
0147     &task
0148   );
0149   assert(sc == RTEMS_SUCCESSFUL);
0150 
0151   sc = rtems_task_start(
0152     task,
0153     entry,
0154     (rtems_task_argument) ctx
0155   );
0156   assert(sc == RTEMS_SUCCESSFUL);
0157 
0158   return task;
0159 }
0160 
0161 bool qoriq_uart_bridge_master_probe(rtems_termios_device_context *base)
0162 {
0163   uart_bridge_master_context *ctx = (uart_bridge_master_context *) base;
0164   intercom_type type = ctx->type;
0165 
0166   qoriq_intercom_service_install(type, uart_bridge_master_service, ctx);
0167   create_task('R', receive_task, ctx);
0168   ctx->transmit_task = create_task('T', transmit_task, ctx);
0169 
0170   return true;
0171 }
0172 
0173 static bool first_open(
0174   struct rtems_termios_tty *tty,
0175   rtems_termios_device_context *base,
0176   struct termios *term,
0177   rtems_libio_open_close_args_t *args
0178 )
0179 {
0180   return false;
0181 }
0182 
0183 static bool set_attributes(
0184   rtems_termios_device_context *base,
0185   const struct termios *term
0186 )
0187 {
0188   return false;
0189 }
0190 
0191 const rtems_termios_device_handler qoriq_uart_bridge_master = {
0192   .first_open = first_open,
0193   .set_attributes = set_attributes,
0194   .mode = TERMIOS_POLLED
0195 };