Here is uart.c (part 1 of 2). Note that I am not using any hardware flow control on receiving data on uart0 even though the assert/de-assert defines are present in the header file. So far, the interrupt-driven buffering seems to be fast enough that it is not needed. I will post an update if this ever proves wrong. Code://--------------------------------------------------------
// uart.c
//
// This code was changed to add an interrupt-driven priority
// command option for uart0, for immediate processing of commands
// like motor and servo commands. It depends upon the
// startup.asm method of initialization, which uses the
// SVG15 interrupt to put the processor into supervisor
// mode while allowing other interrupts to occur.
//
// Use myfunc commands to enable/disable interrupt-driven input to uart0.
// Use commands prefixed with [ and followed by ] to trigger immediate
// processing of the command within the interrupt service routine. See myfunc.c for
// code to process motor commands and servo commands in this manner.
//
#include <cdefBF537.h>
#include "config.h"
#include "uart.h"
#include "srv.h"
#include "print.h"
//-----------------------------------------
// Buffers for interrupt-enabled receive
//
volatile unsigned char rx_buff[RX_BUFF_SIZE];
volatile unsigned char *r_tail; // Ring buffer tail-pointer
volatile unsigned char *r_ptr; // Ring buffer read-pointer
volatile unsigned char priority_buff[PRIORITY_BUFF_SIZE];
volatile unsigned char *p_tail;
volatile unsigned char *p_ptr;
int temp3;
volatile char stop;
volatile char processing_priority_command;
//------------------------------------------
void init_uart0(void) {
*pPORTF_FER |= 0x0003; // enable UART0 pins
*pUART0_GCTL = UCEN;
*pUART0_LCR = DLAB;
*pUART0_DLL = UART0_DIVIDER;
*pUART0_DLH = UART0_DIVIDER >> 8;
*pUART0_LCR = WLS(8); // 8 bit, no parity, one stop bit
// dummy reads to clear possible pending errors / irqs
char dummy = *pUART0_RBR;
dummy = *pUART0_LSR;
dummy = *pUART0_IIR;
SSYNC;
}
void init_fast_uart0(void) {
*pPORTF_FER |= 0x0003; // enable UART0 pins
*pUART0_GCTL = UCEN;
*pUART0_LCR = DLAB;
*pUART0_DLL = UART0_FAST_DIVIDER;
*pUART0_DLH = UART0_FAST_DIVIDER >> 8;
*pUART0_LCR = WLS(8); // 8 bit, no parity, one stop bit
// dummy reads to clear possible pending errors / irqs
char dummy = *pUART0_RBR;
dummy = *pUART0_LSR;
dummy = *pUART0_IIR;
SSYNC;
}
void init_uart1(void) {
*pPORTF_FER |= 0x000C; // enable UART1 pins
*pUART1_GCTL = UCEN;
*pUART1_LCR = DLAB;
*pUART1_DLL = UART1_DIVIDER;
*pUART1_DLH = UART1_DIVIDER >> 8;
*pUART1_LCR = WLS(8); // 8 bit, no parity, one stop bit
char dummy = *pUART1_RBR;
dummy = *pUART1_LSR;
dummy = *pUART1_IIR;
SSYNC;
}
void uart0SendChar(unsigned char c) {
while (*pPORTHIO & 0x0001) // hardware serial flow control -
continue; // S32 pin 17 should be grounded to disable
while (!(*pUART0_LSR & THRE))
continue;
*pUART0_THR = c;
}
void uart0SendString(unsigned char *s) {
char a;
while ((a = *s++)) {
uart0SendChar(a);
}
}
void uart0SendChars(unsigned char *buf, unsigned int size) {
while (size--) {
uart0SendChar(*buf++);
}
}
//-----------------------------------------------------------
// These functions have changed to accommodate both polled and
// interrupt-driven receive
//
unsigned char uart0GetCh() // This one waits for input
{
// if interrupts enabled, wait until something is in buffer
// and return it.
if (UART0_INTERRUPTS_ENABLED) {
unsigned char c;
uart0GetBufferCharWait(&c);
return c;
}
// if interrupts not enabled, wait for Data Ready bit, then
// get char and return it.
while (!(*pUART0_LSR & DR))
;
return *pUART0_RBR;
}
unsigned char uart0GetChar(unsigned char *a) // this one does not wait
{
// if interrupts enabled, check for something in buffer
// and return it.
if (UART0_INTERRUPTS_ENABLED) {
return uart0GetBufferCharNoWait(a);
}
// if interrupts not enabled, check Data Ready bit, if not set, return
// otherwise, get char and return it.
if (!(*pUART0_LSR & DR))
return 0;
*a = *pUART0_RBR;
return 1;
}
//-------------------------------------------------------------
void uart1SendChar(unsigned char c) {
while (!(*pUART1_LSR & THRE))
;
*pUART1_THR = c;
}
void uart1SendString(unsigned char *s) {
char a;
while ((a = *s++)) {
uart1SendChar(a);
}
}
void uart1SendChars(unsigned char *buf, unsigned int size) {
while (size--) {
uart1SendChar(*buf++);
}
}
unsigned char uart1GetCh() {
while (!(*pUART1_LSR & DR))
;
return *pUART1_RBR;
}
unsigned char uart1GetChar(unsigned char *a) {
if (!(*pUART1_LSR & DR))
return 0;
*a = *pUART1_RBR;
return 1;
}
//---------------------------------------------------------------
// Bolo - functions to push and pull chars from ring buffers
// Handles both regular mode and priority mode, using
// separate buffers for each
//
unsigned char buff_receive_push(unsigned char *data) {
disable_interrupts(temp3);
if (processing_priority_command) {
// Check for full buffer
if (p_tail >= p_ptr) {
if ((p_tail - p_ptr) >= PRIORITY_BUFF_SIZE - 1) {
enable_interrupts(temp3);
return (0);
}
} else {
if ((p_tail + PRIORITY_BUFF_SIZE - p_ptr) >= PRIORITY_BUFF_SIZE - 1) {
enable_interrupts(temp3);
return (0);
}
}
*p_tail = *data;
// printf("<buffer push %c to %08x>", *p_tail, p_tail);
p_tail++;
/* Connect Ringbuffer head to tail */
if (p_tail >= priority_buff + PRIORITY_BUFF_SIZE)
p_tail = priority_buff;
} else {
// Check for full buffer
if (r_tail >= r_ptr) {
if ((r_tail - r_ptr) >= RX_BUFF_SIZE - 1) {
enable_interrupts(temp3);
return (0);
}
} else {
if ((r_tail + RX_BUFF_SIZE - r_ptr) >= RX_BUFF_SIZE - 1) {
enable_interrupts(temp3);
return (0);
}
}
*r_tail = *data;
// printf("<buffer push %c to %08x>", *r_tail, r_tail);
r_tail++;
/* Connect Ringbuffer head to tail */
if (r_tail >= rx_buff + RX_BUFF_SIZE)
r_tail = rx_buff;
}
enable_interrupts(temp3);
return (1);
}
unsigned char buff_receive_pull(unsigned char *data) {
disable_interrupts(temp3);
if (processing_priority_command) {
// Check if there's any data in the buffer
if (p_ptr == p_tail) {
enable_interrupts(temp3);
return (0);
}
*data = *p_ptr;
//printf("<%c>", *data, p_ptr);
p_ptr++;
/* Connect head to tail of ringbuffer */
if (p_ptr >= priority_buff + PRIORITY_BUFF_SIZE)
p_ptr = priority_buff;
} else {
// Check if there's any data in the buffer
if (r_ptr == r_tail) {
enable_interrupts(temp3);
return (0);
}
*data = *r_ptr;
//printf("<%c>", *data, r_ptr);
r_ptr++;
/* Connect ringbuffer */
if (r_ptr >= rx_buff + RX_BUFF_SIZE)
r_ptr = rx_buff;
}
enable_interrupts(temp3);
return (1);
}
void uart0_init_interruptable() {
// printf("Initializing uart0 interrupts...");
// Init ringbuffer pointers
r_tail = rx_buff;
r_ptr = rx_buff;
p_tail = priority_buff;
p_ptr = priority_buff;
processing_priority_command = 0;
// Enable UART interrupts on receive
*pUART0_IER |= (ERBFI | ELSI);
// Set uart_ISR as IVG10 handler
*pEVT10 = (void*) uart0_ISR;
// Unmask IVG10 interrupt
*pIMASK |= EVT_IVG10;
// Unmask UART interrupts
*pSIC_IMASK |= (IRQ_DMA8);
}
unsigned char uart0GetBufferCharWait(unsigned char *data) {
unsigned char c;
// printf("GetBufferCharWait");
// printf("r_ptr = %08x, r_tail = %08x", r_ptr, r_tail);
while (UART0_INTERRUPTS_ENABLED && !buff_receive_pull(&c))
;
*data = c;
// printf("<got %c>", *data);
return 1;
}
unsigned char uart0GetBufferCharNoWait(unsigned char *data) {
unsigned char c;
// printf("GetBufferCharNoWait");
if (!(r_ptr == r_tail)) {
buff_receive_pull(&c);
*data = c;
// printf("<got %c>", *data);
return 1;
} else
return 0;
}
void uart0_ISR() {
unsigned char identification_register;
identification_register = *pUART0_IIR;
// Check to see if interrupt was caused by uart error
//
if (identification_register == 0x6) {
// FIXME, atm just clears interrupt
int temp3 = *pUART0_LSR;
temp3++;
return;
}
// Check to see if interrupt was caused by newly received data
//
if (identification_register == 0x4) {
// Read data into ringbuffer
unsigned char c = *pUART0_RBR;
// Manage priority commands
if (c == PRIORITY_COMMAND_HEADER) {
processing_priority_command = 1;
return;
}
if (c == PRIORITY_COMMAND_TRAILER) {
myfunc();
p_tail = priority_buff;
p_ptr = priority_buff;
processing_priority_command = 0;
return;
}
buff_receive_push(&c);
return;
}
}
void uart0_disable_interrupts() {
*pUART0_IER &= ~(ERBFI | ELSI);
}