00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <avr/io.h>
00012 #include <avr/interrupt.h>
00013 #include <stdlib.h>
00014 #include "system.h"
00015 #include "rs232.h"
00016 #include "task.h"
00017 #include "cio.h"
00018
00019 static void InitPort(SERIAL *pS,unsigned short nTSize,unsigned short nRSize, unsigned short nPort,long nBaudRate);
00020 static int ROpen(IOCB *pIOCB);
00021 static int RGetC(IOCB *pIOCB);
00022 static int RPutC(IOCB *pIOCB,int c);
00023 static int RWrite(IOCB *pIOCB,char *b,int l);
00024 static int RStatus(IOCB *pIOCB,int m);
00025
00026 static SERIAL *gSerial[RS232_N_PORTS];
00027
00028 static H_JVEC RJump = {
00029 ROpen,
00030 0,
00031 RGetC,
00032 0,
00033 RPutC,
00034 RWrite,
00035 RStatus,
00036 0,
00037 RInit
00038 };
00039
00040
00041 static RREG SAdr[2] = {
00042 {(unsigned char *)&UDR0,(unsigned char *)&UCSR0A,(unsigned char *)&UCSR0B,(unsigned char *)&UCSR0C,(unsigned short *)&UBRR0},
00043 {(unsigned char *)&UDR1,(unsigned char *)&UCSR1A,(unsigned char *)&UCSR1B,(unsigned char *)&UCSR1C,(unsigned short *)&UBRR1},
00044 };
00045
00046 static int ROpen(IOCB *pIOCB) __attribute__ ((section(".lowtext")));
00047 static int ROpen(IOCB *pIOCB)
00048 {
00049 if(pIOCB->devnum < RS232_N_PORTS)
00050 {
00051 pIOCB->p = (void *)malloc(sizeof(SERIAL));
00052 InitPort((SERIAL *)pIOCB->p,RS232_DEF_T_BUFF_SIZE,RS232_DEF_R_BUFF_SIZE,pIOCB->devnum,RS232_DEF_BAUDRATE);
00053 gSerial[pIOCB->devnum] = (SERIAL *)pIOCB->p;
00054 }
00055 return 0;
00056 }
00057
00058 static int RGetC(IOCB *pIOCB) __attribute__ ((section(".lowtext")));
00059 static int RGetC(IOCB *pIOCB)
00060 {
00061 int retval;
00062 char sr;
00063 SERIAL *pI = (SERIAL *)pIOCB->p;
00064
00065 PendSemaphore(pI->Rx.pSem,0);
00066 sr = Disable();
00067 if(pI->Rx.nChar)
00068 {
00069 retval = (int)pI->Rx.buff[pI->Rx.tail++];
00070 if(pI->Rx.tail == pI->Rx.size) pI->Rx.tail = 0;
00071 pI->Rx.nChar--;
00072 }
00073 else
00074 retval = -1;
00075 Enable(sr);
00076 return retval;
00077 }
00078
00079 static int RPutC(IOCB *pIOCB,int c) __attribute__ ((section(".lowtext")));
00080 static int RPutC(IOCB *pIOCB,int c)
00081 {
00082 char sr;
00083 SERIAL *pI = (SERIAL *)pIOCB->p;
00084
00085 sr = Disable();
00086 if(pI->Tx.nChar < pI->Tx.size)
00087 {
00088 pI->Tx.buff[pI->Tx.head++] = (unsigned char)c;
00089 if(pI->Tx.head == pI->Tx.size) pI->Tx.head = 0;
00090 if(!pI->Tx.nChar)
00091 *pI->regs->pUCSRnB |= BIT(UDRIE0);
00092 pI->Tx.nChar++;
00093 }
00094 Enable(sr);
00095 return 0;
00096 }
00097
00098 static int RWrite(IOCB *pIOCB,char *b,int l) __attribute__ ((section(".lowtext")));
00099 static int RWrite(IOCB *pIOCB,char *b,int l)
00100 {
00101 int i = 0;
00102 SERIAL *pI = (SERIAL *)pIOCB->p;
00103
00104 PendSemaphore(pI->Tx.pSem,0);
00105 for(i=0;i<l;++i)
00106 RPutC(pIOCB,b[i]);
00107 PostSemaphore(pI->Tx.pSem,0);
00108 return i;
00109 }
00110
00111 static int RStatus(IOCB *pIOCB,int m) __attribute__ ((section(".lowtext")));
00112 static int RStatus(IOCB *pIOCB,int m)
00113 {
00114 int rv=0;
00115
00116 SERIAL *pI = (SERIAL *)pIOCB->p;
00117 switch(m)
00118 {
00119 case RS232_STAT_NREC:
00120 rv = pI->Rx.nChar;
00121 break;
00122 case RS232_STAT_TMT:
00123 if(pI->Tx.nChar == 0) rv = 1;
00124 else rv = 0;
00125 break;
00126 }
00127 return rv;
00128 }
00129
00130 static unsigned short CalculateBaudRate(long nBR)
00131 {
00132 return (unsigned short)( ((SYSTEM_CLOCKRATE / nBR) / 16L) - 1 );
00133 }
00134
00135 static char *PNames[2] = {
00136 "RX0",
00137 "RX1"
00138 };
00139
00140 static char *TNames[2] = {
00141 "TX0",
00142 "TX1"
00143 };
00144
00145 static void InitPort(SERIAL *pS,unsigned short nTSize,unsigned short nRSize, unsigned short nPort,long nBaudRate)
00146 {
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156 pS->regs = &SAdr[nPort];
00157 pS->Tx.buff = malloc(nTSize);
00158 pS->Tx.head = 0;
00159 pS->Tx.tail = 0;
00160 pS->Tx.nChar = 0;
00161 pS->Tx.size = nTSize;
00162 pS->Tx.pSem = NewSemaphore(1,SEMAPHORE_MODE_BLOCKING,TNames[nPort]);
00163 pS->Rx.buff = malloc(nRSize);
00164 pS->Rx.head = 0;
00165 pS->Rx.tail = 0;
00166 pS->Rx.nChar = 0;
00167 pS->Rx.size = nRSize;
00168 pS->Rx.pSem = NewSemaphore(0,SEMAPHORE_MODE_BLOCKING,PNames[nPort]);
00169 *pS->regs->pUCSRnB = 0x00;
00170 *pS->regs->pUCSRnA = 0x00;
00171 *pS->regs->pUCSRnC = BIT(UCSZ01) | BIT(UCSZ00);
00172 *pS->regs->pUBRR = CalculateBaudRate(nBaudRate);
00173 *pS->regs->pUCSRnB = BIT(RXCIE0) | BIT(RXEN0) | BIT(TXEN0);
00174 }
00175
00176 int RInit(void) __attribute__ ((section(".lowtext")));
00177 int RInit(void)
00178 {
00179 CioAddHandler("COM",&RJump);
00180 return 0;
00181 }
00182
00183
00184
00185
00186
00187
00188
00189 static void RxIsr(SERIAL *pI)
00190 {
00191 while(*pI->regs->pUCSRnA & BIT(RXC0))
00192 {
00193 pI->Rx.buff[pI->Rx.head++] = *pI->regs->pUDR;
00194 if(pI->Rx.head == pI->Rx.size) pI->Rx.head = 0;
00195 pI->Rx.nChar++;
00196 PostSemaphore(pI->Rx.pSem,0);
00197 }
00198 }
00199
00200 static void TxIsr(SERIAL *pI)
00201 {
00202 char loop = 1;
00203
00204 while((*pI->regs->pUCSRnA & BIT(UDRE0)) && loop)
00205 {
00206 if(pI->Tx.nChar)
00207 {
00208 *pI->regs->pUDR = pI->Tx.buff[pI->Tx.tail++];
00209 if(pI->Tx.tail == pI->Tx.size) pI->Tx.tail = 0;
00210 pI->Tx.nChar--;
00211 }
00212 else
00213 {
00214
00215 *pI->regs->pUCSRnB &= ~(BIT(UDRIE0));
00216 loop = 0;
00217 }
00218 }
00219 }
00220
00221 void USART0_RX_vect(void) __attribute__ ((naked));
00222 void USART0_RX_vect(void)
00223 {
00224 SAVE_IRQ();
00225 ++InterruptCount;
00226 RxIsr(gSerial[0]);
00227 ExitInterrupt();
00228 RESTORE_IRQ();
00229 }
00230
00231 void USART0_UDRE_vect(void) __attribute__ ((naked));
00232 void USART0_UDRE_vect(void)
00233 {
00234 SAVE_IRQ();
00235 ++InterruptCount;
00236 TxIsr(gSerial[0]);
00237 ExitInterrupt();
00238 RESTORE_IRQ();
00239 }
00240
00241 void USART1_RX_vect(void) __attribute__ ((naked));
00242 void USART1_RX_vect(void)
00243 {
00244 SAVE_IRQ();
00245 ++InterruptCount;
00246 RxIsr(gSerial[1]);
00247 ExitInterrupt();
00248 RESTORE_IRQ();
00249 }
00250
00251 void USART1_UDRE_vect(void) __attribute__ ((naked));
00252 void USART1_UDRE_vect(void)
00253 {
00254 SAVE_IRQ();
00255 ++InterruptCount;
00256 TxIsr(gSerial[1]);
00257 ExitInterrupt();
00258 RESTORE_IRQ();
00259 }
00260
00261
00262
00263
00264