]> rtime.felk.cvut.cz Git - fpga/plasma.git/blob - kernel/uart.c
Local copy of Plasma MIPS project.
[fpga/plasma.git] / kernel / uart.c
1 /*--------------------------------------------------------------------
2  * TITLE: Plasma Uart Driver
3  * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4  * DATE CREATED: 12/31/05
5  * FILENAME: uart.c
6  * PROJECT: Plasma CPU core
7  * COPYRIGHT: Software placed into the public domain by the author.
8  *    Software 'as is' without warranty.  Author liable for nothing.
9  * DESCRIPTION:
10  *    Plasma Uart Driver
11  *--------------------------------------------------------------------*/
12 #define NO_ELLIPSIS2
13 #include "plasma.h"
14 #include "rtos.h"
15
16 #ifndef NO_PACKETS
17 #define SUPPORT_DATA_PACKETS
18 #endif
19
20 #define BUFFER_WRITE_SIZE 128
21 #define BUFFER_READ_SIZE 128
22 #define BUFFER_PRINTF_SIZE 1024
23 #undef UartPrintf
24
25 void UartPrintfCritical(const char *format,
26                         int arg0, int arg1, int arg2, int arg3,
27                         int arg4, int arg5, int arg6, int arg7);
28
29 typedef struct Buffer_s {
30    uint8 *data;
31    int size;
32    volatile int read, write;
33    volatile int pendingRead, pendingWrite;
34    OS_Semaphore_t *semaphoreRead, *semaphoreWrite;
35 } Buffer_t;
36
37 static Buffer_t *WriteBuffer, *ReadBuffer;
38 static OS_Semaphore_t *SemaphoreUart;
39 static char PrintfString[BUFFER_PRINTF_SIZE];  //Used in UartPrintf
40
41 #ifdef SUPPORT_DATA_PACKETS
42 //For packet processing [0xff lengthMSB lengthLSB checksum data]
43 static PacketGetFunc_t UartPacketGet;
44 static uint8 *PacketCurrent;
45 static uint32 UartPacketSize;
46 static uint32 UartPacketChecksum, Checksum;
47 static OS_MQueue_t *UartPacketMQueue;
48 static uint32 PacketBytes, PacketLength;
49 static uint32 UartPacketOutLength, UartPacketOutByte;
50 int CountOk, CountError;
51 #endif
52 static uint8 *UartPacketOut;
53
54
55 /******************************************/
56 Buffer_t *BufferCreate(int size)
57 {
58    Buffer_t *buffer;
59    buffer = (Buffer_t*)OS_HeapMalloc(NULL, sizeof(Buffer_t) + size);
60    if(buffer == NULL)
61       return NULL;
62    buffer->data = (uint8*)(buffer + 1);
63    buffer->read = 0;
64    buffer->write = 0;
65    buffer->size = size;
66    buffer->pendingRead = 0;
67    buffer->pendingWrite = 0;
68    buffer->semaphoreRead = OS_SemaphoreCreate("BufferRead", 0);
69    buffer->semaphoreWrite = OS_SemaphoreCreate("BufferWrite", 0);
70    return buffer;
71 }
72
73
74 void BufferWrite(Buffer_t *buffer, int value, int pend)
75 {
76    int writeNext;
77
78    writeNext = buffer->write + 1;
79    if(writeNext >= buffer->size)
80       writeNext = 0;
81
82    //Check if room for value
83    if(writeNext == buffer->read)
84    {
85       if(pend == 0)
86          return;
87       ++buffer->pendingWrite;
88       OS_SemaphorePend(buffer->semaphoreWrite, OS_WAIT_FOREVER);
89    }
90
91    buffer->data[buffer->write] = (uint8)value;
92    buffer->write = writeNext;
93    if(buffer->pendingRead)
94    {
95       --buffer->pendingRead;
96       OS_SemaphorePost(buffer->semaphoreRead);
97    }
98 }
99
100
101 int BufferRead(Buffer_t *buffer, int pend)
102 {
103    int value;
104
105    //Check if empty buffer
106    if(buffer->read == buffer->write)
107    {
108       if(pend == 0)
109          return 0;
110       ++buffer->pendingRead;
111       OS_SemaphorePend(buffer->semaphoreRead, OS_WAIT_FOREVER);
112    }
113
114    value = buffer->data[buffer->read];
115    if(++buffer->read >= buffer->size)
116       buffer->read = 0;
117    if(buffer->pendingWrite)
118    {
119       --buffer->pendingWrite;
120       OS_SemaphorePost(buffer->semaphoreWrite);
121    }
122    return value;
123 }
124
125
126 /******************************************/
127 #ifdef SUPPORT_DATA_PACKETS
128 static void UartPacketRead(uint32 value)
129 {
130    uint32 message[4];
131    if(PacketBytes == 0 && value == 0xff)
132    {
133       ++PacketBytes;
134    }
135    else if(PacketBytes == 1)
136    {
137       ++PacketBytes;
138       PacketLength = value << 8;
139    }
140    else if(PacketBytes == 2)
141    {
142       ++PacketBytes;
143       PacketLength |= value;
144       if(PacketLength <= UartPacketSize)
145       {
146          if(PacketCurrent == NULL)
147             PacketCurrent = UartPacketGet();
148       }
149       else
150       {
151          PacketBytes = 0;
152       }
153    }
154    else if(PacketBytes == 3)
155    {
156       ++PacketBytes;
157       UartPacketChecksum = value;
158       Checksum = 0;
159    }
160    else if(PacketBytes >= 4)
161    {
162       if(PacketCurrent)
163          PacketCurrent[PacketBytes - 4] = (uint8)value;
164       Checksum += value;
165       ++PacketBytes;
166       if(PacketBytes - 4 >= PacketLength)
167       {
168          if((uint8)Checksum == UartPacketChecksum)
169          {
170             //Notify thread that a packet has been received
171             ++CountOk;
172             message[0] = 0;
173             message[1] = (uint32)PacketCurrent;
174             message[2] = PacketLength;
175             if(PacketCurrent)
176                OS_MQueueSend(UartPacketMQueue, message);
177             PacketCurrent = NULL;
178          }
179          else
180          {
181             ++CountError;
182             //printf("E");
183          }
184          PacketBytes = 0;
185       }
186    }
187 }
188
189
190 static int UartPacketWrite(void)
191 {
192    int value=0, i;
193    uint32 message[4];
194    if(UartPacketOut)
195    {
196       if(UartPacketOutByte == 0)
197       {
198          value = 0xff;
199          ++UartPacketOutByte;
200       }
201       else if(UartPacketOutByte == 1)
202       {
203          value = UartPacketOutLength >> 8;
204          ++UartPacketOutByte;
205       }
206       else if(UartPacketOutByte == 2)
207       {
208          value = (uint8)UartPacketOutLength;
209          ++UartPacketOutByte;
210       }
211       else if(UartPacketOutByte == 3)
212       {
213          value = 0;
214          for(i = 0; i < (int)UartPacketOutLength; ++i)
215             value += UartPacketOut[i];
216          value = (uint8)value;
217          ++UartPacketOutByte;
218       }
219       else 
220       {
221          value = UartPacketOut[UartPacketOutByte - 4];
222          ++UartPacketOutByte;
223          if(UartPacketOutByte - 4 >= UartPacketOutLength)
224          {
225             //Notify thread that a packet has been sent
226             message[0] = 1;
227             message[1] = (uint32)UartPacketOut;
228             UartPacketOut = 0;
229             OS_MQueueSend(UartPacketMQueue, message);
230          }
231       }
232    }
233    return value;
234 }
235 #endif
236
237
238 static void UartInterrupt(void *arg)
239 {
240    uint32 status, value, count=0;
241    (void)arg;
242
243    status = OS_InterruptStatus();
244    while(status & IRQ_UART_READ_AVAILABLE)
245    {
246       value = MemoryRead(UART_READ);
247 #ifdef SUPPORT_DATA_PACKETS
248       if(UartPacketGet && (value == 0xff || PacketBytes))
249          UartPacketRead(value);
250       else
251 #endif
252       BufferWrite(ReadBuffer, value, 0);
253       status = OS_InterruptStatus();
254       if(++count >= 16)
255          break;
256    }
257    while(status & IRQ_UART_WRITE_AVAILABLE)
258    {
259 #ifdef SUPPORT_DATA_PACKETS
260       if(UartPacketOut)
261       {
262          value = UartPacketWrite();
263          MemoryWrite(UART_WRITE, value);
264       } else 
265 #endif
266       if(WriteBuffer->read != WriteBuffer->write)
267       {
268          value = BufferRead(WriteBuffer, 0);
269          MemoryWrite(UART_WRITE, value);
270       }
271       else
272       {
273          OS_InterruptMaskClear(IRQ_UART_WRITE_AVAILABLE);
274          break;
275       }
276       status = OS_InterruptStatus();
277    }
278 }
279
280
281 void UartInit(void)
282 {
283    uint32 mask;
284
285    SemaphoreUart = OS_SemaphoreCreate("Uart", 1);
286    WriteBuffer = BufferCreate(BUFFER_WRITE_SIZE);
287    ReadBuffer = BufferCreate(BUFFER_READ_SIZE);
288
289    mask = IRQ_UART_READ_AVAILABLE | IRQ_UART_WRITE_AVAILABLE;
290    OS_InterruptRegister(mask, UartInterrupt);
291    OS_InterruptMaskSet(IRQ_UART_READ_AVAILABLE);
292 }
293
294
295 void UartWrite(int ch)
296 {
297    BufferWrite(WriteBuffer, ch, 1);
298    OS_InterruptMaskSet(IRQ_UART_WRITE_AVAILABLE);
299 }
300
301
302 uint8 UartRead(void)
303 {
304    return (uint8)BufferRead(ReadBuffer, 1);
305 }
306
307
308 void UartWriteData(uint8 *data, int length)
309 {
310    OS_SemaphorePend(SemaphoreUart, OS_WAIT_FOREVER);
311    while(length--)
312       UartWrite(*data++);
313    OS_SemaphorePost(SemaphoreUart);
314 }
315
316
317 void UartReadData(uint8 *data, int length)
318 {
319    OS_SemaphorePend(SemaphoreUart, OS_WAIT_FOREVER);
320    while(length--)
321       *data++ = UartRead();
322    OS_SemaphorePost(SemaphoreUart);
323 }
324
325
326 void UartPrintf(const char *format,
327                 int arg0, int arg1, int arg2, int arg3,
328                 int arg4, int arg5, int arg6, int arg7)
329 {
330    uint8 *ptr;
331 #if 0
332    //Check for string "!m#~" to mask print statement
333    static char moduleLevel[26];
334    if(format[0] == '!' && format[3] == '~')
335    {
336       int level = format[2] - '5';
337       if('a' <= format[1] && format[1] <= 'z')
338       {
339          if(level < moduleLevel[format[1] - 'a'])
340             return;
341       }
342       else if('A' <= format[1] && format[1] <= 'Z')
343          moduleLevel[format[1] - 'A'] = (char)level;
344       format += 4;
345    }
346 #endif
347    OS_SemaphorePend(SemaphoreUart, OS_WAIT_FOREVER);
348    sprintf(PrintfString, format, arg0, arg1, arg2, arg3,
349            arg4, arg5, arg6, arg7);
350    ptr = (uint8*)PrintfString;
351    while(*ptr)
352    {
353       if(*ptr == '\n')
354          UartWrite('\r');
355 #ifdef SUPPORT_DATA_PACKETS
356       if(*ptr == 0xff)
357          *ptr = '@';
358 #endif
359       UartWrite(*ptr++);
360    }
361    OS_SemaphorePost(SemaphoreUart);
362 }
363
364
365 void UartPrintfPoll(const char *format,
366                     int arg0, int arg1, int arg2, int arg3,
367                     int arg4, int arg5, int arg6, int arg7)
368 {
369    uint8 *ptr;
370    uint32 state;
371
372    if(SemaphoreUart)
373       OS_SemaphorePend(SemaphoreUart, OS_WAIT_FOREVER);
374    sprintf(PrintfString, format, arg0, arg1, arg2, arg3,
375            arg4, arg5, arg6, arg7);
376    ptr = (uint8*)PrintfString;
377    while(*ptr)
378    {
379       while((MemoryRead(IRQ_STATUS) & IRQ_UART_WRITE_AVAILABLE) == 0)
380          ;
381       state = OS_CriticalBegin();
382       if((MemoryRead(IRQ_STATUS) & IRQ_UART_WRITE_AVAILABLE) &&
383          UartPacketOut == NULL)
384       {
385          MemoryWrite(UART_WRITE, *ptr++);
386       }
387       OS_CriticalEnd(state);
388    }
389    if(SemaphoreUart)
390       OS_SemaphorePost(SemaphoreUart);
391 }
392
393
394 void UartPrintfCritical(const char *format,
395                         int arg0, int arg1, int arg2, int arg3,
396                         int arg4, int arg5, int arg6, int arg7)
397 {
398    uint8 *ptr;
399    uint32 state;
400
401    state = OS_CriticalBegin();
402    sprintf(PrintfString, format, arg0, arg1, arg2, arg3,
403            arg4, arg5, arg6, arg7);
404    ptr = (uint8*)PrintfString;
405    while(*ptr)
406    {
407       while((MemoryRead(IRQ_STATUS) & IRQ_UART_WRITE_AVAILABLE) == 0)
408          ;
409       MemoryWrite(UART_WRITE, *ptr++);
410 #ifdef SUPPORT_DATA_PACKETS
411       if(UartPacketOut && UartPacketOutByte - 4 < UartPacketOutLength)
412       {
413          ++UartPacketOutByte;
414          --ptr;
415       }
416 #endif
417    }
418    memset(PrintfString, 0, sizeof(PrintfString));
419    OS_CriticalEnd(state);
420 }
421
422
423 void UartPrintfNull(void)
424 {
425 }
426
427
428 void UartScanf(const char *format,
429                int arg0, int arg1, int arg2, int arg3,
430                int arg4, int arg5, int arg6, int arg7)
431 {
432    int index = 0, ch;
433    OS_SemaphorePend(SemaphoreUart, OS_WAIT_FOREVER);
434    for(;;)
435    {
436       ch = UartRead();
437       if(ch != '\b' || index)
438          UartWrite(ch);
439       if(ch == '\n' || ch == '\r')
440          break;
441       else if(ch == '\b')
442       {
443          if(index)
444          {
445             UartWrite(' ');
446             UartWrite(ch);
447             --index;
448          }
449       }
450       else if(index < sizeof(PrintfString))
451          PrintfString[index++] = (uint8)ch;
452    }
453    UartWrite('\n');
454    PrintfString[index] = 0;
455    sscanf(PrintfString, format, arg0, arg1, arg2, arg3,
456           arg4, arg5, arg6, arg7);
457    OS_SemaphorePost(SemaphoreUart);
458 }
459
460
461 #ifdef SUPPORT_DATA_PACKETS
462 void UartPacketConfig(PacketGetFunc_t PacketGetFunc, 
463                       int PacketSize, 
464                       OS_MQueue_t *mQueue)
465 {
466    UartPacketGet = PacketGetFunc;
467    UartPacketSize = PacketSize;
468    UartPacketMQueue = mQueue;
469 }
470
471
472 void UartPacketSend(uint8 *data, int bytes)
473 {
474    UartPacketOutByte = 0;
475    UartPacketOutLength = bytes;
476    UartPacketOut = data;
477    OS_InterruptMaskSet(IRQ_UART_WRITE_AVAILABLE);
478 }
479 #else
480 void UartPacketConfig(PacketGetFunc_t PacketGetFunc, 
481                       int PacketSize, 
482                       OS_MQueue_t *mQueue)
483 { (void)PacketGetFunc; (void)PacketSize; (void)mQueue; }
484
485
486 void UartPacketSend(uint8 *data, int bytes)
487 { (void)data; (void)bytes; }
488 #endif
489
490
491 void Led(int mask, int value)
492 {\r
493    mask &= 0xff;
494    MemoryWrite(GPIO0_CLEAR, mask);       //clear
495    MemoryWrite(GPIO0_OUT, value & mask); //set LEDs
496 }
497
498
499 /******************************************/
500 int puts(const char *string)
501 {
502    uint8 *ptr;
503    OS_SemaphorePend(SemaphoreUart, OS_WAIT_FOREVER);
504    ptr = (uint8*)string;
505    while(*ptr)
506    {
507       if(*ptr == '\n')
508          UartWrite('\r');
509       UartWrite(*ptr++);
510    }
511    OS_SemaphorePost(SemaphoreUart);
512    return 0;
513 }
514
515
516 int getch(void)
517 {
518    return BufferRead(ReadBuffer, 1);
519 }
520
521
522 int kbhit(void)
523 {
524    return ReadBuffer->read != ReadBuffer->write;
525 }
526
527
528 /******************************************/
529 #if 0
530 int LogArray[100], LogIndex;
531 void LogWrite(int a)
532 {
533    if(LogIndex < sizeof(LogArray)/4)
534       LogArray[LogIndex++] = a;
535 }
536
537 void LogDump(void)
538 {
539    int i;
540    for(i = 0; i < LogIndex; ++i)
541    {
542       if(LogArray[i] > 0xfff)
543          UartPrintfCritical("\n", 0,0,0,0,0,0,0,0);
544       UartPrintfCritical("0x%x ", LogArray[i], 0,0,0,0,0,0,0);
545    }
546    LogIndex = 0;
547 }
548 #endif
549