mirror of
git://projects.qi-hardware.com/nn-usb-fpga.git
synced 2025-04-21 12:27:27 +03:00
Adding plasma example
This commit is contained in:
549
plasma/kernel/uart.c
Normal file
549
plasma/kernel/uart.c
Normal file
@@ -0,0 +1,549 @@
|
||||
/*--------------------------------------------------------------------
|
||||
* 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
|
||||
|
||||
Reference in New Issue
Block a user