mirror of
git://projects.qi-hardware.com/nn-usb-fpga.git
synced 2024-12-13 06:33:09 +02:00
550 lines
12 KiB
C
550 lines
12 KiB
C
/*--------------------------------------------------------------------
|
|
* TITLE: Plasma Uart Driver
|
|
* AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
|
|
* DATE CREATED: 12/31/05
|
|
* FILENAME: uart.c
|
|
* PROJECT: Plasma CPU core
|
|
* COPYRIGHT: Software placed into the public domain by the author.
|
|
* Software 'as is' without warranty. Author liable for nothing.
|
|
* DESCRIPTION:
|
|
* Plasma Uart Driver
|
|
*--------------------------------------------------------------------*/
|
|
#define NO_ELLIPSIS2
|
|
#include "plasma.h"
|
|
#include "rtos.h"
|
|
|
|
#ifndef NO_PACKETS
|
|
#define SUPPORT_DATA_PACKETS
|
|
#endif
|
|
|
|
#define BUFFER_WRITE_SIZE 128
|
|
#define BUFFER_READ_SIZE 128
|
|
#define BUFFER_PRINTF_SIZE 1024
|
|
#undef UartPrintf
|
|
|
|
void UartPrintfCritical(const char *format,
|
|
int arg0, int arg1, int arg2, int arg3,
|
|
int arg4, int arg5, int arg6, int arg7);
|
|
|
|
typedef struct Buffer_s {
|
|
uint8 *data;
|
|
int size;
|
|
volatile int read, write;
|
|
volatile int pendingRead, pendingWrite;
|
|
OS_Semaphore_t *semaphoreRead, *semaphoreWrite;
|
|
} Buffer_t;
|
|
|
|
static Buffer_t *WriteBuffer, *ReadBuffer;
|
|
static OS_Semaphore_t *SemaphoreUart;
|
|
static char PrintfString[BUFFER_PRINTF_SIZE]; //Used in UartPrintf
|
|
|
|
#ifdef SUPPORT_DATA_PACKETS
|
|
//For packet processing [0xff lengthMSB lengthLSB checksum data]
|
|
static PacketGetFunc_t UartPacketGet;
|
|
static uint8 *PacketCurrent;
|
|
static uint32 UartPacketSize;
|
|
static uint32 UartPacketChecksum, Checksum;
|
|
static OS_MQueue_t *UartPacketMQueue;
|
|
static uint32 PacketBytes, PacketLength;
|
|
static uint32 UartPacketOutLength, UartPacketOutByte;
|
|
int CountOk, CountError;
|
|
#endif
|
|
static uint8 *UartPacketOut;
|
|
|
|
|
|
/******************************************/
|
|
Buffer_t *BufferCreate(int size)
|
|
{
|
|
Buffer_t *buffer;
|
|
buffer = (Buffer_t*)OS_HeapMalloc(NULL, sizeof(Buffer_t) + size);
|
|
if(buffer == NULL)
|
|
return NULL;
|
|
buffer->data = (uint8*)(buffer + 1);
|
|
buffer->read = 0;
|
|
buffer->write = 0;
|
|
buffer->size = size;
|
|
buffer->pendingRead = 0;
|
|
buffer->pendingWrite = 0;
|
|
buffer->semaphoreRead = OS_SemaphoreCreate("BufferRead", 0);
|
|
buffer->semaphoreWrite = OS_SemaphoreCreate("BufferWrite", 0);
|
|
return buffer;
|
|
}
|
|
|
|
|
|
void BufferWrite(Buffer_t *buffer, int value, int pend)
|
|
{
|
|
int writeNext;
|
|
|
|
writeNext = buffer->write + 1;
|
|
if(writeNext >= buffer->size)
|
|
writeNext = 0;
|
|
|
|
//Check if room for value
|
|
if(writeNext == buffer->read)
|
|
{
|
|
if(pend == 0)
|
|
return;
|
|
++buffer->pendingWrite;
|
|
OS_SemaphorePend(buffer->semaphoreWrite, OS_WAIT_FOREVER);
|
|
}
|
|
|
|
buffer->data[buffer->write] = (uint8)value;
|
|
buffer->write = writeNext;
|
|
if(buffer->pendingRead)
|
|
{
|
|
--buffer->pendingRead;
|
|
OS_SemaphorePost(buffer->semaphoreRead);
|
|
}
|
|
}
|
|
|
|
|
|
int BufferRead(Buffer_t *buffer, int pend)
|
|
{
|
|
int value;
|
|
|
|
//Check if empty buffer
|
|
if(buffer->read == buffer->write)
|
|
{
|
|
if(pend == 0)
|
|
return 0;
|
|
++buffer->pendingRead;
|
|
OS_SemaphorePend(buffer->semaphoreRead, OS_WAIT_FOREVER);
|
|
}
|
|
|
|
value = buffer->data[buffer->read];
|
|
if(++buffer->read >= buffer->size)
|
|
buffer->read = 0;
|
|
if(buffer->pendingWrite)
|
|
{
|
|
--buffer->pendingWrite;
|
|
OS_SemaphorePost(buffer->semaphoreWrite);
|
|
}
|
|
return value;
|
|
}
|
|
|
|
|
|
/******************************************/
|
|
#ifdef SUPPORT_DATA_PACKETS
|
|
static void UartPacketRead(uint32 value)
|
|
{
|
|
uint32 message[4];
|
|
if(PacketBytes == 0 && value == 0xff)
|
|
{
|
|
++PacketBytes;
|
|
}
|
|
else if(PacketBytes == 1)
|
|
{
|
|
++PacketBytes;
|
|
PacketLength = value << 8;
|
|
}
|
|
else if(PacketBytes == 2)
|
|
{
|
|
++PacketBytes;
|
|
PacketLength |= value;
|
|
if(PacketLength <= UartPacketSize)
|
|
{
|
|
if(PacketCurrent == NULL)
|
|
PacketCurrent = UartPacketGet();
|
|
}
|
|
else
|
|
{
|
|
PacketBytes = 0;
|
|
}
|
|
}
|
|
else if(PacketBytes == 3)
|
|
{
|
|
++PacketBytes;
|
|
UartPacketChecksum = value;
|
|
Checksum = 0;
|
|
}
|
|
else if(PacketBytes >= 4)
|
|
{
|
|
if(PacketCurrent)
|
|
PacketCurrent[PacketBytes - 4] = (uint8)value;
|
|
Checksum += value;
|
|
++PacketBytes;
|
|
if(PacketBytes - 4 >= PacketLength)
|
|
{
|
|
if((uint8)Checksum == UartPacketChecksum)
|
|
{
|
|
//Notify thread that a packet has been received
|
|
++CountOk;
|
|
message[0] = 0;
|
|
message[1] = (uint32)PacketCurrent;
|
|
message[2] = PacketLength;
|
|
if(PacketCurrent)
|
|
OS_MQueueSend(UartPacketMQueue, message);
|
|
PacketCurrent = NULL;
|
|
}
|
|
else
|
|
{
|
|
++CountError;
|
|
//printf("E");
|
|
}
|
|
PacketBytes = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static int UartPacketWrite(void)
|
|
{
|
|
int value=0, i;
|
|
uint32 message[4];
|
|
if(UartPacketOut)
|
|
{
|
|
if(UartPacketOutByte == 0)
|
|
{
|
|
value = 0xff;
|
|
++UartPacketOutByte;
|
|
}
|
|
else if(UartPacketOutByte == 1)
|
|
{
|
|
value = UartPacketOutLength >> 8;
|
|
++UartPacketOutByte;
|
|
}
|
|
else if(UartPacketOutByte == 2)
|
|
{
|
|
value = (uint8)UartPacketOutLength;
|
|
++UartPacketOutByte;
|
|
}
|
|
else if(UartPacketOutByte == 3)
|
|
{
|
|
value = 0;
|
|
for(i = 0; i < (int)UartPacketOutLength; ++i)
|
|
value += UartPacketOut[i];
|
|
value = (uint8)value;
|
|
++UartPacketOutByte;
|
|
}
|
|
else
|
|
{
|
|
value = UartPacketOut[UartPacketOutByte - 4];
|
|
++UartPacketOutByte;
|
|
if(UartPacketOutByte - 4 >= UartPacketOutLength)
|
|
{
|
|
//Notify thread that a packet has been sent
|
|
message[0] = 1;
|
|
message[1] = (uint32)UartPacketOut;
|
|
UartPacketOut = 0;
|
|
OS_MQueueSend(UartPacketMQueue, message);
|
|
}
|
|
}
|
|
}
|
|
return value;
|
|
}
|
|
#endif
|
|
|
|
|
|
static void UartInterrupt(void *arg)
|
|
{
|
|
uint32 status, value, count=0;
|
|
(void)arg;
|
|
|
|
status = OS_InterruptStatus();
|
|
while(status & IRQ_UART_READ_AVAILABLE)
|
|
{
|
|
value = MemoryRead(UART_READ);
|
|
#ifdef SUPPORT_DATA_PACKETS
|
|
if(UartPacketGet && (value == 0xff || PacketBytes))
|
|
UartPacketRead(value);
|
|
else
|
|
#endif
|
|
BufferWrite(ReadBuffer, value, 0);
|
|
status = OS_InterruptStatus();
|
|
if(++count >= 16)
|
|
break;
|
|
}
|
|
while(status & IRQ_UART_WRITE_AVAILABLE)
|
|
{
|
|
#ifdef SUPPORT_DATA_PACKETS
|
|
if(UartPacketOut)
|
|
{
|
|
value = UartPacketWrite();
|
|
MemoryWrite(UART_WRITE, value);
|
|
} else
|
|
#endif
|
|
if(WriteBuffer->read != WriteBuffer->write)
|
|
{
|
|
value = BufferRead(WriteBuffer, 0);
|
|
MemoryWrite(UART_WRITE, value);
|
|
}
|
|
else
|
|
{
|
|
OS_InterruptMaskClear(IRQ_UART_WRITE_AVAILABLE);
|
|
break;
|
|
}
|
|
status = OS_InterruptStatus();
|
|
}
|
|
}
|
|
|
|
|
|
void UartInit(void)
|
|
{
|
|
uint32 mask;
|
|
|
|
SemaphoreUart = OS_SemaphoreCreate("Uart", 1);
|
|
WriteBuffer = BufferCreate(BUFFER_WRITE_SIZE);
|
|
ReadBuffer = BufferCreate(BUFFER_READ_SIZE);
|
|
|
|
mask = IRQ_UART_READ_AVAILABLE | IRQ_UART_WRITE_AVAILABLE;
|
|
OS_InterruptRegister(mask, UartInterrupt);
|
|
OS_InterruptMaskSet(IRQ_UART_READ_AVAILABLE);
|
|
}
|
|
|
|
|
|
void UartWrite(int ch)
|
|
{
|
|
BufferWrite(WriteBuffer, ch, 1);
|
|
OS_InterruptMaskSet(IRQ_UART_WRITE_AVAILABLE);
|
|
}
|
|
|
|
|
|
uint8 UartRead(void)
|
|
{
|
|
return (uint8)BufferRead(ReadBuffer, 1);
|
|
}
|
|
|
|
|
|
void UartWriteData(uint8 *data, int length)
|
|
{
|
|
OS_SemaphorePend(SemaphoreUart, OS_WAIT_FOREVER);
|
|
while(length--)
|
|
UartWrite(*data++);
|
|
OS_SemaphorePost(SemaphoreUart);
|
|
}
|
|
|
|
|
|
void UartReadData(uint8 *data, int length)
|
|
{
|
|
OS_SemaphorePend(SemaphoreUart, OS_WAIT_FOREVER);
|
|
while(length--)
|
|
*data++ = UartRead();
|
|
OS_SemaphorePost(SemaphoreUart);
|
|
}
|
|
|
|
|
|
void UartPrintf(const char *format,
|
|
int arg0, int arg1, int arg2, int arg3,
|
|
int arg4, int arg5, int arg6, int arg7)
|
|
{
|
|
uint8 *ptr;
|
|
#if 0
|
|
//Check for string "!m#~" to mask print statement
|
|
static char moduleLevel[26];
|
|
if(format[0] == '!' && format[3] == '~')
|
|
{
|
|
int level = format[2] - '5';
|
|
if('a' <= format[1] && format[1] <= 'z')
|
|
{
|
|
if(level < moduleLevel[format[1] - 'a'])
|
|
return;
|
|
}
|
|
else if('A' <= format[1] && format[1] <= 'Z')
|
|
moduleLevel[format[1] - 'A'] = (char)level;
|
|
format += 4;
|
|
}
|
|
#endif
|
|
OS_SemaphorePend(SemaphoreUart, OS_WAIT_FOREVER);
|
|
sprintf(PrintfString, format, arg0, arg1, arg2, arg3,
|
|
arg4, arg5, arg6, arg7);
|
|
ptr = (uint8*)PrintfString;
|
|
while(*ptr)
|
|
{
|
|
if(*ptr == '\n')
|
|
UartWrite('\r');
|
|
#ifdef SUPPORT_DATA_PACKETS
|
|
if(*ptr == 0xff)
|
|
*ptr = '@';
|
|
#endif
|
|
UartWrite(*ptr++);
|
|
}
|
|
OS_SemaphorePost(SemaphoreUart);
|
|
}
|
|
|
|
|
|
void UartPrintfPoll(const char *format,
|
|
int arg0, int arg1, int arg2, int arg3,
|
|
int arg4, int arg5, int arg6, int arg7)
|
|
{
|
|
uint8 *ptr;
|
|
uint32 state;
|
|
|
|
if(SemaphoreUart)
|
|
OS_SemaphorePend(SemaphoreUart, OS_WAIT_FOREVER);
|
|
sprintf(PrintfString, format, arg0, arg1, arg2, arg3,
|
|
arg4, arg5, arg6, arg7);
|
|
ptr = (uint8*)PrintfString;
|
|
while(*ptr)
|
|
{
|
|
while((MemoryRead(IRQ_STATUS) & IRQ_UART_WRITE_AVAILABLE) == 0)
|
|
;
|
|
state = OS_CriticalBegin();
|
|
if((MemoryRead(IRQ_STATUS) & IRQ_UART_WRITE_AVAILABLE) &&
|
|
UartPacketOut == NULL)
|
|
{
|
|
MemoryWrite(UART_WRITE, *ptr++);
|
|
}
|
|
OS_CriticalEnd(state);
|
|
}
|
|
if(SemaphoreUart)
|
|
OS_SemaphorePost(SemaphoreUart);
|
|
}
|
|
|
|
|
|
void UartPrintfCritical(const char *format,
|
|
int arg0, int arg1, int arg2, int arg3,
|
|
int arg4, int arg5, int arg6, int arg7)
|
|
{
|
|
uint8 *ptr;
|
|
uint32 state;
|
|
|
|
state = OS_CriticalBegin();
|
|
sprintf(PrintfString, format, arg0, arg1, arg2, arg3,
|
|
arg4, arg5, arg6, arg7);
|
|
ptr = (uint8*)PrintfString;
|
|
while(*ptr)
|
|
{
|
|
while((MemoryRead(IRQ_STATUS) & IRQ_UART_WRITE_AVAILABLE) == 0)
|
|
;
|
|
MemoryWrite(UART_WRITE, *ptr++);
|
|
#ifdef SUPPORT_DATA_PACKETS
|
|
if(UartPacketOut && UartPacketOutByte - 4 < UartPacketOutLength)
|
|
{
|
|
++UartPacketOutByte;
|
|
--ptr;
|
|
}
|
|
#endif
|
|
}
|
|
memset(PrintfString, 0, sizeof(PrintfString));
|
|
OS_CriticalEnd(state);
|
|
}
|
|
|
|
|
|
void UartPrintfNull(void)
|
|
{
|
|
}
|
|
|
|
|
|
void UartScanf(const char *format,
|
|
int arg0, int arg1, int arg2, int arg3,
|
|
int arg4, int arg5, int arg6, int arg7)
|
|
{
|
|
int index = 0, ch;
|
|
OS_SemaphorePend(SemaphoreUart, OS_WAIT_FOREVER);
|
|
for(;;)
|
|
{
|
|
ch = UartRead();
|
|
if(ch != '\b' || index)
|
|
UartWrite(ch);
|
|
if(ch == '\n' || ch == '\r')
|
|
break;
|
|
else if(ch == '\b')
|
|
{
|
|
if(index)
|
|
{
|
|
UartWrite(' ');
|
|
UartWrite(ch);
|
|
--index;
|
|
}
|
|
}
|
|
else if(index < sizeof(PrintfString))
|
|
PrintfString[index++] = (uint8)ch;
|
|
}
|
|
UartWrite('\n');
|
|
PrintfString[index] = 0;
|
|
sscanf(PrintfString, format, arg0, arg1, arg2, arg3,
|
|
arg4, arg5, arg6, arg7);
|
|
OS_SemaphorePost(SemaphoreUart);
|
|
}
|
|
|
|
|
|
#ifdef SUPPORT_DATA_PACKETS
|
|
void UartPacketConfig(PacketGetFunc_t PacketGetFunc,
|
|
int PacketSize,
|
|
OS_MQueue_t *mQueue)
|
|
{
|
|
UartPacketGet = PacketGetFunc;
|
|
UartPacketSize = PacketSize;
|
|
UartPacketMQueue = mQueue;
|
|
}
|
|
|
|
|
|
void UartPacketSend(uint8 *data, int bytes)
|
|
{
|
|
UartPacketOutByte = 0;
|
|
UartPacketOutLength = bytes;
|
|
UartPacketOut = data;
|
|
OS_InterruptMaskSet(IRQ_UART_WRITE_AVAILABLE);
|
|
}
|
|
#else
|
|
void UartPacketConfig(PacketGetFunc_t PacketGetFunc,
|
|
int PacketSize,
|
|
OS_MQueue_t *mQueue)
|
|
{ (void)PacketGetFunc; (void)PacketSize; (void)mQueue; }
|
|
|
|
|
|
void UartPacketSend(uint8 *data, int bytes)
|
|
{ (void)data; (void)bytes; }
|
|
#endif
|
|
|
|
|
|
void Led(int mask, int value)
|
|
{
|
|
mask &= 0xff;
|
|
MemoryWrite(GPIO0_CLEAR, mask); //clear
|
|
MemoryWrite(GPIO0_OUT, value & mask); //set LEDs
|
|
}
|
|
|
|
|
|
/******************************************/
|
|
int puts(const char *string)
|
|
{
|
|
uint8 *ptr;
|
|
OS_SemaphorePend(SemaphoreUart, OS_WAIT_FOREVER);
|
|
ptr = (uint8*)string;
|
|
while(*ptr)
|
|
{
|
|
if(*ptr == '\n')
|
|
UartWrite('\r');
|
|
UartWrite(*ptr++);
|
|
}
|
|
OS_SemaphorePost(SemaphoreUart);
|
|
return 0;
|
|
}
|
|
|
|
|
|
int getch(void)
|
|
{
|
|
return BufferRead(ReadBuffer, 1);
|
|
}
|
|
|
|
|
|
int kbhit(void)
|
|
{
|
|
return ReadBuffer->read != ReadBuffer->write;
|
|
}
|
|
|
|
|
|
/******************************************/
|
|
#if 0
|
|
int LogArray[100], LogIndex;
|
|
void LogWrite(int a)
|
|
{
|
|
if(LogIndex < sizeof(LogArray)/4)
|
|
LogArray[LogIndex++] = a;
|
|
}
|
|
|
|
void LogDump(void)
|
|
{
|
|
int i;
|
|
for(i = 0; i < LogIndex; ++i)
|
|
{
|
|
if(LogArray[i] > 0xfff)
|
|
UartPrintfCritical("\n", 0,0,0,0,0,0,0,0);
|
|
UartPrintfCritical("0x%x ", LogArray[i], 0,0,0,0,0,0,0);
|
|
}
|
|
LogIndex = 0;
|
|
}
|
|
#endif
|
|
|