Root/plasma/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
25void UartPrintfCritical(const char *format,
26                        int arg0, int arg1, int arg2, int arg3,
27                        int arg4, int arg5, int arg6, int arg7);
28
29typedef 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
37static Buffer_t *WriteBuffer, *ReadBuffer;
38static OS_Semaphore_t *SemaphoreUart;
39static char PrintfString[BUFFER_PRINTF_SIZE]; //Used in UartPrintf
40
41#ifdef SUPPORT_DATA_PACKETS
42//For packet processing [0xff lengthMSB lengthLSB checksum data]
43static PacketGetFunc_t UartPacketGet;
44static uint8 *PacketCurrent;
45static uint32 UartPacketSize;
46static uint32 UartPacketChecksum, Checksum;
47static OS_MQueue_t *UartPacketMQueue;
48static uint32 PacketBytes, PacketLength;
49static uint32 UartPacketOutLength, UartPacketOutByte;
50int CountOk, CountError;
51#endif
52static uint8 *UartPacketOut;
53
54
55/******************************************/
56Buffer_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
74void 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
101int 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
128static 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
190static 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
238static 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
281void 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
295void UartWrite(int ch)
296{
297   BufferWrite(WriteBuffer, ch, 1);
298   OS_InterruptMaskSet(IRQ_UART_WRITE_AVAILABLE);
299}
300
301
302uint8 UartRead(void)
303{
304   return (uint8)BufferRead(ReadBuffer, 1);
305}
306
307
308void 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
317void 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
326void 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
365void 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
394void 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
423void UartPrintfNull(void)
424{
425}
426
427
428void 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
462void 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
472void 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
480void UartPacketConfig(PacketGetFunc_t PacketGetFunc,
481                      int PacketSize,
482                      OS_MQueue_t *mQueue)
483{ (void)PacketGetFunc; (void)PacketSize; (void)mQueue; }
484
485
486void UartPacketSend(uint8 *data, int bytes)
487{ (void)data; (void)bytes; }
488#endif
489
490
491void Led(int mask, int value)
492{
493   mask &= 0xff;
494   MemoryWrite(GPIO0_CLEAR, mask); //clear
495   MemoryWrite(GPIO0_OUT, value & mask); //set LEDs
496}
497
498
499/******************************************/
500int 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
516int getch(void)
517{
518   return BufferRead(ReadBuffer, 1);
519}
520
521
522int kbhit(void)
523{
524   return ReadBuffer->read != ReadBuffer->write;
525}
526
527
528/******************************************/
529#if 0
530int LogArray[100], LogIndex;
531void LogWrite(int a)
532{
533   if(LogIndex < sizeof(LogArray)/4)
534      LogArray[LogIndex++] = a;
535}
536
537void 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
550

Archive Download this file

Branches:
master



interactive