diff --git a/drivers/serial/arm/uart.c b/drivers/serial/arm/uart.c index ccf305532..3ee9f5edc 100644 --- a/drivers/serial/arm/uart.c +++ b/drivers/serial/arm/uart.c @@ -51,7 +51,7 @@ static void tx_provide(void) bool transferred = false; while (reprocess) { char c; - while (!(uart_regs->fr & PL011_FR_TXFF) && !serial_dequeue(&tx_queue_handle, &tx_queue_handle.queue->head, &c)) { + while (!(uart_regs->fr & PL011_FR_TXFF) && !serial_dequeue(&tx_queue_handle, NULL, &c)) { uart_regs->dr = (uint32_t)c; transferred = true; } @@ -85,7 +85,7 @@ static void rx_return(void) while (reprocess) { while (!(uart_regs->fr & PL011_FR_RXFE) && !serial_queue_full(&rx_queue_handle, rx_queue_handle.queue->tail)) { char c = (char)(uart_regs->dr & PL011_DR_DATA_MASK); - serial_enqueue(&rx_queue_handle, &rx_queue_handle.queue->tail, c); + serial_enqueue(&rx_queue_handle, NULL, c); enqueued = true; } @@ -149,7 +149,7 @@ static void uart_setup(void) uart_regs->lcr_h |= PL011_LCR_PARTY_EN; /* Enable receive interrupts when FIFO level exceeds 1/8 or after 32 ticks */ -#if !SERIAL_TX_ONLY +#if SERIAL_NUM_RX_CLIENTS > 0 uart_regs->ifls &= ~(PL011_IFLS_RX_MASK << PL011_IFLS_RX_SHFT); uart_regs->imsc |= (PL011_IMSC_RX_TIMEOUT | PL011_IMSC_RX_INT); #endif @@ -165,7 +165,7 @@ static void uart_setup(void) uart_regs->tcr |= PL011_CR_TX_EN; /* Enable receive */ -#if !SERIAL_TX_ONLY +#if SERIAL_NUM_RX_CLIENTS > 0 uart_regs->tcr |= PL011_CR_RX_EN; #endif } @@ -174,7 +174,7 @@ void init(void) { uart_setup(); -#if !SERIAL_TX_ONLY +#if SERIAL_NUM_RX_CLIENTS > 0 serial_queue_init(&rx_queue_handle, rx_queue, SERIAL_RX_DATA_REGION_CAPACITY_DRIV, rx_data); #endif serial_queue_init(&tx_queue_handle, tx_queue, SERIAL_TX_DATA_REGION_CAPACITY_DRIV, tx_data); diff --git a/drivers/serial/imx/uart.c b/drivers/serial/imx/uart.c index 1466f9665..4af4464e0 100644 --- a/drivers/serial/imx/uart.c +++ b/drivers/serial/imx/uart.c @@ -52,8 +52,7 @@ static void tx_provide(void) bool transferred = false; while (reprocess) { char c; - while (!(uart_regs->ts & UART_TST_TX_FIFO_FULL) - && !serial_dequeue(&tx_queue_handle, &tx_queue_handle.queue->head, &c)) { + while (!(uart_regs->ts & UART_TST_TX_FIFO_FULL) && !serial_dequeue(&tx_queue_handle, NULL, &c)) { uart_regs->txd = (uint32_t)c; transferred = true; } @@ -87,7 +86,7 @@ static void rx_return(void) while (reprocess) { while (!(uart_regs->ts & UART_TST_RX_FIFO_EMPTY) && !serial_queue_full(&rx_queue_handle, rx_queue_handle.queue->tail)) { char c = (char) uart_regs->rxd; - serial_enqueue(&rx_queue_handle, &rx_queue_handle.queue->tail, c); + serial_enqueue(&rx_queue_handle, NULL, c); enqueued = true; } @@ -141,7 +140,7 @@ static void uart_setup(void) /* Enable transmit and receive */ uart_regs->cr2 |= UART_CR2_TX_EN; -#if !SERIAL_TX_ONLY +#if SERIAL_NUM_RX_CLIENTS > 0 uart_regs->cr2 |= UART_CR2_RX_EN; #endif @@ -161,7 +160,7 @@ static void uart_setup(void) uint32_t fcr = uart_regs->fcr; /* Enable receive interrupts every byte */ -#if !SERIAL_TX_ONLY +#if SERIAL_NUM_RX_CLIENTS > 0 fcr &= ~UART_FCR_RXTL_MASK; fcr |= (1 << UART_FCR_RXTL_SHFT); #endif @@ -171,7 +170,7 @@ static void uart_setup(void) fcr |= (2 << UART_FCR_TXTL_SHFT); uart_regs->fcr = fcr; -#if !SERIAL_TX_ONLY +#if SERIAL_NUM_RX_CLIENTS > 0 uart_regs->cr1 |= UART_CR1_RX_READY_INT; #endif } @@ -180,7 +179,7 @@ void init(void) { uart_setup(); -#if !SERIAL_TX_ONLY +#if SERIAL_NUM_RX_CLIENTS > 0 serial_queue_init(&rx_queue_handle, rx_queue, SERIAL_RX_DATA_REGION_CAPACITY_DRIV, rx_data); #endif serial_queue_init(&tx_queue_handle, tx_queue, SERIAL_TX_DATA_REGION_CAPACITY_DRIV, tx_data); diff --git a/drivers/serial/meson/uart.c b/drivers/serial/meson/uart.c index 8ccb78883..043495761 100644 --- a/drivers/serial/meson/uart.c +++ b/drivers/serial/meson/uart.c @@ -76,7 +76,7 @@ static void tx_provide(void) bool transferred = false; while (reprocess) { char c; - while (!(uart_regs->sr & AML_UART_TX_FULL) && !serial_dequeue(&tx_queue_handle, &tx_queue_handle.queue->head, &c)) { + while (!(uart_regs->sr & AML_UART_TX_FULL) && !serial_dequeue(&tx_queue_handle, NULL, &c)) { uart_regs->wfifo = (uint32_t)c; transferred = true; } @@ -110,7 +110,7 @@ static void rx_return(void) while (reprocess) { while (!(uart_regs->sr & AML_UART_RX_EMPTY) && !serial_queue_full(&rx_queue_handle, rx_queue_handle.queue->tail)) { char c = (char) uart_regs->rfifo; - serial_enqueue(&rx_queue_handle, &rx_queue_handle.queue->tail, c); + serial_enqueue(&rx_queue_handle, NULL, c); enqueued = true; } @@ -186,7 +186,7 @@ static void uart_setup(void) uint32_t irqc = uart_regs->irqc; /* Enable receive interrupts every byte */ -#if !SERIAL_TX_ONLY +#if SERIAL_NUM_RX_CLIENTS > 0 irqc &= ~AML_UART_RECV_IRQ_MASK; irqc |= AML_UART_RECV_IRQ(1); cr |= (AML_UART_RX_INT_EN | AML_UART_RX_EN); @@ -205,7 +205,7 @@ void init(void) { uart_setup(); -#if !SERIAL_TX_ONLY +#if SERIAL_NUM_RX_CLIENTS > 0 serial_queue_init(&rx_queue_handle, rx_queue, SERIAL_RX_DATA_REGION_CAPACITY_DRIV, rx_data); #endif serial_queue_init(&tx_queue_handle, tx_queue, SERIAL_TX_DATA_REGION_CAPACITY_DRIV, tx_data); diff --git a/drivers/serial/snps/uart.c b/drivers/serial/snps/uart.c index 7476afb01..58ce71285 100644 --- a/drivers/serial/snps/uart.c +++ b/drivers/serial/snps/uart.c @@ -57,8 +57,7 @@ static void tx_provide(void) while (reprocess) { char c; - while ((*REG_PTR(UART_LSR) & UART_LSR_THRE) - && !serial_dequeue(&tx_queue_handle, &tx_queue_handle.queue->head, &c)) { + while ((*REG_PTR(UART_LSR) & UART_LSR_THRE) && !serial_dequeue(&tx_queue_handle, NULL, &c)) { *REG_PTR(UART_THR) = c; transferred = true; } @@ -95,7 +94,7 @@ static void rx_return(void) while ((*REG_PTR(UART_LSR) & UART_LSR_DR) && !serial_queue_full(&rx_queue_handle, rx_queue_handle.queue->tail)) { char c = *REG_PTR(UART_RBR); - int err = serial_enqueue(&rx_queue_handle, &rx_queue_handle.queue->tail, c); + int err = serial_enqueue(&rx_queue_handle, NULL, c); assert(!err); enqueued = true; } @@ -169,7 +168,7 @@ void init(void) /* Enable both Recieve Data Available and Transmit Holding Register Empty IRQs. */ *REG_PTR(UART_IER) = (UART_IER_ERBFI | UART_IER_ETBEI); -#if !SERIAL_TX_ONLY +#if SERIAL_NUM_RX_CLIENTS > 0 serial_queue_init(&rx_queue_handle, rx_queue, SERIAL_RX_DATA_REGION_CAPACITY_DRIV, rx_data); #endif serial_queue_init(&tx_queue_handle, tx_queue, SERIAL_TX_DATA_REGION_CAPACITY_DRIV, tx_data); diff --git a/drivers/serial/virtio/console.c b/drivers/serial/virtio/console.c index cf6a94806..28c77f762 100644 --- a/drivers/serial/virtio/console.c +++ b/drivers/serial/virtio/console.c @@ -111,8 +111,7 @@ static void tx_provide(void) bool transferred = false; while (reprocess) { char c; - while (!virtio_avail_full_tx(&tx_virtq) - && !serial_dequeue(&tx_queue_handle, &tx_queue_handle.queue->head, &c)) { + while (!virtio_avail_full_tx(&tx_virtq) && !serial_dequeue(&tx_queue_handle, NULL, &c)) { /* First, allocate somewhere to put the character */ uint32_t char_idx = -1; @@ -250,7 +249,7 @@ static void rx_return(void) assert(!(pkt.flags & VIRTQ_DESC_F_NEXT)); uint32_t char_idx = addr - virtio_rx_char_paddr; - serial_enqueue(&rx_queue_handle, &rx_queue_handle.queue->tail, virtio_rx_char[char_idx]); + serial_enqueue(&rx_queue_handle, NULL, virtio_rx_char[char_idx]); /* Free the packet descriptor */ int err = ialloc_free(&rx_ialloc_desc, pkt_used.id); @@ -417,7 +416,7 @@ void init() console_setup(); -#if !SERIAL_TX_ONLY +#if SERIAL_NUM_RX_CLIENTS > 0 serial_queue_init(&rx_queue_handle, rx_queue, SERIAL_RX_DATA_REGION_CAPACITY_DRIV, rx_data); #endif serial_queue_init(&tx_queue_handle, tx_queue, SERIAL_TX_DATA_REGION_CAPACITY_DRIV, tx_data); @@ -442,4 +441,4 @@ void notified(microkit_channel ch) LOG_DRIVER_ERR("received notification on unexpected channel: %u\n", ch); break; } -} \ No newline at end of file +} diff --git a/examples/echo_server/include/serial_config/serial_config.h b/examples/echo_server/include/serial_config/serial_config.h index cd0e744a0..1e5ff1e61 100644 --- a/examples/echo_server/include/serial_config/serial_config.h +++ b/examples/echo_server/include/serial_config/serial_config.h @@ -10,21 +10,15 @@ #include #include -/* Number of clients that can be connected to the serial server. */ -#define SERIAL_NUM_CLIENTS 3 +/* Number of clients capable of transmission. */ +#define SERIAL_NUM_TX_CLIENTS 3 -/* Only support transmission and not receive. */ -#define SERIAL_TX_ONLY 1 +/* Number of clients capable of reception. */ +#define SERIAL_NUM_RX_CLIENTS 0 /* Associate a colour with each client's output. */ #define SERIAL_WITH_COLOUR 1 -/* Control character to switch input stream - ctrl \. To input character input twice. */ -#define SERIAL_SWITCH_CHAR 28 - -/* Control character to terminate client number input. */ -#define SERIAL_TERMINATE_NUM '\r' - /* Default baud rate of the uart device */ #define UART_DEFAULT_BAUD 115200 diff --git a/examples/serial/include/serial_config/serial_config.h b/examples/serial/include/serial_config/serial_config.h index eeb1f8a7b..1a6694c8e 100644 --- a/examples/serial/include/serial_config/serial_config.h +++ b/examples/serial/include/serial_config/serial_config.h @@ -10,23 +10,24 @@ #include #include -#define SERIAL_NUM_CLIENTS 2 +/* Number of clients capable of transmission. */ +#define SERIAL_NUM_TX_CLIENTS 2 -/* Only support transmission and not receive. */ -#define SERIAL_TX_ONLY 0 +/* Number of clients capable of reception. */ +#define SERIAL_NUM_RX_CLIENTS 2 /* Associate a colour with each client's output. */ #define SERIAL_WITH_COLOUR 1 +/* Default baud rate of the uart device */ +#define UART_DEFAULT_BAUD 115200 + /* Control character to switch input stream - ctrl \. To input character input twice. */ #define SERIAL_SWITCH_CHAR 28 /* Control character to terminate client number input. */ #define SERIAL_TERMINATE_NUM '\r' -/* Default baud rate of the uart device */ -#define UART_DEFAULT_BAUD 115200 - /* String to be printed to start console input */ #define SERIAL_CONSOLE_BEGIN_STRING "Begin input\n" #define SERIAL_CONSOLE_BEGIN_STRING_LEN 12 diff --git a/examples/serial/serial_server.c b/examples/serial/serial_server.c index 2a49f2b3d..f2b7f66ed 100644 --- a/examples/serial/serial_server.c +++ b/examples/serial/serial_server.c @@ -35,7 +35,7 @@ void notified(microkit_channel ch) bool reprocess = true; char c; while (reprocess) { - while (!serial_dequeue(&rx_queue_handle, &rx_queue_handle.queue->head, &c)) { + while (!serial_dequeue(&rx_queue_handle, NULL, &c)) { if (c == '\r') { sddf_putchar_unbuffered('\\'); sddf_putchar_unbuffered('r'); diff --git a/include/sddf/serial/queue.h b/include/sddf/serial/queue.h index 3f3a97752..37848ffd9 100644 --- a/include/sddf/serial/queue.h +++ b/include/sddf/serial/queue.h @@ -62,6 +62,7 @@ static inline int serial_queue_full(serial_queue_handle_t *queue_handle, uint32_ * @param queue_handle queue to enqueue into. * @param local_tail address of the tail to be incremented. This allows for clients to * enqueue multiple characters before making the changes visible. + * Leave NULL to increment shared queue tail. * @param character character to be enqueued. * * @return -1 when queue is empty, 0 on success. @@ -69,12 +70,14 @@ static inline int serial_queue_full(serial_queue_handle_t *queue_handle, uint32_ static inline int serial_enqueue(serial_queue_handle_t *queue_handle, uint32_t *local_tail, char character) { - if (serial_queue_full(queue_handle, *local_tail)) { + uint32_t *tail = (local_tail == NULL) ? &queue_handle->queue->tail : local_tail; + + if (serial_queue_full(queue_handle, *tail)) { return -1; } - queue_handle->data_region[*local_tail % queue_handle->capacity] = character; - (*local_tail)++; + queue_handle->data_region[*tail % queue_handle->capacity] = character; + (*tail)++; return 0; } @@ -85,6 +88,7 @@ static inline int serial_enqueue(serial_queue_handle_t *queue_handle, uint32_t * * @param queue_handle queue to dequeue from. * @param local_head address of the head to be incremented. This allows for clients to * dequeue multiple characters before making the changes visible. + * Leave NULL to increment shared queue head. * @param character character to copy into. * * @return -1 when queue is empty, 0 on success. @@ -92,12 +96,14 @@ static inline int serial_enqueue(serial_queue_handle_t *queue_handle, uint32_t * static inline int serial_dequeue(serial_queue_handle_t *queue_handle, uint32_t *local_head, char *character) { - if (serial_queue_empty(queue_handle, *local_head)) { + uint32_t *head = (local_head == NULL) ? &queue_handle->queue->head : local_head; + + if (serial_queue_empty(queue_handle, *head)) { return -1; } - *character = queue_handle->data_region[*local_head % queue_handle->capacity]; - (*local_head)++; + *character = queue_handle->data_region[*head % queue_handle->capacity]; + (*head)++; return 0; } diff --git a/serial/components/virt_rx.c b/serial/components/virt_rx.c index 4d107d1b5..0b153aaac 100644 --- a/serial/components/virt_rx.c +++ b/serial/components/virt_rx.c @@ -21,7 +21,7 @@ char *rx_data_drv; char *rx_data_cli0; serial_queue_handle_t rx_queue_handle_drv; -serial_queue_handle_t rx_queue_handle_cli[SERIAL_NUM_CLIENTS]; +serial_queue_handle_t rx_queue_handle_cli[SERIAL_NUM_RX_CLIENTS]; #define MAX_CLI_BASE_10 4 typedef enum mode {normal, switched, number} mode_t; @@ -45,7 +45,7 @@ void rx_return(void) uint32_t local_tail = rx_queue_handle_cli[current_client].queue->tail; char c = '\0'; while (reprocess) { - while (!serial_dequeue(&rx_queue_handle_drv, &rx_queue_handle_drv.queue->head, &c)) { + while (!serial_dequeue(&rx_queue_handle_drv, NULL, &c)) { switch (current_mode) { case normal: switch (c) { @@ -78,7 +78,7 @@ void rx_return(void) default: if (c == SERIAL_TERMINATE_NUM) { int input_number = sddf_atoi(next_client); - if (input_number >= 0 && input_number < SERIAL_NUM_CLIENTS) { + if (input_number >= 0 && input_number < SERIAL_NUM_RX_CLIENTS) { if (transferred && serial_require_producer_signal(&rx_queue_handle_cli[current_client])) { serial_update_visible_tail(&rx_queue_handle_cli[current_client], local_tail); serial_cancel_producer_signal(&rx_queue_handle_cli[current_client]); diff --git a/serial/components/virt_tx.c b/serial/components/virt_tx.c index b57200771..4b4f99e93 100644 --- a/serial/components/virt_tx.c +++ b/serial/components/virt_tx.c @@ -41,17 +41,17 @@ const char *colours[] = { #define COLOUR_END "\x1b[0m" #define COLOUR_END_LEN 4 -char *client_names[SERIAL_NUM_CLIENTS]; +char *client_names[SERIAL_NUM_TX_CLIENTS]; #endif serial_queue_handle_t tx_queue_handle_drv; -serial_queue_handle_t tx_queue_handle_cli[SERIAL_NUM_CLIENTS]; +serial_queue_handle_t tx_queue_handle_cli[SERIAL_NUM_TX_CLIENTS]; -#define TX_PENDING_LEN (SERIAL_NUM_CLIENTS + 1) +#define TX_PENDING_LEN (SERIAL_NUM_TX_CLIENTS + 1) typedef struct tx_pending { uint32_t queue[TX_PENDING_LEN]; - bool clients_pending[SERIAL_NUM_CLIENTS]; + bool clients_pending[SERIAL_NUM_TX_CLIENTS]; uint32_t head; uint32_t tail; } tx_pending_t; @@ -71,7 +71,7 @@ static void tx_pending_push(uint32_t client) } /* Ensure the pending queue is not already full */ - assert(tx_pending_length() < SERIAL_NUM_CLIENTS); + assert(tx_pending_length() < SERIAL_NUM_TX_CLIENTS); tx_pending.queue[tx_pending.tail] = client; tx_pending.clients_pending[client] = true; @@ -134,7 +134,7 @@ void tx_return(void) } uint32_t client; - bool notify_client[SERIAL_NUM_CLIENTS] = {false}; + bool notify_client[SERIAL_NUM_TX_CLIENTS] = { false }; bool transferred = false; for (uint32_t req = 0; req < num_pending_tx; req++) { tx_pending_pop(&client); @@ -160,7 +160,7 @@ void tx_return(void) microkit_notify(DRIVER_CH); } - for (uint32_t client = 0; client < SERIAL_NUM_CLIENTS; client++) { + for (uint32_t client = 0; client < SERIAL_NUM_TX_CLIENTS; client++) { if (notify_client[client] && serial_require_consumer_signal(&tx_queue_handle_cli[client])) { serial_cancel_consumer_signal(&tx_queue_handle_cli[client]); microkit_notify(client + CLIENT_OFFSET); @@ -170,7 +170,7 @@ void tx_return(void) void tx_provide(microkit_channel ch) { - if (ch > SERIAL_NUM_CLIENTS) { + if (ch > SERIAL_NUM_TX_CLIENTS) { sddf_dprintf("VIRT_TX|LOG: Received notification from unknown channel %u\n", ch); return; } @@ -206,7 +206,7 @@ void init(void) serial_queue_init(&tx_queue_handle_drv, tx_queue_drv, SERIAL_TX_DATA_REGION_CAPACITY_DRIV, tx_data_drv); serial_virt_queue_init_sys(microkit_name, tx_queue_handle_cli, tx_queue_cli0, tx_data_cli0); -#if !SERIAL_TX_ONLY +#if SERIAL_NUM_RX_CLIENTS > 0 /* Print a deterministic string to allow console input to begin */ sddf_memcpy(tx_queue_handle_drv.data_region, SERIAL_CONSOLE_BEGIN_STRING, SERIAL_CONSOLE_BEGIN_STRING_LEN); serial_update_visible_tail(&tx_queue_handle_drv, SERIAL_CONSOLE_BEGIN_STRING_LEN); @@ -215,7 +215,7 @@ void init(void) #if SERIAL_WITH_COLOUR serial_channel_names_init(client_names); - for (uint32_t i = 0; i < SERIAL_NUM_CLIENTS; i++) { + for (uint32_t i = 0; i < SERIAL_NUM_TX_CLIENTS; i++) { sddf_dprintf("%s'%s' is client %u%s\n", colours[i % ARRAY_SIZE(colours)], client_names[i], i, COLOUR_END); } #endif diff --git a/util/putchar_serial.c b/util/putchar_serial.c index 4da61d927..ad8140e84 100644 --- a/util/putchar_serial.c +++ b/util/putchar_serial.c @@ -58,4 +58,4 @@ void serial_putchar_init(microkit_channel serial_tx_ch, serial_queue_handle_t *s tx_ch = serial_tx_ch; tx_queue_handle = serial_tx_queue_handle; local_tail = serial_tx_queue_handle->queue->tail; -} \ No newline at end of file +}