]> git.sur5r.net Git - freertos/blob - Demo/PIC18_MPLAB/serial/serial.c
Update to V4.3.0 as described in http://www.FreeRTOS.org/History.txt
[freertos] / Demo / PIC18_MPLAB / serial / serial.c
1 /*\r
2         FreeRTOS.org V4.3.0 - Copyright (C) 2003-2007 Richard Barry.\r
3 \r
4         This file is part of the FreeRTOS.org distribution.\r
5 \r
6         FreeRTOS.org is free software; you can redistribute it and/or modify\r
7         it under the terms of the GNU General Public License as published by\r
8         the Free Software Foundation; either version 2 of the License, or\r
9         (at your option) any later version.\r
10 \r
11         FreeRTOS.org is distributed in the hope that it will be useful,\r
12         but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14         GNU General Public License for more details.\r
15 \r
16         You should have received a copy of the GNU General Public License\r
17         along with FreeRTOS.org; if not, write to the Free Software\r
18         Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
19 \r
20         A special exception to the GPL can be applied should you wish to distribute\r
21         a combined work that includes FreeRTOS.org, without being obliged to provide\r
22         the source code for any proprietary components.  See the licensing section \r
23         of http://www.FreeRTOS.org for full details of how and when the exception\r
24         can be applied.\r
25 \r
26         ***************************************************************************\r
27         See http://www.FreeRTOS.org for documentation, latest information, license \r
28         and contact details.  Please ensure to read the configuration and relevant \r
29         port sections of the online documentation.\r
30 \r
31         Also see http://www.SafeRTOS.com for an IEC 61508 compliant version along\r
32         with commercial development and support options.\r
33         ***************************************************************************\r
34 */\r
35 \r
36 /*\r
37 Changes from V1.2.5\r
38 \r
39         +  Clear overrun errors in the Rx ISR.  Overrun errors prevent any further\r
40            characters being received.\r
41 \r
42 Changes from V2.0.0\r
43 \r
44         + Use portTickType in place of unsigned pdLONG for delay periods.\r
45         + cQueueReieveFromISR() used in place of xQueueReceive() in ISR.\r
46 */\r
47 \r
48 /* BASIC INTERRUPT DRIVEN SERIAL PORT DRIVER. */\r
49 \r
50 /* Scheduler header files. */\r
51 #include "FreeRTOS.h"\r
52 #include "task.h"\r
53 #include "serial.h"\r
54 #include "queue.h"\r
55 \r
56 /*\r
57  * Prototypes for ISR's.  The PIC architecture means that these functions\r
58  * have to be called from port.c.  The prototypes are not however included\r
59  * in the header as the header is common to all ports.\r
60  */\r
61 void vSerialTxISR( void );\r
62 void vSerialRxISR( void );\r
63 \r
64 /* Hardware pin definitions. */\r
65 #define serTX_PIN       TRISCbits.TRISC6\r
66 #define serRX_PIN       TRISCbits.TRISC7\r
67 \r
68 /* Bit/register definitions. */\r
69 #define serINPUT                                ( 1 )\r
70 #define serOUTPUT                               ( 0 )\r
71 #define serTX_ENABLE                    ( ( unsigned portSHORT ) 1 )\r
72 #define serRX_ENABLE                    ( ( unsigned portSHORT ) 1 )\r
73 #define serHIGH_SPEED                   ( ( unsigned portSHORT ) 1 )\r
74 #define serCONTINUOUS_RX                ( ( unsigned portSHORT ) 1 )\r
75 #define serCLEAR_OVERRUN                ( ( unsigned portSHORT ) 0 )\r
76 #define serINTERRUPT_ENABLED    ( ( unsigned portSHORT ) 1 )\r
77 #define serINTERRUPT_DISABLED   ( ( unsigned portSHORT ) 0 )\r
78 \r
79 /* All ISR's use the PIC18 low priority interrupt. */\r
80 #define                                                 serLOW_PRIORITY ( 0 )\r
81 \r
82 /*-----------------------------------------------------------*/\r
83 \r
84 /* Queues to interface between comms API and interrupt routines. */\r
85 static xQueueHandle xRxedChars; \r
86 static xQueueHandle xCharsForTx;\r
87 \r
88 /*-----------------------------------------------------------*/\r
89 \r
90 xComPortHandle xSerialPortInitMinimal( unsigned portLONG ulWantedBaud, unsigned portBASE_TYPE uxQueueLength )\r
91 {\r
92 unsigned portLONG ulBaud;\r
93 \r
94         /* Calculate the baud rate generator constant.\r
95         SPBRG = ( (FOSC / Desired Baud Rate) / 16 ) - 1 */\r
96         ulBaud = configCPU_CLOCK_HZ / ulWantedBaud;\r
97         ulBaud /= ( unsigned portLONG ) 16;\r
98         ulBaud -= ( unsigned portLONG ) 1;\r
99 \r
100         /* Create the queues used by the ISR's to interface to tasks. */\r
101         xRxedChars = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( portCHAR ) );\r
102         xCharsForTx = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( portCHAR ) );\r
103 \r
104         portENTER_CRITICAL();\r
105         {\r
106                 /* Start with config registers cleared, so we can just set the wanted\r
107                 bits. */\r
108                 TXSTA = ( unsigned portSHORT ) 0;\r
109                 RCSTA = ( unsigned portSHORT ) 0;\r
110 \r
111                 /* Set the baud rate generator using the above calculated constant. */\r
112                 SPBRG = ( unsigned portCHAR ) ulBaud;\r
113 \r
114                 /* Setup the IO pins to enable the USART IO. */\r
115                 serTX_PIN = serOUTPUT;\r
116                 serRX_PIN = serINPUT;\r
117 \r
118                 /* Set the serial interrupts to use the same priority as the tick. */\r
119                 IPR1bits.TXIP = serLOW_PRIORITY;\r
120                 IPR1bits.RCIP = serLOW_PRIORITY;\r
121 \r
122                 /* Setup Tx configuration. */\r
123                 TXSTAbits.BRGH = serHIGH_SPEED;\r
124                 TXSTAbits.TXEN = serTX_ENABLE;\r
125 \r
126                 /* Setup Rx configuration. */\r
127                 RCSTAbits.SPEN = serRX_ENABLE;\r
128                 RCSTAbits.CREN = serCONTINUOUS_RX;\r
129 \r
130                 /* Enable the Rx interrupt now, the Tx interrupt will get enabled when\r
131                 we have data to send. */\r
132                 PIE1bits.RCIE = serINTERRUPT_ENABLED;\r
133         }\r
134         portEXIT_CRITICAL();\r
135 \r
136         /* Unlike other ports, this serial code does not allow for more than one\r
137         com port.  We therefore don't return a pointer to a port structure and \r
138         can     instead just return NULL. */\r
139         return NULL;\r
140 }\r
141 /*-----------------------------------------------------------*/\r
142 \r
143 xComPortHandle xSerialPortInit( eCOMPort ePort, eBaud eWantedBaud, eParity eWantedParity, eDataBits eWantedDataBits, eStopBits eWantedStopBits, unsigned portBASE_TYPE uxBufferLength )\r
144 {\r
145         /* This is not implemented in this port.\r
146         Use xSerialPortInitMinimal() instead. */\r
147 }\r
148 /*-----------------------------------------------------------*/\r
149 \r
150 portBASE_TYPE xSerialGetChar( xComPortHandle pxPort, signed portCHAR *pcRxedChar, portTickType xBlockTime )\r
151 {\r
152         /* Get the next character from the buffer.  Return false if no characters\r
153         are available, or arrive before xBlockTime expires. */\r
154         if( xQueueReceive( xRxedChars, pcRxedChar, xBlockTime ) )\r
155         {\r
156                 return pdTRUE;\r
157         }\r
158         else\r
159         {\r
160                 return pdFALSE;\r
161         }\r
162 }\r
163 /*-----------------------------------------------------------*/\r
164 \r
165 portBASE_TYPE xSerialPutChar( xComPortHandle pxPort, signed portCHAR cOutChar, portTickType xBlockTime )\r
166 {\r
167         /* Return false if after the block time there is no room on the Tx queue. */\r
168         if( xQueueSend( xCharsForTx, ( const void * ) &cOutChar, xBlockTime ) != pdPASS )\r
169         {\r
170                 return pdFAIL;\r
171         }\r
172 \r
173         /* Turn interrupt on - ensure the compiler only generates a single \r
174         instruction for this. */\r
175         PIE1bits.TXIE = serINTERRUPT_ENABLED;\r
176 \r
177         return pdPASS;\r
178 }\r
179 /*-----------------------------------------------------------*/\r
180 \r
181 void vSerialClose( xComPortHandle xPort )\r
182 {\r
183         /* Not implemented for this port.\r
184         To implement, turn off the interrupts and delete the memory\r
185         allocated to the queues. */\r
186 }\r
187 /*-----------------------------------------------------------*/\r
188 \r
189 #pragma interruptlow vSerialRxISR save=PRODH, PRODL, TABLAT, section(".tmpdata")\r
190 void vSerialRxISR( void )\r
191 {\r
192 portCHAR cChar;\r
193 \r
194         /* Get the character and post it on the queue of Rxed characters.\r
195         If the post causes a task to wake force a context switch as the woken task\r
196         may have a higher priority than the task we have interrupted. */\r
197         cChar = RCREG;\r
198 \r
199         /* Clear any overrun errors. */\r
200         if( RCSTAbits.OERR )\r
201         {\r
202                 RCSTAbits.CREN = serCLEAR_OVERRUN;\r
203                 RCSTAbits.CREN = serCONTINUOUS_RX;      \r
204         }\r
205 \r
206         if( xQueueSendFromISR( xRxedChars, ( const void * ) &cChar, pdFALSE ) )\r
207         {\r
208                 taskYIELD();\r
209         }\r
210 }\r
211 /*-----------------------------------------------------------*/\r
212 \r
213 #pragma interruptlow vSerialTxISR save=PRODH, PRODL, TABLAT, section(".tmpdata")\r
214 void vSerialTxISR( void )\r
215 {\r
216 portCHAR cChar, cTaskWoken;\r
217 \r
218         if( xQueueReceiveFromISR( xCharsForTx, &cChar, &cTaskWoken ) == pdTRUE )\r
219         {\r
220                 /* Send the next character queued for Tx. */\r
221                 TXREG = cChar;\r
222         }\r
223         else\r
224         {\r
225                 /* Queue empty, nothing to send. */\r
226                 PIE1bits.TXIE = serINTERRUPT_DISABLED;\r
227         }\r
228 }\r
229 \r
230 \r
231 \r