]> begriffs open source - cmsis-freertos/blob - Demo/AVR_ATMega323_WinAVR/serial/serial.c
Update cmsis_os2.c
[cmsis-freertos] / Demo / AVR_ATMega323_WinAVR / serial / serial.c
1 /*
2     FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
3     All rights reserved
4
5     VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
6
7     This file is part of the FreeRTOS distribution.
8
9     FreeRTOS is free software; you can redistribute it and/or modify it under
10     the terms of the GNU General Public License (version 2) as published by the
11     Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
12
13     ***************************************************************************
14     >>!   NOTE: The modification to the GPL is included to allow you to     !<<
15     >>!   distribute a combined work that includes FreeRTOS without being   !<<
16     >>!   obliged to provide the source code for proprietary components     !<<
17     >>!   outside of the FreeRTOS kernel.                                   !<<
18     ***************************************************************************
19
20     FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
21     WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
22     FOR A PARTICULAR PURPOSE.  Full license text is available on the following
23     link: http://www.freertos.org/a00114.html
24
25     ***************************************************************************
26      *                                                                       *
27      *    FreeRTOS provides completely free yet professionally developed,    *
28      *    robust, strictly quality controlled, supported, and cross          *
29      *    platform software that is more than just the market leader, it     *
30      *    is the industry's de facto standard.                               *
31      *                                                                       *
32      *    Help yourself get started quickly while simultaneously helping     *
33      *    to support the FreeRTOS project by purchasing a FreeRTOS           *
34      *    tutorial book, reference manual, or both:                          *
35      *    http://www.FreeRTOS.org/Documentation                              *
36      *                                                                       *
37     ***************************************************************************
38
39     http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading
40     the FAQ page "My application does not run, what could be wrong?".  Have you
41     defined configASSERT()?
42
43     http://www.FreeRTOS.org/support - In return for receiving this top quality
44     embedded software for free we request you assist our global community by
45     participating in the support forum.
46
47     http://www.FreeRTOS.org/training - Investing in training allows your team to
48     be as productive as possible as early as possible.  Now you can receive
49     FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
50     Ltd, and the world's leading authority on the world's leading RTOS.
51
52     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
53     including FreeRTOS+Trace - an indispensable productivity tool, a DOS
54     compatible FAT file system, and our tiny thread aware UDP/IP stack.
55
56     http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
57     Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
58
59     http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
60     Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS
61     licenses offer ticketed support, indemnification and commercial middleware.
62
63     http://www.SafeRTOS.com - High Integrity Systems also provide a safety
64     engineered and independently SIL3 certified version for use in safety and
65     mission critical applications that require provable dependability.
66
67     1 tab == 4 spaces!
68 */
69
70 /*
71 Changes from V1.2.3
72
73         + The function xPortInitMinimal() has been renamed to 
74           xSerialPortInitMinimal() and the function xPortInit() has been renamed
75           to xSerialPortInit().
76
77 Changes from V2.0.0
78
79         + Delay periods are now specified using variables and constants of
80           TickType_t rather than unsigned long.
81         + xQueueReceiveFromISR() used in place of xQueueReceive() within the ISR.
82
83 Changes from V2.6.0
84
85         + Replaced the inb() and outb() functions with direct memory
86           access.  This allows the port to be built with the 20050414 build of
87           WinAVR.
88 */
89
90 /* BASIC INTERRUPT DRIVEN SERIAL PORT DRIVER. */
91
92
93 #include <stdlib.h>
94 #include <avr/interrupt.h>
95 #include "FreeRTOS.h"
96 #include "queue.h"
97 #include "task.h"
98 #include "serial.h"
99
100 #define serBAUD_DIV_CONSTANT                    ( ( unsigned long ) 16 )
101
102 /* Constants for writing to UCSRB. */
103 #define serRX_INT_ENABLE                                ( ( unsigned char ) 0x80 )
104 #define serRX_ENABLE                                    ( ( unsigned char ) 0x10 )
105 #define serTX_ENABLE                                    ( ( unsigned char ) 0x08 )
106 #define serTX_INT_ENABLE                                ( ( unsigned char ) 0x20 )
107
108 /* Constants for writing to UCSRC. */
109 #define serUCSRC_SELECT                                 ( ( unsigned char ) 0x80 )
110 #define serEIGHT_DATA_BITS                              ( ( unsigned char ) 0x06 )
111
112 static QueueHandle_t xRxedChars; 
113 static QueueHandle_t xCharsForTx; 
114
115 #define vInterruptOn()                                                                          \
116 {                                                                                                                       \
117         unsigned char ucByte;                                                           \
118                                                                                                                         \
119         ucByte = UCSRB;                                                                                 \
120         ucByte |= serTX_INT_ENABLE;                                                             \
121         UCSRB = ucByte;                                                                                 \
122 }                                                                                                                                                               
123 /*-----------------------------------------------------------*/
124
125 #define vInterruptOff()                                                                         \
126 {                                                                                                                       \
127         unsigned char ucInByte;                                                         \
128                                                                                                                         \
129         ucInByte = UCSRB;                                                                               \
130         ucInByte &= ~serTX_INT_ENABLE;                                                  \
131         UCSRB = ucInByte;                                                                               \
132 }
133 /*-----------------------------------------------------------*/
134
135 xComPortHandle xSerialPortInitMinimal( unsigned long ulWantedBaud, unsigned portBASE_TYPE uxQueueLength )
136 {
137 unsigned long ulBaudRateCounter;
138 unsigned char ucByte;
139
140         portENTER_CRITICAL();
141         {
142                 /* Create the queues used by the com test task. */
143                 xRxedChars = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( signed char ) );
144                 xCharsForTx = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( signed char ) );
145
146                 /* Calculate the baud rate register value from the equation in the
147                 data sheet. */
148                 ulBaudRateCounter = ( configCPU_CLOCK_HZ / ( serBAUD_DIV_CONSTANT * ulWantedBaud ) ) - ( unsigned long ) 1;
149
150                 /* Set the baud rate. */        
151                 ucByte = ( unsigned char ) ( ulBaudRateCounter & ( unsigned long ) 0xff );      
152                 UBRRL = ucByte;
153
154                 ulBaudRateCounter >>= ( unsigned long ) 8;
155                 ucByte = ( unsigned char ) ( ulBaudRateCounter & ( unsigned long ) 0xff );      
156                 UBRRH = ucByte;
157
158                 /* Enable the Rx interrupt.  The Tx interrupt will get enabled
159                 later. Also enable the Rx and Tx. */
160                 UCSRB = ( serRX_INT_ENABLE | serRX_ENABLE | serTX_ENABLE );
161
162                 /* Set the data bits to 8. */
163                 UCSRC = ( serUCSRC_SELECT | serEIGHT_DATA_BITS );
164         }
165         portEXIT_CRITICAL();
166         
167         /* Unlike other ports, this serial code does not allow for more than one
168         com port.  We therefore don't return a pointer to a port structure and can
169         instead just return NULL. */
170         return NULL;
171 }
172 /*-----------------------------------------------------------*/
173
174 signed portBASE_TYPE xSerialGetChar( xComPortHandle pxPort, signed char *pcRxedChar, TickType_t xBlockTime )
175 {
176         /* Only one port is supported. */
177         ( void ) pxPort;
178
179         /* Get the next character from the buffer.  Return false if no characters
180         are available, or arrive before xBlockTime expires. */
181         if( xQueueReceive( xRxedChars, pcRxedChar, xBlockTime ) )
182         {
183                 return pdTRUE;
184         }
185         else
186         {
187                 return pdFALSE;
188         }
189 }
190 /*-----------------------------------------------------------*/
191
192 signed portBASE_TYPE xSerialPutChar( xComPortHandle pxPort, signed char cOutChar, TickType_t xBlockTime )
193 {
194         /* Only one port is supported. */
195         ( void ) pxPort;
196
197         /* Return false if after the block time there is no room on the Tx queue. */
198         if( xQueueSend( xCharsForTx, &cOutChar, xBlockTime ) != pdPASS )
199         {
200                 return pdFAIL;
201         }
202
203         vInterruptOn();
204
205         return pdPASS;
206 }
207 /*-----------------------------------------------------------*/
208
209 void vSerialClose( xComPortHandle xPort )
210 {
211 unsigned char ucByte;
212
213         /* The parameter is not used. */
214         ( void ) xPort;
215
216         /* Turn off the interrupts.  We may also want to delete the queues and/or
217         re-install the original ISR. */
218
219         portENTER_CRITICAL();
220         {
221                 vInterruptOff();
222                 ucByte = UCSRB;
223                 ucByte &= ~serRX_INT_ENABLE;
224                 UCSRB = ucByte;
225         }
226         portEXIT_CRITICAL();
227 }
228 /*-----------------------------------------------------------*/
229
230 SIGNAL( SIG_UART_RECV )
231 {
232 signed char cChar;
233 signed portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
234
235         /* Get the character and post it on the queue of Rxed characters.
236         If the post causes a task to wake force a context switch as the woken task
237         may have a higher priority than the task we have interrupted. */
238         cChar = UDR;
239
240         xQueueSendFromISR( xRxedChars, &cChar, &xHigherPriorityTaskWoken );
241
242         if( xHigherPriorityTaskWoken != pdFALSE )
243         {
244                 taskYIELD();
245         }
246 }
247 /*-----------------------------------------------------------*/
248
249 SIGNAL( SIG_UART_DATA )
250 {
251 signed char cChar, cTaskWoken;
252
253         if( xQueueReceiveFromISR( xCharsForTx, &cChar, &cTaskWoken ) == pdTRUE )
254         {
255                 /* Send the next character queued for Tx. */
256                 UDR = cChar;
257         }
258         else
259         {
260                 /* Queue empty, nothing to send. */
261                 vInterruptOff();
262         }
263 }
264