Skip to content

Instantly share code, notes, and snippets.

@LastZactionHero
Created February 11, 2019 04:35
Show Gist options
  • Save LastZactionHero/de749d0c17322c4ec882e79b0cf09278 to your computer and use it in GitHub Desktop.
Save LastZactionHero/de749d0c17322c4ec882e79b0cf09278 to your computer and use it in GitHub Desktop.
Buffered Uart TX
#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