Created
February 11, 2019 04:35
-
-
Save LastZactionHero/de749d0c17322c4ec882e79b0cf09278 to your computer and use it in GitHub Desktop.
Buffered Uart TX
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <pthread.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
pthread_mutex_t tx_queue_lock; | |
typedef struct buffered_tx { | |
char *string; | |
int tx_posn; | |
struct buffered_tx *next; | |
} buffered_tx_t; | |
buffered_tx_t *tx_queue = NULL; | |
// ------------------------------------------------ | |
// UART Status | |
#define TX_BUFFER_LEN 16 | |
char tx_buffer[TX_BUFFER_LEN]; | |
int bufferReadIdx = 0; | |
int bufferFillIdx = 0; | |
int txBufferFull() { | |
return ((bufferFillIdx + 1) % TX_BUFFER_LEN) == bufferReadIdx; | |
} | |
int txBufferEmpty() { | |
return bufferFillIdx == bufferReadIdx; | |
} | |
void txAddToBuffer(char c) { | |
tx_buffer[bufferFillIdx] = c; | |
bufferFillIdx = (bufferFillIdx + 1) % TX_BUFFER_LEN; | |
} | |
// ------------------------------------------------ | |
void queueTx(buffered_tx_t *tx) { | |
if (tx == NULL) { return; } | |
int strLen = strlen(tx->string); | |
// Transmit until buffer is full | |
while (tx != NULL && tx->tx_posn < strLen && !txBufferFull()) { | |
txAddToBuffer(tx->string[tx->tx_posn++]); | |
} | |
// End of this message: Move on to the next one if available | |
pthread_mutex_lock(&tx_queue_lock); | |
if (tx->tx_posn == strLen) { | |
tx_queue = tx->next; | |
free(tx->string); | |
free(tx); | |
} | |
pthread_mutex_unlock(&tx_queue_lock); | |
return; | |
} | |
void *uart_handler(void *arg) { | |
while (1) { | |
while (!txBufferEmpty()) { | |
printf("%c", tx_buffer[bufferReadIdx]); | |
bufferReadIdx = (bufferReadIdx + 1)% TX_BUFFER_LEN; | |
if (txBufferEmpty()) { | |
queueTx(tx_queue); | |
} | |
} | |
} | |
return NULL; | |
} | |
// Append a message to the buffered tx queue | |
void bufferedTx(char *string) { | |
// Create a new message and copy the string | |
buffered_tx_t *tail = (buffered_tx_t*) calloc(sizeof(buffered_tx_t), 1); | |
tail->string = calloc(strlen(string) + 1, 1); | |
strncpy(tail->string, string, strlen(string)); | |
// Append the new message to the end of the queue | |
pthread_mutex_lock(&tx_queue_lock); | |
if (tx_queue == NULL) { | |
tx_queue = tail; | |
} else { | |
buffered_tx_t *iter = tx_queue; | |
while (iter->next) { iter = iter->next; } | |
iter->next = tail; | |
} | |
pthread_mutex_unlock(&tx_queue_lock); | |
// Start transmit if this is the first message | |
if (tail == tx_queue) { queueTx(tail); } | |
} | |
int main() { | |
pthread_mutex_init(&tx_queue_lock, NULL); | |
pthread_t thread_id; | |
pthread_create(&thread_id, NULL, uart_handler, NULL); | |
bufferedTx("Hello world! I'm a string to print on the UART!\n"); | |
bufferedTx("Well, hello again! I'm another string that wants to be printed as efficiently as possible!\n"); | |
bufferedTx("String three!\n"); | |
pthread_join(thread_id, NULL); | |
pthread_mutex_destroy(&tx_queue_lock); | |
printf("\n"); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment