]> git.sur5r.net Git - freertos/blob - Demo/AVR_ATMega323_IAR/serial/serial.c
87e5f97d48cbc5e3e50468eb99ba40949604ec92
[freertos] / Demo / AVR_ATMega323_IAR / serial / serial.c
1 /*\r
2     FreeRTOS V6.0.0 - Copyright (C) 2009 Real Time Engineers Ltd.\r
3 \r
4     This file is part of the FreeRTOS distribution.\r
5 \r
6     FreeRTOS is free software; you can redistribute it and/or modify it    under\r
7     the terms of the GNU General Public License (version 2) as published by the\r
8     Free Software Foundation and modified by the FreeRTOS exception.\r
9     **NOTE** The exception to the GPL is included to allow you to distribute a\r
10     combined work that includes FreeRTOS without being obliged to provide the\r
11     source code for proprietary components outside of the FreeRTOS kernel.\r
12     Alternative commercial license and support terms are also available upon\r
13     request.  See the licensing section of http://www.FreeRTOS.org for full\r
14     license details.\r
15 \r
16     FreeRTOS is distributed in the hope that it will be useful,    but WITHOUT\r
17     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
18     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for\r
19     more details.\r
20 \r
21     You should have received a copy of the GNU General Public License along\r
22     with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59\r
23     Temple Place, Suite 330, Boston, MA  02111-1307  USA.\r
24 \r
25 \r
26     ***************************************************************************\r
27     *                                                                         *\r
28     * The FreeRTOS eBook and reference manual are available to purchase for a *\r
29     * small fee. Help yourself get started quickly while also helping the     *\r
30     * FreeRTOS project! See http://www.FreeRTOS.org/Documentation for details *\r
31     *                                                                         *\r
32     ***************************************************************************\r
33 \r
34     1 tab == 4 spaces!\r
35 \r
36     Please ensure to read the configuration and relevant port sections of the\r
37     online documentation.\r
38 \r
39     http://www.FreeRTOS.org - Documentation, latest information, license and\r
40     contact details.\r
41 \r
42     http://www.SafeRTOS.com - A version that is certified for use in safety\r
43     critical systems.\r
44 \r
45     http://www.OpenRTOS.com - Commercial support, development, porting,\r
46     licensing and training services.\r
47 */\r
48 \r
49 \r
50 /* BASIC INTERRUPT DRIVEN SERIAL PORT DRIVER FOR IAR AVR PORT. */\r
51 \r
52 \r
53 #include <stdlib.h>\r
54 #include "FreeRTOS.h"\r
55 #include "queue.h"\r
56 #include "task.h"\r
57 #include "serial.h"\r
58 \r
59 #define serBAUD_DIV_CONSTANT                    ( ( unsigned long ) 16 )\r
60 \r
61 /* Constants for writing to UCSRB. */\r
62 #define serRX_INT_ENABLE                                ( ( unsigned char ) 0x80 )\r
63 #define serRX_ENABLE                                    ( ( unsigned char ) 0x10 )\r
64 #define serTX_ENABLE                                    ( ( unsigned char ) 0x08 )\r
65 #define serTX_INT_ENABLE                                ( ( unsigned char ) 0x20 )\r
66 \r
67 /* Constants for writing to UCSRC. */\r
68 #define serUCSRC_SELECT                                 ( ( unsigned char ) 0x80 )\r
69 #define serEIGHT_DATA_BITS                              ( ( unsigned char ) 0x06 )\r
70 \r
71 static xQueueHandle xRxedChars;\r
72 static xQueueHandle xCharsForTx;\r
73 \r
74 #define vInterruptOn()                                                                          \\r
75 {                                                                                                                       \\r
76         unsigned char ucByte;                                                           \\r
77                                                                                                                         \\r
78         ucByte = UCSRB;                                                                                 \\r
79         ucByte |= serTX_INT_ENABLE;                                                             \\r
80         outb( UCSRB, ucByte );                                                                  \\r
81 }                                                                                                                                                               \r
82 /*-----------------------------------------------------------*/\r
83 \r
84 #define vInterruptOff()                                                                         \\r
85 {                                                                                                                       \\r
86         unsigned char ucByte;                                                           \\r
87                                                                                                                         \\r
88         ucByte = UCSRB;                                                                                 \\r
89         ucByte &= ~serTX_INT_ENABLE;                                                    \\r
90         outb( UCSRB, ucByte );                                                                  \\r
91 }\r
92 /*-----------------------------------------------------------*/\r
93 \r
94 xComPortHandle xSerialPortInitMinimal( unsigned long ulWantedBaud, unsigned portBASE_TYPE uxQueueLength )\r
95 {\r
96 unsigned long ulBaudRateCounter;\r
97 unsigned char ucByte;\r
98 \r
99         portENTER_CRITICAL();\r
100         {\r
101                 /* Create the queues used by the com test task. */\r
102                 xRxedChars = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( signed char ) );\r
103                 xCharsForTx = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( signed char ) );\r
104 \r
105                 /* Calculate the baud rate register value from the equation in the\r
106                 data sheet. */\r
107                 ulBaudRateCounter = ( configCPU_CLOCK_HZ / ( serBAUD_DIV_CONSTANT * ulWantedBaud ) ) - ( unsigned long ) 1;\r
108 \r
109                 /* Set the baud rate. */        \r
110                 ucByte = ( unsigned char ) ( ulBaudRateCounter & ( unsigned long ) 0xff );      \r
111                 outb( UBRRL, ucByte );\r
112 \r
113                 ulBaudRateCounter >>= ( unsigned long ) 8;\r
114                 ucByte = ( unsigned char ) ( ulBaudRateCounter & ( unsigned long ) 0xff );      \r
115                 outb( UBRRH, ucByte );\r
116 \r
117                 /* Enable the Rx interrupt.  The Tx interrupt will get enabled\r
118                 later. Also enable the Rx and Tx. */\r
119                 outb( UCSRB, serRX_INT_ENABLE | serRX_ENABLE | serTX_ENABLE );\r
120 \r
121                 /* Set the data bits to 8. */\r
122                 outb( UCSRC, serUCSRC_SELECT | serEIGHT_DATA_BITS );\r
123         }\r
124         portEXIT_CRITICAL();\r
125         \r
126         /* Unlike other ports, this serial code does not allow for more than one\r
127         com port.  We therefore don't return a pointer to a port structure and can\r
128         instead just return NULL. */\r
129         return NULL;\r
130 }\r
131 /*-----------------------------------------------------------*/\r
132 \r
133 signed portBASE_TYPE xSerialGetChar( xComPortHandle pxPort, signed char *pcRxedChar, portTickType xBlockTime )\r
134 {\r
135         /* Get the next character from the buffer.  Return false if no characters\r
136         are available, or arrive before xBlockTime expires. */\r
137         if( xQueueReceive( xRxedChars, pcRxedChar, xBlockTime ) )\r
138         {\r
139                 return pdTRUE;\r
140         }\r
141         else\r
142         {\r
143                 return pdFALSE;\r
144         }\r
145 }\r
146 /*-----------------------------------------------------------*/\r
147 \r
148 signed portBASE_TYPE xSerialPutChar( xComPortHandle pxPort, signed char cOutChar, portTickType xBlockTime )\r
149 {\r
150         /* Return false if after the block time there is no room on the Tx queue. */\r
151         if( xQueueSend( xCharsForTx, &cOutChar, xBlockTime ) != pdPASS )\r
152         {\r
153                 return pdFAIL;\r
154         }\r
155 \r
156         vInterruptOn();\r
157 \r
158         return pdPASS;\r
159 }\r
160 /*-----------------------------------------------------------*/\r
161 \r
162 void vSerialClose( xComPortHandle xPort )\r
163 {\r
164 unsigned char ucByte;\r
165 \r
166         /* Turn off the interrupts.  We may also want to delete the queues and/or\r
167         re-install the original ISR. */\r
168 \r
169         portENTER_CRITICAL();\r
170         {\r
171                 vInterruptOff();\r
172                 ucByte = UCSRB;\r
173                 ucByte &= ~serRX_INT_ENABLE;\r
174                 outb( UCSRB, ucByte );\r
175         }\r
176         portEXIT_CRITICAL();\r
177 }\r
178 /*-----------------------------------------------------------*/\r
179 \r
180 __interrupt void SIG_UART_RECV( void )\r
181 {\r
182 signed char ucChar, xHigherPriorityTaskWoken = pdFALSE;\r
183 \r
184         /* Get the character and post it on the queue of Rxed characters.\r
185         If the post causes a task to wake force a context switch as the woken task\r
186         may have a higher priority than the task we have interrupted. */\r
187         ucChar = UDR;\r
188 \r
189         xQueueSendFromISR( xRxedChars, &ucChar, &xHigherPriorityTaskWoken );\r
190 \r
191         if( xHigherPriorityTaskWoken != pdFALSE )\r
192         {\r
193                 taskYIELD();\r
194         }\r
195 }\r
196 /*-----------------------------------------------------------*/\r
197 \r
198 __interrupt void SIG_UART_DATA( void )\r
199 {\r
200 signed char cChar, cTaskWoken = pdFALSE;\r
201 \r
202         if( xQueueReceiveFromISR( xCharsForTx, &cChar, &cTaskWoken ) == pdTRUE )\r
203         {\r
204                 /* Send the next character queued for Tx. */\r
205                 outb( UDR, cChar );\r
206         }\r
207         else\r
208         {\r
209                 /* Queue empty, nothing to send. */\r
210                 vInterruptOff();\r
211         }\r
212 }\r
213 \r