📄 uart.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"#define SUPPORT_DATA_PACKETS#define BUFFER_WRITE_SIZE 128#define BUFFER_READ_SIZE 128#define BUFFER_PRINTF_SIZE 1024#undef UartPrintfvoid 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;#endifstatic 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_PACKETSstatic 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) PacketCurrent = UartPacketGet(); else { PacketCurrent = NULL; 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 have been received ++CountOk; message[0] = 0; message[1] = (uint32)PacketCurrent; message[2] = PacketLength; if(PacketCurrent) OS_MQueueSend(UartPacketMQueue, message); } 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;}#endifstatic 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; 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_PACKETSvoid 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);}#endifvoid Led(int value){ value |= 0xffffff00; MemoryWrite(GPIO0_OUT, value); //Change LEDs}/******************************************/#ifndef WIN32int 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;}#endif/******************************************/#if 0int 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -